From c386a727126b643f6e22ea5c3f1a3f2467952d05 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 4 Dec 2013 17:03:46 +0000 Subject: [PATCH] initial commit --- conf/nginx.conf | 16 + conf/wp-config.php | 99 + manifest.json | 42 + scripts/install | 45 + scripts/remove | 10 + sources/index.php | 17 + sources/license.txt | 385 + sources/readme.html | 93 + sources/wp-activate.php | 132 + sources/wp-admin/about.php | 181 + sources/wp-admin/admin-ajax.php | 94 + sources/wp-admin/admin-footer.php | 90 + sources/wp-admin/admin-functions.php | 15 + sources/wp-admin/admin-header.php | 234 + sources/wp-admin/admin-post.php | 45 + sources/wp-admin/admin.php | 347 + sources/wp-admin/async-upload.php | 98 + sources/wp-admin/comment.php | 303 + sources/wp-admin/credits.php | 190 + sources/wp-admin/css/color-picker-rtl.css | 27 + sources/wp-admin/css/color-picker-rtl.min.css | 1 + sources/wp-admin/css/color-picker.css | 107 + sources/wp-admin/css/color-picker.min.css | 1 + sources/wp-admin/css/colors-classic.css | 2252 +++ sources/wp-admin/css/colors-classic.min.css | 1 + sources/wp-admin/css/colors-fresh.css | 2141 +++ sources/wp-admin/css/colors-fresh.min.css | 1 + .../wp-admin/css/customize-controls-rtl.css | 77 + .../css/customize-controls-rtl.min.css | 1 + sources/wp-admin/css/customize-controls.css | 440 + .../wp-admin/css/customize-controls.min.css | 1 + sources/wp-admin/css/farbtastic.css | 52 + sources/wp-admin/css/ie-rtl.css | 236 + sources/wp-admin/css/ie-rtl.min.css | 1 + sources/wp-admin/css/ie.css | 622 + sources/wp-admin/css/ie.min.css | 1 + sources/wp-admin/css/install.css | 263 + sources/wp-admin/css/install.min.css | 1 + sources/wp-admin/css/media-rtl.css | 71 + sources/wp-admin/css/media-rtl.min.css | 1 + sources/wp-admin/css/media.css | 353 + sources/wp-admin/css/media.min.css | 1 + sources/wp-admin/css/wp-admin-rtl.css | 2895 +++ sources/wp-admin/css/wp-admin-rtl.min.css | 1 + sources/wp-admin/css/wp-admin.css | 9424 ++++++++++ sources/wp-admin/css/wp-admin.min.css | 1 + sources/wp-admin/custom-background.php | 428 + sources/wp-admin/custom-header.php | 1045 ++ sources/wp-admin/customize.php | 243 + sources/wp-admin/edit-comments.php | 255 + sources/wp-admin/edit-form-advanced.php | 608 + sources/wp-admin/edit-form-comment.php | 152 + sources/wp-admin/edit-link-form.php | 141 + sources/wp-admin/edit-tag-form.php | 96 + sources/wp-admin/edit-tags.php | 465 + sources/wp-admin/edit.php | 325 + sources/wp-admin/export.php | 244 + sources/wp-admin/freedoms.php | 57 + sources/wp-admin/images/about-globe-2x.png | Bin 0 -> 10570 bytes sources/wp-admin/images/about-search-2x.png | Bin 0 -> 6867 bytes sources/wp-admin/images/about-updates-2x.png | Bin 0 -> 11813 bytes sources/wp-admin/images/align-center-2x.png | Bin 0 -> 147 bytes sources/wp-admin/images/align-center.png | Bin 0 -> 546 bytes sources/wp-admin/images/align-left-2x.png | Bin 0 -> 143 bytes sources/wp-admin/images/align-left.png | Bin 0 -> 554 bytes sources/wp-admin/images/align-none-2x.png | Bin 0 -> 121 bytes sources/wp-admin/images/align-none.png | Bin 0 -> 417 bytes sources/wp-admin/images/align-right-2x.png | Bin 0 -> 142 bytes sources/wp-admin/images/align-right.png | Bin 0 -> 509 bytes sources/wp-admin/images/arrows-2x.png | Bin 0 -> 863 bytes sources/wp-admin/images/arrows-dark-2x.png | Bin 0 -> 719 bytes sources/wp-admin/images/arrows-dark-vs-2x.png | Bin 0 -> 761 bytes sources/wp-admin/images/arrows-dark-vs.png | Bin 0 -> 243 bytes sources/wp-admin/images/arrows-dark.png | Bin 0 -> 243 bytes sources/wp-admin/images/arrows-pr-2x.png | Bin 0 -> 723 bytes sources/wp-admin/images/arrows-pr.png | Bin 0 -> 461 bytes sources/wp-admin/images/arrows-vs-2x.png | Bin 0 -> 723 bytes sources/wp-admin/images/arrows-vs.png | Bin 0 -> 243 bytes sources/wp-admin/images/arrows.png | Bin 0 -> 243 bytes sources/wp-admin/images/bubble_bg-2x.gif | Bin 0 -> 507 bytes sources/wp-admin/images/bubble_bg-rtl-2x.gif | Bin 0 -> 499 bytes sources/wp-admin/images/bubble_bg-rtl.gif | Bin 0 -> 400 bytes sources/wp-admin/images/bubble_bg.gif | Bin 0 -> 395 bytes .../images/comment-grey-bubble-2x.png | Bin 0 -> 259 bytes .../wp-admin/images/comment-grey-bubble.png | Bin 0 -> 114 bytes sources/wp-admin/images/date-button-2x.gif | Bin 0 -> 992 bytes sources/wp-admin/images/date-button.gif | Bin 0 -> 400 bytes sources/wp-admin/images/generic.png | Bin 0 -> 719 bytes sources/wp-admin/images/icons32-2x.png | Bin 0 -> 35645 bytes sources/wp-admin/images/icons32-vs-2x.png | Bin 0 -> 37994 bytes sources/wp-admin/images/icons32-vs.png | Bin 0 -> 12920 bytes sources/wp-admin/images/icons32.png | Bin 0 -> 12989 bytes sources/wp-admin/images/imgedit-icons-2x.png | Bin 0 -> 14853 bytes sources/wp-admin/images/imgedit-icons.png | Bin 0 -> 6989 bytes sources/wp-admin/images/list-2x.png | Bin 0 -> 1523 bytes sources/wp-admin/images/list.png | Bin 0 -> 1003 bytes sources/wp-admin/images/loading.gif | Bin 0 -> 2530 bytes sources/wp-admin/images/lock-2x.png | Bin 0 -> 716 bytes sources/wp-admin/images/lock.png | Bin 0 -> 338 bytes sources/wp-admin/images/marker.png | Bin 0 -> 377 bytes sources/wp-admin/images/mask.png | Bin 0 -> 2001 bytes sources/wp-admin/images/media-button-2x.png | Bin 0 -> 850 bytes .../wp-admin/images/media-button-image.gif | Bin 0 -> 206 bytes .../wp-admin/images/media-button-music.gif | Bin 0 -> 205 bytes .../wp-admin/images/media-button-other.gif | Bin 0 -> 245 bytes .../wp-admin/images/media-button-video.gif | Bin 0 -> 139 bytes sources/wp-admin/images/media-button.png | Bin 0 -> 323 bytes sources/wp-admin/images/menu-2x.png | Bin 0 -> 30324 bytes sources/wp-admin/images/menu-shadow-rtl.png | Bin 0 -> 92 bytes sources/wp-admin/images/menu-shadow.png | Bin 0 -> 89 bytes sources/wp-admin/images/menu-vs-2x.png | Bin 0 -> 29592 bytes sources/wp-admin/images/menu-vs.png | Bin 0 -> 9320 bytes sources/wp-admin/images/menu.png | Bin 0 -> 9165 bytes sources/wp-admin/images/no.png | Bin 0 -> 755 bytes sources/wp-admin/images/post-formats-vs.png | Bin 0 -> 2794 bytes sources/wp-admin/images/post-formats.png | Bin 0 -> 2220 bytes sources/wp-admin/images/post-formats32-vs.png | Bin 0 -> 7512 bytes sources/wp-admin/images/post-formats32.png | Bin 0 -> 7829 bytes sources/wp-admin/images/press-this-2x.png | Bin 0 -> 755 bytes sources/wp-admin/images/press-this.png | Bin 0 -> 417 bytes sources/wp-admin/images/resize-2x.gif | Bin 0 -> 234 bytes sources/wp-admin/images/resize-rtl-2x.gif | Bin 0 -> 232 bytes sources/wp-admin/images/resize-rtl.gif | Bin 0 -> 1418 bytes sources/wp-admin/images/resize.gif | Bin 0 -> 71 bytes sources/wp-admin/images/se.png | Bin 0 -> 120 bytes sources/wp-admin/images/sort-2x.gif | Bin 0 -> 97 bytes sources/wp-admin/images/sort.gif | Bin 0 -> 54 bytes sources/wp-admin/images/stars-2x.png | Bin 0 -> 1257 bytes sources/wp-admin/images/stars-rtl-2x.png | Bin 0 -> 3212 bytes sources/wp-admin/images/stars-rtl.png | Bin 0 -> 926 bytes sources/wp-admin/images/stars.png | Bin 0 -> 924 bytes sources/wp-admin/images/welcome-icons-2x.png | Bin 0 -> 6349 bytes sources/wp-admin/images/welcome-icons.png | Bin 0 -> 2152 bytes sources/wp-admin/images/wheel.png | Bin 0 -> 11505 bytes sources/wp-admin/images/wordpress-logo-2x.png | Bin 0 -> 4867 bytes sources/wp-admin/images/wordpress-logo.png | Bin 0 -> 2480 bytes sources/wp-admin/images/wp-badge-2x.png | Bin 0 -> 28160 bytes sources/wp-admin/images/wp-badge.png | Bin 0 -> 12099 bytes sources/wp-admin/images/wp-logo-2x.png | Bin 0 -> 1806 bytes sources/wp-admin/images/wp-logo-vs-2x.png | Bin 0 -> 2087 bytes sources/wp-admin/images/wp-logo-vs.png | Bin 0 -> 751 bytes sources/wp-admin/images/wp-logo.png | Bin 0 -> 661 bytes sources/wp-admin/images/wpspin_light-2x.gif | Bin 0 -> 9097 bytes sources/wp-admin/images/wpspin_light.gif | Bin 0 -> 2193 bytes sources/wp-admin/images/xit-2x.gif | Bin 0 -> 823 bytes sources/wp-admin/images/xit.gif | Bin 0 -> 182 bytes sources/wp-admin/images/yes.png | Bin 0 -> 539 bytes sources/wp-admin/import.php | 133 + sources/wp-admin/includes/admin.php | 72 + sources/wp-admin/includes/ajax-actions.php | 2246 +++ sources/wp-admin/includes/bookmark.php | 316 + sources/wp-admin/includes/class-ftp-pure.php | 190 + .../wp-admin/includes/class-ftp-sockets.php | 250 + sources/wp-admin/includes/class-ftp.php | 907 + sources/wp-admin/includes/class-pclzip.php | 5687 ++++++ .../includes/class-wp-comments-list-table.php | 564 + .../includes/class-wp-filesystem-base.php | 763 + .../includes/class-wp-filesystem-direct.php | 384 + .../includes/class-wp-filesystem-ftpext.php | 415 + .../class-wp-filesystem-ftpsockets.php | 351 + .../includes/class-wp-filesystem-ssh2.php | 391 + .../wp-admin/includes/class-wp-importer.php | 302 + .../includes/class-wp-links-list-table.php | 189 + .../wp-admin/includes/class-wp-list-table.php | 930 + .../includes/class-wp-media-list-table.php | 437 + .../includes/class-wp-ms-sites-list-table.php | 346 + .../class-wp-ms-themes-list-table.php | 356 + .../includes/class-wp-ms-users-list-table.php | 272 + .../class-wp-plugin-install-list-table.php | 282 + .../includes/class-wp-plugins-list-table.php | 437 + .../includes/class-wp-posts-list-table.php | 1104 ++ .../includes/class-wp-terms-list-table.php | 378 + .../class-wp-theme-install-list-table.php | 397 + .../includes/class-wp-themes-list-table.php | 264 + .../includes/class-wp-upgrader-skins.php | 662 + .../wp-admin/includes/class-wp-upgrader.php | 2401 +++ .../includes/class-wp-users-list-table.php | 324 + sources/wp-admin/includes/comment.php | 171 + .../wp-admin/includes/continents-cities.php | 493 + sources/wp-admin/includes/dashboard.php | 1310 ++ sources/wp-admin/includes/deprecated.php | 1133 ++ sources/wp-admin/includes/export.php | 437 + sources/wp-admin/includes/file.php | 1111 ++ sources/wp-admin/includes/image-edit.php | 734 + sources/wp-admin/includes/image.php | 450 + sources/wp-admin/includes/import.php | 186 + sources/wp-admin/includes/list-table.php | 113 + sources/wp-admin/includes/media.php | 2708 +++ sources/wp-admin/includes/menu.php | 229 + sources/wp-admin/includes/meta-boxes.php | 1000 + sources/wp-admin/includes/misc.php | 700 + sources/wp-admin/includes/ms-deprecated.php | 78 + sources/wp-admin/includes/ms.php | 819 + sources/wp-admin/includes/nav-menu.php | 1290 ++ sources/wp-admin/includes/plugin-install.php | 454 + sources/wp-admin/includes/plugin.php | 1851 ++ sources/wp-admin/includes/post.php | 1452 ++ sources/wp-admin/includes/revision.php | 224 + sources/wp-admin/includes/schema.php | 1008 + sources/wp-admin/includes/screen.php | 1080 ++ sources/wp-admin/includes/taxonomy.php | 254 + sources/wp-admin/includes/template.php | 1962 ++ sources/wp-admin/includes/theme-install.php | 194 + sources/wp-admin/includes/theme.php | 312 + sources/wp-admin/includes/update-core.php | 1002 + sources/wp-admin/includes/update.php | 382 + sources/wp-admin/includes/upgrade.php | 2050 ++ sources/wp-admin/includes/user.php | 373 + sources/wp-admin/includes/widgets.php | 228 + sources/wp-admin/index.php | 146 + sources/wp-admin/install-helper.php | 198 + sources/wp-admin/install.php | 256 + sources/wp-admin/js/about.js | 80 + sources/wp-admin/js/about.min.js | 1 + sources/wp-admin/js/accordion.js | 55 + sources/wp-admin/js/accordion.min.js | 1 + sources/wp-admin/js/color-picker.js | 132 + sources/wp-admin/js/color-picker.min.js | 1 + sources/wp-admin/js/comment.js | 49 + sources/wp-admin/js/comment.min.js | 1 + sources/wp-admin/js/common.js | 452 + sources/wp-admin/js/common.min.js | 1 + sources/wp-admin/js/custom-background.js | 74 + sources/wp-admin/js/custom-background.min.js | 1 + sources/wp-admin/js/custom-header.js | 60 + sources/wp-admin/js/customize-controls.js | 1009 + sources/wp-admin/js/customize-controls.min.js | 1 + sources/wp-admin/js/dashboard.js | 117 + sources/wp-admin/js/dashboard.min.js | 1 + sources/wp-admin/js/edit-comments.js | 608 + sources/wp-admin/js/edit-comments.min.js | 1 + sources/wp-admin/js/editor.js | 245 + sources/wp-admin/js/editor.min.js | 1 + sources/wp-admin/js/farbtastic.js | 276 + sources/wp-admin/js/gallery.js | 199 + sources/wp-admin/js/gallery.min.js | 1 + sources/wp-admin/js/image-edit.js | 575 + sources/wp-admin/js/image-edit.min.js | 1 + sources/wp-admin/js/inline-edit-post.js | 330 + sources/wp-admin/js/inline-edit-post.min.js | 1 + sources/wp-admin/js/inline-edit-tax.js | 121 + sources/wp-admin/js/inline-edit-tax.min.js | 1 + sources/wp-admin/js/iris.min.js | 4 + sources/wp-admin/js/link.js | 67 + sources/wp-admin/js/link.min.js | 1 + sources/wp-admin/js/media-gallery.js | 25 + sources/wp-admin/js/media-gallery.min.js | 1 + sources/wp-admin/js/media-upload.js | 88 + sources/wp-admin/js/media-upload.min.js | 1 + sources/wp-admin/js/media.js | 124 + sources/wp-admin/js/media.min.js | 1 + sources/wp-admin/js/nav-menu.js | 1176 ++ sources/wp-admin/js/nav-menu.min.js | 1 + .../wp-admin/js/password-strength-meter.js | 74 + .../js/password-strength-meter.min.js | 1 + sources/wp-admin/js/plugin-install.js | 53 + sources/wp-admin/js/plugin-install.min.js | 1 + sources/wp-admin/js/post.js | 921 + sources/wp-admin/js/post.min.js | 1 + sources/wp-admin/js/postbox.js | 186 + sources/wp-admin/js/postbox.min.js | 1 + sources/wp-admin/js/revisions.js | 1080 ++ sources/wp-admin/js/revisions.min.js | 1 + sources/wp-admin/js/set-post-thumbnail.js | 21 + sources/wp-admin/js/set-post-thumbnail.min.js | 1 + sources/wp-admin/js/tags.js | 68 + sources/wp-admin/js/tags.min.js | 1 + sources/wp-admin/js/theme-preview.js | 56 + sources/wp-admin/js/theme-preview.min.js | 1 + sources/wp-admin/js/theme.js | 279 + sources/wp-admin/js/theme.min.js | 1 + sources/wp-admin/js/user-profile.js | 78 + sources/wp-admin/js/user-profile.min.js | 1 + sources/wp-admin/js/user-suggest.js | 13 + sources/wp-admin/js/user-suggest.min.js | 1 + sources/wp-admin/js/widgets.js | 289 + sources/wp-admin/js/widgets.min.js | 1 + sources/wp-admin/js/word-count.js | 42 + sources/wp-admin/js/word-count.min.js | 1 + sources/wp-admin/js/wp-fullscreen.js | 725 + sources/wp-admin/js/wp-fullscreen.min.js | 1 + sources/wp-admin/js/xfn.js | 16 + sources/wp-admin/js/xfn.min.js | 1 + sources/wp-admin/link-add.php | 29 + sources/wp-admin/link-manager.php | 100 + sources/wp-admin/link-parse-opml.php | 96 + sources/wp-admin/link.php | 120 + sources/wp-admin/load-scripts.php | 162 + sources/wp-admin/load-styles.php | 151 + sources/wp-admin/maint/repair.php | 121 + sources/wp-admin/media-new.php | 85 + sources/wp-admin/media-upload.php | 58 + sources/wp-admin/media.php | 147 + sources/wp-admin/menu-header.php | 189 + sources/wp-admin/menu.php | 242 + sources/wp-admin/moderation.php | 12 + sources/wp-admin/ms-admin.php | 13 + sources/wp-admin/ms-delete-site.php | 92 + sources/wp-admin/ms-edit.php | 13 + sources/wp-admin/ms-options.php | 12 + sources/wp-admin/ms-sites.php | 13 + sources/wp-admin/ms-themes.php | 13 + sources/wp-admin/ms-upgrade-network.php | 13 + sources/wp-admin/ms-users.php | 13 + sources/wp-admin/my-sites.php | 120 + sources/wp-admin/nav-menus.php | 765 + sources/wp-admin/network.php | 549 + sources/wp-admin/network/about.php | 16 + sources/wp-admin/network/admin.php | 24 + sources/wp-admin/network/credits.php | 16 + sources/wp-admin/network/edit.php | 27 + sources/wp-admin/network/freedoms.php | 16 + sources/wp-admin/network/index.php | 82 + sources/wp-admin/network/menu.php | 63 + sources/wp-admin/network/plugin-editor.php | 16 + sources/wp-admin/network/plugin-install.php | 19 + sources/wp-admin/network/plugins.php | 16 + sources/wp-admin/network/profile.php | 16 + sources/wp-admin/network/settings.php | 303 + sources/wp-admin/network/setup.php | 16 + sources/wp-admin/network/site-info.php | 180 + sources/wp-admin/network/site-new.php | 153 + sources/wp-admin/network/site-settings.php | 155 + sources/wp-admin/network/site-themes.php | 182 + sources/wp-admin/network/site-users.php | 310 + sources/wp-admin/network/sites.php | 257 + sources/wp-admin/network/theme-editor.php | 16 + sources/wp-admin/network/theme-install.php | 19 + sources/wp-admin/network/themes.php | 275 + sources/wp-admin/network/update-core.php | 16 + sources/wp-admin/network/update.php | 19 + sources/wp-admin/network/upgrade.php | 102 + sources/wp-admin/network/user-edit.php | 16 + sources/wp-admin/network/user-new.php | 107 + sources/wp-admin/network/users.php | 299 + sources/wp-admin/options-discussion.php | 274 + sources/wp-admin/options-general.php | 330 + sources/wp-admin/options-head.php | 18 + sources/wp-admin/options-media.php | 137 + sources/wp-admin/options-permalink.php | 289 + sources/wp-admin/options-reading.php | 185 + sources/wp-admin/options-writing.php | 195 + sources/wp-admin/options.php | 256 + sources/wp-admin/plugin-editor.php | 273 + sources/wp-admin/plugin-install.php | 100 + sources/wp-admin/plugins.php | 437 + sources/wp-admin/post-new.php | 66 + sources/wp-admin/post.php | 312 + sources/wp-admin/press-this.php | 657 + sources/wp-admin/profile.php | 18 + sources/wp-admin/revision.php | 219 + sources/wp-admin/setup-config.php | 307 + sources/wp-admin/theme-editor.php | 246 + sources/wp-admin/theme-install.php | 86 + sources/wp-admin/themes.php | 322 + sources/wp-admin/tools.php | 71 + sources/wp-admin/update-core.php | 631 + sources/wp-admin/update.php | 257 + sources/wp-admin/upgrade-functions.php | 12 + sources/wp-admin/upgrade.php | 115 + sources/wp-admin/upload.php | 250 + sources/wp-admin/user-edit.php | 442 + sources/wp-admin/user-new.php | 440 + sources/wp-admin/user/about.php | 13 + sources/wp-admin/user/admin.php | 25 + sources/wp-admin/user/credits.php | 13 + sources/wp-admin/user/freedoms.php | 13 + sources/wp-admin/user/index.php | 12 + sources/wp-admin/user/menu.php | 22 + sources/wp-admin/user/profile.php | 12 + sources/wp-admin/user/user-edit.php | 12 + sources/wp-admin/users.php | 458 + sources/wp-admin/widgets.php | 417 + sources/wp-blog-header.php | 18 + sources/wp-comments-post.php | 154 + sources/wp-config-sample.php | 99 + sources/wp-content/index.php | 2 + sources/wp-content/languages/admin-fr_FR.mo | Bin 0 -> 381100 bytes sources/wp-content/languages/admin-fr_FR.po | 15440 ++++++++++++++++ .../languages/admin-network-fr_FR.mo | Bin 0 -> 51161 bytes .../languages/admin-network-fr_FR.po | 1809 ++ .../languages/continents-cities-fr_FR.mo | Bin 0 -> 9301 bytes .../languages/continents-cities-fr_FR.po | 1985 ++ sources/wp-content/languages/fr_FR.mo | Bin 0 -> 178928 bytes sources/wp-content/languages/fr_FR.po | 9041 +++++++++ .../languages/themes/twentythirteen-fr_FR.mo | Bin 0 -> 7430 bytes .../languages/themes/twentythirteen-fr_FR.po | 860 + .../languages/themes/twentytwelve-fr_FR.mo | Bin 0 -> 8362 bytes .../languages/themes/twentytwelve-fr_FR.po | 775 + sources/wp-content/plugins/akismet/admin.php | 925 + .../wp-content/plugins/akismet/akismet.css | 1 + .../wp-content/plugins/akismet/akismet.gif | Bin 0 -> 2777 bytes sources/wp-content/plugins/akismet/akismet.js | 126 + .../wp-content/plugins/akismet/akismet.php | 613 + .../wp-content/plugins/akismet/img/logo.png | Bin 0 -> 2710 bytes .../plugins/akismet/img/logo@2x.png | Bin 0 -> 1467 bytes sources/wp-content/plugins/akismet/index.php | 2 + sources/wp-content/plugins/akismet/legacy.php | 396 + sources/wp-content/plugins/akismet/readme.txt | 172 + sources/wp-content/plugins/akismet/widget.php | 108 + sources/wp-content/plugins/hello.php | 82 + sources/wp-content/plugins/index.php | 3 + sources/wp-content/themes/index.php | 3 + .../wp-content/themes/twentythirteen/404.php | 31 + .../themes/twentythirteen/archive.php | 55 + .../themes/twentythirteen/author-bio.php | 34 + .../themes/twentythirteen/author.php | 62 + .../themes/twentythirteen/category.php | 41 + .../themes/twentythirteen/comments.php | 59 + .../themes/twentythirteen/content-aside.php | 31 + .../themes/twentythirteen/content-audio.php | 37 + .../themes/twentythirteen/content-chat.php | 31 + .../themes/twentythirteen/content-gallery.php | 45 + .../themes/twentythirteen/content-image.php | 41 + .../themes/twentythirteen/content-link.php | 36 + .../themes/twentythirteen/content-none.php | 31 + .../themes/twentythirteen/content-quote.php | 27 + .../themes/twentythirteen/content-status.php | 25 + .../themes/twentythirteen/content-video.php | 41 + .../themes/twentythirteen/content.php | 57 + .../twentythirteen/css/editor-style.css | 578 + .../themes/twentythirteen/css/ie.css | 284 + .../themes/twentythirteen/fonts/COPYING.txt | 9 + .../themes/twentythirteen/fonts/LICENSE.txt | 339 + .../fonts/genericons-regular-webfont.eot | Bin 0 -> 10388 bytes .../fonts/genericons-regular-webfont.svg | 105 + .../fonts/genericons-regular-webfont.ttf | Bin 0 -> 19864 bytes .../fonts/genericons-regular-webfont.woff | Bin 0 -> 12156 bytes .../twentythirteen/fonts/genericons.css | 157 + .../themes/twentythirteen/footer.php | 26 + .../themes/twentythirteen/functions.php | 548 + .../themes/twentythirteen/header.php | 51 + .../themes/twentythirteen/image.php | 82 + .../twentythirteen/images/dotted-line-2x.png | Bin 0 -> 86 bytes .../images/dotted-line-light-2x.png | Bin 0 -> 85 bytes .../images/dotted-line-light.png | Bin 0 -> 80 bytes .../twentythirteen/images/dotted-line.png | Bin 0 -> 80 bytes .../images/headers/circle-thumbnail.png | Bin 0 -> 8001 bytes .../twentythirteen/images/headers/circle.png | Bin 0 -> 33848 bytes .../images/headers/diamond-thumbnail.png | Bin 0 -> 1847 bytes .../twentythirteen/images/headers/diamond.png | Bin 0 -> 14266 bytes .../images/headers/star-thumbnail.png | Bin 0 -> 4039 bytes .../twentythirteen/images/headers/star.png | Bin 0 -> 22620 bytes .../twentythirteen/images/search-icon-2x.png | Bin 0 -> 829 bytes .../twentythirteen/images/search-icon.png | Bin 0 -> 422 bytes .../themes/twentythirteen/inc/back-compat.php | 71 + .../twentythirteen/inc/custom-header.php | 227 + .../themes/twentythirteen/index.php | 38 + .../themes/twentythirteen/js/functions.js | 81 + .../themes/twentythirteen/js/html5.js | 7 + .../twentythirteen/js/theme-customizer.js | 40 + .../languages/twentythirteen.pot | 333 + .../wp-content/themes/twentythirteen/page.php | 50 + .../wp-content/themes/twentythirteen/rtl.css | 766 + .../themes/twentythirteen/screenshot.png | Bin 0 -> 54593 bytes .../themes/twentythirteen/search.php | 36 + .../themes/twentythirteen/sidebar-main.php | 18 + .../themes/twentythirteen/sidebar.php | 22 + .../themes/twentythirteen/single.php | 28 + .../themes/twentythirteen/style.css | 3125 ++++ .../wp-content/themes/twentythirteen/tag.php | 43 + .../twentythirteen/taxonomy-post_format.php | 41 + .../wp-content/themes/twentytwelve/404.php | 29 + .../themes/twentytwelve/archive.php | 63 + .../wp-content/themes/twentytwelve/author.php | 84 + .../themes/twentytwelve/category.php | 51 + .../themes/twentytwelve/comments.php | 60 + .../themes/twentytwelve/content-aside.php | 28 + .../themes/twentytwelve/content-image.php | 28 + .../themes/twentytwelve/content-link.php | 26 + .../themes/twentytwelve/content-none.php | 20 + .../themes/twentytwelve/content-page.php | 26 + .../themes/twentytwelve/content-quote.php | 25 + .../themes/twentytwelve/content-status.php | 42 + .../themes/twentytwelve/content.php | 70 + .../wp-content/themes/twentytwelve/css/ie.css | 243 + .../themes/twentytwelve/editor-style-rtl.css | 28 + .../themes/twentytwelve/editor-style.css | 342 + .../wp-content/themes/twentytwelve/footer.php | 23 + .../themes/twentytwelve/functions.php | 510 + .../wp-content/themes/twentytwelve/header.php | 53 + .../wp-content/themes/twentytwelve/image.php | 116 + .../themes/twentytwelve/inc/custom-header.php | 167 + .../wp-content/themes/twentytwelve/index.php | 66 + .../themes/twentytwelve/js/html5.js | 7 + .../themes/twentytwelve/js/navigation.js | 33 + .../twentytwelve/js/theme-customizer.js | 64 + .../twentytwelve/languages/twentytwelve.pot | 353 + .../page-templates/front-page.php | 35 + .../page-templates/full-width.php | 30 + .../wp-content/themes/twentytwelve/page.php | 29 + .../wp-content/themes/twentytwelve/rtl.css | 237 + .../themes/twentytwelve/screenshot.png | Bin 0 -> 171045 bytes .../wp-content/themes/twentytwelve/search.php | 49 + .../themes/twentytwelve/sidebar-front.php | 35 + .../themes/twentytwelve/sidebar.php | 17 + .../wp-content/themes/twentytwelve/single.php | 33 + .../wp-content/themes/twentytwelve/style.css | 1742 ++ .../wp-content/themes/twentytwelve/tag.php | 52 + sources/wp-cron.php | 112 + sources/wp-includes/ID3/getid3.lib.php | 1341 ++ sources/wp-includes/ID3/getid3.php | 1776 ++ .../wp-includes/ID3/license.commercial.txt | 27 + sources/wp-includes/ID3/license.txt | 28 + .../ID3/module.audio-video.asf.php | 2019 ++ .../ID3/module.audio-video.flv.php | 729 + .../ID3/module.audio-video.matroska.php | 1765 ++ .../ID3/module.audio-video.quicktime.php | 2221 +++ .../ID3/module.audio-video.riff.php | 2435 +++ sources/wp-includes/ID3/module.audio.ac3.php | 473 + sources/wp-includes/ID3/module.audio.dts.php | 290 + sources/wp-includes/ID3/module.audio.flac.php | 442 + sources/wp-includes/ID3/module.audio.mp3.php | 2009 ++ sources/wp-includes/ID3/module.audio.ogg.php | 671 + sources/wp-includes/ID3/module.tag.apetag.php | 370 + sources/wp-includes/ID3/module.tag.id3v1.php | 359 + sources/wp-includes/ID3/module.tag.id3v2.php | 3414 ++++ .../wp-includes/ID3/module.tag.lyrics3.php | 294 + sources/wp-includes/ID3/readme.txt | 603 + sources/wp-includes/SimplePie/Author.php | 157 + sources/wp-includes/SimplePie/Cache.php | 133 + sources/wp-includes/SimplePie/Cache/Base.php | 114 + sources/wp-includes/SimplePie/Cache/DB.php | 137 + sources/wp-includes/SimplePie/Cache/File.php | 173 + .../wp-includes/SimplePie/Cache/Memcache.php | 183 + sources/wp-includes/SimplePie/Cache/MySQL.php | 438 + sources/wp-includes/SimplePie/Caption.php | 210 + sources/wp-includes/SimplePie/Category.php | 157 + .../SimplePie/Content/Type/Sniffer.php | 332 + sources/wp-includes/SimplePie/Copyright.php | 130 + sources/wp-includes/SimplePie/Core.php | 57 + sources/wp-includes/SimplePie/Credit.php | 156 + .../SimplePie/Decode/HTML/Entities.php | 617 + sources/wp-includes/SimplePie/Enclosure.php | 1380 ++ sources/wp-includes/SimplePie/Exception.php | 52 + sources/wp-includes/SimplePie/File.php | 292 + sources/wp-includes/SimplePie/HTTP/Parser.php | 500 + sources/wp-includes/SimplePie/IRI.php | 1238 ++ sources/wp-includes/SimplePie/Item.php | 2964 +++ sources/wp-includes/SimplePie/Locator.php | 372 + sources/wp-includes/SimplePie/Misc.php | 2247 +++ sources/wp-includes/SimplePie/Net/IPv6.php | 276 + sources/wp-includes/SimplePie/Parse/Date.php | 983 + sources/wp-includes/SimplePie/Parser.php | 407 + sources/wp-includes/SimplePie/Rating.php | 129 + sources/wp-includes/SimplePie/Registry.php | 225 + sources/wp-includes/SimplePie/Restriction.php | 155 + sources/wp-includes/SimplePie/Sanitize.php | 554 + sources/wp-includes/SimplePie/Source.php | 611 + .../SimplePie/XML/Declaration/Parser.php | 362 + sources/wp-includes/SimplePie/gzdecode.php | 371 + sources/wp-includes/Text/Diff.php | 450 + .../wp-includes/Text/Diff/Engine/native.php | 436 + .../wp-includes/Text/Diff/Engine/shell.php | 162 + .../wp-includes/Text/Diff/Engine/string.php | 248 + .../wp-includes/Text/Diff/Engine/xdiff.php | 64 + sources/wp-includes/Text/Diff/Renderer.php | 235 + .../wp-includes/Text/Diff/Renderer/inline.php | 206 + sources/wp-includes/admin-bar.php | 798 + sources/wp-includes/atomlib.php | 352 + sources/wp-includes/author-template.php | 453 + sources/wp-includes/bookmark-template.php | 272 + sources/wp-includes/bookmark.php | 387 + sources/wp-includes/cache.php | 653 + sources/wp-includes/canonical.php | 560 + sources/wp-includes/capabilities.php | 1472 ++ sources/wp-includes/category-template.php | 1215 ++ sources/wp-includes/category.php | 359 + .../wp-includes/certificates/ca-bundle.crt | 3554 ++++ sources/wp-includes/class-IXR.php | 1070 ++ sources/wp-includes/class-feed.php | 140 + sources/wp-includes/class-http.php | 1954 ++ sources/wp-includes/class-json.php | 936 + sources/wp-includes/class-oembed.php | 397 + sources/wp-includes/class-phpass.php | 260 + sources/wp-includes/class-phpmailer.php | 2826 +++ sources/wp-includes/class-pop3.php | 652 + sources/wp-includes/class-simplepie.php | 3119 ++++ sources/wp-includes/class-smtp.php | 1003 + sources/wp-includes/class-snoopy.php | 1256 ++ sources/wp-includes/class-wp-admin-bar.php | 506 + .../wp-includes/class-wp-ajax-response.php | 139 + .../class-wp-customize-control.php | 817 + .../class-wp-customize-manager.php | 1059 ++ .../class-wp-customize-section.php | 96 + .../class-wp-customize-setting.php | 439 + sources/wp-includes/class-wp-editor.php | 919 + sources/wp-includes/class-wp-embed.php | 323 + sources/wp-includes/class-wp-error.php | 208 + .../wp-includes/class-wp-http-ixr-client.php | 92 + .../wp-includes/class-wp-image-editor-gd.php | 426 + .../class-wp-image-editor-imagick.php | 488 + sources/wp-includes/class-wp-image-editor.php | 423 + sources/wp-includes/class-wp-theme.php | 1200 ++ sources/wp-includes/class-wp-walker.php | 408 + .../wp-includes/class-wp-xmlrpc-server.php | 5525 ++++++ sources/wp-includes/class-wp.php | 645 + sources/wp-includes/class.wp-dependencies.php | 481 + sources/wp-includes/class.wp-scripts.php | 220 + sources/wp-includes/class.wp-styles.php | 171 + sources/wp-includes/comment-template.php | 2128 +++ sources/wp-includes/comment.php | 2096 +++ sources/wp-includes/compat.php | 96 + sources/wp-includes/cron.php | 414 + sources/wp-includes/css/admin-bar-rtl.css | 201 + sources/wp-includes/css/admin-bar-rtl.min.css | 1 + sources/wp-includes/css/admin-bar.css | 689 + sources/wp-includes/css/admin-bar.min.css | 1 + sources/wp-includes/css/buttons.css | 288 + sources/wp-includes/css/buttons.min.css | 1 + sources/wp-includes/css/editor.css | 2295 +++ sources/wp-includes/css/editor.min.css | 28 + sources/wp-includes/css/jquery-ui-dialog.css | 307 + .../wp-includes/css/jquery-ui-dialog.min.css | 28 + sources/wp-includes/css/media-views-rtl.css | 312 + .../wp-includes/css/media-views-rtl.min.css | 1 + sources/wp-includes/css/media-views.css | 1673 ++ sources/wp-includes/css/media-views.min.css | 1 + sources/wp-includes/css/wp-auth-check.css | 94 + sources/wp-includes/css/wp-auth-check.min.css | 1 + sources/wp-includes/css/wp-pointer.css | 228 + sources/wp-includes/css/wp-pointer.min.css | 1 + sources/wp-includes/date.php | 447 + sources/wp-includes/default-constants.php | 316 + sources/wp-includes/default-filters.php | 304 + sources/wp-includes/default-widgets.php | 1207 ++ sources/wp-includes/deprecated.php | 3392 ++++ sources/wp-includes/feed-atom-comments.php | 87 + sources/wp-includes/feed-atom.php | 83 + sources/wp-includes/feed-rdf.php | 77 + sources/wp-includes/feed-rss.php | 46 + sources/wp-includes/feed-rss2-comments.php | 94 + sources/wp-includes/feed-rss2.php | 105 + sources/wp-includes/feed.php | 552 + sources/wp-includes/formatting.php | 3433 ++++ sources/wp-includes/functions.php | 4206 +++++ sources/wp-includes/functions.wp-scripts.php | 253 + sources/wp-includes/functions.wp-styles.php | 242 + sources/wp-includes/general-template.php | 2372 +++ sources/wp-includes/http.php | 558 + .../images/admin-bar-sprite-2x.png | Bin 0 -> 4122 bytes .../wp-includes/images/admin-bar-sprite.png | Bin 0 -> 2470 bytes .../images/arrow-pointer-blue-2x.png | Bin 0 -> 52574 bytes .../wp-includes/images/arrow-pointer-blue.png | Bin 0 -> 793 bytes sources/wp-includes/images/blank.gif | Bin 0 -> 43 bytes .../wp-includes/images/crystal/archive.png | Bin 0 -> 2897 bytes sources/wp-includes/images/crystal/audio.png | Bin 0 -> 2595 bytes sources/wp-includes/images/crystal/code.png | Bin 0 -> 1604 bytes .../wp-includes/images/crystal/default.png | Bin 0 -> 490 bytes .../wp-includes/images/crystal/document.png | Bin 0 -> 2230 bytes .../images/crystal/interactive.png | Bin 0 -> 2680 bytes .../wp-includes/images/crystal/license.txt | 9 + .../images/crystal/spreadsheet.png | Bin 0 -> 2680 bytes sources/wp-includes/images/crystal/text.png | Bin 0 -> 707 bytes sources/wp-includes/images/crystal/video.png | Bin 0 -> 1339 bytes sources/wp-includes/images/down_arrow-2x.gif | Bin 0 -> 83 bytes sources/wp-includes/images/down_arrow.gif | Bin 0 -> 60 bytes .../images/icon-pointer-flag-2x.png | Bin 0 -> 1369 bytes .../wp-includes/images/icon-pointer-flag.png | Bin 0 -> 783 bytes sources/wp-includes/images/rss-2x.png | Bin 0 -> 1306 bytes sources/wp-includes/images/rss.png | Bin 0 -> 608 bytes .../wp-includes/images/smilies/icon_arrow.gif | Bin 0 -> 170 bytes .../images/smilies/icon_biggrin.gif | Bin 0 -> 172 bytes .../images/smilies/icon_confused.gif | Bin 0 -> 171 bytes .../wp-includes/images/smilies/icon_cool.gif | Bin 0 -> 172 bytes .../wp-includes/images/smilies/icon_cry.gif | Bin 0 -> 498 bytes .../wp-includes/images/smilies/icon_eek.gif | Bin 0 -> 170 bytes .../wp-includes/images/smilies/icon_evil.gif | Bin 0 -> 236 bytes .../images/smilies/icon_exclaim.gif | Bin 0 -> 236 bytes .../wp-includes/images/smilies/icon_idea.gif | Bin 0 -> 176 bytes .../wp-includes/images/smilies/icon_lol.gif | Bin 0 -> 336 bytes .../wp-includes/images/smilies/icon_mad.gif | Bin 0 -> 174 bytes .../images/smilies/icon_mrgreen.gif | Bin 0 -> 349 bytes .../images/smilies/icon_neutral.gif | Bin 0 -> 171 bytes .../images/smilies/icon_question.gif | Bin 0 -> 248 bytes .../wp-includes/images/smilies/icon_razz.gif | Bin 0 -> 176 bytes .../images/smilies/icon_redface.gif | Bin 0 -> 650 bytes .../images/smilies/icon_rolleyes.gif | Bin 0 -> 485 bytes .../wp-includes/images/smilies/icon_sad.gif | Bin 0 -> 171 bytes .../wp-includes/images/smilies/icon_smile.gif | Bin 0 -> 174 bytes .../images/smilies/icon_surprised.gif | Bin 0 -> 174 bytes .../images/smilies/icon_twisted.gif | Bin 0 -> 238 bytes .../wp-includes/images/smilies/icon_wink.gif | Bin 0 -> 170 bytes .../wp-includes/images/toggle-arrow-2x.png | Bin 0 -> 354 bytes sources/wp-includes/images/toggle-arrow.png | Bin 0 -> 333 bytes .../wp-includes/images/uploader-icons-2x.png | Bin 0 -> 3915 bytes sources/wp-includes/images/uploader-icons.png | Bin 0 -> 1593 bytes .../wp-includes/images/wlw/wp-comments.png | Bin 0 -> 1373 bytes sources/wp-includes/images/wlw/wp-icon.png | Bin 0 -> 664 bytes .../wp-includes/images/wlw/wp-watermark.png | Bin 0 -> 5102 bytes sources/wp-includes/images/wpicons-2x.png | Bin 0 -> 125467 bytes sources/wp-includes/images/wpicons.png | Bin 0 -> 16089 bytes sources/wp-includes/images/wpmini-blue-2x.png | Bin 0 -> 2087 bytes sources/wp-includes/images/wpmini-blue.png | Bin 0 -> 751 bytes sources/wp-includes/images/wpspin-2x.gif | Bin 0 -> 9097 bytes sources/wp-includes/images/wpspin.gif | Bin 0 -> 2193 bytes sources/wp-includes/images/xit-2x.gif | Bin 0 -> 823 bytes sources/wp-includes/images/xit.gif | Bin 0 -> 182 bytes sources/wp-includes/js/admin-bar.js | 343 + sources/wp-includes/js/admin-bar.min.js | 1 + sources/wp-includes/js/autosave.js | 702 + sources/wp-includes/js/autosave.min.js | 1 + sources/wp-includes/js/backbone.min.js | 7 + sources/wp-includes/js/colorpicker.js | 707 + sources/wp-includes/js/colorpicker.min.js | 1 + sources/wp-includes/js/comment-reply.js | 48 + sources/wp-includes/js/comment-reply.min.js | 1 + sources/wp-includes/js/crop/cropper.css | 165 + sources/wp-includes/js/crop/cropper.js | 516 + sources/wp-includes/js/crop/marqueeHoriz.gif | Bin 0 -> 277 bytes sources/wp-includes/js/crop/marqueeVert.gif | Bin 0 -> 293 bytes sources/wp-includes/js/customize-base.js | 585 + sources/wp-includes/js/customize-base.min.js | 1 + sources/wp-includes/js/customize-loader.js | 164 + .../wp-includes/js/customize-loader.min.js | 1 + sources/wp-includes/js/customize-preview.js | 146 + .../wp-includes/js/customize-preview.min.js | 1 + sources/wp-includes/js/heartbeat.js | 490 + sources/wp-includes/js/heartbeat.min.js | 1 + sources/wp-includes/js/hoverIntent.js | 115 + sources/wp-includes/js/hoverIntent.min.js | 1 + .../js/imgareaselect/border-anim-h.gif | Bin 0 -> 178 bytes .../js/imgareaselect/border-anim-v.gif | Bin 0 -> 178 bytes .../js/imgareaselect/imgareaselect.css | 41 + .../js/imgareaselect/jquery.imgareaselect.js | 1205 ++ .../imgareaselect/jquery.imgareaselect.min.js | 1 + sources/wp-includes/js/jcrop/Jcrop.gif | Bin 0 -> 323 bytes .../wp-includes/js/jcrop/jquery.Jcrop.min.css | 29 + .../wp-includes/js/jcrop/jquery.Jcrop.min.js | 22 + .../wp-includes/js/jquery/jquery-migrate.js | 521 + .../js/jquery/jquery-migrate.min.js | 2 + .../wp-includes/js/jquery/jquery.color.min.js | 2 + sources/wp-includes/js/jquery/jquery.form.js | 1193 ++ .../wp-includes/js/jquery/jquery.form.min.js | 11 + .../wp-includes/js/jquery/jquery.hotkeys.js | 131 + .../js/jquery/jquery.hotkeys.min.js | 1 + sources/wp-includes/js/jquery/jquery.js | 6 + .../js/jquery/jquery.masonry.min.js | 10 + sources/wp-includes/js/jquery/jquery.query.js | 11 + .../wp-includes/js/jquery/jquery.schedule.js | 36 + .../js/jquery/jquery.serialize-object.js | 31 + .../js/jquery/jquery.table-hotkeys.js | 99 + .../js/jquery/jquery.table-hotkeys.min.js | 1 + .../js/jquery/jquery.ui.touch-punch.js | 11 + sources/wp-includes/js/jquery/suggest.js | 315 + sources/wp-includes/js/jquery/suggest.min.js | 1 + .../js/jquery/ui/jquery.ui.accordion.min.js | 4 + .../jquery/ui/jquery.ui.autocomplete.min.js | 4 + .../js/jquery/ui/jquery.ui.button.min.js | 4 + .../js/jquery/ui/jquery.ui.core.min.js | 4 + .../js/jquery/ui/jquery.ui.datepicker.min.js | 5 + .../js/jquery/ui/jquery.ui.dialog.min.js | 4 + .../js/jquery/ui/jquery.ui.draggable.min.js | 4 + .../js/jquery/ui/jquery.ui.droppable.min.js | 4 + .../jquery/ui/jquery.ui.effect-blind.min.js | 4 + .../jquery/ui/jquery.ui.effect-bounce.min.js | 4 + .../js/jquery/ui/jquery.ui.effect-clip.min.js | 4 + .../js/jquery/ui/jquery.ui.effect-drop.min.js | 4 + .../jquery/ui/jquery.ui.effect-explode.min.js | 4 + .../js/jquery/ui/jquery.ui.effect-fade.min.js | 4 + .../js/jquery/ui/jquery.ui.effect-fold.min.js | 4 + .../ui/jquery.ui.effect-highlight.min.js | 4 + .../jquery/ui/jquery.ui.effect-pulsate.min.js | 4 + .../jquery/ui/jquery.ui.effect-scale.min.js | 4 + .../jquery/ui/jquery.ui.effect-shake.min.js | 4 + .../jquery/ui/jquery.ui.effect-slide.min.js | 4 + .../ui/jquery.ui.effect-transfer.min.js | 4 + .../js/jquery/ui/jquery.ui.effect.min.js | 4 + .../js/jquery/ui/jquery.ui.menu.min.js | 4 + .../js/jquery/ui/jquery.ui.mouse.min.js | 4 + .../js/jquery/ui/jquery.ui.position.min.js | 4 + .../js/jquery/ui/jquery.ui.progressbar.min.js | 4 + .../js/jquery/ui/jquery.ui.resizable.min.js | 4 + .../js/jquery/ui/jquery.ui.selectable.min.js | 4 + .../js/jquery/ui/jquery.ui.slider.min.js | 4 + .../js/jquery/ui/jquery.ui.sortable.min.js | 4 + .../js/jquery/ui/jquery.ui.spinner.min.js | 4 + .../js/jquery/ui/jquery.ui.tabs.min.js | 4 + .../js/jquery/ui/jquery.ui.tooltip.min.js | 4 + .../js/jquery/ui/jquery.ui.widget.min.js | 4 + sources/wp-includes/js/json2.js | 480 + sources/wp-includes/js/json2.min.js | 1 + sources/wp-includes/js/mce-view.js | 349 + sources/wp-includes/js/mce-view.min.js | 1 + sources/wp-includes/js/media-editor.js | 717 + sources/wp-includes/js/media-editor.min.js | 1 + sources/wp-includes/js/media-models.js | 862 + sources/wp-includes/js/media-models.min.js | 1 + sources/wp-includes/js/media-views.js | 3966 ++++ sources/wp-includes/js/media-views.min.js | 2 + .../js/mediaelement/background.png | Bin 0 -> 166 bytes .../wp-includes/js/mediaelement/bigplay.png | Bin 0 -> 3001 bytes .../wp-includes/js/mediaelement/bigplay.svg | 1 + .../wp-includes/js/mediaelement/controls.png | Bin 0 -> 1892 bytes .../wp-includes/js/mediaelement/controls.svg | 1 + .../js/mediaelement/flashmediaelement.swf | Bin 0 -> 29142 bytes .../wp-includes/js/mediaelement/loading.gif | Bin 0 -> 6224 bytes .../mediaelement-and-player.min.js | 173 + .../mediaelement/mediaelementplayer.min.css | 1 + .../mediaelement/silverlightmediaelement.xap | Bin 0 -> 12461 bytes .../js/mediaelement/wp-mediaelement.css | 15 + .../js/mediaelement/wp-mediaelement.js | 15 + sources/wp-includes/js/plupload/changelog.txt | 241 + sources/wp-includes/js/plupload/handlers.js | 491 + .../wp-includes/js/plupload/handlers.min.js | 1 + sources/wp-includes/js/plupload/license.txt | 339 + .../wp-includes/js/plupload/plupload.flash.js | 1 + .../js/plupload/plupload.flash.swf | Bin 0 -> 18958 bytes .../wp-includes/js/plupload/plupload.html4.js | 1 + .../wp-includes/js/plupload/plupload.html5.js | 1 + sources/wp-includes/js/plupload/plupload.js | 2 + .../js/plupload/plupload.silverlight.js | 1 + .../js/plupload/plupload.silverlight.xap | Bin 0 -> 44139 bytes .../wp-includes/js/plupload/wp-plupload.js | 343 + .../js/plupload/wp-plupload.min.js | 1 + sources/wp-includes/js/quicktags.js | 620 + sources/wp-includes/js/quicktags.min.js | 1 + sources/wp-includes/js/shortcode.js | 342 + sources/wp-includes/js/shortcode.min.js | 1 + sources/wp-includes/js/swfobject.js | 4 + sources/wp-includes/js/swfupload/handlers.js | 375 + .../wp-includes/js/swfupload/handlers.min.js | 1 + sources/wp-includes/js/swfupload/license.txt | 32 + .../js/swfupload/plugins/swfupload.cookies.js | 53 + .../js/swfupload/plugins/swfupload.queue.js | 98 + .../js/swfupload/plugins/swfupload.speed.js | 342 + .../swfupload/plugins/swfupload.swfobject.js | 105 + sources/wp-includes/js/swfupload/swfupload.js | 980 + .../wp-includes/js/swfupload/swfupload.swf | Bin 0 -> 13133 bytes .../js/thickbox/loadingAnimation.gif | Bin 0 -> 15238 bytes .../wp-includes/js/thickbox/macFFBgHack.png | Bin 0 -> 94 bytes .../wp-includes/js/thickbox/tb-close-2x.png | Bin 0 -> 412 bytes sources/wp-includes/js/thickbox/tb-close.png | Bin 0 -> 387 bytes sources/wp-includes/js/thickbox/thickbox.css | 178 + sources/wp-includes/js/thickbox/thickbox.js | 319 + .../js/tinymce/langs/wp-langs-en.js | 504 + .../wp-includes/js/tinymce/langs/wp-langs.php | 565 + sources/wp-includes/js/tinymce/license.txt | 504 + .../wp-includes/js/tinymce/mark_loaded_src.js | 20 + .../plugins/directionality/editor_plugin.js | 1 + .../directionality/editor_plugin_src.js | 85 + .../plugins/fullscreen/editor_plugin.js | 1 + .../plugins/fullscreen/editor_plugin_src.js | 234 + .../tinymce/plugins/fullscreen/fullscreen.htm | 117 + .../plugins/inlinepopups/editor_plugin.js | 1 + .../plugins/inlinepopups/editor_plugin_src.js | 699 + .../skins/clearlooks2/img/alert.gif | Bin 0 -> 810 bytes .../skins/clearlooks2/img/button.gif | Bin 0 -> 272 bytes .../skins/clearlooks2/img/buttons.gif | Bin 0 -> 989 bytes .../skins/clearlooks2/img/confirm.gif | Bin 0 -> 907 bytes .../skins/clearlooks2/img/corners.gif | Bin 0 -> 909 bytes .../skins/clearlooks2/img/drag.gif | Bin 0 -> 51 bytes .../skins/clearlooks2/img/horizontal.gif | Bin 0 -> 769 bytes .../skins/clearlooks2/img/vertical.gif | Bin 0 -> 84 bytes .../inlinepopups/skins/clearlooks2/window.css | 126 + .../tinymce/plugins/inlinepopups/template.htm | 387 + .../js/tinymce/plugins/media/css/media.css | 17 + .../js/tinymce/plugins/media/editor_plugin.js | 1 + .../plugins/media/editor_plugin_src.js | 897 + .../js/tinymce/plugins/media/js/embed.js | 73 + .../js/tinymce/plugins/media/js/media.js | 513 + .../js/tinymce/plugins/media/media.htm | 922 + .../js/tinymce/plugins/media/moxieplayer.swf | Bin 0 -> 19980 bytes .../js/tinymce/plugins/paste/editor_plugin.js | 1 + .../plugins/paste/editor_plugin_src.js | 885 + .../js/tinymce/plugins/paste/js/pastetext.js | 36 + .../js/tinymce/plugins/paste/js/pasteword.js | 51 + .../js/tinymce/plugins/paste/pastetext.htm | 27 + .../js/tinymce/plugins/paste/pasteword.htm | 21 + .../plugins/spellchecker/changelog.txt | 33 + .../spellchecker/classes/EnchantSpell.php | 71 + .../spellchecker/classes/GoogleSpell.php | 161 + .../plugins/spellchecker/classes/PSpell.php | 82 + .../spellchecker/classes/PSpellShell.php | 117 + .../spellchecker/classes/SpellChecker.php | 62 + .../spellchecker/classes/utils/JSON.php | 595 + .../spellchecker/classes/utils/Logger.php | 268 + .../tinymce/plugins/spellchecker/config.php | 27 + .../plugins/spellchecker/css/content.css | 1 + .../plugins/spellchecker/editor_plugin.js | 1 + .../plugins/spellchecker/editor_plugin_src.js | 471 + .../plugins/spellchecker/img/wline.gif | Bin 0 -> 46 bytes .../plugins/spellchecker/includes/general.php | 98 + .../js/tinymce/plugins/spellchecker/rpc.php | 112 + .../tinymce/plugins/tabfocus/editor_plugin.js | 1 + .../plugins/tabfocus/editor_plugin_src.js | 122 + .../plugins/wordpress/editor_plugin.js | 1 + .../plugins/wordpress/editor_plugin_src.js | 447 + .../tinymce/plugins/wordpress/img/audio.gif | Bin 0 -> 146 bytes .../tinymce/plugins/wordpress/img/image.gif | Bin 0 -> 95 bytes .../tinymce/plugins/wordpress/img/media.gif | Bin 0 -> 149 bytes .../js/tinymce/plugins/wordpress/img/page.gif | Bin 0 -> 108 bytes .../tinymce/plugins/wordpress/img/trans.gif | Bin 0 -> 43 bytes .../tinymce/plugins/wordpress/img/video.gif | Bin 0 -> 93 bytes .../plugins/wpdialogs/editor_plugin.js | 1 + .../plugins/wpdialogs/editor_plugin_src.js | 80 + .../js/tinymce/plugins/wpdialogs/js/popup.js | 436 + .../tinymce/plugins/wpdialogs/js/popup.min.js | 1 + .../tinymce/plugins/wpdialogs/js/wpdialog.js | 28 + .../plugins/wpdialogs/js/wpdialog.min.js | 1 + .../plugins/wpeditimage/css/editimage.css | 443 + .../plugins/wpeditimage/editimage.html | 274 + .../plugins/wpeditimage/editor_plugin.js | 1 + .../plugins/wpeditimage/editor_plugin_src.js | 326 + .../plugins/wpeditimage/img/delete-2x.png | Bin 0 -> 5064 bytes .../plugins/wpeditimage/img/delete.png | Bin 0 -> 1386 bytes .../plugins/wpeditimage/img/image-2x.png | Bin 0 -> 2687 bytes .../tinymce/plugins/wpeditimage/img/image.png | Bin 0 -> 946 bytes .../plugins/wpeditimage/js/editimage.js | 613 + .../wpfullscreen/css/wp-fullscreen.css | 13 + .../plugins/wpfullscreen/editor_plugin.js | 1 + .../plugins/wpfullscreen/editor_plugin_src.js | 189 + .../plugins/wpgallery/editor_plugin.js | 1 + .../plugins/wpgallery/editor_plugin_src.js | 156 + .../plugins/wpgallery/img/delete-2x.png | Bin 0 -> 5064 bytes .../tinymce/plugins/wpgallery/img/delete.png | Bin 0 -> 1386 bytes .../tinymce/plugins/wpgallery/img/edit-2x.png | Bin 0 -> 4924 bytes .../js/tinymce/plugins/wpgallery/img/edit.png | Bin 0 -> 1590 bytes .../js/tinymce/plugins/wpgallery/img/t.gif | Bin 0 -> 43 bytes .../tinymce/plugins/wplink/editor_plugin.js | 1 + .../plugins/wplink/editor_plugin_src.js | 59 + .../tinymce/plugins/wpview/editor_plugin.js | 1 + .../plugins/wpview/editor_plugin_src.js | 188 + .../js/tinymce/themes/advanced/about.htm | 52 + .../js/tinymce/themes/advanced/anchor.htm | 26 + .../js/tinymce/themes/advanced/charmap.htm | 55 + .../tinymce/themes/advanced/color_picker.htm | 70 + .../themes/advanced/editor_template.js | 1 + .../themes/advanced/editor_template_src.js | 1490 ++ .../js/tinymce/themes/advanced/image.htm | 80 + .../themes/advanced/img/colorpicker.jpg | Bin 0 -> 2584 bytes .../js/tinymce/themes/advanced/img/flash.gif | Bin 0 -> 239 bytes .../tinymce/themes/advanced/img/gotmoxie.png | Bin 0 -> 892 bytes .../js/tinymce/themes/advanced/img/icons.gif | Bin 0 -> 11982 bytes .../js/tinymce/themes/advanced/img/iframe.gif | Bin 0 -> 600 bytes .../tinymce/themes/advanced/img/pagebreak.gif | Bin 0 -> 325 bytes .../tinymce/themes/advanced/img/quicktime.gif | Bin 0 -> 301 bytes .../tinymce/themes/advanced/img/realmedia.gif | Bin 0 -> 439 bytes .../tinymce/themes/advanced/img/shockwave.gif | Bin 0 -> 384 bytes .../js/tinymce/themes/advanced/img/trans.gif | Bin 0 -> 43 bytes .../js/tinymce/themes/advanced/img/video.gif | Bin 0 -> 597 bytes .../themes/advanced/img/windowsmedia.gif | Bin 0 -> 415 bytes .../js/tinymce/themes/advanced/js/about.js | 73 + .../js/tinymce/themes/advanced/js/anchor.js | 56 + .../js/tinymce/themes/advanced/js/charmap.js | 363 + .../themes/advanced/js/color_picker.js | 345 + .../js/tinymce/themes/advanced/js/image.js | 253 + .../js/tinymce/themes/advanced/js/link.js | 159 + .../themes/advanced/js/source_editor.js | 78 + .../js/tinymce/themes/advanced/link.htm | 57 + .../js/tinymce/themes/advanced/shortcuts.htm | 47 + .../themes/advanced/skins/default/content.css | 50 + .../themes/advanced/skins/default/dialog.css | 118 + .../advanced/skins/default/img/buttons.png | Bin 0 -> 3133 bytes .../advanced/skins/default/img/items.gif | Bin 0 -> 64 bytes .../advanced/skins/default/img/menu_arrow.gif | Bin 0 -> 68 bytes .../advanced/skins/default/img/menu_check.gif | Bin 0 -> 70 bytes .../advanced/skins/default/img/progress.gif | Bin 0 -> 1787 bytes .../advanced/skins/default/img/tabs.gif | Bin 0 -> 1322 bytes .../themes/advanced/skins/default/ui.css | 219 + .../advanced/skins/highcontrast/content.css | 24 + .../advanced/skins/highcontrast/dialog.css | 106 + .../themes/advanced/skins/highcontrast/ui.css | 106 + .../themes/advanced/skins/o2k7/content.css | 48 + .../themes/advanced/skins/o2k7/dialog.css | 118 + .../advanced/skins/o2k7/img/button_bg.png | Bin 0 -> 2766 bytes .../skins/o2k7/img/button_bg_black.png | Bin 0 -> 651 bytes .../skins/o2k7/img/button_bg_silver.png | Bin 0 -> 2084 bytes .../tinymce/themes/advanced/skins/o2k7/ui.css | 222 + .../themes/advanced/skins/o2k7/ui_black.css | 8 + .../themes/advanced/skins/o2k7/ui_silver.css | 5 + .../advanced/skins/wp_theme/content.css | 132 + .../themes/advanced/skins/wp_theme/dialog.css | 140 + .../advanced/skins/wp_theme/img/embedded.png | Bin 0 -> 27345 bytes .../advanced/skins/wp_theme/img/gallery.png | Bin 0 -> 26240 bytes .../advanced/skins/wp_theme/img/more_bug.gif | Bin 0 -> 146 bytes .../advanced/skins/wp_theme/img/page_bug.gif | Bin 0 -> 176 bytes .../advanced/skins/wp_theme/img/tabs.gif | Bin 0 -> 1322 bytes .../tinymce/themes/advanced/source_editor.htm | 25 + sources/wp-includes/js/tinymce/tiny_mce.js | 1 + .../wp-includes/js/tinymce/tiny_mce_popup.js | 5 + .../js/tinymce/utils/editable_selects.js | 70 + .../js/tinymce/utils/form_utils.js | 210 + .../wp-includes/js/tinymce/utils/mctabs.js | 162 + .../wp-includes/js/tinymce/utils/validate.js | 252 + .../wp-includes/js/tinymce/wp-mce-help.php | 281 + .../js/tinymce/wp-tinymce-schema.js | 940 + .../wp-includes/js/tinymce/wp-tinymce.js.gz | Bin 0 -> 116238 bytes sources/wp-includes/js/tinymce/wp-tinymce.php | 38 + sources/wp-includes/js/tw-sack.js | 193 + sources/wp-includes/js/tw-sack.min.js | 1 + sources/wp-includes/js/underscore.min.js | 5 + sources/wp-includes/js/utils.js | 171 + sources/wp-includes/js/utils.min.js | 1 + sources/wp-includes/js/wp-ajax-response.js | 64 + .../wp-includes/js/wp-ajax-response.min.js | 1 + sources/wp-includes/js/wp-auth-check.js | 106 + sources/wp-includes/js/wp-auth-check.min.js | 1 + sources/wp-includes/js/wp-backbone.js | 384 + sources/wp-includes/js/wp-backbone.min.js | 1 + sources/wp-includes/js/wp-list-revisions.js | 24 + .../wp-includes/js/wp-list-revisions.min.js | 1 + sources/wp-includes/js/wp-lists.js | 464 + sources/wp-includes/js/wp-lists.min.js | 1 + sources/wp-includes/js/wp-pointer.js | 281 + sources/wp-includes/js/wp-pointer.min.js | 1 + sources/wp-includes/js/wp-util.js | 105 + sources/wp-includes/js/wp-util.min.js | 1 + sources/wp-includes/js/wplink.js | 586 + sources/wp-includes/js/wplink.min.js | 1 + sources/wp-includes/js/zxcvbn-async.js | 17 + sources/wp-includes/js/zxcvbn-async.min.js | 1 + sources/wp-includes/js/zxcvbn.min.js | 43 + sources/wp-includes/kses.php | 1474 ++ sources/wp-includes/l10n.php | 805 + sources/wp-includes/link-template.php | 2506 +++ sources/wp-includes/load.php | 785 + sources/wp-includes/locale.php | 356 + sources/wp-includes/media-template.php | 497 + sources/wp-includes/media.php | 2091 +++ sources/wp-includes/meta.php | 938 + sources/wp-includes/ms-blogs.php | 757 + sources/wp-includes/ms-default-constants.php | 151 + sources/wp-includes/ms-default-filters.php | 76 + sources/wp-includes/ms-deprecated.php | 347 + sources/wp-includes/ms-files.php | 82 + sources/wp-includes/ms-functions.php | 2142 +++ sources/wp-includes/ms-load.php | 264 + sources/wp-includes/ms-settings.php | 136 + sources/wp-includes/nav-menu-template.php | 633 + sources/wp-includes/nav-menu.php | 794 + sources/wp-includes/option.php | 1074 ++ sources/wp-includes/pluggable-deprecated.php | 192 + sources/wp-includes/pluggable.php | 1786 ++ sources/wp-includes/plugin.php | 809 + sources/wp-includes/pomo/entry.php | 78 + sources/wp-includes/pomo/mo.php | 257 + sources/wp-includes/pomo/po.php | 384 + sources/wp-includes/pomo/streams.php | 209 + sources/wp-includes/pomo/translations.php | 275 + sources/wp-includes/post-formats.php | 243 + sources/wp-includes/post-template.php | 1445 ++ .../wp-includes/post-thumbnail-template.php | 142 + sources/wp-includes/post.php | 5066 +++++ sources/wp-includes/query.php | 3943 ++++ .../wp-includes/registration-functions.php | 7 + sources/wp-includes/registration.php | 7 + sources/wp-includes/revision.php | 603 + sources/wp-includes/rewrite.php | 2028 ++ sources/wp-includes/rss-functions.php | 9 + sources/wp-includes/rss.php | 936 + sources/wp-includes/script-loader.php | 927 + sources/wp-includes/shortcodes.php | 388 + sources/wp-includes/taxonomy.php | 3453 ++++ sources/wp-includes/template-loader.php | 76 + sources/wp-includes/template.php | 445 + .../theme-compat/comments-popup.php | 129 + sources/wp-includes/theme-compat/comments.php | 101 + sources/wp-includes/theme-compat/footer.php | 30 + sources/wp-includes/theme-compat/header.php | 49 + sources/wp-includes/theme-compat/sidebar.php | 83 + sources/wp-includes/theme.php | 1753 ++ sources/wp-includes/update.php | 614 + sources/wp-includes/user.php | 1713 ++ sources/wp-includes/vars.php | 141 + sources/wp-includes/version.php | 37 + sources/wp-includes/widgets.php | 1259 ++ sources/wp-includes/wlwmanifest.xml | 43 + sources/wp-includes/wp-db.php | 1752 ++ sources/wp-includes/wp-diff.php | 500 + sources/wp-links-opml.php | 80 + sources/wp-load.php | 62 + sources/wp-login.php | 921 + sources/wp-mail.php | 231 + sources/wp-settings.php | 361 + sources/wp-signup.php | 736 + sources/wp-trackback.php | 127 + sources/xmlrpc.php | 99 + 1078 files changed, 339483 insertions(+) create mode 100644 conf/nginx.conf create mode 100644 conf/wp-config.php create mode 100644 manifest.json create mode 100755 scripts/install create mode 100755 scripts/remove create mode 100644 sources/index.php create mode 100644 sources/license.txt create mode 100644 sources/readme.html create mode 100644 sources/wp-activate.php create mode 100644 sources/wp-admin/about.php create mode 100644 sources/wp-admin/admin-ajax.php create mode 100644 sources/wp-admin/admin-footer.php create mode 100644 sources/wp-admin/admin-functions.php create mode 100644 sources/wp-admin/admin-header.php create mode 100644 sources/wp-admin/admin-post.php create mode 100644 sources/wp-admin/admin.php create mode 100644 sources/wp-admin/async-upload.php create mode 100644 sources/wp-admin/comment.php create mode 100644 sources/wp-admin/credits.php create mode 100644 sources/wp-admin/css/color-picker-rtl.css create mode 100644 sources/wp-admin/css/color-picker-rtl.min.css create mode 100644 sources/wp-admin/css/color-picker.css create mode 100644 sources/wp-admin/css/color-picker.min.css create mode 100644 sources/wp-admin/css/colors-classic.css create mode 100644 sources/wp-admin/css/colors-classic.min.css create mode 100644 sources/wp-admin/css/colors-fresh.css create mode 100644 sources/wp-admin/css/colors-fresh.min.css create mode 100644 sources/wp-admin/css/customize-controls-rtl.css create mode 100644 sources/wp-admin/css/customize-controls-rtl.min.css create mode 100644 sources/wp-admin/css/customize-controls.css create mode 100644 sources/wp-admin/css/customize-controls.min.css create mode 100644 sources/wp-admin/css/farbtastic.css create mode 100644 sources/wp-admin/css/ie-rtl.css create mode 100644 sources/wp-admin/css/ie-rtl.min.css create mode 100644 sources/wp-admin/css/ie.css create mode 100644 sources/wp-admin/css/ie.min.css create mode 100644 sources/wp-admin/css/install.css create mode 100644 sources/wp-admin/css/install.min.css create mode 100644 sources/wp-admin/css/media-rtl.css create mode 100644 sources/wp-admin/css/media-rtl.min.css create mode 100644 sources/wp-admin/css/media.css create mode 100644 sources/wp-admin/css/media.min.css create mode 100644 sources/wp-admin/css/wp-admin-rtl.css create mode 100644 sources/wp-admin/css/wp-admin-rtl.min.css create mode 100644 sources/wp-admin/css/wp-admin.css create mode 100644 sources/wp-admin/css/wp-admin.min.css create mode 100644 sources/wp-admin/custom-background.php create mode 100644 sources/wp-admin/custom-header.php create mode 100644 sources/wp-admin/customize.php create mode 100644 sources/wp-admin/edit-comments.php create mode 100644 sources/wp-admin/edit-form-advanced.php create mode 100644 sources/wp-admin/edit-form-comment.php create mode 100644 sources/wp-admin/edit-link-form.php create mode 100644 sources/wp-admin/edit-tag-form.php create mode 100644 sources/wp-admin/edit-tags.php create mode 100644 sources/wp-admin/edit.php create mode 100644 sources/wp-admin/export.php create mode 100644 sources/wp-admin/freedoms.php create mode 100644 sources/wp-admin/images/about-globe-2x.png create mode 100644 sources/wp-admin/images/about-search-2x.png create mode 100644 sources/wp-admin/images/about-updates-2x.png create mode 100644 sources/wp-admin/images/align-center-2x.png create mode 100644 sources/wp-admin/images/align-center.png create mode 100644 sources/wp-admin/images/align-left-2x.png create mode 100644 sources/wp-admin/images/align-left.png create mode 100644 sources/wp-admin/images/align-none-2x.png create mode 100644 sources/wp-admin/images/align-none.png create mode 100644 sources/wp-admin/images/align-right-2x.png create mode 100644 sources/wp-admin/images/align-right.png create mode 100644 sources/wp-admin/images/arrows-2x.png create mode 100644 sources/wp-admin/images/arrows-dark-2x.png create mode 100644 sources/wp-admin/images/arrows-dark-vs-2x.png create mode 100644 sources/wp-admin/images/arrows-dark-vs.png create mode 100644 sources/wp-admin/images/arrows-dark.png create mode 100644 sources/wp-admin/images/arrows-pr-2x.png create mode 100644 sources/wp-admin/images/arrows-pr.png create mode 100644 sources/wp-admin/images/arrows-vs-2x.png create mode 100644 sources/wp-admin/images/arrows-vs.png create mode 100644 sources/wp-admin/images/arrows.png create mode 100644 sources/wp-admin/images/bubble_bg-2x.gif create mode 100644 sources/wp-admin/images/bubble_bg-rtl-2x.gif create mode 100644 sources/wp-admin/images/bubble_bg-rtl.gif create mode 100644 sources/wp-admin/images/bubble_bg.gif create mode 100644 sources/wp-admin/images/comment-grey-bubble-2x.png create mode 100644 sources/wp-admin/images/comment-grey-bubble.png create mode 100644 sources/wp-admin/images/date-button-2x.gif create mode 100644 sources/wp-admin/images/date-button.gif create mode 100644 sources/wp-admin/images/generic.png create mode 100644 sources/wp-admin/images/icons32-2x.png create mode 100644 sources/wp-admin/images/icons32-vs-2x.png create mode 100644 sources/wp-admin/images/icons32-vs.png create mode 100644 sources/wp-admin/images/icons32.png create mode 100644 sources/wp-admin/images/imgedit-icons-2x.png create mode 100644 sources/wp-admin/images/imgedit-icons.png create mode 100644 sources/wp-admin/images/list-2x.png create mode 100644 sources/wp-admin/images/list.png create mode 100644 sources/wp-admin/images/loading.gif create mode 100644 sources/wp-admin/images/lock-2x.png create mode 100644 sources/wp-admin/images/lock.png create mode 100644 sources/wp-admin/images/marker.png create mode 100644 sources/wp-admin/images/mask.png create mode 100644 sources/wp-admin/images/media-button-2x.png create mode 100644 sources/wp-admin/images/media-button-image.gif create mode 100644 sources/wp-admin/images/media-button-music.gif create mode 100644 sources/wp-admin/images/media-button-other.gif create mode 100644 sources/wp-admin/images/media-button-video.gif create mode 100644 sources/wp-admin/images/media-button.png create mode 100644 sources/wp-admin/images/menu-2x.png create mode 100644 sources/wp-admin/images/menu-shadow-rtl.png create mode 100644 sources/wp-admin/images/menu-shadow.png create mode 100644 sources/wp-admin/images/menu-vs-2x.png create mode 100644 sources/wp-admin/images/menu-vs.png create mode 100644 sources/wp-admin/images/menu.png create mode 100644 sources/wp-admin/images/no.png create mode 100644 sources/wp-admin/images/post-formats-vs.png create mode 100644 sources/wp-admin/images/post-formats.png create mode 100644 sources/wp-admin/images/post-formats32-vs.png create mode 100644 sources/wp-admin/images/post-formats32.png create mode 100644 sources/wp-admin/images/press-this-2x.png create mode 100644 sources/wp-admin/images/press-this.png create mode 100644 sources/wp-admin/images/resize-2x.gif create mode 100644 sources/wp-admin/images/resize-rtl-2x.gif create mode 100644 sources/wp-admin/images/resize-rtl.gif create mode 100644 sources/wp-admin/images/resize.gif create mode 100644 sources/wp-admin/images/se.png create mode 100644 sources/wp-admin/images/sort-2x.gif create mode 100644 sources/wp-admin/images/sort.gif create mode 100644 sources/wp-admin/images/stars-2x.png create mode 100644 sources/wp-admin/images/stars-rtl-2x.png create mode 100644 sources/wp-admin/images/stars-rtl.png create mode 100644 sources/wp-admin/images/stars.png create mode 100644 sources/wp-admin/images/welcome-icons-2x.png create mode 100644 sources/wp-admin/images/welcome-icons.png create mode 100644 sources/wp-admin/images/wheel.png create mode 100644 sources/wp-admin/images/wordpress-logo-2x.png create mode 100644 sources/wp-admin/images/wordpress-logo.png create mode 100644 sources/wp-admin/images/wp-badge-2x.png create mode 100644 sources/wp-admin/images/wp-badge.png create mode 100644 sources/wp-admin/images/wp-logo-2x.png create mode 100644 sources/wp-admin/images/wp-logo-vs-2x.png create mode 100644 sources/wp-admin/images/wp-logo-vs.png create mode 100644 sources/wp-admin/images/wp-logo.png create mode 100644 sources/wp-admin/images/wpspin_light-2x.gif create mode 100644 sources/wp-admin/images/wpspin_light.gif create mode 100644 sources/wp-admin/images/xit-2x.gif create mode 100644 sources/wp-admin/images/xit.gif create mode 100644 sources/wp-admin/images/yes.png create mode 100644 sources/wp-admin/import.php create mode 100644 sources/wp-admin/includes/admin.php create mode 100644 sources/wp-admin/includes/ajax-actions.php create mode 100644 sources/wp-admin/includes/bookmark.php create mode 100644 sources/wp-admin/includes/class-ftp-pure.php create mode 100644 sources/wp-admin/includes/class-ftp-sockets.php create mode 100644 sources/wp-admin/includes/class-ftp.php create mode 100644 sources/wp-admin/includes/class-pclzip.php create mode 100644 sources/wp-admin/includes/class-wp-comments-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-filesystem-base.php create mode 100644 sources/wp-admin/includes/class-wp-filesystem-direct.php create mode 100644 sources/wp-admin/includes/class-wp-filesystem-ftpext.php create mode 100644 sources/wp-admin/includes/class-wp-filesystem-ftpsockets.php create mode 100644 sources/wp-admin/includes/class-wp-filesystem-ssh2.php create mode 100644 sources/wp-admin/includes/class-wp-importer.php create mode 100644 sources/wp-admin/includes/class-wp-links-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-media-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-ms-sites-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-ms-themes-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-ms-users-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-plugin-install-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-plugins-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-posts-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-terms-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-theme-install-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-themes-list-table.php create mode 100644 sources/wp-admin/includes/class-wp-upgrader-skins.php create mode 100644 sources/wp-admin/includes/class-wp-upgrader.php create mode 100644 sources/wp-admin/includes/class-wp-users-list-table.php create mode 100644 sources/wp-admin/includes/comment.php create mode 100644 sources/wp-admin/includes/continents-cities.php create mode 100644 sources/wp-admin/includes/dashboard.php create mode 100644 sources/wp-admin/includes/deprecated.php create mode 100644 sources/wp-admin/includes/export.php create mode 100644 sources/wp-admin/includes/file.php create mode 100644 sources/wp-admin/includes/image-edit.php create mode 100644 sources/wp-admin/includes/image.php create mode 100644 sources/wp-admin/includes/import.php create mode 100644 sources/wp-admin/includes/list-table.php create mode 100644 sources/wp-admin/includes/media.php create mode 100644 sources/wp-admin/includes/menu.php create mode 100644 sources/wp-admin/includes/meta-boxes.php create mode 100644 sources/wp-admin/includes/misc.php create mode 100644 sources/wp-admin/includes/ms-deprecated.php create mode 100644 sources/wp-admin/includes/ms.php create mode 100644 sources/wp-admin/includes/nav-menu.php create mode 100644 sources/wp-admin/includes/plugin-install.php create mode 100644 sources/wp-admin/includes/plugin.php create mode 100644 sources/wp-admin/includes/post.php create mode 100644 sources/wp-admin/includes/revision.php create mode 100644 sources/wp-admin/includes/schema.php create mode 100644 sources/wp-admin/includes/screen.php create mode 100644 sources/wp-admin/includes/taxonomy.php create mode 100644 sources/wp-admin/includes/template.php create mode 100644 sources/wp-admin/includes/theme-install.php create mode 100644 sources/wp-admin/includes/theme.php create mode 100644 sources/wp-admin/includes/update-core.php create mode 100644 sources/wp-admin/includes/update.php create mode 100644 sources/wp-admin/includes/upgrade.php create mode 100644 sources/wp-admin/includes/user.php create mode 100644 sources/wp-admin/includes/widgets.php create mode 100644 sources/wp-admin/index.php create mode 100644 sources/wp-admin/install-helper.php create mode 100644 sources/wp-admin/install.php create mode 100644 sources/wp-admin/js/about.js create mode 100644 sources/wp-admin/js/about.min.js create mode 100644 sources/wp-admin/js/accordion.js create mode 100644 sources/wp-admin/js/accordion.min.js create mode 100644 sources/wp-admin/js/color-picker.js create mode 100644 sources/wp-admin/js/color-picker.min.js create mode 100644 sources/wp-admin/js/comment.js create mode 100644 sources/wp-admin/js/comment.min.js create mode 100644 sources/wp-admin/js/common.js create mode 100644 sources/wp-admin/js/common.min.js create mode 100644 sources/wp-admin/js/custom-background.js create mode 100644 sources/wp-admin/js/custom-background.min.js create mode 100644 sources/wp-admin/js/custom-header.js create mode 100644 sources/wp-admin/js/customize-controls.js create mode 100644 sources/wp-admin/js/customize-controls.min.js create mode 100644 sources/wp-admin/js/dashboard.js create mode 100644 sources/wp-admin/js/dashboard.min.js create mode 100644 sources/wp-admin/js/edit-comments.js create mode 100644 sources/wp-admin/js/edit-comments.min.js create mode 100644 sources/wp-admin/js/editor.js create mode 100644 sources/wp-admin/js/editor.min.js create mode 100644 sources/wp-admin/js/farbtastic.js create mode 100644 sources/wp-admin/js/gallery.js create mode 100644 sources/wp-admin/js/gallery.min.js create mode 100644 sources/wp-admin/js/image-edit.js create mode 100644 sources/wp-admin/js/image-edit.min.js create mode 100644 sources/wp-admin/js/inline-edit-post.js create mode 100644 sources/wp-admin/js/inline-edit-post.min.js create mode 100644 sources/wp-admin/js/inline-edit-tax.js create mode 100644 sources/wp-admin/js/inline-edit-tax.min.js create mode 100644 sources/wp-admin/js/iris.min.js create mode 100644 sources/wp-admin/js/link.js create mode 100644 sources/wp-admin/js/link.min.js create mode 100644 sources/wp-admin/js/media-gallery.js create mode 100644 sources/wp-admin/js/media-gallery.min.js create mode 100644 sources/wp-admin/js/media-upload.js create mode 100644 sources/wp-admin/js/media-upload.min.js create mode 100644 sources/wp-admin/js/media.js create mode 100644 sources/wp-admin/js/media.min.js create mode 100644 sources/wp-admin/js/nav-menu.js create mode 100644 sources/wp-admin/js/nav-menu.min.js create mode 100644 sources/wp-admin/js/password-strength-meter.js create mode 100644 sources/wp-admin/js/password-strength-meter.min.js create mode 100644 sources/wp-admin/js/plugin-install.js create mode 100644 sources/wp-admin/js/plugin-install.min.js create mode 100644 sources/wp-admin/js/post.js create mode 100644 sources/wp-admin/js/post.min.js create mode 100644 sources/wp-admin/js/postbox.js create mode 100644 sources/wp-admin/js/postbox.min.js create mode 100644 sources/wp-admin/js/revisions.js create mode 100644 sources/wp-admin/js/revisions.min.js create mode 100644 sources/wp-admin/js/set-post-thumbnail.js create mode 100644 sources/wp-admin/js/set-post-thumbnail.min.js create mode 100644 sources/wp-admin/js/tags.js create mode 100644 sources/wp-admin/js/tags.min.js create mode 100644 sources/wp-admin/js/theme-preview.js create mode 100644 sources/wp-admin/js/theme-preview.min.js create mode 100644 sources/wp-admin/js/theme.js create mode 100644 sources/wp-admin/js/theme.min.js create mode 100644 sources/wp-admin/js/user-profile.js create mode 100644 sources/wp-admin/js/user-profile.min.js create mode 100644 sources/wp-admin/js/user-suggest.js create mode 100644 sources/wp-admin/js/user-suggest.min.js create mode 100644 sources/wp-admin/js/widgets.js create mode 100644 sources/wp-admin/js/widgets.min.js create mode 100644 sources/wp-admin/js/word-count.js create mode 100644 sources/wp-admin/js/word-count.min.js create mode 100644 sources/wp-admin/js/wp-fullscreen.js create mode 100644 sources/wp-admin/js/wp-fullscreen.min.js create mode 100644 sources/wp-admin/js/xfn.js create mode 100644 sources/wp-admin/js/xfn.min.js create mode 100644 sources/wp-admin/link-add.php create mode 100644 sources/wp-admin/link-manager.php create mode 100644 sources/wp-admin/link-parse-opml.php create mode 100644 sources/wp-admin/link.php create mode 100644 sources/wp-admin/load-scripts.php create mode 100644 sources/wp-admin/load-styles.php create mode 100644 sources/wp-admin/maint/repair.php create mode 100644 sources/wp-admin/media-new.php create mode 100644 sources/wp-admin/media-upload.php create mode 100644 sources/wp-admin/media.php create mode 100644 sources/wp-admin/menu-header.php create mode 100644 sources/wp-admin/menu.php create mode 100644 sources/wp-admin/moderation.php create mode 100644 sources/wp-admin/ms-admin.php create mode 100644 sources/wp-admin/ms-delete-site.php create mode 100644 sources/wp-admin/ms-edit.php create mode 100644 sources/wp-admin/ms-options.php create mode 100644 sources/wp-admin/ms-sites.php create mode 100644 sources/wp-admin/ms-themes.php create mode 100644 sources/wp-admin/ms-upgrade-network.php create mode 100644 sources/wp-admin/ms-users.php create mode 100644 sources/wp-admin/my-sites.php create mode 100644 sources/wp-admin/nav-menus.php create mode 100644 sources/wp-admin/network.php create mode 100644 sources/wp-admin/network/about.php create mode 100644 sources/wp-admin/network/admin.php create mode 100644 sources/wp-admin/network/credits.php create mode 100644 sources/wp-admin/network/edit.php create mode 100644 sources/wp-admin/network/freedoms.php create mode 100644 sources/wp-admin/network/index.php create mode 100644 sources/wp-admin/network/menu.php create mode 100644 sources/wp-admin/network/plugin-editor.php create mode 100644 sources/wp-admin/network/plugin-install.php create mode 100644 sources/wp-admin/network/plugins.php create mode 100644 sources/wp-admin/network/profile.php create mode 100644 sources/wp-admin/network/settings.php create mode 100644 sources/wp-admin/network/setup.php create mode 100644 sources/wp-admin/network/site-info.php create mode 100644 sources/wp-admin/network/site-new.php create mode 100644 sources/wp-admin/network/site-settings.php create mode 100644 sources/wp-admin/network/site-themes.php create mode 100644 sources/wp-admin/network/site-users.php create mode 100644 sources/wp-admin/network/sites.php create mode 100644 sources/wp-admin/network/theme-editor.php create mode 100644 sources/wp-admin/network/theme-install.php create mode 100644 sources/wp-admin/network/themes.php create mode 100644 sources/wp-admin/network/update-core.php create mode 100644 sources/wp-admin/network/update.php create mode 100644 sources/wp-admin/network/upgrade.php create mode 100644 sources/wp-admin/network/user-edit.php create mode 100644 sources/wp-admin/network/user-new.php create mode 100644 sources/wp-admin/network/users.php create mode 100644 sources/wp-admin/options-discussion.php create mode 100644 sources/wp-admin/options-general.php create mode 100644 sources/wp-admin/options-head.php create mode 100644 sources/wp-admin/options-media.php create mode 100644 sources/wp-admin/options-permalink.php create mode 100644 sources/wp-admin/options-reading.php create mode 100644 sources/wp-admin/options-writing.php create mode 100644 sources/wp-admin/options.php create mode 100644 sources/wp-admin/plugin-editor.php create mode 100644 sources/wp-admin/plugin-install.php create mode 100644 sources/wp-admin/plugins.php create mode 100644 sources/wp-admin/post-new.php create mode 100644 sources/wp-admin/post.php create mode 100644 sources/wp-admin/press-this.php create mode 100644 sources/wp-admin/profile.php create mode 100644 sources/wp-admin/revision.php create mode 100644 sources/wp-admin/setup-config.php create mode 100644 sources/wp-admin/theme-editor.php create mode 100644 sources/wp-admin/theme-install.php create mode 100644 sources/wp-admin/themes.php create mode 100644 sources/wp-admin/tools.php create mode 100644 sources/wp-admin/update-core.php create mode 100644 sources/wp-admin/update.php create mode 100644 sources/wp-admin/upgrade-functions.php create mode 100644 sources/wp-admin/upgrade.php create mode 100644 sources/wp-admin/upload.php create mode 100644 sources/wp-admin/user-edit.php create mode 100644 sources/wp-admin/user-new.php create mode 100644 sources/wp-admin/user/about.php create mode 100644 sources/wp-admin/user/admin.php create mode 100644 sources/wp-admin/user/credits.php create mode 100644 sources/wp-admin/user/freedoms.php create mode 100644 sources/wp-admin/user/index.php create mode 100644 sources/wp-admin/user/menu.php create mode 100644 sources/wp-admin/user/profile.php create mode 100644 sources/wp-admin/user/user-edit.php create mode 100644 sources/wp-admin/users.php create mode 100644 sources/wp-admin/widgets.php create mode 100644 sources/wp-blog-header.php create mode 100644 sources/wp-comments-post.php create mode 100644 sources/wp-config-sample.php create mode 100644 sources/wp-content/index.php create mode 100644 sources/wp-content/languages/admin-fr_FR.mo create mode 100644 sources/wp-content/languages/admin-fr_FR.po create mode 100644 sources/wp-content/languages/admin-network-fr_FR.mo create mode 100644 sources/wp-content/languages/admin-network-fr_FR.po create mode 100644 sources/wp-content/languages/continents-cities-fr_FR.mo create mode 100644 sources/wp-content/languages/continents-cities-fr_FR.po create mode 100644 sources/wp-content/languages/fr_FR.mo create mode 100644 sources/wp-content/languages/fr_FR.po create mode 100644 sources/wp-content/languages/themes/twentythirteen-fr_FR.mo create mode 100644 sources/wp-content/languages/themes/twentythirteen-fr_FR.po create mode 100644 sources/wp-content/languages/themes/twentytwelve-fr_FR.mo create mode 100644 sources/wp-content/languages/themes/twentytwelve-fr_FR.po create mode 100644 sources/wp-content/plugins/akismet/admin.php create mode 100644 sources/wp-content/plugins/akismet/akismet.css create mode 100644 sources/wp-content/plugins/akismet/akismet.gif create mode 100644 sources/wp-content/plugins/akismet/akismet.js create mode 100644 sources/wp-content/plugins/akismet/akismet.php create mode 100644 sources/wp-content/plugins/akismet/img/logo.png create mode 100644 sources/wp-content/plugins/akismet/img/logo@2x.png create mode 100644 sources/wp-content/plugins/akismet/index.php create mode 100644 sources/wp-content/plugins/akismet/legacy.php create mode 100644 sources/wp-content/plugins/akismet/readme.txt create mode 100644 sources/wp-content/plugins/akismet/widget.php create mode 100644 sources/wp-content/plugins/hello.php create mode 100644 sources/wp-content/plugins/index.php create mode 100644 sources/wp-content/themes/index.php create mode 100644 sources/wp-content/themes/twentythirteen/404.php create mode 100644 sources/wp-content/themes/twentythirteen/archive.php create mode 100644 sources/wp-content/themes/twentythirteen/author-bio.php create mode 100644 sources/wp-content/themes/twentythirteen/author.php create mode 100644 sources/wp-content/themes/twentythirteen/category.php create mode 100644 sources/wp-content/themes/twentythirteen/comments.php create mode 100644 sources/wp-content/themes/twentythirteen/content-aside.php create mode 100644 sources/wp-content/themes/twentythirteen/content-audio.php create mode 100644 sources/wp-content/themes/twentythirteen/content-chat.php create mode 100644 sources/wp-content/themes/twentythirteen/content-gallery.php create mode 100644 sources/wp-content/themes/twentythirteen/content-image.php create mode 100644 sources/wp-content/themes/twentythirteen/content-link.php create mode 100644 sources/wp-content/themes/twentythirteen/content-none.php create mode 100644 sources/wp-content/themes/twentythirteen/content-quote.php create mode 100644 sources/wp-content/themes/twentythirteen/content-status.php create mode 100644 sources/wp-content/themes/twentythirteen/content-video.php create mode 100644 sources/wp-content/themes/twentythirteen/content.php create mode 100644 sources/wp-content/themes/twentythirteen/css/editor-style.css create mode 100644 sources/wp-content/themes/twentythirteen/css/ie.css create mode 100644 sources/wp-content/themes/twentythirteen/fonts/COPYING.txt create mode 100644 sources/wp-content/themes/twentythirteen/fonts/LICENSE.txt create mode 100644 sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.eot create mode 100644 sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.svg create mode 100644 sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.ttf create mode 100644 sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.woff create mode 100644 sources/wp-content/themes/twentythirteen/fonts/genericons.css create mode 100644 sources/wp-content/themes/twentythirteen/footer.php create mode 100644 sources/wp-content/themes/twentythirteen/functions.php create mode 100644 sources/wp-content/themes/twentythirteen/header.php create mode 100644 sources/wp-content/themes/twentythirteen/image.php create mode 100644 sources/wp-content/themes/twentythirteen/images/dotted-line-2x.png create mode 100644 sources/wp-content/themes/twentythirteen/images/dotted-line-light-2x.png create mode 100644 sources/wp-content/themes/twentythirteen/images/dotted-line-light.png create mode 100644 sources/wp-content/themes/twentythirteen/images/dotted-line.png create mode 100644 sources/wp-content/themes/twentythirteen/images/headers/circle-thumbnail.png create mode 100644 sources/wp-content/themes/twentythirteen/images/headers/circle.png create mode 100644 sources/wp-content/themes/twentythirteen/images/headers/diamond-thumbnail.png create mode 100644 sources/wp-content/themes/twentythirteen/images/headers/diamond.png create mode 100644 sources/wp-content/themes/twentythirteen/images/headers/star-thumbnail.png create mode 100644 sources/wp-content/themes/twentythirteen/images/headers/star.png create mode 100644 sources/wp-content/themes/twentythirteen/images/search-icon-2x.png create mode 100644 sources/wp-content/themes/twentythirteen/images/search-icon.png create mode 100644 sources/wp-content/themes/twentythirteen/inc/back-compat.php create mode 100644 sources/wp-content/themes/twentythirteen/inc/custom-header.php create mode 100644 sources/wp-content/themes/twentythirteen/index.php create mode 100644 sources/wp-content/themes/twentythirteen/js/functions.js create mode 100644 sources/wp-content/themes/twentythirteen/js/html5.js create mode 100644 sources/wp-content/themes/twentythirteen/js/theme-customizer.js create mode 100644 sources/wp-content/themes/twentythirteen/languages/twentythirteen.pot create mode 100644 sources/wp-content/themes/twentythirteen/page.php create mode 100644 sources/wp-content/themes/twentythirteen/rtl.css create mode 100644 sources/wp-content/themes/twentythirteen/screenshot.png create mode 100644 sources/wp-content/themes/twentythirteen/search.php create mode 100644 sources/wp-content/themes/twentythirteen/sidebar-main.php create mode 100644 sources/wp-content/themes/twentythirteen/sidebar.php create mode 100644 sources/wp-content/themes/twentythirteen/single.php create mode 100644 sources/wp-content/themes/twentythirteen/style.css create mode 100644 sources/wp-content/themes/twentythirteen/tag.php create mode 100644 sources/wp-content/themes/twentythirteen/taxonomy-post_format.php create mode 100644 sources/wp-content/themes/twentytwelve/404.php create mode 100644 sources/wp-content/themes/twentytwelve/archive.php create mode 100644 sources/wp-content/themes/twentytwelve/author.php create mode 100644 sources/wp-content/themes/twentytwelve/category.php create mode 100644 sources/wp-content/themes/twentytwelve/comments.php create mode 100644 sources/wp-content/themes/twentytwelve/content-aside.php create mode 100644 sources/wp-content/themes/twentytwelve/content-image.php create mode 100644 sources/wp-content/themes/twentytwelve/content-link.php create mode 100644 sources/wp-content/themes/twentytwelve/content-none.php create mode 100644 sources/wp-content/themes/twentytwelve/content-page.php create mode 100644 sources/wp-content/themes/twentytwelve/content-quote.php create mode 100644 sources/wp-content/themes/twentytwelve/content-status.php create mode 100644 sources/wp-content/themes/twentytwelve/content.php create mode 100644 sources/wp-content/themes/twentytwelve/css/ie.css create mode 100644 sources/wp-content/themes/twentytwelve/editor-style-rtl.css create mode 100644 sources/wp-content/themes/twentytwelve/editor-style.css create mode 100644 sources/wp-content/themes/twentytwelve/footer.php create mode 100644 sources/wp-content/themes/twentytwelve/functions.php create mode 100644 sources/wp-content/themes/twentytwelve/header.php create mode 100644 sources/wp-content/themes/twentytwelve/image.php create mode 100644 sources/wp-content/themes/twentytwelve/inc/custom-header.php create mode 100644 sources/wp-content/themes/twentytwelve/index.php create mode 100644 sources/wp-content/themes/twentytwelve/js/html5.js create mode 100644 sources/wp-content/themes/twentytwelve/js/navigation.js create mode 100644 sources/wp-content/themes/twentytwelve/js/theme-customizer.js create mode 100644 sources/wp-content/themes/twentytwelve/languages/twentytwelve.pot create mode 100644 sources/wp-content/themes/twentytwelve/page-templates/front-page.php create mode 100644 sources/wp-content/themes/twentytwelve/page-templates/full-width.php create mode 100644 sources/wp-content/themes/twentytwelve/page.php create mode 100644 sources/wp-content/themes/twentytwelve/rtl.css create mode 100644 sources/wp-content/themes/twentytwelve/screenshot.png create mode 100644 sources/wp-content/themes/twentytwelve/search.php create mode 100644 sources/wp-content/themes/twentytwelve/sidebar-front.php create mode 100644 sources/wp-content/themes/twentytwelve/sidebar.php create mode 100644 sources/wp-content/themes/twentytwelve/single.php create mode 100644 sources/wp-content/themes/twentytwelve/style.css create mode 100644 sources/wp-content/themes/twentytwelve/tag.php create mode 100644 sources/wp-cron.php create mode 100644 sources/wp-includes/ID3/getid3.lib.php create mode 100644 sources/wp-includes/ID3/getid3.php create mode 100644 sources/wp-includes/ID3/license.commercial.txt create mode 100644 sources/wp-includes/ID3/license.txt create mode 100644 sources/wp-includes/ID3/module.audio-video.asf.php create mode 100644 sources/wp-includes/ID3/module.audio-video.flv.php create mode 100644 sources/wp-includes/ID3/module.audio-video.matroska.php create mode 100644 sources/wp-includes/ID3/module.audio-video.quicktime.php create mode 100644 sources/wp-includes/ID3/module.audio-video.riff.php create mode 100644 sources/wp-includes/ID3/module.audio.ac3.php create mode 100644 sources/wp-includes/ID3/module.audio.dts.php create mode 100644 sources/wp-includes/ID3/module.audio.flac.php create mode 100644 sources/wp-includes/ID3/module.audio.mp3.php create mode 100644 sources/wp-includes/ID3/module.audio.ogg.php create mode 100644 sources/wp-includes/ID3/module.tag.apetag.php create mode 100644 sources/wp-includes/ID3/module.tag.id3v1.php create mode 100644 sources/wp-includes/ID3/module.tag.id3v2.php create mode 100644 sources/wp-includes/ID3/module.tag.lyrics3.php create mode 100644 sources/wp-includes/ID3/readme.txt create mode 100644 sources/wp-includes/SimplePie/Author.php create mode 100644 sources/wp-includes/SimplePie/Cache.php create mode 100644 sources/wp-includes/SimplePie/Cache/Base.php create mode 100644 sources/wp-includes/SimplePie/Cache/DB.php create mode 100644 sources/wp-includes/SimplePie/Cache/File.php create mode 100644 sources/wp-includes/SimplePie/Cache/Memcache.php create mode 100644 sources/wp-includes/SimplePie/Cache/MySQL.php create mode 100644 sources/wp-includes/SimplePie/Caption.php create mode 100644 sources/wp-includes/SimplePie/Category.php create mode 100644 sources/wp-includes/SimplePie/Content/Type/Sniffer.php create mode 100644 sources/wp-includes/SimplePie/Copyright.php create mode 100644 sources/wp-includes/SimplePie/Core.php create mode 100644 sources/wp-includes/SimplePie/Credit.php create mode 100644 sources/wp-includes/SimplePie/Decode/HTML/Entities.php create mode 100644 sources/wp-includes/SimplePie/Enclosure.php create mode 100644 sources/wp-includes/SimplePie/Exception.php create mode 100644 sources/wp-includes/SimplePie/File.php create mode 100644 sources/wp-includes/SimplePie/HTTP/Parser.php create mode 100644 sources/wp-includes/SimplePie/IRI.php create mode 100644 sources/wp-includes/SimplePie/Item.php create mode 100644 sources/wp-includes/SimplePie/Locator.php create mode 100644 sources/wp-includes/SimplePie/Misc.php create mode 100644 sources/wp-includes/SimplePie/Net/IPv6.php create mode 100644 sources/wp-includes/SimplePie/Parse/Date.php create mode 100644 sources/wp-includes/SimplePie/Parser.php create mode 100644 sources/wp-includes/SimplePie/Rating.php create mode 100644 sources/wp-includes/SimplePie/Registry.php create mode 100644 sources/wp-includes/SimplePie/Restriction.php create mode 100644 sources/wp-includes/SimplePie/Sanitize.php create mode 100644 sources/wp-includes/SimplePie/Source.php create mode 100644 sources/wp-includes/SimplePie/XML/Declaration/Parser.php create mode 100644 sources/wp-includes/SimplePie/gzdecode.php create mode 100644 sources/wp-includes/Text/Diff.php create mode 100644 sources/wp-includes/Text/Diff/Engine/native.php create mode 100644 sources/wp-includes/Text/Diff/Engine/shell.php create mode 100644 sources/wp-includes/Text/Diff/Engine/string.php create mode 100644 sources/wp-includes/Text/Diff/Engine/xdiff.php create mode 100644 sources/wp-includes/Text/Diff/Renderer.php create mode 100644 sources/wp-includes/Text/Diff/Renderer/inline.php create mode 100644 sources/wp-includes/admin-bar.php create mode 100644 sources/wp-includes/atomlib.php create mode 100644 sources/wp-includes/author-template.php create mode 100644 sources/wp-includes/bookmark-template.php create mode 100644 sources/wp-includes/bookmark.php create mode 100644 sources/wp-includes/cache.php create mode 100644 sources/wp-includes/canonical.php create mode 100644 sources/wp-includes/capabilities.php create mode 100644 sources/wp-includes/category-template.php create mode 100644 sources/wp-includes/category.php create mode 100644 sources/wp-includes/certificates/ca-bundle.crt create mode 100644 sources/wp-includes/class-IXR.php create mode 100644 sources/wp-includes/class-feed.php create mode 100644 sources/wp-includes/class-http.php create mode 100644 sources/wp-includes/class-json.php create mode 100644 sources/wp-includes/class-oembed.php create mode 100644 sources/wp-includes/class-phpass.php create mode 100644 sources/wp-includes/class-phpmailer.php create mode 100644 sources/wp-includes/class-pop3.php create mode 100644 sources/wp-includes/class-simplepie.php create mode 100644 sources/wp-includes/class-smtp.php create mode 100644 sources/wp-includes/class-snoopy.php create mode 100644 sources/wp-includes/class-wp-admin-bar.php create mode 100644 sources/wp-includes/class-wp-ajax-response.php create mode 100644 sources/wp-includes/class-wp-customize-control.php create mode 100644 sources/wp-includes/class-wp-customize-manager.php create mode 100644 sources/wp-includes/class-wp-customize-section.php create mode 100644 sources/wp-includes/class-wp-customize-setting.php create mode 100644 sources/wp-includes/class-wp-editor.php create mode 100644 sources/wp-includes/class-wp-embed.php create mode 100644 sources/wp-includes/class-wp-error.php create mode 100644 sources/wp-includes/class-wp-http-ixr-client.php create mode 100644 sources/wp-includes/class-wp-image-editor-gd.php create mode 100644 sources/wp-includes/class-wp-image-editor-imagick.php create mode 100644 sources/wp-includes/class-wp-image-editor.php create mode 100644 sources/wp-includes/class-wp-theme.php create mode 100644 sources/wp-includes/class-wp-walker.php create mode 100644 sources/wp-includes/class-wp-xmlrpc-server.php create mode 100644 sources/wp-includes/class-wp.php create mode 100644 sources/wp-includes/class.wp-dependencies.php create mode 100644 sources/wp-includes/class.wp-scripts.php create mode 100644 sources/wp-includes/class.wp-styles.php create mode 100644 sources/wp-includes/comment-template.php create mode 100644 sources/wp-includes/comment.php create mode 100644 sources/wp-includes/compat.php create mode 100644 sources/wp-includes/cron.php create mode 100644 sources/wp-includes/css/admin-bar-rtl.css create mode 100644 sources/wp-includes/css/admin-bar-rtl.min.css create mode 100644 sources/wp-includes/css/admin-bar.css create mode 100644 sources/wp-includes/css/admin-bar.min.css create mode 100644 sources/wp-includes/css/buttons.css create mode 100644 sources/wp-includes/css/buttons.min.css create mode 100644 sources/wp-includes/css/editor.css create mode 100644 sources/wp-includes/css/editor.min.css create mode 100644 sources/wp-includes/css/jquery-ui-dialog.css create mode 100644 sources/wp-includes/css/jquery-ui-dialog.min.css create mode 100644 sources/wp-includes/css/media-views-rtl.css create mode 100644 sources/wp-includes/css/media-views-rtl.min.css create mode 100644 sources/wp-includes/css/media-views.css create mode 100644 sources/wp-includes/css/media-views.min.css create mode 100644 sources/wp-includes/css/wp-auth-check.css create mode 100644 sources/wp-includes/css/wp-auth-check.min.css create mode 100644 sources/wp-includes/css/wp-pointer.css create mode 100644 sources/wp-includes/css/wp-pointer.min.css create mode 100644 sources/wp-includes/date.php create mode 100644 sources/wp-includes/default-constants.php create mode 100644 sources/wp-includes/default-filters.php create mode 100644 sources/wp-includes/default-widgets.php create mode 100644 sources/wp-includes/deprecated.php create mode 100644 sources/wp-includes/feed-atom-comments.php create mode 100644 sources/wp-includes/feed-atom.php create mode 100644 sources/wp-includes/feed-rdf.php create mode 100644 sources/wp-includes/feed-rss.php create mode 100644 sources/wp-includes/feed-rss2-comments.php create mode 100644 sources/wp-includes/feed-rss2.php create mode 100644 sources/wp-includes/feed.php create mode 100644 sources/wp-includes/formatting.php create mode 100644 sources/wp-includes/functions.php create mode 100644 sources/wp-includes/functions.wp-scripts.php create mode 100644 sources/wp-includes/functions.wp-styles.php create mode 100644 sources/wp-includes/general-template.php create mode 100644 sources/wp-includes/http.php create mode 100644 sources/wp-includes/images/admin-bar-sprite-2x.png create mode 100644 sources/wp-includes/images/admin-bar-sprite.png create mode 100644 sources/wp-includes/images/arrow-pointer-blue-2x.png create mode 100644 sources/wp-includes/images/arrow-pointer-blue.png create mode 100644 sources/wp-includes/images/blank.gif create mode 100644 sources/wp-includes/images/crystal/archive.png create mode 100644 sources/wp-includes/images/crystal/audio.png create mode 100644 sources/wp-includes/images/crystal/code.png create mode 100644 sources/wp-includes/images/crystal/default.png create mode 100644 sources/wp-includes/images/crystal/document.png create mode 100644 sources/wp-includes/images/crystal/interactive.png create mode 100644 sources/wp-includes/images/crystal/license.txt create mode 100644 sources/wp-includes/images/crystal/spreadsheet.png create mode 100644 sources/wp-includes/images/crystal/text.png create mode 100644 sources/wp-includes/images/crystal/video.png create mode 100644 sources/wp-includes/images/down_arrow-2x.gif create mode 100644 sources/wp-includes/images/down_arrow.gif create mode 100644 sources/wp-includes/images/icon-pointer-flag-2x.png create mode 100644 sources/wp-includes/images/icon-pointer-flag.png create mode 100644 sources/wp-includes/images/rss-2x.png create mode 100644 sources/wp-includes/images/rss.png create mode 100644 sources/wp-includes/images/smilies/icon_arrow.gif create mode 100644 sources/wp-includes/images/smilies/icon_biggrin.gif create mode 100644 sources/wp-includes/images/smilies/icon_confused.gif create mode 100644 sources/wp-includes/images/smilies/icon_cool.gif create mode 100644 sources/wp-includes/images/smilies/icon_cry.gif create mode 100644 sources/wp-includes/images/smilies/icon_eek.gif create mode 100644 sources/wp-includes/images/smilies/icon_evil.gif create mode 100644 sources/wp-includes/images/smilies/icon_exclaim.gif create mode 100644 sources/wp-includes/images/smilies/icon_idea.gif create mode 100644 sources/wp-includes/images/smilies/icon_lol.gif create mode 100644 sources/wp-includes/images/smilies/icon_mad.gif create mode 100644 sources/wp-includes/images/smilies/icon_mrgreen.gif create mode 100644 sources/wp-includes/images/smilies/icon_neutral.gif create mode 100644 sources/wp-includes/images/smilies/icon_question.gif create mode 100644 sources/wp-includes/images/smilies/icon_razz.gif create mode 100644 sources/wp-includes/images/smilies/icon_redface.gif create mode 100644 sources/wp-includes/images/smilies/icon_rolleyes.gif create mode 100644 sources/wp-includes/images/smilies/icon_sad.gif create mode 100644 sources/wp-includes/images/smilies/icon_smile.gif create mode 100644 sources/wp-includes/images/smilies/icon_surprised.gif create mode 100644 sources/wp-includes/images/smilies/icon_twisted.gif create mode 100644 sources/wp-includes/images/smilies/icon_wink.gif create mode 100644 sources/wp-includes/images/toggle-arrow-2x.png create mode 100644 sources/wp-includes/images/toggle-arrow.png create mode 100644 sources/wp-includes/images/uploader-icons-2x.png create mode 100644 sources/wp-includes/images/uploader-icons.png create mode 100644 sources/wp-includes/images/wlw/wp-comments.png create mode 100644 sources/wp-includes/images/wlw/wp-icon.png create mode 100644 sources/wp-includes/images/wlw/wp-watermark.png create mode 100644 sources/wp-includes/images/wpicons-2x.png create mode 100644 sources/wp-includes/images/wpicons.png create mode 100644 sources/wp-includes/images/wpmini-blue-2x.png create mode 100644 sources/wp-includes/images/wpmini-blue.png create mode 100644 sources/wp-includes/images/wpspin-2x.gif create mode 100644 sources/wp-includes/images/wpspin.gif create mode 100644 sources/wp-includes/images/xit-2x.gif create mode 100644 sources/wp-includes/images/xit.gif create mode 100644 sources/wp-includes/js/admin-bar.js create mode 100644 sources/wp-includes/js/admin-bar.min.js create mode 100644 sources/wp-includes/js/autosave.js create mode 100644 sources/wp-includes/js/autosave.min.js create mode 100644 sources/wp-includes/js/backbone.min.js create mode 100644 sources/wp-includes/js/colorpicker.js create mode 100644 sources/wp-includes/js/colorpicker.min.js create mode 100644 sources/wp-includes/js/comment-reply.js create mode 100644 sources/wp-includes/js/comment-reply.min.js create mode 100644 sources/wp-includes/js/crop/cropper.css create mode 100644 sources/wp-includes/js/crop/cropper.js create mode 100644 sources/wp-includes/js/crop/marqueeHoriz.gif create mode 100644 sources/wp-includes/js/crop/marqueeVert.gif create mode 100644 sources/wp-includes/js/customize-base.js create mode 100644 sources/wp-includes/js/customize-base.min.js create mode 100644 sources/wp-includes/js/customize-loader.js create mode 100644 sources/wp-includes/js/customize-loader.min.js create mode 100644 sources/wp-includes/js/customize-preview.js create mode 100644 sources/wp-includes/js/customize-preview.min.js create mode 100644 sources/wp-includes/js/heartbeat.js create mode 100644 sources/wp-includes/js/heartbeat.min.js create mode 100644 sources/wp-includes/js/hoverIntent.js create mode 100644 sources/wp-includes/js/hoverIntent.min.js create mode 100644 sources/wp-includes/js/imgareaselect/border-anim-h.gif create mode 100644 sources/wp-includes/js/imgareaselect/border-anim-v.gif create mode 100644 sources/wp-includes/js/imgareaselect/imgareaselect.css create mode 100644 sources/wp-includes/js/imgareaselect/jquery.imgareaselect.js create mode 100644 sources/wp-includes/js/imgareaselect/jquery.imgareaselect.min.js create mode 100644 sources/wp-includes/js/jcrop/Jcrop.gif create mode 100644 sources/wp-includes/js/jcrop/jquery.Jcrop.min.css create mode 100644 sources/wp-includes/js/jcrop/jquery.Jcrop.min.js create mode 100644 sources/wp-includes/js/jquery/jquery-migrate.js create mode 100644 sources/wp-includes/js/jquery/jquery-migrate.min.js create mode 100644 sources/wp-includes/js/jquery/jquery.color.min.js create mode 100644 sources/wp-includes/js/jquery/jquery.form.js create mode 100644 sources/wp-includes/js/jquery/jquery.form.min.js create mode 100644 sources/wp-includes/js/jquery/jquery.hotkeys.js create mode 100644 sources/wp-includes/js/jquery/jquery.hotkeys.min.js create mode 100644 sources/wp-includes/js/jquery/jquery.js create mode 100644 sources/wp-includes/js/jquery/jquery.masonry.min.js create mode 100644 sources/wp-includes/js/jquery/jquery.query.js create mode 100644 sources/wp-includes/js/jquery/jquery.schedule.js create mode 100644 sources/wp-includes/js/jquery/jquery.serialize-object.js create mode 100644 sources/wp-includes/js/jquery/jquery.table-hotkeys.js create mode 100644 sources/wp-includes/js/jquery/jquery.table-hotkeys.min.js create mode 100644 sources/wp-includes/js/jquery/jquery.ui.touch-punch.js create mode 100644 sources/wp-includes/js/jquery/suggest.js create mode 100644 sources/wp-includes/js/jquery/suggest.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.accordion.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.autocomplete.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.button.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.core.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.datepicker.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.dialog.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.draggable.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.droppable.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-blind.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-bounce.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-clip.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-drop.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-explode.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-fade.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-fold.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-highlight.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-pulsate.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-scale.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-shake.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-slide.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect-transfer.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.effect.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.menu.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.mouse.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.position.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.progressbar.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.resizable.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.selectable.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.slider.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.sortable.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.spinner.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.tabs.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.tooltip.min.js create mode 100644 sources/wp-includes/js/jquery/ui/jquery.ui.widget.min.js create mode 100644 sources/wp-includes/js/json2.js create mode 100644 sources/wp-includes/js/json2.min.js create mode 100644 sources/wp-includes/js/mce-view.js create mode 100644 sources/wp-includes/js/mce-view.min.js create mode 100644 sources/wp-includes/js/media-editor.js create mode 100644 sources/wp-includes/js/media-editor.min.js create mode 100644 sources/wp-includes/js/media-models.js create mode 100644 sources/wp-includes/js/media-models.min.js create mode 100644 sources/wp-includes/js/media-views.js create mode 100644 sources/wp-includes/js/media-views.min.js create mode 100644 sources/wp-includes/js/mediaelement/background.png create mode 100644 sources/wp-includes/js/mediaelement/bigplay.png create mode 100644 sources/wp-includes/js/mediaelement/bigplay.svg create mode 100644 sources/wp-includes/js/mediaelement/controls.png create mode 100644 sources/wp-includes/js/mediaelement/controls.svg create mode 100644 sources/wp-includes/js/mediaelement/flashmediaelement.swf create mode 100644 sources/wp-includes/js/mediaelement/loading.gif create mode 100644 sources/wp-includes/js/mediaelement/mediaelement-and-player.min.js create mode 100644 sources/wp-includes/js/mediaelement/mediaelementplayer.min.css create mode 100644 sources/wp-includes/js/mediaelement/silverlightmediaelement.xap create mode 100644 sources/wp-includes/js/mediaelement/wp-mediaelement.css create mode 100644 sources/wp-includes/js/mediaelement/wp-mediaelement.js create mode 100644 sources/wp-includes/js/plupload/changelog.txt create mode 100644 sources/wp-includes/js/plupload/handlers.js create mode 100644 sources/wp-includes/js/plupload/handlers.min.js create mode 100644 sources/wp-includes/js/plupload/license.txt create mode 100644 sources/wp-includes/js/plupload/plupload.flash.js create mode 100644 sources/wp-includes/js/plupload/plupload.flash.swf create mode 100644 sources/wp-includes/js/plupload/plupload.html4.js create mode 100644 sources/wp-includes/js/plupload/plupload.html5.js create mode 100644 sources/wp-includes/js/plupload/plupload.js create mode 100644 sources/wp-includes/js/plupload/plupload.silverlight.js create mode 100644 sources/wp-includes/js/plupload/plupload.silverlight.xap create mode 100644 sources/wp-includes/js/plupload/wp-plupload.js create mode 100644 sources/wp-includes/js/plupload/wp-plupload.min.js create mode 100644 sources/wp-includes/js/quicktags.js create mode 100644 sources/wp-includes/js/quicktags.min.js create mode 100644 sources/wp-includes/js/shortcode.js create mode 100644 sources/wp-includes/js/shortcode.min.js create mode 100644 sources/wp-includes/js/swfobject.js create mode 100644 sources/wp-includes/js/swfupload/handlers.js create mode 100644 sources/wp-includes/js/swfupload/handlers.min.js create mode 100644 sources/wp-includes/js/swfupload/license.txt create mode 100644 sources/wp-includes/js/swfupload/plugins/swfupload.cookies.js create mode 100644 sources/wp-includes/js/swfupload/plugins/swfupload.queue.js create mode 100644 sources/wp-includes/js/swfupload/plugins/swfupload.speed.js create mode 100644 sources/wp-includes/js/swfupload/plugins/swfupload.swfobject.js create mode 100644 sources/wp-includes/js/swfupload/swfupload.js create mode 100644 sources/wp-includes/js/swfupload/swfupload.swf create mode 100644 sources/wp-includes/js/thickbox/loadingAnimation.gif create mode 100644 sources/wp-includes/js/thickbox/macFFBgHack.png create mode 100644 sources/wp-includes/js/thickbox/tb-close-2x.png create mode 100644 sources/wp-includes/js/thickbox/tb-close.png create mode 100644 sources/wp-includes/js/thickbox/thickbox.css create mode 100644 sources/wp-includes/js/thickbox/thickbox.js create mode 100644 sources/wp-includes/js/tinymce/langs/wp-langs-en.js create mode 100644 sources/wp-includes/js/tinymce/langs/wp-langs.php create mode 100644 sources/wp-includes/js/tinymce/license.txt create mode 100644 sources/wp-includes/js/tinymce/mark_loaded_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/directionality/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/directionality/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/fullscreen/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/fullscreen/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/fullscreen/fullscreen.htm create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/button.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/drag.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/window.css create mode 100644 sources/wp-includes/js/tinymce/plugins/inlinepopups/template.htm create mode 100644 sources/wp-includes/js/tinymce/plugins/media/css/media.css create mode 100644 sources/wp-includes/js/tinymce/plugins/media/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/media/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/media/js/embed.js create mode 100644 sources/wp-includes/js/tinymce/plugins/media/js/media.js create mode 100644 sources/wp-includes/js/tinymce/plugins/media/media.htm create mode 100644 sources/wp-includes/js/tinymce/plugins/media/moxieplayer.swf create mode 100644 sources/wp-includes/js/tinymce/plugins/paste/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/paste/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/paste/js/pastetext.js create mode 100644 sources/wp-includes/js/tinymce/plugins/paste/js/pasteword.js create mode 100644 sources/wp-includes/js/tinymce/plugins/paste/pastetext.htm create mode 100644 sources/wp-includes/js/tinymce/plugins/paste/pasteword.htm create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/changelog.txt create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/EnchantSpell.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/GoogleSpell.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/PSpell.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/PSpellShell.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/SpellChecker.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/utils/JSON.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/classes/utils/Logger.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/config.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/css/content.css create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/img/wline.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/includes/general.php create mode 100644 sources/wp-includes/js/tinymce/plugins/spellchecker/rpc.php create mode 100644 sources/wp-includes/js/tinymce/plugins/tabfocus/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/tabfocus/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/img/audio.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/img/image.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/img/media.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/img/page.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wordpress/img/video.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wpdialogs/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpdialogs/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpdialogs/js/popup.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpdialogs/js/popup.min.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpdialogs/js/wpdialog.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpdialogs/js/wpdialog.min.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/css/editimage.css create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/editimage.html create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/img/delete-2x.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/img/delete.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/img/image-2x.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/img/image.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpeditimage/js/editimage.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpfullscreen/css/wp-fullscreen.css create mode 100644 sources/wp-includes/js/tinymce/plugins/wpfullscreen/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpfullscreen/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/img/delete-2x.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/img/delete.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/img/edit-2x.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/img/edit.png create mode 100644 sources/wp-includes/js/tinymce/plugins/wpgallery/img/t.gif create mode 100644 sources/wp-includes/js/tinymce/plugins/wplink/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wplink/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpview/editor_plugin.js create mode 100644 sources/wp-includes/js/tinymce/plugins/wpview/editor_plugin_src.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/about.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/anchor.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/charmap.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/color_picker.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/editor_template.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/editor_template_src.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/image.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/colorpicker.jpg create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/flash.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/gotmoxie.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/icons.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/iframe.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/pagebreak.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/quicktime.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/realmedia.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/shockwave.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/trans.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/video.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/img/windowsmedia.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/about.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/anchor.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/charmap.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/color_picker.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/image.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/link.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/js/source_editor.js create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/link.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/shortcuts.htm create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/content.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/dialog.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/img/buttons.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/img/items.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/img/menu_arrow.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/img/menu_check.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/img/progress.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/img/tabs.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/default/ui.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/highcontrast/content.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/highcontrast/dialog.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/highcontrast/ui.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/content.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/dialog.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/img/button_bg.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/img/button_bg_black.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/img/button_bg_silver.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/ui.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/ui_black.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/o2k7/ui_silver.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/content.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/dialog.css create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/img/embedded.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/img/gallery.png create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/img/more_bug.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/img/page_bug.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/img/tabs.gif create mode 100644 sources/wp-includes/js/tinymce/themes/advanced/source_editor.htm create mode 100644 sources/wp-includes/js/tinymce/tiny_mce.js create mode 100644 sources/wp-includes/js/tinymce/tiny_mce_popup.js create mode 100644 sources/wp-includes/js/tinymce/utils/editable_selects.js create mode 100644 sources/wp-includes/js/tinymce/utils/form_utils.js create mode 100644 sources/wp-includes/js/tinymce/utils/mctabs.js create mode 100644 sources/wp-includes/js/tinymce/utils/validate.js create mode 100644 sources/wp-includes/js/tinymce/wp-mce-help.php create mode 100644 sources/wp-includes/js/tinymce/wp-tinymce-schema.js create mode 100644 sources/wp-includes/js/tinymce/wp-tinymce.js.gz create mode 100644 sources/wp-includes/js/tinymce/wp-tinymce.php create mode 100644 sources/wp-includes/js/tw-sack.js create mode 100644 sources/wp-includes/js/tw-sack.min.js create mode 100644 sources/wp-includes/js/underscore.min.js create mode 100644 sources/wp-includes/js/utils.js create mode 100644 sources/wp-includes/js/utils.min.js create mode 100644 sources/wp-includes/js/wp-ajax-response.js create mode 100644 sources/wp-includes/js/wp-ajax-response.min.js create mode 100644 sources/wp-includes/js/wp-auth-check.js create mode 100644 sources/wp-includes/js/wp-auth-check.min.js create mode 100644 sources/wp-includes/js/wp-backbone.js create mode 100644 sources/wp-includes/js/wp-backbone.min.js create mode 100644 sources/wp-includes/js/wp-list-revisions.js create mode 100644 sources/wp-includes/js/wp-list-revisions.min.js create mode 100644 sources/wp-includes/js/wp-lists.js create mode 100644 sources/wp-includes/js/wp-lists.min.js create mode 100644 sources/wp-includes/js/wp-pointer.js create mode 100644 sources/wp-includes/js/wp-pointer.min.js create mode 100644 sources/wp-includes/js/wp-util.js create mode 100644 sources/wp-includes/js/wp-util.min.js create mode 100644 sources/wp-includes/js/wplink.js create mode 100644 sources/wp-includes/js/wplink.min.js create mode 100644 sources/wp-includes/js/zxcvbn-async.js create mode 100644 sources/wp-includes/js/zxcvbn-async.min.js create mode 100644 sources/wp-includes/js/zxcvbn.min.js create mode 100644 sources/wp-includes/kses.php create mode 100644 sources/wp-includes/l10n.php create mode 100644 sources/wp-includes/link-template.php create mode 100644 sources/wp-includes/load.php create mode 100644 sources/wp-includes/locale.php create mode 100644 sources/wp-includes/media-template.php create mode 100644 sources/wp-includes/media.php create mode 100644 sources/wp-includes/meta.php create mode 100644 sources/wp-includes/ms-blogs.php create mode 100644 sources/wp-includes/ms-default-constants.php create mode 100644 sources/wp-includes/ms-default-filters.php create mode 100644 sources/wp-includes/ms-deprecated.php create mode 100644 sources/wp-includes/ms-files.php create mode 100644 sources/wp-includes/ms-functions.php create mode 100644 sources/wp-includes/ms-load.php create mode 100644 sources/wp-includes/ms-settings.php create mode 100644 sources/wp-includes/nav-menu-template.php create mode 100644 sources/wp-includes/nav-menu.php create mode 100644 sources/wp-includes/option.php create mode 100644 sources/wp-includes/pluggable-deprecated.php create mode 100644 sources/wp-includes/pluggable.php create mode 100644 sources/wp-includes/plugin.php create mode 100644 sources/wp-includes/pomo/entry.php create mode 100644 sources/wp-includes/pomo/mo.php create mode 100644 sources/wp-includes/pomo/po.php create mode 100644 sources/wp-includes/pomo/streams.php create mode 100644 sources/wp-includes/pomo/translations.php create mode 100644 sources/wp-includes/post-formats.php create mode 100644 sources/wp-includes/post-template.php create mode 100644 sources/wp-includes/post-thumbnail-template.php create mode 100644 sources/wp-includes/post.php create mode 100644 sources/wp-includes/query.php create mode 100644 sources/wp-includes/registration-functions.php create mode 100644 sources/wp-includes/registration.php create mode 100644 sources/wp-includes/revision.php create mode 100644 sources/wp-includes/rewrite.php create mode 100644 sources/wp-includes/rss-functions.php create mode 100644 sources/wp-includes/rss.php create mode 100644 sources/wp-includes/script-loader.php create mode 100644 sources/wp-includes/shortcodes.php create mode 100644 sources/wp-includes/taxonomy.php create mode 100644 sources/wp-includes/template-loader.php create mode 100644 sources/wp-includes/template.php create mode 100644 sources/wp-includes/theme-compat/comments-popup.php create mode 100644 sources/wp-includes/theme-compat/comments.php create mode 100644 sources/wp-includes/theme-compat/footer.php create mode 100644 sources/wp-includes/theme-compat/header.php create mode 100644 sources/wp-includes/theme-compat/sidebar.php create mode 100644 sources/wp-includes/theme.php create mode 100644 sources/wp-includes/update.php create mode 100644 sources/wp-includes/user.php create mode 100644 sources/wp-includes/vars.php create mode 100644 sources/wp-includes/version.php create mode 100644 sources/wp-includes/widgets.php create mode 100644 sources/wp-includes/wlwmanifest.xml create mode 100644 sources/wp-includes/wp-db.php create mode 100644 sources/wp-includes/wp-diff.php create mode 100644 sources/wp-links-opml.php create mode 100644 sources/wp-load.php create mode 100644 sources/wp-login.php create mode 100644 sources/wp-mail.php create mode 100644 sources/wp-settings.php create mode 100644 sources/wp-signup.php create mode 100644 sources/wp-trackback.php create mode 100644 sources/xmlrpc.php diff --git a/conf/nginx.conf b/conf/nginx.conf new file mode 100644 index 0000000..e929e8e --- /dev/null +++ b/conf/nginx.conf @@ -0,0 +1,16 @@ +location PATHTOCHANGE { + alias ALIASTOCHANGE; + if ($scheme = http) { + rewrite ^ https://$server_name$request_uri? permanent; + } + index index.php; + try_files $uri $uri/ /index.php?$args; + location ~ [^/]\.php(/|$) { + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + fastcgi_pass unix:/var/run/php5-fpm.sock; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param REMOTE_USER $remote_user; + fastcgi_param PATH_INFO $fastcgi_path_info; + } +} diff --git a/conf/wp-config.php b/conf/wp-config.php new file mode 100644 index 0000000..0d562a6 --- /dev/null +++ b/conf/wp-config.php @@ -0,0 +1,99 @@ +]P8)5%(S;4Jv;}5Hpi'); +define('LOGGED_IN_KEY', 'b(M|@_C*=RCx~~=X(-G|t{%3Up=h(Z|_UP&YA)]-d-js|VX3b1v1;NH[`#4L[EO='); +define('NONCE_KEY', 'XseL2lp5}2_?~s&EJ_Ut7{(VC-e4n$t_y(t}EpHKEy0`7<6'); +define('AUTH_SALT', '+M|psJjNE(>kpozF-%$PN7y=q+E5PE?f-QBN[|.q0]m|n(6@Yo@h03YW3p~|*G5g5vYmoci[t$ 9EqLKS4-~;W>y'); +define('LOGGED_IN_SALT', 'jgQ4 ~ 0f6|zS}Cd6<&y7?+iRU`woOK65|M-_+X.[r Ka 6l}1fiH-m$dN2t)BcH'); +define('NONCE_SALT', ';-FHEOgPbgx{{;Z19L7:v|f+9j-T5mv)g.L6-6_5KH|{-|p?G<}^rZ>$1qI/!wRb'); +/**#@-*/ + +/** + * Préfixe de base de données pour les tables de WordPress. + * + * Vous pouvez installer plusieurs WordPress sur une seule base de données + * si vous leur donnez chacune un préfixe unique. + * N'utilisez que des chiffres, des lettres non-accentuées, et des caractères soulignés! + */ +$table_prefix = 'wp_'; + +/** + * Langue de localisation de WordPress, par défaut en Anglais. + * + * Modifiez cette valeur pour localiser WordPress. Un fichier MO correspondant + * au langage choisi doit être installé dans le dossier wp-content/languages. + * Par exemple, pour mettre en place une traduction française, mettez le fichier + * fr_FR.mo dans wp-content/languages, et réglez l'option ci-dessous à "fr_FR". + */ +define('WPLANG', 'fr_FR'); + +/** + * Pour les développeurs : le mode deboguage de WordPress. + * + * En passant la valeur suivante à "true", vous activez l'affichage des + * notifications d'erreurs pendant votre essais. + * Il est fortemment recommandé que les développeurs d'extensions et + * de thèmes se servent de WP_DEBUG dans leur environnement de + * développement. + */ +define('WP_DEBUG', false); + +/* C'est tout, ne touchez pas à ce qui suit ! Bon blogging ! */ + +/** Chemin absolu vers le dossier de WordPress. */ +if ( !defined('ABSPATH') ) + define('ABSPATH', dirname(__FILE__) . '/'); + +/** Réglage des variables de WordPress et de ses fichiers inclus. */ +require_once(ABSPATH . 'wp-settings.php'); diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..34f0e5c --- /dev/null +++ b/manifest.json @@ -0,0 +1,42 @@ +{ + "name": "Wordpress", + "id": "wordpress", + "description": { + "en": "WordPress is web software you can use to create a beautiful website or blog", + "fr": "Outils de création de Blog ou de site web" + }, + "developer": { + "name": "beudbeud", + "email": "beudbeud@beudibox.Fr", + "url": "http://wordpress.org/" + }, + "multi_instance": "true", + "arguments": { + "install" : [ + { + "name": "domain", + "ask": { + "en": "Choose a domain for Wordpress" + }, + "example": "domain.org" + }, + { + "name": "path", + "ask": { + "en": "Choose a path for Wordpress" + }, + "example": "/blog", + "default": "" + }, + { + "name": "admin_passwd", + "ask": { + "en": "Choose a password for Wordpress administrator" + }, + "example": "", + "default": "" + } + + ] + } +} diff --git a/scripts/install b/scripts/install new file mode 100755 index 0000000..2354b60 --- /dev/null +++ b/scripts/install @@ -0,0 +1,45 @@ +#!/bin/bash + +# Retrieve arguments +domain=$1 +path=$2 +admin_passwd=$3 + +# Check domain/path availability +sudo yunohost app checkurl $domain$path -a wordpress +if [[ ! $? -eq 0 ]]; then + exit 1 +fi + +# Use 'wordpress' as database name and user +db_user=wordpress + +# Initialize database and store mysql password for upgrade +sudo yunohost app initdb $db_user -p $db_pwd) +sudo yunohost app setting wordpress mysqlpwd -v $db_pwd + +# Copy files to the right place +final_path=/var/www/wordpress +sudo mkdir -p $final_path +sudo cp -a ../sources/* $final_path +sudo cp ../conf/wp-config.php $final_path/config/ + +# Change variables in Wordpress configuration +sudo sed -i "s/yunouser/$db_user/g" $final_path/wp-config.php +sudo sed -i "s/yunopass/$db_pwd/g" $final_path/wp-config.php +sudo sed -i "s/yunobase/$db_user/g" $final_path/wp-config.php + +# Set permissions to roundcube directory +sudo chown -R www-data: $final_path + +#Installation Wordpress +curl -X POST -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:12.0) Gecko/20100101 Firefox/12.0" -e "http://dev.example.com/yeshello/wp-admin/install.php?step=2" -H "Content-Type:application/x-www-form-urlencoded" -H "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" -H "Accept-Encoding:gzip, deflate" --data "?step=2&weblog_title=yeshello&user_name=admin&admin_password=admin&admin_password2=admin&admin_email=mathias%40example.com&Submit=Install+WordPress" http://$domain$path/wp-admin/install.php?step=2&weblog_title=Yunohost&user_name=admin&admin_password=$admin_passwd&admin_password2=$admin_passwd&admin_email=admin@$domain&Submit=Install+WordPress + +# Modify Nginx configuration file and copy it to Nginx conf directory +sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf +sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf +sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/wordpress.conf + +# Reload Nginx and regenerate SSOwat conf +sudo service nginx reload +sudo yunohost app ssowatconf diff --git a/scripts/remove b/scripts/remove new file mode 100755 index 0000000..ba51622 --- /dev/null +++ b/scripts/remove @@ -0,0 +1,10 @@ +#!/bin/bash + +db_user=wordpress +db_name=wordpress +root_pwd=$(sudo cat /etc/yunohost/mysql) +domain=$(sudo yunohost app setting wordpress domain) + +mysql -u root -p$root_pwd -e "DROP DATABASE $db_name ; DROP USER $db_user ;" +sudo rm -rf /var/www/wordpress +sudo rm -f /etc/nginx/conf.d/$domain.d/wordpress.conf diff --git a/sources/index.php b/sources/index.php new file mode 100644 index 0000000..dd3d554 --- /dev/null +++ b/sources/index.php @@ -0,0 +1,17 @@ + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + +WRITTEN OFFER + +The source code for any program binaries or compressed scripts that are +included with WordPress can be freely obtained at the following URL: + + http://wordpress.org/download/source/ diff --git a/sources/readme.html b/sources/readme.html new file mode 100644 index 0000000..1416aea --- /dev/null +++ b/sources/readme.html @@ -0,0 +1,93 @@ + + + + + WordPress › À lire + + + +

+ WordPress +
Version 3.7 + +

+

Plateforme de publication sémantique personnelle

+ +

Préambule

+

Bienvenue. WordPress est un projet très spécial pour moi. Chaque développeur et contributeur ajoute quelque chose d'unique à ce projet, et ensemble nous créons quelque chose de beau, et dont je suis fier de faire partie. Nous avons passé des milliers d'heures sur le développement de WordPress, et nous nous attachons tous les jours à vous faciliter la vie. Merci à vous d'en faire une partie de votre monde.

+

— Matt Mullenweg

+ +

Installation : la fameuse installation en 5 minutes

+
    +
  1. Décompressez l'archive dans un dossier vide de votre ordinateur, puis mettez tous ces fichiers en ligne ;
  2. +
  3. Ouvrez le fichier wp-config-sample.php avec votre éditeur de texte préféré, comme WordPad ou similaire, et complétez les informations liées à votre base de données ;
  4. +
  5. Sauvegardez le fichier sous le nom wp-config.php ;
  6. +
  7. Envoyez le tout sur votre hébergement via un logiciel client FTP ;
  8. +
  9. Ouvrez le fichier /wp-admin/install.php dans votre navigateur. Celui-ci vous guidera dans la création du fichier wp-config.php, qui contient les détails de connexion à votre base de données ; +
      +
    1. Si cela ne marchait pas, ne vous inquiétez pas : certains hébergeurs n'autorisent pas la création de fichier. Ouvrez le fichier wp-config.php avec un éditeur de texte, et saisissez-y directement les détails de connexion à votre base de données ;
    2. +
    3. Enregistrez le fichier sous le nom wp-config.php et mettez-le en ligne ;
    4. +
    5. Ouvrez le fichier wp-admin/install.php dans votre navigateur ;
    6. +
    +
  10. +
  11. Une fois le fichier de configuration correctement rempli, l'installateur met en place les tables nécessaires à votre blog. Si vous obtenez une erreur, vérifiez le contenu du fichier wp-config.php, et réessayez. Si cela échoue encore une fois, rendez-vous sur les forums d'entraide et soyez le plus précis possible dans vos explications. Si tout se passe bien, passez à l'étape suivante ;
  12. +
  13. Si vous n'avez pas précisé de mot de passe, notez bien celui qui vous est donné. Si vous n'avez pas précisé d'identifiant utilisateur, ce sera admin ;
  14. +
  15. Une fois l'installation terminée, le script d'installation vous renverra vers la page de connexion. Connectez-vous avec l'identifiant et le mot de passe précisés (ou générés) durant l'installation. Si le mot de passe a été généré pour vous, cliquez sur "Profil" pour le modifier.
  16. +
+ +

Mise à jour

+

A l'aide de l'outil de mise à jour automatique

+

Si votre version de WordPress est égale ou supérieure à 2.7, vous pouvez utiliser l'outil de mise à jour automatique :

+
    +
  1. Ouvrez la page wp-admin/update-core.php dans votre navigateur, et suivez les instructions ;
  2. +
  3. Vous pensiez qu'il y aurait d'autres étapes ? C'est tout !
  4. +
+ +

Mise à jour manuelle (obligatoire pour les versions de WordPress inférieures à 2.7) :

+
    +
  1. Avant tout, assurez-vous bien de disposer de copies de sauvegarde de tous les fichiers que vous avez modifiés, par exemple index.php.
  2. +
  3. Effacez vos anciens fichiers WordPress, sauf ceux que vous avez modifié, comme wp-config.php ou le contenu du dossier /wp-content/.
  4. +
  5. Mettez en ligne les nouveaux fichiers en provenance de l'archive de WordPress.
  6. +
  7. Allez sur la page /wp-admin/upgrade.php avec votre navigateur internet.
  8. +
+ +

Migrer depuis d'autres logiciels/plates-formes

+

WordPress peut importer les articles en provenance de nombreux autres outils (en). Vous devez d'abord installer WordPress comme expliqué plus haut, puis utiliser un des importateurs.

+ +

Prérequis fonctionnels

+
    +
  • PHP version 5.2.4 ou plus ;
  • +
  • MySQL version 5.0 ou plus.
  • +
+ +

Ressources en ligne

+

Si vous vous posez des questions dont les réponses ne figurent pas sur ce document, vous disposez de nombreuses ressources en ligne :

+
+
Le Codex WordPress
+
Le Codex est l'encyclopédie liée à tout le fonctionnement de WordPress. Il s'agit de la source d'informations la plus complète qui soit.
+
Le blog de WordPress
+
C'est ici que vous trouverez les dernières informations, les annonces et les nouveautés de WordPress. Les derniers articles de ce blog sont affichés dans le Tableau de Bord de WordPress par défaut.
+
Planète WordPress
+
La Planète WordPress est un agrégateur de news qui distille les articles de plusieurs blogs WordPress à travers le web.
+
Support WordPress Francophone
+
Si vous avez cherché partout et que malgré cela vous n'avez trouvé aucune réponse, les forums sont très actifs et son immense communauté sera prête à vous aider. Pour un traitement efficace de votre problème, faites en sorte d'utiliser, lors de la création de votre sujet, un titre et une description aussi pertinents et clairs que possible.
+
Canal IRC WordPress
+
Il existe un canal IRC qui est le rendez-vous des utilisateurs WordPress, et occasionnellement, propose son aide aux sujets liés au support. La page Wiki devrait vous indiquer la bonne direction.
+
+ +

Pour finir

+
    +
  • Si vous avez des suggestions, des idées, des commentaires ou si (oups !) avez trouvé un bug, venez nous rejoindre sur les forums anglophones.
  • +
  • WordPress possède une API d'extension robuste, qui permet d'étendre les possibilités de son code de manière simple. Si vous êtes un développeur intéressé par son utilisation, rendez-vous sur la documentation des extensions sur le Codex. Vous ne devriez pas avoir à modifier une partie du code original.
  • +
+ +

Faites connaître WordPress !

+

WordPress ne possède pas une kyrielle de millions de dollars pour s'offrir une campagne marketing, ni de célèbres sponsors, mais nous avons bien mieux : VOUS. Si vous appréciez WordPress, n'hésitez pas à en parler à votre entourage, vos amis, en aidant d'autres personnes ayant un niveau inférieur au vôtre, ou encore écrire un article faisant référence à notre travail.

+ +

WordPress est la reprise officielle de b2/cafélog, provenant de Michel V. Le travail a continué d'être assuré par les développeurs WordPress. Si vous voulez apporter votre soutien à WordPress, n'hésitez pas à faire un don.

+ +

Licence

+

WordPress est un logiciel libre, mis à disposition sous les termes de la licence GPL version 2, ou de toute version suivante, au choix (voir license.txt (en anglais)).

+ + + \ No newline at end of file diff --git a/sources/wp-activate.php b/sources/wp-activate.php new file mode 100644 index 0000000..226780c --- /dev/null +++ b/sources/wp-activate.php @@ -0,0 +1,132 @@ +cache_enabled = false; + +// Fix for page title +$wp_query->is_404 = false; + +/** + * Fires before the Site Activation page is loaded. + * + * @since 3.0 + */ +do_action( 'activate_header' ); + +/** + * Adds an action hook specific to this page that fires on wp_head + * + * @since MU + */ +function do_activate_header() { + /** + * Fires before the Site Activation page is loaded, but on the wp_head action. + * + * @since 3.0 + */ + do_action( 'activate_wp_head' ); +} +add_action( 'wp_head', 'do_activate_header' ); + +/** + * Loads styles specific to this page. + * + * @since MU + */ +function wpmu_activate_stylesheet() { + ?> + + + +
+ + +

+
+

+ +
+

+

+ +

+
+ + get_error_code() || 'blog_taken' == $result->get_error_code() ) { + $signup = $result->get_error_data(); + ?> +

+ '; + if ( $signup->domain . $signup->path == '' ) { + printf( __('Your account has been activated. You may now log in to the site using your chosen username of “%2$s”. Please check your email inbox at %3$s for your password and login instructions. If you do not receive an email, please check your junk or spam folder. If you still do not receive an email within an hour, you can reset your password.'), network_site_url( 'wp-login.php', 'login' ), $signup->user_login, $signup->user_email, wp_lostpassword_url() ); + } else { + printf( __('Your site at %2$s is active. You may now log in to your site using your chosen username of “%3$s”. Please check your email inbox at %4$s for your password and login instructions. If you do not receive an email, please check your junk or spam folder. If you still do not receive an email within an hour, you can reset your password.'), 'http://' . $signup->domain, $signup->domain, $signup->user_login, $signup->user_email, wp_lostpassword_url() ); + } + echo '

'; + } else { + ?> +

+ '.$result->get_error_message().'

'; + } + } else { + extract($result); + $url = get_blogaddress_by_id( (int) $blog_id); + $user = get_userdata( (int) $user_id); + ?> +

+ +
+

user_login ?>

+

+
+ + +

View your site or Log in'), $url, $url . 'wp-login.php' ); ?>

+ +

Log in or go back to the homepage.' ), network_site_url('wp-login.php', 'login'), network_home_url() ); ?>

+ +
+ + diff --git a/sources/wp-admin/about.php b/sources/wp-admin/about.php new file mode 100644 index 0000000..c0ef6c6 --- /dev/null +++ b/sources/wp-admin/about.php @@ -0,0 +1,181 @@ + +
+ +

+ +
+ +
+ + + +
+

+

Version %1$s addressed %2$s bug.', + 'Version %1$s addressed %2$s bugs.', 11 ), '3.7.1', number_format_i18n( 11 ) ); ?> + the release notes.' ), 'http://codex.wordpress.org/Version_3.7.1' ); ?> +

+
+ +
+

+ +
+
+

+

+
+
+ +
+
+

+

+

+
+ $wp_version . '.1.next.minor', + 'version' => $wp_version . '.1.next.minor', + 'php_version' => $required_php_version, + 'mysql_version' => $required_mysql_version, + ); + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + $updater = new WP_Automatic_Updater; + $can_auto_update = wp_http_supports( array( 'ssl' ) ) && $updater->should_update( 'core', $future_minor_update, ABSPATH ); + + if ( $can_auto_update ) { + echo '

' . __( 'This site is able to apply these updates automatically. Cool!' ). '

'; + + // If the updater is disabled entirely, don't show them anything. + } elseif ( ! $updater->is_disabled() ) { + echo '

'; + // If this is is filtered to false, they won't get emails, so don't claim we will. + // Assumption: If the user can update core, they can see what the admin email is. + + /** This filter is documented in wp-admin/includes/class-wp-upgrader.php */ + if ( apply_filters( 'send_core_update_notification_email', true, $future_minor_update ) ) { + printf( __( 'This site is not able to apply these updates automatically. But we’ll email %s when there is a new security release.' ), esc_html( get_site_option( 'admin_email' ) ) ); + } else { + _e( 'This site is not able to apply these updates automatically.' ); + } + echo '

'; + } + } + ?> +
+
+ +
+

+ +
+
+

+

+
+
+ +

+ change your password?' ), esc_url( self_admin_url( 'profile.php' ) ) ); ?> +
+
+
+ +
+
+
+

+

+
+
+

+

+
+
+
+ +
+

+ +
+
+

+

+
+
+

+

+
+
+

+

wp_get_sites() allows developers to easily get an array of all the sites on your network without resorting to a direct database query — just one of many improvements to multisite in WordPress 3.7.' ); ?>

+
+
+ +
+ + | + + +
+ +
+Version %1$s addressed a security issue.', + 'Version %1$s addressed some security issues.' ); + +/* translators: 1: WordPress version number, 2: plural number of bugs. */ +_n_noop( 'Version %1$s addressed %2$s bug.', + 'Version %1$s addressed %2$s bugs.' ); + +/* translators: 1: WordPress version number, 2: plural number of bugs. Singular security issue. */ +_n_noop( 'Version %1$s addressed a security issue and fixed %2$s bug.', + 'Version %1$s addressed a security issue and fixed %2$s bugs.' ); + +/* translators: 1: WordPress version number, 2: plural number of bugs. More than one security issue. */ +_n_noop( 'Version %1$s addressed some security issues and fixed %2$s bug.', + 'Version %1$s addressed some security issues and fixed %2$s bugs.' ); + +__( 'For more information, see the release notes.' ); diff --git a/sources/wp-admin/admin-ajax.php b/sources/wp-admin/admin-ajax.php new file mode 100644 index 0000000..b220d33 --- /dev/null +++ b/sources/wp-admin/admin-ajax.php @@ -0,0 +1,94 @@ + + +
+
+
+ + + + +
+ + + diff --git a/sources/wp-admin/admin-functions.php b/sources/wp-admin/admin-functions.php new file mode 100644 index 0000000..f596749 --- /dev/null +++ b/sources/wp-admin/admin-functions.php @@ -0,0 +1,15 @@ +site_name ) ); +elseif ( is_user_admin() ) + $admin_title = sprintf( __('Global Dashboard: %s'), esc_html( $current_site->site_name ) ); +else + $admin_title = get_bloginfo( 'name' ); + +if ( $admin_title == $title ) + $admin_title = sprintf( __( '%1$s — WordPress' ), $title ); +else + $admin_title = sprintf( __( '%1$s ‹ %2$s — WordPress' ), $title, $admin_title ); + +/** + * Filter the content for an admin page. + * + * @since 3.1.0 + * + * @param string $admin_title The page title, with extra context added. + * @param string $title The original page title. + */ +$admin_title = apply_filters( 'admin_title', $admin_title, $title ); + +wp_user_settings(); + +_wp_admin_html_begin(); +?> +<title><?php echo $admin_title; ?> + + + for a specific admin page based on $hook_suffix. + * + * @since 2.1.0 + */ +do_action( "admin_head-$hook_suffix" ); + +/** + * Fires in for all admin pages. + * + * @since 2.1.0 + */ +do_action( 'admin_head' ); + +if ( get_user_setting('mfold') == 'f' ) + $admin_body_class .= ' folded'; + +if ( !get_user_setting('unfold') ) + $admin_body_class .= ' auto-fold'; + +if ( is_admin_bar_showing() ) + $admin_body_class .= ' admin-bar'; + +if ( is_rtl() ) + $admin_body_class .= ' rtl'; + +if ( $current_screen->post_type ) + $admin_body_class .= ' post-type-' . $current_screen->post_type; + +if ( $current_screen->taxonomy ) + $admin_body_class .= ' taxonomy-' . $current_screen->taxonomy; + +$admin_body_class .= ' branch-' . str_replace( array( '.', ',' ), '-', floatval( $wp_version ) ); +$admin_body_class .= ' version-' . str_replace( '.', '-', preg_replace( '/^([.0-9]+).*/', '$1', $wp_version ) ); +$admin_body_class .= ' admin-color-' . sanitize_html_class( get_user_option( 'admin_color' ), 'fresh' ); +$admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) ); + +if ( wp_is_mobile() ) + $admin_body_class .= ' mobile'; + +$admin_body_class .= ' no-customize-support'; + +?> + + CSS classes. + * + * This filter differs from the post_class or body_class filters in two important ways: + * 1. $classes is a space-separated string of class names instead of an array. + * 2. Not all core admin classes are filterable, notably: wp-admin, wp-core-ui, and no-js cannot be removed. + * + * @since 2.3.0 + * + * @param string $classes Space-separated string of CSS classes. + */ +?> +"> + + + + +
+ + +
+ + + +
+set_parentage( $parent_file ); + +?> + +
+render_screen_meta(); + +if ( is_network_admin() ) { + /** + * Print network admin screen notices. + * + * @since 3.1.0 + */ + do_action( 'network_admin_notices' ); +} elseif ( is_user_admin() ) { + /** + * Print user admin screen notices. + * + * @since 3.1.0 + */ + do_action( 'user_admin_notices' ); +} else { + /** + * Print admin screen notices. + * + * @since 3.1.0 + */ + do_action( 'admin_notices' ); +} + +/** + * Print generic admin screen notices. + * + * @since 3.1.0 + */ +do_action( 'all_admin_notices' ); + +if ( $parent_file == 'options-general.php' ) + require(ABSPATH . 'wp-admin/options-head.php'); diff --git a/sources/wp-admin/admin-post.php b/sources/wp-admin/admin-post.php new file mode 100644 index 0000000..7103994 --- /dev/null +++ b/sources/wp-admin/admin-post.php @@ -0,0 +1,45 @@ + 50 && mt_rand( 0, (int)( $c / 50 ) ) == 1 ) ) { + require_once( ABSPATH . WPINC . '/http.php' ); + $response = wp_remote_get( admin_url( 'upgrade.php?step=1' ), array( 'timeout' => 120, 'httpversion' => '1.1' ) ); + /** + * Fires after the multisite DB upgrade is complete. + * + * @since 3.0.0 + * + * @param array|WP_Error $response The upgrade response array or WP_Error on failure. + */ + do_action( 'after_mu_upgrade', $response ); + unset($response); + } + unset($c); + } +} + +require_once(ABSPATH . 'wp-admin/includes/admin.php'); + +auth_redirect(); + +// Schedule trash collection +if ( !wp_next_scheduled('wp_scheduled_delete') && !defined('WP_INSTALLING') ) + wp_schedule_event(time(), 'daily', 'wp_scheduled_delete'); + +set_screen_options(); + +$date_format = get_option('date_format'); +$time_format = get_option('time_format'); + +wp_enqueue_script( 'common' ); + +$editing = false; + +if ( isset($_GET['page']) ) { + $plugin_page = wp_unslash( $_GET['page'] ); + $plugin_page = plugin_basename($plugin_page); +} + +if ( isset( $_REQUEST['post_type'] ) && post_type_exists( $_REQUEST['post_type'] ) ) + $typenow = $_REQUEST['post_type']; +else + $typenow = ''; + +if ( isset( $_REQUEST['taxonomy'] ) && taxonomy_exists( $_REQUEST['taxonomy'] ) ) + $taxnow = $_REQUEST['taxonomy']; +else + $taxnow = ''; + +if ( WP_NETWORK_ADMIN ) + require(ABSPATH . 'wp-admin/network/menu.php'); +elseif ( WP_USER_ADMIN ) + require(ABSPATH . 'wp-admin/user/menu.php'); +else + require(ABSPATH . 'wp-admin/menu.php'); + +if ( current_user_can( 'manage_options' ) ) { + /** + * Filter the maximum memory limit available for administration screens. + * + * This only applies to administrators, who may require more memory for tasks like updates. + * Memory limits when processing images (uploaded or edited by users of any role) are + * handled separately. + * + * The WP_MAX_MEMORY_LIMIT constant specifically defines the maximum memory limit available + * when in the administration back-end. The default is 256M, or 256 megabytes of memory. + * + * @since 3.0.0 + * + * @param string 'WP_MAX_MEMORY_LIMIT' The maximum WordPress memory limit. Default 256M. + */ + @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); +} + +/** + * Fires as an admin screen or script is being initialized. + * + * Note, this does not just run on user-facing admin screens. + * It runs on admin-ajax.php and admin-post.php as well. + * + * This is roughly analgous to the more general 'init' hook, which fires earlier. + * + * @since 2.5.0 + */ +do_action( 'admin_init' ); + +if ( isset($plugin_page) ) { + if ( !empty($typenow) ) + $the_parent = $pagenow . '?post_type=' . $typenow; + else + $the_parent = $pagenow; + if ( ! $page_hook = get_plugin_page_hook($plugin_page, $the_parent) ) { + $page_hook = get_plugin_page_hook($plugin_page, $plugin_page); + // backwards compatibility for plugins using add_management_page + if ( empty( $page_hook ) && 'edit.php' == $pagenow && '' != get_plugin_page_hook($plugin_page, 'tools.php') ) { + // There could be plugin specific params on the URL, so we need the whole query string + if ( !empty($_SERVER[ 'QUERY_STRING' ]) ) + $query_string = $_SERVER[ 'QUERY_STRING' ]; + else + $query_string = 'page=' . $plugin_page; + wp_redirect( admin_url('tools.php?' . $query_string) ); + exit; + } + } + unset($the_parent); +} + +$hook_suffix = ''; +if ( isset($page_hook) ) + $hook_suffix = $page_hook; +else if ( isset($plugin_page) ) + $hook_suffix = $plugin_page; +else if ( isset($pagenow) ) + $hook_suffix = $pagenow; + +set_current_screen(); + +// Handle plugin admin pages. +if ( isset($plugin_page) ) { + if ( $page_hook ) { + /** + * Fires before a particular screen is loaded. + * + * The load-* hook fires in a number of contexts. This hook is for plugin screens + * where a callback is provided when the screen is registered. + * + * The dynamic portion of the hook name, $page_hook, refers to a mixture of plugin + * page information including: + * 1. The page type. If the plugin page is registered as a submenu page, such as for + * Settings, the page type would be 'settings'. Otherwise the type is 'toplevel'. + * 2. A separator of '_page_'. + * 3. The plugin basename minus the file extension. + * + * Together, the three parts form the $page_hook. Citing the example above, + * the hook name used would be 'load-settings_page_pluginbasename'. + * + * @see get_plugin_page_hook() + * + * @since 2.1.0 + */ + do_action( 'load-' . $page_hook ); + if (! isset($_GET['noheader'])) + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + /** + * Used to call the registered callback for a plugin screen. + * + * @access private + * + * @since 1.5.0 + */ + do_action( $page_hook ); + } else { + if ( validate_file($plugin_page) ) + wp_die(__('Invalid plugin page')); + + if ( !( file_exists(WP_PLUGIN_DIR . "/$plugin_page") && is_file(WP_PLUGIN_DIR . "/$plugin_page") ) && !( file_exists(WPMU_PLUGIN_DIR . "/$plugin_page") && is_file(WPMU_PLUGIN_DIR . "/$plugin_page") ) ) + wp_die(sprintf(__('Cannot load %s.'), htmlentities($plugin_page))); + + /** + * Fires before a particular screen is loaded. + * + * The load-* hook fires in a number of contexts. This hook is for plugin screens + * where the file to load is directly included, rather than the use of a function. + * + * The dynamic portion of the hook name, $plugin_page, refers to the plugin basename. + * + * @see plugin_basename() + * + * @since 1.5.0 + */ + do_action( 'load-' . $plugin_page ); + + if ( !isset($_GET['noheader'])) + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + if ( file_exists(WPMU_PLUGIN_DIR . "/$plugin_page") ) + include(WPMU_PLUGIN_DIR . "/$plugin_page"); + else + include(WP_PLUGIN_DIR . "/$plugin_page"); + } + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + exit(); +} else if (isset($_GET['import'])) { + + $importer = $_GET['import']; + + if ( ! current_user_can('import') ) + wp_die(__('You are not allowed to import.')); + + if ( validate_file($importer) ) { + wp_redirect( admin_url( 'import.php?invalid=' . $importer ) ); + exit; + } + + if ( ! isset($wp_importers[$importer]) || ! is_callable($wp_importers[$importer][2]) ) { + wp_redirect( admin_url( 'import.php?invalid=' . $importer ) ); + exit; + } + + /** + * Fires before an importer screen is loaded. + * + * The dynamic portion of the hook name, $importer, refers to the importer slug. + * + * @since 3.5.0 + */ + do_action( 'load-importer-' . $importer ); + + $parent_file = 'tools.php'; + $submenu_file = 'import.php'; + $title = __('Import'); + + if (! isset($_GET['noheader'])) + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + + define('WP_IMPORTING', true); + + /** + * Whether to filter imported data through kses on import. + * + * Multisite uses this hook to filter all data through kses by default, + * as a super administrator may be assisting an untrusted user. + * + * @since 3.1.0 + * + * @param bool false Whether to force data to be filtered through kses. Default false. + */ + if ( apply_filters( 'force_filtered_html_on_import', false ) ) + kses_init_filters(); // Always filter imported data with kses on multisite. + + call_user_func($wp_importers[$importer][2]); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + // Make sure rules are flushed + flush_rewrite_rules(false); + + exit(); +} else { + /** + * Fires before a particular screen is loaded. + * + * The load-* hook fires in a number of contexts. This hook is for core screens. + * + * The dynamic portion of the hook name, $pagenow, is a global variable + * referring to the filename of the current page, such as 'admin.php', + * 'post-new.php' etc. A complete hook for the latter would be 'load-post-new.php'. + * + * @since 2.1.0 + */ + do_action( 'load-' . $pagenow ); + // Backwards compatibility with old load-page-new.php, load-page.php, + // and load-categories.php actions. + if ( $typenow == 'page' ) { + if ( $pagenow == 'post-new.php' ) + do_action( 'load-page-new.php' ); + elseif ( $pagenow == 'post.php' ) + do_action( 'load-page.php' ); + } elseif ( $pagenow == 'edit-tags.php' ) { + if ( $taxnow == 'category' ) + do_action( 'load-categories.php' ); + elseif ( $taxnow == 'link_category' ) + do_action( 'load-edit-link-categories.php' ); + } +} + +if ( ! empty( $_REQUEST['action'] ) ) { + /** + * Fires when an 'action' request variable is sent. + * + * The dynamic portion of the hook name, $_REQUEST['action'], + * refers to the action derived from the GET or POST request. + * + * @since 2.6.0 + */ + do_action( 'admin_action_' . $_REQUEST['action'] ); +} diff --git a/sources/wp-admin/async-upload.php b/sources/wp-admin/async-upload.php new file mode 100644 index 0000000..3a24b52 --- /dev/null +++ b/sources/wp-admin/async-upload.php @@ -0,0 +1,98 @@ +post_type ) + wp_die( __( 'Unknown post type.' ) ); + if ( ! current_user_can( 'edit_post', $id ) ) + wp_die( __( 'You are not allowed to edit this item.' ) ); + + switch ( $_REQUEST['fetch'] ) { + case 3 : + if ( $thumb_url = wp_get_attachment_image_src( $id, 'thumbnail', true ) ) + echo ''; + echo '' . _x( 'Edit', 'media item' ) . ''; + $title = $post->post_title ? $post->post_title : wp_basename( $post->guid ); // title shouldn't ever be empty, but use filename just in cas.e + echo '
' . esc_html( wp_html_excerpt( $title, 60, '…' ) ) . '
'; + break; + case 2 : + add_filter('attachment_fields_to_edit', 'media_single_attachment_fields_to_edit', 10, 2); + echo get_media_item($id, array( 'send' => false, 'delete' => true )); + break; + default: + add_filter('attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2); + echo get_media_item($id); + break; + } + exit; +} + +check_admin_referer('media-form'); + +$post_id = 0; +if ( isset( $_REQUEST['post_id'] ) ) { + $post_id = absint( $_REQUEST['post_id'] ); + if ( ! get_post( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) + $post_id = 0; +} + +$id = media_handle_upload( 'async-upload', $post_id ); +if ( is_wp_error($id) ) { + echo '
+ ' . __('Dismiss') . ' + ' . sprintf(__('“%s” has failed to upload due to an error'), esc_html($_FILES['async-upload']['name']) ) . '
' . + esc_html($id->get_error_message()) . '
'; + exit; +} + +if ( $_REQUEST['short'] ) { + // short form response - attachment ID only + echo $id; +} else { + // long form response - big chunk o html + $type = $_REQUEST['type']; + echo apply_filters("async_upload_{$type}", $id); +} diff --git a/sources/wp-admin/comment.php b/sources/wp-admin/comment.php new file mode 100644 index 0000000..c2d57f0 --- /dev/null +++ b/sources/wp-admin/comment.php @@ -0,0 +1,303 @@ +

$msg

"; + include( ABSPATH . 'wp-admin/admin-footer.php' ); + die; +} + +switch( $action ) { + +case 'editcomment' : + $title = __('Edit Comment'); + + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

' . __( 'You can edit the information left in a comment if needed. This is often useful when you notice that a commenter has made a typographical error.' ) . '

' . + '

' . __( 'You can also moderate the comment from this screen using the Status box, where you can also change the timestamp of the comment.' ) . '

' + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __( 'For more information:' ) . '

' . + '

' . __( 'Documentation on Comments' ) . '

' . + '

' . __( 'Support Forums' ) . '

' + ); + + wp_enqueue_script('comment'); + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + + $comment_id = absint( $_GET['c'] ); + + if ( !$comment = get_comment( $comment_id ) ) + comment_footer_die( __('Oops, no comment with this ID.') . sprintf(' ' . __('Go back') . '.', 'javascript:history.go(-1)') ); + + if ( !current_user_can( 'edit_comment', $comment_id ) ) + comment_footer_die( __('You are not allowed to edit this comment.') ); + + if ( 'trash' == $comment->comment_approved ) + comment_footer_die( __('This comment is in the Trash. Please move it out of the Trash if you want to edit it.') ); + + $comment = get_comment_to_edit( $comment_id ); + + include( ABSPATH . 'wp-admin/edit-form-comment.php' ); + + break; + +case 'delete' : +case 'approve' : +case 'trash' : +case 'spam' : + + $title = __('Moderate Comment'); + + $comment_id = absint( $_GET['c'] ); + + if ( !$comment = get_comment_to_edit( $comment_id ) ) { + wp_redirect( admin_url('edit-comments.php?error=1') ); + die(); + } + + if ( !current_user_can( 'edit_comment', $comment->comment_ID ) ) { + wp_redirect( admin_url('edit-comments.php?error=2') ); + die(); + } + + // No need to re-approve/re-trash/re-spam a comment. + if ( $action == str_replace( '1', 'approve', $comment->comment_approved ) ) { + wp_redirect( admin_url( 'edit-comments.php?same=' . $comment_id ) ); + die(); + } + + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + + $formaction = $action . 'comment'; + $nonce_action = 'approve' == $action ? 'approve-comment_' : 'delete-comment_'; + $nonce_action .= $comment_id; + +?> +
+ +
+ + +

+ +comment_approved != '0' ) { // if not unapproved + $message = ''; + switch ( $comment->comment_approved ) { + case '1' : + $message = __('This comment is currently approved.'); + break; + case 'spam' : + $message = __('This comment is currently marked as spam.'); + break; + case 'trash' : + $message = __('This comment is currently in the Trash.'); + break; + } + if ( $message ) + echo '

' . $message . '

'; +} +?> +

+ + + + + + +comment_author_email ) { ?> + + + + + +comment_author_url ) { ?> + + + + + + + + + +
comment_author; ?>
comment_author_email; ?>
comment_author_url; ?>
comment_content; ?>
+ +

+ +
+ + + + + + +
+ + + + + +
+ +
+
+' . __('Go back') . '.', 'edit-comments.php') ); + if ( !current_user_can( 'edit_comment', $comment->comment_ID ) ) + comment_footer_die( __('You are not allowed to edit comments on this post.') ); + + if ( '' != wp_get_referer() && ! $noredir && false === strpos(wp_get_referer(), 'comment.php') ) + $redir = wp_get_referer(); + elseif ( '' != wp_get_original_referer() && ! $noredir ) + $redir = wp_get_original_referer(); + elseif ( in_array( $action, array( 'approvecomment', 'unapprovecomment' ) ) ) + $redir = admin_url('edit-comments.php?p=' . absint( $comment->comment_post_ID ) ); + else + $redir = admin_url('edit-comments.php'); + + $redir = remove_query_arg( array('spammed', 'unspammed', 'trashed', 'untrashed', 'deleted', 'ids', 'approved', 'unapproved'), $redir ); + + switch ( $action ) { + case 'deletecomment' : + wp_delete_comment( $comment_id ); + $redir = add_query_arg( array('deleted' => '1'), $redir ); + break; + case 'trashcomment' : + wp_trash_comment($comment_id); + $redir = add_query_arg( array('trashed' => '1', 'ids' => $comment_id), $redir ); + break; + case 'untrashcomment' : + wp_untrash_comment($comment_id); + $redir = add_query_arg( array('untrashed' => '1'), $redir ); + break; + case 'spamcomment' : + wp_spam_comment($comment_id); + $redir = add_query_arg( array('spammed' => '1', 'ids' => $comment_id), $redir ); + break; + case 'unspamcomment' : + wp_unspam_comment($comment_id); + $redir = add_query_arg( array('unspammed' => '1'), $redir ); + break; + case 'approvecomment' : + wp_set_comment_status( $comment_id, 'approve' ); + $redir = add_query_arg( array( 'approved' => 1 ), $redir ); + break; + case 'unapprovecomment' : + wp_set_comment_status( $comment_id, 'hold' ); + $redir = add_query_arg( array( 'unapproved' => 1 ), $redir ); + break; + } + + wp_redirect( $redir ); + die; + break; + +case 'editedcomment' : + + $comment_id = absint( $_POST['comment_ID'] ); + $comment_post_id = absint( $_POST['comment_post_ID'] ); + + check_admin_referer( 'update-comment_' . $comment_id ); + + edit_comment(); + + $location = ( empty( $_POST['referredby'] ) ? "edit-comments.php?p=$comment_post_id" : $_POST['referredby'] ) . '#comment-' . $comment_id; + + /** + * Filter the URI the user is redirected to after editing a comment in the admin. + * + * @since 2.1.0 + * + * @param string $location The URI the user will be redirected to. + * @param int $comment_id The ID of the comment being edited. + */ + $location = apply_filters( 'comment_edit_redirect', $location, $comment_id ); + wp_redirect( $location ); + + exit(); + break; + +default: + wp_die( __('Unknown action.') ); + break; + +} // end switch + +include( ABSPATH . 'wp-admin/admin-footer.php' ); diff --git a/sources/wp-admin/credits.php b/sources/wp-admin/credits.php new file mode 100644 index 0000000..06fe44b --- /dev/null +++ b/sources/wp-admin/credits.php @@ -0,0 +1,190 @@ +' . esc_html( $display_name ) . ''; +} + +/** + * Retrieve the link to an external library used in WordPress. + * + * @access private + * @since 3.2.0 + * + * @param string &$data External library data, passed by reference. + * @return string Link to the external library. + */ +function _wp_credits_build_object_link( &$data ) { + $data = '' . $data[0] . ''; +} + +list( $display_version ) = explode( '-', $wp_version ); + +include( ABSPATH . 'wp-admin/admin-header.php' ); +?> +
+ +

+ +
+ +
+ + + +' . sprintf( __( 'WordPress is created by a worldwide team of passionate individuals. Get involved in WordPress.' ), + 'http://wordpress.org/about/', + /* translators: Url to the codex documentation on contributing to WordPress used on the credits page */ + __( 'http://codex.wordpress.org/Contributing_to_WordPress' ) ) . '

'; + include( ABSPATH . 'wp-admin/admin-footer.php' ); + exit; +} + +echo '

' . __( 'WordPress is created by a worldwide team of passionate individuals.' ) . "

\n"; + +$gravatar = is_ssl() ? 'https://secure.gravatar.com/avatar/' : 'http://0.gravatar.com/avatar/'; + +foreach ( $credits['groups'] as $group_slug => $group_data ) { + if ( $group_data['name'] ) { + if ( 'Translators' == $group_data['name'] ) { + // Considered a special slug in the API response. (Also, will never be returned for en_US.) + $title = _x( 'Translators', 'Translate this to be the equivalent of English Translators in your language for the credits page Translators section' ); + } elseif ( isset( $group_data['placeholders'] ) ) { + $title = vsprintf( translate( $group_data['name'] ), $group_data['placeholders'] ); + } else { + $title = translate( $group_data['name'] ); + } + + echo '

' . $title . "

\n"; + } + + if ( ! empty( $group_data['shuffle'] ) ) + shuffle( $group_data['data'] ); // We were going to sort by ability to pronounce "hierarchical," but that wouldn't be fair to Matt. + + switch ( $group_data['type'] ) { + case 'list' : + array_walk( $group_data['data'], '_wp_credits_add_profile_link', $credits['data']['profiles'] ); + echo '

' . wp_sprintf( '%l.', $group_data['data'] ) . "

\n\n"; + break; + case 'libraries' : + array_walk( $group_data['data'], '_wp_credits_build_object_link' ); + echo '

' . wp_sprintf( '%l.', $group_data['data'] ) . "

\n\n"; + break; + default: + $compact = 'compact' == $group_data['type']; + $classes = 'wp-people-group ' . ( $compact ? 'compact' : '' ); + echo '\n"; + break; + } +} + +?> +

Get involved in WordPress.' ), + /* translators: Url to the codex documentation on contributing to WordPress used on the credits page */ + __( 'http://codex.wordpress.org/Contributing_to_WordPress' ) ); ?>

+ +
+ #upload-menu { + border-bottom-color: #fff; +} + +#postcustomstuff table, +#your-profile fieldset, +#rightnow, +div.dashboard-widget, +#dashboard-widgets p.dashboard-widget-links { + border-color: #d1e5ee; +} + +#poststuff .inside label.spam, +#poststuff .inside label.deleted { + color: red; +} + +#poststuff .inside label.waiting { + color: orange; +} + +#poststuff .inside label.approved { + color: green; +} + +#postcustomstuff table { + border-color: #dfdfdf; + background-color: #f9f9f9; +} + +#postcustomstuff thead th { + background-color: #f1f1f1; +} + +table.widefat { + border-color: #d1e5ee; + background-color: #fff; +} + +div.dashboard-widget-error { + background-color: #c43; +} + +div.dashboard-widget-notice { + background-color: #cfe1ef; +} + +div.dashboard-widget-submit { + border-top-color: #ccc; +} + +ul.category-tabs li { + border-color: transparent; +} + +div.tabs-panel, +.wp-tab-panel, +ul.add-menu-item-tabs li.tabs, +.wp-tab-active { + border-color: #d1e5ee; + background-color: #fff; +} + +ul.category-tabs li.tabs { + border-color: #d1e5ee #d1e5ee #fff; +} + +ul.category-tabs li.tabs, +ul.add-menu-item-tabs li.tabs, +.wp-tab-active { + background-color: #fff; +} + +kbd, +code { + background: #eff8ff; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="file"], +input[type="email"], +input[type="number"], +input[type="search"], +input[type="tel"], +input[type="url"], +select { + border-color: #d1e5ee; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="file"]:focus, +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +select:focus { + border-color: #b0c8d7; +} + +input.disabled, +textarea.disabled { + background-color: #ccc; +} + +#plugin-information .action-button a, +#plugin-information .action-button a:hover, +#plugin-information .action-button a:visited { + color: #fff; +} + +.revisions-meta, +.widget .widget-top, +.postbox h3, +.stuffbox h3, +.widefat thead tr th, +.widefat tfoot tr th, +h3.dashboard-widget-title, +h3.dashboard-widget-title span, +h3.dashboard-widget-title small, +.sidebar-name, +#nav-menu-header, +#nav-menu-footer, +.menu-item-handle, +#fullscreen-topbar { + background: #f5fafd; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#f7fcfe)); + background-image: -webkit-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -moz-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -o-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: linear-gradient(to top, #eff8ff, #f7fcfe); +} + +.widget .widget-top, +.postbox h3, +.stuffbox h3 { + border-bottom-color: #d1e5ee; + text-shadow: #fff 0 1px 0; + -webkit-box-shadow: 0 1px 0 #fff; + box-shadow: 0 1px 0 #fff; +} + +.form-table th, +.form-wrap label { + color: #222; + text-shadow: #fff 0 1px 0; +} + +.description, +.form-wrap p { + color: #666; +} + +strong .post-com-count span { + background-color: #21759b; +} + +.sorthelper { + background-color: #ccf3fa; +} + +.ac_match, +.subsubsub a.current { + color: #000; +} + +.wrap h2 { + color: #174f69; +} + +.wrap .add-new-h2, +.wrap .add-new-h2:active { + background: #f1f1f1; +} + +.subtitle { + color: #777; +} + +.ac_over { + background-color: #f0f0b8; +} + +.ac_results { + background-color: #fff; + border-color: #b0c8d7; +} + +.ac_results li { + color: #101010; +} + +.alternate, +.alt { + background-color: #f7fcfe; +} + +.available-theme a.screenshot { + background-color: #eff8ff; + border-color: #acd; +} + +#current-theme { + border-bottom-color: #d1e5ee; +} + +.bar { + background-color: #e8e8e8; + border-right-color: #99d; +} + +#media-upload, +#media-upload .media-item .slidetoggle { + background: #fff; +} + +#media-upload .slidetoggle { + border-top-color: #dfdfdf; +} + +div.error, +.login #login_error { + background-color: #ffebe8; + border-color: #c00; +} + +div.error a { + color: #c00; +} + +.form-invalid { + background-color: #ffebe8 !important; +} + +.form-invalid input, +.form-invalid select { + border-color: #c00 !important; +} + +.submit, +#commentsdiv #add-new-comment { + border-color: #dfdfdf; +} + +.highlight { + background-color: #e4f2fd; + color: #000; +} + +.howto, +.nonessential, +#edit-slug-box, +.form-input-tip, +.subsubsub { + color: #666; +} + +.media-upload-form label.form-help, +td.help { + color: #9a9a9a; +} + +.ui-autocomplete { + border-color: #b0c8d7; + background-color: #eff8ff; +} + +.ui-autocomplete li a.ui-state-focus { + background-color: #def1ff; +} + +.post-com-count { + color: #fff; +} + +.post-com-count span { + background-color: #bbb; + color: #fff; +} + +.post-com-count:hover span { + background-color: #d54e21; +} + +.quicktags, .search { + background-color: #ccc; + color: #000; +} + +.side-info h5 { + border-bottom-color: #dadada; +} + +.side-info ul { + color: #666; +} + +a:hover, +a:active { + color: #d54e21; +} + +a:focus { + color: #124964; +} + +#adminmenu a:hover, +#adminmenu li.menu-top > a:focus, +#adminmenu .wp-submenu a:hover, +#the-comment-list .comment a:hover, +#rightnow a:hover, +#media-upload a.del-link:hover, +div.dashboard-widget-submit input:hover, +.subsubsub a:hover, +.subsubsub a.current:hover, +.ui-tabs-nav a:hover, +.plugins .inactive a:hover, +#all-plugins-table .plugins .inactive a:hover, +#search-plugins-table .plugins .inactive a:hover { + color: #d54e21; +} + +#the-comment-list .comment-item, +#dashboard-widgets #dashboard_quick_press form p.submit { + border-color: #dfdfdf; +} + +#side-sortables .category-tabs .tabs a, +#side-sortables .add-menu-item-tabs .tabs a, +.wp-tab-bar .wp-tab-active a { + color: #333; +} + +#dashboard_right_now .table_content, +#dashboard_right_now .table_discussion { + border-top-color: #d1e5ee; +} + +#rightnow .rbutton { + background-color: #ebebeb; + color: #264761; +} + +.submitbox .submit { + background-color: #464646; + color: #ccc; +} + +.plugins a.delete:hover, +#all-plugins-table .plugins a.delete:hover, +#search-plugins-table .plugins a.delete:hover, +.submitbox .submitdelete { + color: #f00; + border-bottom-color: #f00; +} + +.submitbox .submitdelete:hover, +#media-items a.delete:hover, +#media-items a.delete-permanently:hover { + color: #fff; + background-color: #f00; + border-bottom-color: #f00; +} + +#normal-sortables .submitbox .submitdelete:hover { + color: #000; + background-color: #f00; + border-bottom-color: #f00; +} + +.tablenav .dots { + border-color: transparent; +} + +.tablenav .next, +.tablenav .prev { + border-color: transparent; + color: #21759b; +} + +.tablenav .next:hover, +.tablenav .prev:hover { + border-color: transparent; + color: #d54e21; +} + +div.updated, +.login .message { + background-color: #ffffe0; + border-color: #e6db55; +} + +.update-message { + color: #000; +} + +a.page-numbers { + border-bottom-color: #b8d3e2; +} + +.commentlist li { + border-bottom-color: #ccc; +} + +.widefat td, +.widefat th { + border-top-color: #fff; + border-bottom-color: #d0dfe9; +} + +.widefat th { + text-shadow: rgba(255,255,255,0.8) 0 1px 0; +} + +.widefat td { + color: #555; +} +.widefat p, +.widefat ol, +.widefat ul { + color: #333; +} + +.widefat thead tr th, +.widefat tfoot tr th, +h3.dashboard-widget-title, +h3.dashboard-widget-title span, +h3.dashboard-widget-title small { + color: #333; +} + +th.sortable a:hover, +th.sortable a:active, +th.sortable a:focus { + color: #333; +} + +th.sortable a:focus { + background: #e1e1e1; + background-image: -webkit-gradient(linear, left bottom, left top, from(#dcdcdc), to(#e9e9e9)); + background-image: -webkit-linear-gradient(bottom, #dcdcdc, #e9e9e9); + background-image: -moz-linear-gradient(bottom, #dcdcdc, #e9e9e9); + background-image: -o-linear-gradient(bottom, #dcdcdc, #e9e9e9); + background-image: linear-gradient(to top, #dcdcdc, #e9e9e9); +} + +h3.dashboard-widget-title small a { + color: #d7d7d7; +} + +h3.dashboard-widget-title small a:hover { + color: #fff; +} + +a, +#adminmenu a, +#the-comment-list p.comment-author strong a, +#media-upload a.del-link, +#media-items a.delete, +#media-items a.delete-permanently, +.plugins a.delete, +.ui-tabs-nav a { + color: #21759b; +} + +#adminmenu .awaiting-mod, +#adminmenu .update-plugins, +#sidemenu a .update-plugins, +#rightnow .reallynow { + background-color: #464646; + color: #fff; + -webkit-box-shadow: rgba(255,255,255,0.5) 0 1px 0; + box-shadow: rgba(255,255,255,0.5) 0 1px 0; +} +#plugin-information .action-button { + background-color: #d54e21; + color: #fff; +} + +#adminmenu li.current a .awaiting-mod, +#adminmenu li a.wp-has-current-submenu .update-plugins{ + background-color: #464646; + color: #fff; + -webkit-box-shadow: rgba(255,255,255,0.5) 0 1px 0; + box-shadow: rgba(255,255,255,0.5) 0 1px 0; +} + +div#media-upload-header, +div#plugin-information-header { + background-color: #f9f9f9; + border-bottom-color: #dfdfdf; +} + +#currenttheme img { + border-color: #666; +} + +#dashboard_secondary div.dashboard-widget-content ul li a { + background-color: #f9f9f9; +} + +input.readonly, textarea.readonly { + background-color: #ddd; +} + +#editable-post-name { + background-color: #fffbcc; +} + +#edit-slug-box strong, +.tablenav .displaying-num, +#submitted-on, +.submitted-on { + color: #777; +} + +.login #nav a, +.login #backtoblog a { + color: #21759b !important; +} + +.login #nav a:hover, +.login #backtoblog a:hover { + color: #d54e21 !important; +} + +#wpfooter { + color: #777; + border-color: #b0c8d7; +} + +.imgedit-group, +#media-items .media-item, +.media-item .describe { + border-color: #dfdfdf; +} + +.checkbox, +.side-info, +.plugins tr, +#your-profile #rich_editing { + background-color: #fcfcfc; +} + +.plugins .inactive, +.plugins .inactive th, +.plugins .inactive td, +tr.inactive + tr.plugin-update-tr .plugin-update { + background-color: #f7fcfe; +} + +.plugin-update-tr .update-message { + background-color: #fffbe4; + border-color: #dfdfdf; +} + +.plugins .active, +.plugins .active th, +.plugins .active td { + color: #000; +} + +.plugins .inactive a { + color: #579; +} + +#the-comment-list tr.undo, +#the-comment-list div.undo { + background-color: #f4f4f4; +} + +#the-comment-list .unapproved { + background-color: #ffffe0; +} + +#the-comment-list .approve a { + color: #006505; +} + +#the-comment-list .unapprove a { + color: #d98500; +} + +table.widefat span.delete a, +table.widefat span.trash a, +table.widefat span.spam a, +#dashboard_recent_comments .delete a, +#dashboard_recent_comments .trash a, +#dashboard_recent_comments .spam a { + color: #bc0b0b; +} + +.welcome-panel { + background: #f5fafd; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#f7fcfe)); + background-image: -webkit-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -moz-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -o-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: linear-gradient(to top, #eff8ff, #f7fcfe); + border-color: #d1e5ee; +} +.welcome-panel p { + color: #777; +} +.welcome-panel-column p { + color: #464646; +} +.welcome-panel h3 { + text-shadow: 1px 1px 1px #fff; +} + +.widget, +#widget-list .widget-top, +.postbox, +#titlediv, +#poststuff .postarea, +.stuffbox { + border-color: #d1e5ee; + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.widget, +#widget-list .widget-top, +.postbox, +.menu-item-settings { + background: #f5fafd; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#f7fcfe)); + background-image: -webkit-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -moz-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -o-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: linear-gradient(to top, #eff8ff, #f7fcfe); +} + +.postbox h3 { + color: #174f69; +} + +.widget .widget-top { + color: #174f69; +} + +.js .sidebar-name:hover h3, +.js .postbox h3:hover { + color: #000; +} + +.curtime #timestamp { + background-image: url(../images/date-button.gif); +} + +#quicktags #ed_link { + color: #00f; +} + +#rightnow .youhave { + background-color: #f0f6fb; +} + +#rightnow a { + color: #448abd; +} + +.tagchecklist span a, +#bulk-titles div a { + background: url(../images/xit.gif) no-repeat; +} + +.tagchecklist span a:hover, +#bulk-titles div a:hover { + background: url(../images/xit.gif) no-repeat -10px 0; +} + +#update-nag, .update-nag { + background-color: #fffbcc; + border-color: #e6db55; + color: #555; +} + +#screen-meta { + background-color: #eff8ff; + border-color: #d1e5ee; + -webkit-box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.05 ); + box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.05 ); +} + +#contextual-help-back { + background: #fff; +} + +.contextual-help-tabs a:hover { + background-color: #ceeaff; + color: #333; +} + +#contextual-help-back, +.contextual-help-tabs .active { + border-color: #d1e5ee; +} + +.contextual-help-tabs .active, +.contextual-help-tabs .active a, +.contextual-help-tabs .active a:hover { + background: #fff; + color: #000; +} + +/* screen options and help tabs */ +#screen-options-link-wrap, +#contextual-help-link-wrap { + border-right: 1px solid #d1e5ee; + border-left: 1px solid #d1e5ee; + border-bottom: 1px solid #d1e5ee; + background: #eff8ff; + background-image: -webkit-gradient(linear, left bottom, left top, from(#def1ff), to(#eff8ff)); + background-image: -webkit-linear-gradient(bottom, #def1ff, #eff8ff); + background-image: -moz-linear-gradient(bottom, #def1ff, #eff8ff); + background-image: -o-linear-gradient(bottom, #def1ff, #eff8ff); + background-image: linear-gradient(to top, #def1ff, #eff8ff); +} + +#screen-meta-links a { + color: #606060; + background: transparent url(../images/arrows.png) no-repeat right 4px; +} + +#screen-meta-links a:hover, +#screen-meta-links a:active { + color: #000; + background-color: transparent; +} + +#screen-meta-links a.screen-meta-active { + background-position: right -31px; +} + +/* end screen options and help tabs */ + +.login #backtoblog a { + color: #464646; +} + +#wphead { + border-bottom: 1px solid #d0dfe9; +} + +#wphead h1 a { + color: #174f69; +} + +#wpfooter a:link, +#wpfooter a:visited { + text-decoration: none; +} + +#wpfooter a:hover { + color: #000; + text-decoration: underline; +} + +.file-error, +abbr.required, +.widget-control-remove:hover, +table.widefat .delete a:hover, +table.widefat .trash a:hover, +table.widefat .spam a:hover, +#dashboard_recent_comments .delete a:hover, +#dashboard_recent_comments .trash a:hover +#dashboard_recent_comments .spam a:hover { + color: #f00; +} + +#pass-strength-result { + background-color: #eee; + border-color: #ddd !important; +} + +#pass-strength-result.bad { + background-color: #ffb78c; + border-color: #ff853c !important; +} + +#pass-strength-result.good { + background-color: #ffec8b; + border-color: #fc0 !important; +} + +#pass-strength-result.short { + background-color: #ffa0a0; + border-color: #f04040 !important; +} + +#pass-strength-result.strong { + background-color: #c3ff88; + border-color: #8dff1c !important; +} + +/* editors */ +#poststuff .wp-editor-wrap .wp_themeSkin .mceStatusbar { + border-color: #d0dfe9; + background-color: #eff8ff; +} + +#poststuff .wp-editor-wrap .wp_themeSkin .mceStatusbar * { + color: #555; +} + +#poststuff #editor-toolbar .active { + border-color: #d0dfe9 #d0dfe9 #eff8ff; + background-color: #eff8ff; + color: #333; +} + +.wp-editor-wrap .wp-editor-container, +.wp-editor-wrap .wp_themeSkin table.mceLayout { + border-color: #d1e5ee #d1e5ee #d0dfe9; +} + +#editorcontainer { + border-color: #d1e5ee #d1e5ee #d0dfe9; +} + +#post-status-info { + border-color: #d0dfe9 #d1e5ee #d1e5ee; +} + +/* TinyMCE */ + +.wp-admin .wp-editor-wrap .wp-switch-editor { + background-color: #d3e9f2; + border-color: #d1e5ee #d1e5ee #d3e9f2; + color: #174F69; +} + +.wp-admin .wp-editor-wrap .wp-switch-editor:active { + background-color: #f5fafd; +} + +.wp-admin .wp-editor-wrap.tmce-active .switch-tmce, +.wp-admin .wp-editor-wrap.html-active .switch-html { + background: #f7fcfe; + border-color: #d1e5ee #d1e5ee #f7fcfe; +} + +.wp-admin .wp-editor-wrap .quicktags-toolbar, +.wp-admin .wp-editor-wrap .wp_themeSkin tr.mceFirst td.mceToolbar { + border-color: #d0dfe9; + background-color: #f5fafd; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#f7fcfe)); + background-image: -webkit-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -moz-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: -o-linear-gradient(bottom, #eff8ff, #f7fcfe); + background-image: linear-gradient(to top, #eff8ff, #f7fcfe); +} + +.wp-admin .wp_themeSkin table.mceListBox { + border-color: #d1e5ee; +} + +.wp-admin .wp_themeSkin table.mceListBoxEnabled:hover, +.wp-admin .wp_themeSkin table.mceListBoxEnabled:active, +.wp-admin .wp_themeSkin table.mceListBoxHover, +.wp-admin .wp_themeSkin table.mceListBoxHover:active, +.wp-admin .wp_themeSkin table.mceListBoxSelected { + border-color: #b8cfdf; +} + +.wp-admin .wp_themeSkin a.mceButtonEnabled:hover, +.wp-admin .wp_themeSkin table.mceSplitButton:hover { + border-color: #c3d2dc; + background: #f4f9fc; + background-image: -webkit-gradient(linear, left bottom, left top, from(#f4f9fc), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #f4f9fc, #fff); + background-image: -moz-linear-gradient(bottom, #f4f9fc, #fff); + background-image: -o-linear-gradient(bottom, #f4f9fc, #fff); + background-image: linear-gradient(to top, #f4f9fc, #fff); +} + +.wp-admin .wp_themeSkin a.mceButton:active, +.wp-admin .wp_themeSkin a.mceButtonEnabled:active, +.wp-admin .wp_themeSkin a.mceButtonSelected:active, +.wp-admin .wp_themeSkin a.mceButtonActive, +.wp-admin .wp_themeSkin a.mceButtonActive:active, +.wp-admin .wp_themeSkin a.mceButtonActive:hover, +.wp-admin .wp_themeSkin .mceSplitButtonSelected table, +.wp-admin .wp_themeSkin .mceSplitButtonSelected table:hover { + border-color: #8f9da9 #c3d2dc #c3d2dc #8f9da9; + background: #f4f9fc; + background-image: -webkit-gradient(linear, left bottom, left top, from(#fff), to(#f4f9fc)); + background-image: -webkit-linear-gradient(bottom, #fff, #f4f9fc); + background-image: -moz-linear-gradient(bottom, #fff, #f4f9fc); + background-image: -o-linear-gradient(bottom, #fff, #f4f9fc); + background-image: linear-gradient(to top, #fff, #f4f9fc); +} + +.wp-admin .wp_themeSkin .mceSplitButtonSelected table a.mceOpen, +.wp-admin .wp_themeSkin .mceSplitButtonSelected table a.mceAction { + border-color: #8f9da9 #c3d2dc #c3d2dc #8f9da9; +} + +.wp-admin .wp_themeSkin .mceSplitButton:hover a { + border-color: #c3d2dc; +} +/* end TinyMCE */ + +.editwidget .widget-inside { + border-color: #d0dfe9; +} + +#titlediv #title { + background-color: #fff; +} + +#tTips p#tTips_inside { + background-color: #ddd; + color: #333; +} + +#poststuff .inside .the-tagcloud { + border-color: #ddd; +} + +/* menu */ +#adminmenuback, +#adminmenuwrap { + background-color: #eff8ff; + border-color: #d1e5ee; +} + +#adminmenushadow, +#adminmenuback { + background-image: url(../images/menu-shadow.png); + background-position: top right; + background-repeat: repeat-y; +} + +#adminmenu li.wp-menu-separator { + background: #d1e5ee; + border-color: #bed1dd; +} + +#adminmenu div.separator { + border-color: #d1e5ee; +} + +#adminmenu a.menu-top, +#adminmenu .wp-submenu .wp-submenu-head { + border-top-color: #fff; + border-bottom-color: #cae6ff; +} + +#adminmenu li.wp-menu-open { + border-color: #d1e5ee; +} + +#adminmenu li.menu-top:hover, +#adminmenu li.opensub > a.menu-top, +#adminmenu li > a.menu-top:focus { + background-color: #e0f1ff; + color: #d54e21; + text-shadow: 0 1px 0 rgba( 255, 255, 255, 0.4 ); +} + +/* So it doesn't get applied to the number spans (comments, updates, etc) */ +#adminmenu li.menu-top:hover > a span, +#adminmenu li.menu-top > a:focus span { + text-shadow: none; +} + +#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu, +#adminmenu li.current a.menu-top, +.folded #adminmenu li.wp-has-current-submenu, +.folded #adminmenu li.current.menu-top, +#adminmenu .wp-menu-arrow, +#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head { + background: #5589aa; + background-image: -webkit-gradient(linear, left bottom, left top, from(#5589aa), to(#619bbb)); + background-image: -webkit-linear-gradient(bottom, #5589aa, #619bbb); + background-image: -moz-linear-gradient(bottom, #5589aa, #619bbb); + background-image: -o-linear-gradient(bottom, #5589aa, #619bbb); + background-image: linear-gradient(to top, #5589aa, #619bbb); +} + +#adminmenu .wp-menu-arrow div { + background: #5589aa; + background-image: -webkit-gradient(linear, right bottom, left top, from(#5589aa), to(#619bbb)); + background-image: -webkit-linear-gradient(bottom right, #5589aa, #619bbb); + background-image: -moz-linear-gradient(bottom right, #5589aa, #619bbb); + background-image: -o-linear-gradient(bottom right, #5589aa, #619bbb); + background-image: linear-gradient(to top left, #5589aa, #619bbb); +} + +#adminmenu li.wp-not-current-submenu .wp-menu-arrow { + border-top-color: #fff; + border-bottom-color: #cae6ff; + background: #e0f1ff; +} + +#adminmenu li.wp-not-current-submenu .wp-menu-arrow div { + background: #e0f1ff; + border-color: #cae6ff; +} + +.folded #adminmenu li.menu-top li:hover a { + background-image: none; +} + +#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu, +#adminmenu li.current a.menu-top, +#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head { + text-shadow: 0 -1px 0 #333; + color: #fff; + border-top-color: #5a8fad; + border-bottom-color: #5589aa; +} + +.folded #adminmenu li.wp-has-current-submenu, +.folded #adminmenu li.current.menu-top { + border-top-color: #5a8fad; + border-bottom-color: #5589aa; +} + +#adminmenu .wp-submenu a:hover, +#adminmenu .wp-submenu a:focus { + background-color: #eff8ff; + color: #333; +} + +#adminmenu .wp-submenu li.current, +#adminmenu .wp-submenu li.current a, +#adminmenu .wp-submenu li.current a:hover { + color: #333; +} + +#adminmenu .wp-submenu, +.folded #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, +.folded #adminmenu .wp-has-current-submenu .wp-submenu { + background-color: #fff; + border-color: #d0dfe9; + -webkit-box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); + box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); +} + +#adminmenu .wp-submenu .wp-submenu-head { + background-color: #e0f1ff; + color: #333; +} + +/* collapse menu button */ +#collapse-menu { + color: #a0c3d5; + border-top-color: #f9f9f9; +} + +#collapse-menu:hover { + color: #5a8fad; +} + +#collapse-button { + border-color: #d0dfe9; + background: #eff8ff; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #eff8ff, #fff); + background-image: -moz-linear-gradient(bottom, #eff8ff, #fff); + background-image: -o-linear-gradient(bottom, #eff8ff, #fff); + background-image: linear-gradient(to top, #eff8ff, #fff); +} + +#collapse-menu:hover #collapse-button { + border-color: #a0c3d5; +} + +#collapse-button div { + background: transparent url(../images/arrows-vs.png) no-repeat 0 -72px; +} + +.folded #collapse-button div { + background-position: 0 -108px; +} + +/* Auto-folding of the admin menu */ +@media only screen and (max-width: 900px) { + .auto-fold #adminmenu li.wp-has-current-submenu, + .auto-fold #adminmenu li.current.menu-top { + background-color: #5589aa; + background-image: -webkit-gradient(linear, left bottom, left top, from(#5589aa), to(#619bbb)); + background-image: -webkit-linear-gradient(bottom, #5589aa, #619bbb); + background-image: -moz-linear-gradient(bottom, #5589aa, #619bbb); + background-image: -o-linear-gradient(bottom, #5589aa, #619bbb); + background-image: linear-gradient(bottom, #5589aa, #619bbb); + } + + .auto-fold #adminmenu li.wp-has-current-submenu, + .auto-fold #adminmenu li.current.menu-top { + border-top-color: #5a8fad; + border-bottom-color: #5589aa; + } + + .auto-fold #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu .wp-submenu { + background-color: #fff; + border-color: #d0dfe9; + -webkit-box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); + box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); + } + + .auto-fold #collapse-button div { + background-position: 0 -108px; + } +} + +/* menu and screen icons */ +.icon16, +.icon32, +div.wp-menu-image { + background-color: transparent; + background-repeat: no-repeat; +} + +.icon16.icon-dashboard, +.menu-icon-dashboard div.wp-menu-image, +.icon16.icon-post, +.menu-icon-post div.wp-menu-image, +.icon16.icon-media, +.menu-icon-media div.wp-menu-image, +.icon16.icon-links, +.menu-icon-links div.wp-menu-image, +.icon16.icon-page, +.menu-icon-page div.wp-menu-image, +.icon16.icon-comments, +.menu-icon-comments div.wp-menu-image, +.icon16.icon-appearance, +.menu-icon-appearance div.wp-menu-image, +.icon16.icon-plugins, +.menu-icon-plugins div.wp-menu-image, +.icon16.icon-users, +.menu-icon-users div.wp-menu-image, +.icon16.icon-tools, +.menu-icon-tools div.wp-menu-image, +.icon16.icon-settings, +.menu-icon-settings div.wp-menu-image, +.icon16.icon-site, +.menu-icon-site div.wp-menu-image, +.icon16.icon-generic, +.menu-icon-generic div.wp-menu-image { + background-image: url(../images/menu-vs.png?ver=20121105); +} + +.icon16.icon-dashboard, +#adminmenu .menu-icon-dashboard div.wp-menu-image { + background-position: -59px -33px; +} + +#adminmenu .menu-icon-dashboard:hover div.wp-menu-image, +#adminmenu .menu-icon-dashboard.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-dashboard.current div.wp-menu-image { + background-position: -59px -1px; +} + +.icon16.icon-post, +#adminmenu .menu-icon-post div.wp-menu-image { + background-position: -269px -33px; +} + +#adminmenu .menu-icon-post:hover div.wp-menu-image, +#adminmenu .menu-icon-post.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-post.current div.wp-menu-image { + background-position: -269px -1px; +} + +.icon16.icon-media, +#adminmenu .menu-icon-media div.wp-menu-image { + background-position: -119px -33px; +} + +#adminmenu .menu-icon-media:hover div.wp-menu-image, +#adminmenu .menu-icon-media.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-media.current div.wp-menu-image { + background-position: -119px -1px; +} + +.icon16.icon-links, +#adminmenu .menu-icon-links div.wp-menu-image { + background-position: -89px -33px; +} + +#adminmenu .menu-icon-links:hover div.wp-menu-image, +#adminmenu .menu-icon-links.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-links.current div.wp-menu-image { + background-position: -89px -1px; +} + +.icon16.icon-page, +#adminmenu .menu-icon-page div.wp-menu-image { + background-position: -149px -33px; +} + +#adminmenu .menu-icon-page:hover div.wp-menu-image, +#adminmenu .menu-icon-page.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-page.current div.wp-menu-image { + background-position: -149px -1px; +} + +.icon16.icon-comments, +#adminmenu .menu-icon-comments div.wp-menu-image { + background-position: -29px -33px; +} + +#adminmenu .menu-icon-comments:hover div.wp-menu-image, +#adminmenu .menu-icon-comments.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-comments.current div.wp-menu-image { + background-position: -29px -1px; +} + +.icon16.icon-appearance, +#adminmenu .menu-icon-appearance div.wp-menu-image { + background-position: 1px -33px; +} + +#adminmenu .menu-icon-appearance:hover div.wp-menu-image, +#adminmenu .menu-icon-appearance.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-appearance.current div.wp-menu-image { + background-position: 1px -1px; +} + +.icon16.icon-plugins, +#adminmenu .menu-icon-plugins div.wp-menu-image { + background-position: -179px -33px; +} + +#adminmenu .menu-icon-plugins:hover div.wp-menu-image, +#adminmenu .menu-icon-plugins.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-plugins.current div.wp-menu-image { + background-position: -179px -1px; +} + +.icon16.icon-users, +#adminmenu .menu-icon-users div.wp-menu-image { + background-position: -300px -33px; +} + +#adminmenu .menu-icon-users:hover div.wp-menu-image, +#adminmenu .menu-icon-users.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-users.current div.wp-menu-image { + background-position: -300px -1px; +} + +.icon16.icon-tools, +#adminmenu .menu-icon-tools div.wp-menu-image { + background-position: -209px -33px; +} + +#adminmenu .menu-icon-tools:hover div.wp-menu-image, +#adminmenu .menu-icon-tools.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-tools.current div.wp-menu-image { + background-position: -209px -1px; +} + +.icon16.icon-settings, +#adminmenu .menu-icon-settings div.wp-menu-image { + background-position: -239px -33px; +} + +#adminmenu .menu-icon-settings:hover div.wp-menu-image, +#adminmenu .menu-icon-settings.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-settings.current div.wp-menu-image { + background-position: -239px -1px; +} + +.icon16.icon-site, +#adminmenu .menu-icon-site div.wp-menu-image { + background-position: -359px -33px; +} + +#adminmenu .menu-icon-site:hover div.wp-menu-image, +#adminmenu .menu-icon-site.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-site.current div.wp-menu-image { + background-position: -359px -1px; +} + +.icon16.icon-generic, +#adminmenu .menu-icon-generic div.wp-menu-image { + background-position: -330px -33px; +} + +#adminmenu .menu-icon-generic:hover div.wp-menu-image, +#adminmenu .menu-icon-generic.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-generic.current div.wp-menu-image { + background-position: -330px -1px; +} +/* end menu and screen icons */ + +/* Screen Icons */ +.icon32.icon-post, +#icon-edit, +#icon-post, +.icon32.icon-dashboard, +#icon-index, +.icon32.icon-media, +#icon-upload, +.icon32.icon-links, +#icon-link-manager, +#icon-link, +#icon-link-category, +.icon32.icon-page, +#icon-edit-pages, +#icon-page, +.icon32.icon-comments, +#icon-edit-comments, +.icon32.icon-appearance, +#icon-themes, +.icon32.icon-plugins, +#icon-plugins, +.icon32.icon-users, +#icon-users, +#icon-profile, +#icon-user-edit, +.icon32.icon-tools, +#icon-tools, +#icon-admin, +.icon32.icon-settings, +#icon-options-general, +.icon32.icon-site, +#icon-ms-admin, +.icon32.icon-generic, +#icon-generic { + background-image: url(../images/icons32-vs.png?ver=20121105); +} + +.icon32.icon-post, +#icon-edit, +#icon-post { + background-position: -552px -5px; +} + +.icon32.icon-dashboard, +#icon-index { + background-position: -137px -5px; +} + +.icon32.icon-media, +#icon-upload { + background-position: -251px -5px; +} + +.icon32.icon-links, +#icon-link-manager, +#icon-link, +#icon-link-category { + background-position: -190px -5px; +} + +.icon32.icon-page, +#icon-edit-pages, +#icon-page { + background-position: -312px -5px; +} + +.icon32.icon-comments, +#icon-edit-comments { + background-position: -72px -5px; +} + +.icon32.icon-appearance, +#icon-themes { + background-position: -11px -5px; +} + +.icon32.icon-plugins, +#icon-plugins { + background-position: -370px -5px; +} + +.icon32.icon-users, +#icon-users, +#icon-profile, +#icon-user-edit { + background-position: -600px -5px; +} + +.icon32.icon-tools, +#icon-tools, +#icon-admin { + background-position: -432px -5px; +} + +.icon32.icon-settings, +#icon-options-general { + background-position: -492px -5px; +} + +.icon32.icon-site, +#icon-ms-admin { + background-position: -659px -5px; +} + +.icon32.icon-generic, +#icon-generic { + background-position: -708px -5px; +} + +/* end screen icons */ + +/* Post format icons */ + +.post-format-icon { + background: url(../images/post-formats-vs.png) no-repeat; +} + +/* Diff */ +table.diff .diff-deletedline { + background-color: #ffe9e9; +} + +table.diff .diff-deletedline del { + background-color: #faa; +} + +table.diff .diff-addedline { + background-color: #e9ffe9; +} + +table.diff .diff-addedline ins { + background-color: #afa; +} + +.revisions-meta { + border: 1px solid #d1e5ee; +} + +.revisions-controls { + background: #fff; + background: -webkit-gradient(linear, left bottom, left top, color-stop(0%,rgba(255,255,255,1)), color-stop(30px,rgba(255,255,255,1)), color-stop(100%,rgba(255,255,255,1))); + background: -webkit-linear-gradient(bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); + background: -moz-linear-gradient(bottom, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); + background: -o-linear-gradient(bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); + background: linear-gradient(to top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); +} + +.revisions-tooltip, +.revisions-tooltip-arrow span { + border-color: #d1e5ee; + background-color: #fff; +} + +.revisions-tickmarks > div { + border-color: #d1e5ee; +} + +/* jQuery UI Slider */ +.wp-slider.ui-slider { + border-color: #d1e5ee; +} + +.wp-slider .ui-slider-handle { + color: #333; + border-color: none; +} + +.wp-slider .ui-slider-handle { + border-color: #d0dfe9; + background: #eff8ff; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #eff8ff, #fff); + background-image: -moz-linear-gradient(bottom, #eff8ff, #fff); + background-image: -o-linear-gradient(bottom, #eff8ff, #fff); + background-image: linear-gradient(to top, #eff8ff, #fff); +} + +.wp-slider .ui-slider-handle:hover, +.wp-slider .ui-slider-handle:focus { + border-color: #a0c3d5; +} + +.wp-slider .ui-slider-handle.ui-state-hover, +.wp-slider .ui-slider-handle.ui-state-focus { + border-color: #a0c3d5; + outline: none; +} + +/* edit image */ +#sidemenu a { + background-color: #f9f9f9; + border-color: #f9f9f9; + border-bottom-color: #dfdfdf; +} + +#sidemenu a.current { + background-color: #fff; + border-color: #dfdfdf #dfdfdf #fff; + color: #d54e21; +} + +#replyerror { + border-color: #ddd; + background-color: #f9f9f9; +} + +/* table vim shortcuts */ +.vim-current, +.vim-current th, +.vim-current td { + background-color: #e4f2fd !important; +} + +/* Install Plugins */ +#plugin-information .fyi ul { + background-color: #eaf3fa; +} + +#plugin-information .fyi h2.mainheader { + background-color: #cee1ef; +} + +#plugin-information pre, +#plugin-information code { + background-color: #ededff; +} + +#plugin-information pre { + border: 1px solid #ccc; +} + +/* inline editor */ +#bulk-titles { + border-color: #ddd; +} + +.inline-editor div.title { + background-color: #eaf3fa; +} + +.inline-editor ul.cat-checklist { + background-color: #fff; + border-color: #ddd; +} + +.inline-editor .quick-edit-save { + background-color: #f1f1f1; +} + +fieldset.inline-edit-col-right .inline-edit-col { + border-color: #dfdfdf; +} + +.attention { + color: #d54e21; +} + +.js .meta-box-sortables .postbox:hover .handlediv { + background: transparent url(../images/arrows-vs.png) no-repeat 6px 7px; +} + +.tablenav .tablenav-pages { + color: #555; +} + +.tablenav .tablenav-pages a { + border-color: #d1e5ee; + background: #eee; + -moz-box-shadow: inset 0 1px 0 #fff; + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; +} + +.tablenav .tablenav-pages a:hover, +.tablenav .tablenav-pages a:focus { + color: #d54e21; +} + +.tablenav .tablenav-pages a.disabled, +.tablenav .tablenav-pages a.disabled:hover, +.tablenav .tablenav-pages a.disabled:focus { + color: #aaa; +} + +.tablenav .tablenav-pages .current { + background: #dfdfdf; + border-color: #d3d3d3; +} + +#availablethemes, +#availablethemes td { + border-color: #acd; +} + +#current-theme img { + border-color: #b0c8d7; +} + +#TB_window #TB_title a.tb-theme-preview-link, +#TB_window #TB_title a.tb-theme-preview-link:visited { + color: #999; +} + +#TB_window #TB_title a.tb-theme-preview-link:hover, +#TB_window #TB_title a.tb-theme-preview-link:focus { + color: #ccc; +} + +.misc-pub-section { + border-top-color: #fff; + border-bottom-color: #d1e5ee; +} + +#minor-publishing { + border-bottom-color: #cae6ff; +} + +#post-body .misc-pub-section { + border-left-color: #eee; +} + +.post-com-count span { + background-color: #bbb; +} + +.form-table .color-palette td { + border-color: #fff; +} + +.sortable-placeholder { + border-color: #bbb; + background-color: #f5f5f5; +} + +#post-body ul.category-tabs li.tabs a, +#post-body ul.add-menu-item-tabs li.tabs a, +body.press-this ul.category-tabs li.tabs a { + color: #333; +} + +.view-switch #view-switch-list, +.view-switch #view-switch-excerpt { + background-color: transparent; + background-image: url('../images/list.png'); + background-repeat: no-repeat; +} + +.view-switch #view-switch-list { + background-position: 0 0; +} + +.view-switch .current #view-switch-list { + background-position: -40px 0; +} + +.view-switch #view-switch-excerpt { + background-position: -20px 0; +} + +.view-switch .current #view-switch-excerpt { + background-position: -60px 0; +} + +#header-logo { + background: transparent url(../images/wp-logo-vs.png?ver=20101102) no-repeat scroll center center; +} + +.popular-tags, +.feature-filter { + background-color: #fff; + border-color: #d1e5ee; +} + +div.widgets-sortables, +#widgets-left .inactive, +#available-widgets .widget-holder { + background-color: #f7fcfe; + border-color: #d0dfe9; +} + +#available-widgets .widget-description { + color: #555; +} + +.sidebar-name { + color: #464646; + text-shadow: #fff 0 1px 0; + border-color: #d0dfe9; + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; +} + +.js .sidebar-name:hover, +.js #removing-widget { + color: #d54e21; +} + +#removing-widget span { + color: black; +} + +.js .sidebar-name-arrow { + background: transparent url(../images/arrows-vs.png) no-repeat 5px 9px; +} + +.js .sidebar-name:hover .sidebar-name-arrow { + background: transparent url(../images/arrows-dark-vs.png) no-repeat 5px 9px; +} + +.in-widget-title { + color: #606060; +} + +.deleting .widget-title * { + color: #aaa; +} + +.imgedit-menu div { + border-color: #d5d5d5; + background-color: #f1f1f1; +} + +.imgedit-menu div:hover { + border-color: #c1c1c1; + background-color: #eaeaea; +} + +.imgedit-menu div.disabled { + border-color: #ccc; + background-color: #ddd; + filter: alpha(opacity=50); + opacity: 0.5; +} + +#dashboard_recent_comments div.undo { + border-top-color: #dfdfdf; +} + +.comment-ays, +.comment-ays th { + border-color: #ddd; +} + +.comment-ays th { + background-color: #f1f1f1; +} + +/* added from nav-menu.css */ +#menu-management .menu-edit { + border-color: #d0dfe9; +} + +#post-body { + background: #fff; + border-top-color: #fff; + border-bottom-color: #d0dfe9; +} + +#nav-menu-header { + border-bottom-color: #d0dfe9; +} + +#nav-menu-footer { + border-top-color: #fff; +} + +#menu-management .nav-tabs-arrow a { + color: #c1c1c1; +} + +#menu-management .nav-tabs-arrow a:hover { + color: #d54e21; +} + +#menu-management .nav-tabs-arrow a:active { + color: #464646; +} + +#menu-management .nav-tab-active { + border-color: #dfdfdf; +} + +#menu-management .nav-tab { + background: #f7fcfe; + border-color: #d0dfe9; +} + +.js .input-with-default-title { + color: #aaa; +} + +#cancel-save { + color: #f00; +} + +#cancel-save:hover { + background-color: #f00; + color: #fff; +} + +.list-container { + border-color: #dfdfdf; +} + +.menu-item-handle { + border-color: #d0dfe9; +} + +.menu li.deleting .menu-item-handle { + background-color: #f66; + text-shadow: #ccc; +} + +.item-type { /* Menu item controls */ + color: #999; +} + +.item-controls .menu-item-delete:hover { + color: #f00; +} + +.nav-menus-php .item-edit { + background: transparent url(../images/arrows-vs.png) no-repeat 8px 10px; + border-bottom-color: #eff8ff; +} + +.nav-menus-php .item-edit:hover { + background: transparent url(../images/arrows-dark-vs.png) no-repeat 8px 10px; +} + +.menu-item-settings { /* Menu editing */ + border-color: #d0dfe9; +} + +.link-to-original { + color: #777; + border-color: #d0dfe9; +} + +#cancel-save:hover { + color: #fff !important; +} + +#update-menu-item { + color: #fff !important; +} + +#update-menu-item:hover, +#update-menu-item:active, +#update-menu-item:focus { + color: #eaf2fa !important; + border-color: #13455b !important; +} + +.submitbox .submitcancel { + color: #21759b; + border-bottom-color: #21759b; +} + +.submitbox .submitcancel:hover { + background: #21759b; + color: #fff; +} +/* end added from nav-menu.css */ + +.nav-tab { + border-color: #d1e5ee #d1e5ee #fff; +} + +.nav-tab:hover, +.nav-tab-active { + border-color: #acd #acd #fff; +} + +h2.nav-tab-wrapper, h3.nav-tab-wrapper { + border-bottom-color: #acd; +} + +#menu-management .nav-tab-active, +.menu-item-handle, +.menu-item-settings { + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; +} + +#menu-management .nav-tab-active { + background: #f7fcfe; + border-bottom-color: #f7fcfe; +} + +#upload-form label { + color: #777; +} + +/* custom header & background pages */ + +/* full screen */ +.fullscreen-overlay { + background: #fff; +} + +.wp-fullscreen-focus #wp-fullscreen-title, +.wp-fullscreen-focus #wp-fullscreen-container { + border-color: #bed1dd; +} + +#fullscreen-topbar { + border-bottom-color: #d1e5ee; +} + +/* Begin About Pages */ + +.about-wrap h1 { + color: #333; + text-shadow: 1px 1px 1px #fff; +} + +.about-text { + color: #777; +} + +.wp-badge { + color: #fff; + text-shadow: 0 -1px 0 rgba(22, 57, 81, 0.3); +} + +.about-wrap h2 .nav-tab { + color: #21759b; +} + +.about-wrap h2 .nav-tab:hover { + color: #d54e21; +} + +.about-wrap h2 .nav-tab-active, +.about-wrap h2 .nav-tab-active:hover { + color: #333; +} + +.about-wrap h2 .nav-tab-active { + text-shadow: 1px 1px 1px #fff; + color: #464646; +} + +.about-wrap h3 { + color: #333; + text-shadow: 1px 1px 1px #fff; +} + +.about-wrap .feature-section h4 { + color: #464646; +} + +.about-wrap h4.wp-people-group { + text-shadow: 1px 1px 1px #fff; +} + +.about-wrap .point-releases { + border-bottom: 1px solid #dfdfdf; +} + +.about-wrap .point-releases h3 { + border-top: 1px solid #dfdfdf; +} + +.about-wrap .point-releases h3:first-child { + border: 0; +} + +.about-wrap li.wp-person img.gravatar { + -webkit-box-shadow: 0 0 4px rgba( 0, 0, 0, 0.4 ); + box-shadow: 0 0 4px rgba( 0, 0, 0, 0.4 ); +} + +.about-wrap li.wp-person .title { + color: #464646; + text-shadow: 1px 1px 1px #fff; +} + +.freedoms-php .about-wrap ol li { + color: #999; +} + +.freedoms-php .about-wrap ol p { + color: #464646; +} + +/* End About Pages */ + + +/*------------------------------------------------------------------------------ + 2.0 - Right to Left Styles +------------------------------------------------------------------------------*/ + +.rtl .bar { + border-right-color: transparent; + border-left-color: #99d; +} + +.rtl #screen-meta-links a.show-settings { + background-position: left 3px; +} + +.rtl #screen-meta-links a.show-settings.screen-meta-active { + background-position: left -33px; +} + +/* Menu */ +.rtl #adminmenushadow, +.rtl #adminmenuback { + background-image: url(../images/menu-shadow-rtl.png); + background-position: top left; +} + +.rtl #adminmenu .wp-submenu .wp-submenu-head { + border-right-color: transparent; + border-left-color: #d1e5ee; +} + +.rtl #adminmenu .wp-submenu, +.rtl.folded #adminmenu .wp-has-current-submenu .wp-submenu { + -webkit-box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); + box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); +} + +.rtl #adminmenu .wp-has-current-submenu .wp-submenu { + -webkit-box-shadow: none; + box-shadow: none; +} + +/* Collapse Menu Button */ +.rtl #collapse-button div { + background-position: 0 -108px; +} + +.rtl.folded #collapse-button div { + background-position: 0 -72px; +} + +/* Auto-folding of the admin menu for RTL */ +@media only screen and (max-width: 900px) { + .rtl.auto-fold #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, + .rtl.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu { + -webkit-box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); + box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); + } + + .rtl.auto-fold #collapse-button div { + background-position: 0 -72px; + } +} + +/* edit image */ +.js.rtl .meta-box-sortables .postbox:hover .handlediv { + background: transparent url(../images/arrows-vs.png) no-repeat 6px 7px; +} + +.rtl #post-body .misc-pub-section { + border-right-color: transparent; + border-left-color: #d1e5ee; +} + +.js.rtl .sidebar-name-arrow { + background: transparent url(../images/arrows-vs.png) no-repeat 5px 9px; +} + +.js.rtl .sidebar-name:hover .sidebar-name-arrow { + background: transparent url(../images/arrows-dark-vs.png) no-repeat 5px 9px; +} + +/** + * HiDPI Displays + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + + .curtime #timestamp { + background-image: url("../images/date-button-2x.gif?ver=20120916"); + background-size: 16px auto; + } + + .tagchecklist span a, + #bulk-titles div a, + .tagchecklist span a:hover, + #bulk-titles div a:hover { + background-image: url("../images/xit-2x.gif?ver=20120916"); + background-size: 20px auto; + } + + #screen-meta-links a.show-settings, + #screen-meta-links a.show-settings.screen-meta-active, + #adminmenu .wp-has-submenu:hover .wp-menu-toggle, + #adminmenu .wp-menu-open .wp-menu-toggle, + #collapse-button div, + .nav-menus-php .item-edit, + .js .meta-box-sortables .postbox:hover .handlediv, + .sidebar-name-arrow, + .rtl #adminmenu .wp-has-submenu:hover .wp-menu-toggle, + .rtl #adminmenu .wp-menu-open .wp-menu-toggle, + .js.rtl .meta-box-sortables .postbox:hover .handlediv, + .rtl .sidebar-name-arrow { + background-image: url("../images/arrows-vs-2x.png?ver=20120916"); + background-size: 15px 123px; + } + + #adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle, + #adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle, + .nav-menus-php .item-edit:hover, + .sidebar-name:hover .sidebar-name-arrow, + .rtl #adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle, + .rtl #adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle, + .rtl .sidebar-name:hover .sidebar-name-arrow { + background-image: url("../images/arrows-dark-vs-2x.png?ver=20120916"); + background-size: 15px 123px; + } + + .view-switch #view-switch-list, + .view-switch #view-switch-excerpt { + background-image: url("../images/list-2x.png?ver=20120916"); + background-size: 80px 20px; + } + + .icon32.icon-post, + #icon-edit, + #icon-post, + .icon32.icon-dashboard, + #icon-index, + .icon32.icon-media, + #icon-upload, + .icon32.icon-links, + #icon-link-manager, + #icon-link, + #icon-link-category, + .icon32.icon-page, + #icon-edit-pages, + #icon-page, + .icon32.icon-comments, + #icon-edit-comments, + .icon32.icon-appearance, + #icon-themes, + .icon32.icon-plugins, + #icon-plugins, + .icon32.icon-users, + #icon-users, + #icon-profile, + #icon-user-edit, + .icon32.icon-tools, + #icon-tools, + #icon-admin, + .icon32.icon-settings, + #icon-options-general, + .icon32.icon-site, + #icon-ms-admin, + .icon32.icon-generic, + #icon-generic { + background-image: url(../images/icons32-vs-2x.png?ver=20121105); + background-size: 756px 45px; + } + + .icon16.icon-dashboard, + .menu-icon-dashboard div.wp-menu-image, + .icon16.icon-post, + .menu-icon-post div.wp-menu-image, + .icon16.icon-media, + .menu-icon-media div.wp-menu-image, + .icon16.icon-links, + .menu-icon-links div.wp-menu-image, + .icon16.icon-page, + .menu-icon-page div.wp-menu-image, + .icon16.icon-comments, + .menu-icon-comments div.wp-menu-image, + .icon16.icon-appearance, + .menu-icon-appearance div.wp-menu-image, + .icon16.icon-plugins, + .menu-icon-plugins div.wp-menu-image, + .icon16.icon-users, + .menu-icon-users div.wp-menu-image, + .icon16.icon-tools, + .menu-icon-tools div.wp-menu-image, + .icon16.icon-settings, + .menu-icon-settings div.wp-menu-image, + .icon16.icon-site, + .menu-icon-site div.wp-menu-image, + .icon16.icon-generic, + .menu-icon-generic div.wp-menu-image { + background-image: url('../images/menu-vs-2x.png?ver=20121105'); + background-size: 390px 64px; + } + + #header-logo { + background-image: url('../images/wp-logo-vs-2x.png?ver=20120916'); + background-size: 16px auto; + } + + /* 16px post formats */ + .post-format-icon { + background-image: url(../images/post-formats32-vs.png); + background-size: 16px 304px; + } + +} diff --git a/sources/wp-admin/css/colors-classic.min.css b/sources/wp-admin/css/colors-classic.min.css new file mode 100644 index 0000000..4f3c0ff --- /dev/null +++ b/sources/wp-admin/css/colors-classic.min.css @@ -0,0 +1 @@ +.find-box-search,.find-box-buttons{background-color:#eff8ff;border-top:1px solid #dce6f8}.find-box{background-color:#5589aa}.find-box-head{color:#fff}.find-box-inside{background-color:#fff}a.page-numbers:hover{border-color:#999}body,#wpbody,.form-table .pre,.ui-autocomplete li a{color:#333}body>#upload-menu{border-bottom-color:#fff}#postcustomstuff table,#your-profile fieldset,#rightnow,div.dashboard-widget,#dashboard-widgets p.dashboard-widget-links{border-color:#d1e5ee}#poststuff .inside label.spam,#poststuff .inside label.deleted{color:red}#poststuff .inside label.waiting{color:orange}#poststuff .inside label.approved{color:green}#postcustomstuff table{border-color:#dfdfdf;background-color:#f9f9f9}#postcustomstuff thead th{background-color:#f1f1f1}table.widefat{border-color:#d1e5ee;background-color:#fff}div.dashboard-widget-error{background-color:#c43}div.dashboard-widget-notice{background-color:#cfe1ef}div.dashboard-widget-submit{border-top-color:#ccc}ul.category-tabs li{border-color:transparent}div.tabs-panel,.wp-tab-panel,ul.add-menu-item-tabs li.tabs,.wp-tab-active{border-color:#d1e5ee;background-color:#fff}ul.category-tabs li.tabs{border-color:#d1e5ee #d1e5ee #fff}ul.category-tabs li.tabs,ul.add-menu-item-tabs li.tabs,.wp-tab-active{background-color:#fff}kbd,code{background:#eff8ff}textarea,input[type=text],input[type=password],input[type=file],input[type=email],input[type=number],input[type=search],input[type=tel],input[type=url],select{border-color:#d1e5ee}textarea:focus,input[type=text]:focus,input[type=password]:focus,input[type=file]:focus,input[type=email]:focus,input[type=number]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=url]:focus,select:focus{border-color:#b0c8d7}input.disabled,textarea.disabled{background-color:#ccc}#plugin-information .action-button a,#plugin-information .action-button a:hover,#plugin-information .action-button a:visited{color:#fff}.revisions-meta,.widget .widget-top,.postbox h3,.stuffbox h3,.widefat thead tr th,.widefat tfoot tr th,h3.dashboard-widget-title,h3.dashboard-widget-title span,h3.dashboard-widget-title small,.sidebar-name,#nav-menu-header,#nav-menu-footer,.menu-item-handle,#fullscreen-topbar{background:#f5fafd;background-image:-webkit-gradient(linear,left bottom,left top,from(#eff8ff),to(#f7fcfe));background-image:-webkit-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-moz-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-o-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:linear-gradient(to top,#eff8ff,#f7fcfe)}.widget .widget-top,.postbox h3,.stuffbox h3{border-bottom-color:#d1e5ee;text-shadow:#fff 0 1px 0;-webkit-box-shadow:0 1px 0 #fff;box-shadow:0 1px 0 #fff}.form-table th,.form-wrap label{color:#222;text-shadow:#fff 0 1px 0}.description,.form-wrap p{color:#666}strong .post-com-count span{background-color:#21759b}.sorthelper{background-color:#ccf3fa}.ac_match,.subsubsub a.current{color:#000}.wrap h2{color:#174f69}.wrap .add-new-h2,.wrap .add-new-h2:active{background:#f1f1f1}.subtitle{color:#777}.ac_over{background-color:#f0f0b8}.ac_results{background-color:#fff;border-color:#b0c8d7}.ac_results li{color:#101010}.alternate,.alt{background-color:#f7fcfe}.available-theme a.screenshot{background-color:#eff8ff;border-color:#acd}#current-theme{border-bottom-color:#d1e5ee}.bar{background-color:#e8e8e8;border-right-color:#99d}#media-upload,#media-upload .media-item .slidetoggle{background:#fff}#media-upload .slidetoggle{border-top-color:#dfdfdf}div.error,.login #login_error{background-color:#ffebe8;border-color:#c00}div.error a{color:#c00}.form-invalid{background-color:#ffebe8!important}.form-invalid input,.form-invalid select{border-color:#c00!important}.submit,#commentsdiv #add-new-comment{border-color:#dfdfdf}.highlight{background-color:#e4f2fd;color:#000}.howto,.nonessential,#edit-slug-box,.form-input-tip,.subsubsub{color:#666}.media-upload-form label.form-help,td.help{color:#9a9a9a}.ui-autocomplete{border-color:#b0c8d7;background-color:#eff8ff}.ui-autocomplete li a.ui-state-focus{background-color:#def1ff}.post-com-count{color:#fff}.post-com-count span{background-color:#bbb;color:#fff}.post-com-count:hover span{background-color:#d54e21}.quicktags,.search{background-color:#ccc;color:#000}.side-info h5{border-bottom-color:#dadada}.side-info ul{color:#666}a:hover,a:active{color:#d54e21}a:focus{color:#124964}#adminmenu a:hover,#adminmenu li.menu-top>a:focus,#adminmenu .wp-submenu a:hover,#the-comment-list .comment a:hover,#rightnow a:hover,#media-upload a.del-link:hover,div.dashboard-widget-submit input:hover,.subsubsub a:hover,.subsubsub a.current:hover,.ui-tabs-nav a:hover,.plugins .inactive a:hover,#all-plugins-table .plugins .inactive a:hover,#search-plugins-table .plugins .inactive a:hover{color:#d54e21}#the-comment-list .comment-item,#dashboard-widgets #dashboard_quick_press form p.submit{border-color:#dfdfdf}#side-sortables .category-tabs .tabs a,#side-sortables .add-menu-item-tabs .tabs a,.wp-tab-bar .wp-tab-active a{color:#333}#dashboard_right_now .table_content,#dashboard_right_now .table_discussion{border-top-color:#d1e5ee}#rightnow .rbutton{background-color:#ebebeb;color:#264761}.submitbox .submit{background-color:#464646;color:#ccc}.plugins a.delete:hover,#all-plugins-table .plugins a.delete:hover,#search-plugins-table .plugins a.delete:hover,.submitbox .submitdelete{color:red;border-bottom-color:red}.submitbox .submitdelete:hover,#media-items a.delete:hover,#media-items a.delete-permanently:hover{color:#fff;background-color:red;border-bottom-color:red}#normal-sortables .submitbox .submitdelete:hover{color:#000;background-color:red;border-bottom-color:red}.tablenav .dots{border-color:transparent}.tablenav .next,.tablenav .prev{border-color:transparent;color:#21759b}.tablenav .next:hover,.tablenav .prev:hover{border-color:transparent;color:#d54e21}div.updated,.login .message{background-color:#ffffe0;border-color:#e6db55}.update-message{color:#000}a.page-numbers{border-bottom-color:#b8d3e2}.commentlist li{border-bottom-color:#ccc}.widefat td,.widefat th{border-top-color:#fff;border-bottom-color:#d0dfe9}.widefat th{text-shadow:rgba(255,255,255,.8) 0 1px 0}.widefat td{color:#555}.widefat p,.widefat ol,.widefat ul{color:#333}.widefat thead tr th,.widefat tfoot tr th,h3.dashboard-widget-title,h3.dashboard-widget-title span,h3.dashboard-widget-title small{color:#333}th.sortable a:hover,th.sortable a:active,th.sortable a:focus{color:#333}th.sortable a:focus{background:#e1e1e1;background-image:-webkit-gradient(linear,left bottom,left top,from(#dcdcdc),to(#e9e9e9));background-image:-webkit-linear-gradient(bottom,#dcdcdc,#e9e9e9);background-image:-moz-linear-gradient(bottom,#dcdcdc,#e9e9e9);background-image:-o-linear-gradient(bottom,#dcdcdc,#e9e9e9);background-image:linear-gradient(to top,#dcdcdc,#e9e9e9)}h3.dashboard-widget-title small a{color:#d7d7d7}h3.dashboard-widget-title small a:hover{color:#fff}a,#adminmenu a,#the-comment-list p.comment-author strong a,#media-upload a.del-link,#media-items a.delete,#media-items a.delete-permanently,.plugins a.delete,.ui-tabs-nav a{color:#21759b}#adminmenu .awaiting-mod,#adminmenu .update-plugins,#sidemenu a .update-plugins,#rightnow .reallynow{background-color:#464646;color:#fff;-webkit-box-shadow:rgba(255,255,255,.5) 0 1px 0;box-shadow:rgba(255,255,255,.5) 0 1px 0}#plugin-information .action-button{background-color:#d54e21;color:#fff}#adminmenu li.current a .awaiting-mod,#adminmenu li a.wp-has-current-submenu .update-plugins{background-color:#464646;color:#fff;-webkit-box-shadow:rgba(255,255,255,.5) 0 1px 0;box-shadow:rgba(255,255,255,.5) 0 1px 0}div#media-upload-header,div#plugin-information-header{background-color:#f9f9f9;border-bottom-color:#dfdfdf}#currenttheme img{border-color:#666}#dashboard_secondary div.dashboard-widget-content ul li a{background-color:#f9f9f9}input.readonly,textarea.readonly{background-color:#ddd}#editable-post-name{background-color:#fffbcc}#edit-slug-box strong,.tablenav .displaying-num,#submitted-on,.submitted-on{color:#777}.login #nav a,.login #backtoblog a{color:#21759b!important}.login #nav a:hover,.login #backtoblog a:hover{color:#d54e21!important}#wpfooter{color:#777;border-color:#b0c8d7}.imgedit-group,#media-items .media-item,.media-item .describe{border-color:#dfdfdf}.checkbox,.side-info,.plugins tr,#your-profile #rich_editing{background-color:#fcfcfc}.plugins .inactive,.plugins .inactive th,.plugins .inactive td,tr.inactive+tr.plugin-update-tr .plugin-update{background-color:#f7fcfe}.plugin-update-tr .update-message{background-color:#fffbe4;border-color:#dfdfdf}.plugins .active,.plugins .active th,.plugins .active td{color:#000}.plugins .inactive a{color:#579}#the-comment-list tr.undo,#the-comment-list div.undo{background-color:#f4f4f4}#the-comment-list .unapproved{background-color:#ffffe0}#the-comment-list .approve a{color:#006505}#the-comment-list .unapprove a{color:#d98500}table.widefat span.delete a,table.widefat span.trash a,table.widefat span.spam a,#dashboard_recent_comments .delete a,#dashboard_recent_comments .trash a,#dashboard_recent_comments .spam a{color:#bc0b0b}.welcome-panel{background:#f5fafd;background-image:-webkit-gradient(linear,left bottom,left top,from(#eff8ff),to(#f7fcfe));background-image:-webkit-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-moz-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-o-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:linear-gradient(to top,#eff8ff,#f7fcfe);border-color:#d1e5ee}.welcome-panel p{color:#777}.welcome-panel-column p{color:#464646}.welcome-panel h3{text-shadow:1px 1px 1px #fff}.widget,#widget-list .widget-top,.postbox,#titlediv,#poststuff .postarea,.stuffbox{border-color:#d1e5ee;-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff;-webkit-border-radius:3px;border-radius:3px}.widget,#widget-list .widget-top,.postbox,.menu-item-settings{background:#f5fafd;background-image:-webkit-gradient(linear,left bottom,left top,from(#eff8ff),to(#f7fcfe));background-image:-webkit-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-moz-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-o-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:linear-gradient(to top,#eff8ff,#f7fcfe)}.postbox h3{color:#174f69}.widget .widget-top{color:#174f69}.js .sidebar-name:hover h3,.js .postbox h3:hover{color:#000}.curtime #timestamp{background-image:url(../images/date-button.gif)}#quicktags #ed_link{color:#00f}#rightnow .youhave{background-color:#f0f6fb}#rightnow a{color:#448abd}.tagchecklist span a,#bulk-titles div a{background:url(../images/xit.gif) no-repeat}.tagchecklist span a:hover,#bulk-titles div a:hover{background:url(../images/xit.gif) no-repeat -10px 0}#update-nag,.update-nag{background-color:#fffbcc;border-color:#e6db55;color:#555}#screen-meta{background-color:#eff8ff;border-color:#d1e5ee;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.05);box-shadow:0 1px 3px rgba(0,0,0,.05)}#contextual-help-back{background:#fff}.contextual-help-tabs a:hover{background-color:#ceeaff;color:#333}#contextual-help-back,.contextual-help-tabs .active{border-color:#d1e5ee}.contextual-help-tabs .active,.contextual-help-tabs .active a,.contextual-help-tabs .active a:hover{background:#fff;color:#000}#screen-options-link-wrap,#contextual-help-link-wrap{border-right:1px solid #d1e5ee;border-left:1px solid #d1e5ee;border-bottom:1px solid #d1e5ee;background:#eff8ff;background-image:-webkit-gradient(linear,left bottom,left top,from(#def1ff),to(#eff8ff));background-image:-webkit-linear-gradient(bottom,#def1ff,#eff8ff);background-image:-moz-linear-gradient(bottom,#def1ff,#eff8ff);background-image:-o-linear-gradient(bottom,#def1ff,#eff8ff);background-image:linear-gradient(to top,#def1ff,#eff8ff)}#screen-meta-links a{color:#606060;background:transparent url(../images/arrows.png) no-repeat right 4px}#screen-meta-links a:hover,#screen-meta-links a:active{color:#000;background-color:transparent}#screen-meta-links a.screen-meta-active{background-position:right -31px}.login #backtoblog a{color:#464646}#wphead{border-bottom:1px solid #d0dfe9}#wphead h1 a{color:#174f69}#wpfooter a:link,#wpfooter a:visited{text-decoration:none}#wpfooter a:hover{color:#000;text-decoration:underline}.file-error,abbr.required,.widget-control-remove:hover,table.widefat .delete a:hover,table.widefat .trash a:hover,table.widefat .spam a:hover,#dashboard_recent_comments .delete a:hover,#dashboard_recent_comments .trash a:hover #dashboard_recent_comments .spam a:hover{color:red}#pass-strength-result{background-color:#eee;border-color:#ddd!important}#pass-strength-result.bad{background-color:#ffb78c;border-color:#ff853c!important}#pass-strength-result.good{background-color:#ffec8b;border-color:#fc0!important}#pass-strength-result.short{background-color:#ffa0a0;border-color:#f04040!important}#pass-strength-result.strong{background-color:#c3ff88;border-color:#8dff1c!important}#poststuff .wp-editor-wrap .wp_themeSkin .mceStatusbar{border-color:#d0dfe9;background-color:#eff8ff}#poststuff .wp-editor-wrap .wp_themeSkin .mceStatusbar *{color:#555}#poststuff #editor-toolbar .active{border-color:#d0dfe9 #d0dfe9 #eff8ff;background-color:#eff8ff;color:#333}.wp-editor-wrap .wp-editor-container,.wp-editor-wrap .wp_themeSkin table.mceLayout{border-color:#d1e5ee #d1e5ee #d0dfe9}#editorcontainer{border-color:#d1e5ee #d1e5ee #d0dfe9}#post-status-info{border-color:#d0dfe9 #d1e5ee #d1e5ee}.wp-admin .wp-editor-wrap .wp-switch-editor{background-color:#d3e9f2;border-color:#d1e5ee #d1e5ee #d3e9f2;color:#174F69}.wp-admin .wp-editor-wrap .wp-switch-editor:active{background-color:#f5fafd}.wp-admin .wp-editor-wrap.tmce-active .switch-tmce,.wp-admin .wp-editor-wrap.html-active .switch-html{background:#f7fcfe;border-color:#d1e5ee #d1e5ee #f7fcfe}.wp-admin .wp-editor-wrap .quicktags-toolbar,.wp-admin .wp-editor-wrap .wp_themeSkin tr.mceFirst td.mceToolbar{border-color:#d0dfe9;background-color:#f5fafd;background-image:-webkit-gradient(linear,left bottom,left top,from(#eff8ff),to(#f7fcfe));background-image:-webkit-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-moz-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:-o-linear-gradient(bottom,#eff8ff,#f7fcfe);background-image:linear-gradient(to top,#eff8ff,#f7fcfe)}.wp-admin .wp_themeSkin table.mceListBox{border-color:#d1e5ee}.wp-admin .wp_themeSkin table.mceListBoxEnabled:hover,.wp-admin .wp_themeSkin table.mceListBoxEnabled:active,.wp-admin .wp_themeSkin table.mceListBoxHover,.wp-admin .wp_themeSkin table.mceListBoxHover:active,.wp-admin .wp_themeSkin table.mceListBoxSelected{border-color:#b8cfdf}.wp-admin .wp_themeSkin a.mceButtonEnabled:hover,.wp-admin .wp_themeSkin table.mceSplitButton:hover{border-color:#c3d2dc;background:#f4f9fc;background-image:-webkit-gradient(linear,left bottom,left top,from(#f4f9fc),to(#fff));background-image:-webkit-linear-gradient(bottom,#f4f9fc,#fff);background-image:-moz-linear-gradient(bottom,#f4f9fc,#fff);background-image:-o-linear-gradient(bottom,#f4f9fc,#fff);background-image:linear-gradient(to top,#f4f9fc,#fff)}.wp-admin .wp_themeSkin a.mceButton:active,.wp-admin .wp_themeSkin a.mceButtonEnabled:active,.wp-admin .wp_themeSkin a.mceButtonSelected:active,.wp-admin .wp_themeSkin a.mceButtonActive,.wp-admin .wp_themeSkin a.mceButtonActive:active,.wp-admin .wp_themeSkin a.mceButtonActive:hover,.wp-admin .wp_themeSkin .mceSplitButtonSelected table,.wp-admin .wp_themeSkin .mceSplitButtonSelected table:hover{border-color:#8f9da9 #c3d2dc #c3d2dc #8f9da9;background:#f4f9fc;background-image:-webkit-gradient(linear,left bottom,left top,from(#fff),to(#f4f9fc));background-image:-webkit-linear-gradient(bottom,#fff,#f4f9fc);background-image:-moz-linear-gradient(bottom,#fff,#f4f9fc);background-image:-o-linear-gradient(bottom,#fff,#f4f9fc);background-image:linear-gradient(to top,#fff,#f4f9fc)}.wp-admin .wp_themeSkin .mceSplitButtonSelected table a.mceOpen,.wp-admin .wp_themeSkin .mceSplitButtonSelected table a.mceAction{border-color:#8f9da9 #c3d2dc #c3d2dc #8f9da9}.wp-admin .wp_themeSkin .mceSplitButton:hover a{border-color:#c3d2dc}.editwidget .widget-inside{border-color:#d0dfe9}#titlediv #title{background-color:#fff}#tTips p#tTips_inside{background-color:#ddd;color:#333}#poststuff .inside .the-tagcloud{border-color:#ddd}#adminmenuback,#adminmenuwrap{background-color:#eff8ff;border-color:#d1e5ee}#adminmenushadow,#adminmenuback{background-image:url(../images/menu-shadow.png);background-position:top right;background-repeat:repeat-y}#adminmenu li.wp-menu-separator{background:#d1e5ee;border-color:#bed1dd}#adminmenu div.separator{border-color:#d1e5ee}#adminmenu a.menu-top,#adminmenu .wp-submenu .wp-submenu-head{border-top-color:#fff;border-bottom-color:#cae6ff}#adminmenu li.wp-menu-open{border-color:#d1e5ee}#adminmenu li.menu-top:hover,#adminmenu li.opensub>a.menu-top,#adminmenu li>a.menu-top:focus{background-color:#e0f1ff;color:#d54e21;text-shadow:0 1px 0 rgba(255,255,255,.4)}#adminmenu li.menu-top:hover>a span,#adminmenu li.menu-top>a:focus span{text-shadow:none}#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu,#adminmenu li.current a.menu-top,.folded #adminmenu li.wp-has-current-submenu,.folded #adminmenu li.current.menu-top,#adminmenu .wp-menu-arrow,#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head{background:#5589aa;background-image:-webkit-gradient(linear,left bottom,left top,from(#5589aa),to(#619bbb));background-image:-webkit-linear-gradient(bottom,#5589aa,#619bbb);background-image:-moz-linear-gradient(bottom,#5589aa,#619bbb);background-image:-o-linear-gradient(bottom,#5589aa,#619bbb);background-image:linear-gradient(to top,#5589aa,#619bbb)}#adminmenu .wp-menu-arrow div{background:#5589aa;background-image:-webkit-gradient(linear,right bottom,left top,from(#5589aa),to(#619bbb));background-image:-webkit-linear-gradient(bottom right,#5589aa,#619bbb);background-image:-moz-linear-gradient(bottom right,#5589aa,#619bbb);background-image:-o-linear-gradient(bottom right,#5589aa,#619bbb);background-image:linear-gradient(to top left,#5589aa,#619bbb)}#adminmenu li.wp-not-current-submenu .wp-menu-arrow{border-top-color:#fff;border-bottom-color:#cae6ff;background:#e0f1ff}#adminmenu li.wp-not-current-submenu .wp-menu-arrow div{background:#e0f1ff;border-color:#cae6ff}.folded #adminmenu li.menu-top li:hover a{background-image:none}#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu,#adminmenu li.current a.menu-top,#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head{text-shadow:0 -1px 0 #333;color:#fff;border-top-color:#5a8fad;border-bottom-color:#5589aa}.folded #adminmenu li.wp-has-current-submenu,.folded #adminmenu li.current.menu-top{border-top-color:#5a8fad;border-bottom-color:#5589aa}#adminmenu .wp-submenu a:hover,#adminmenu .wp-submenu a:focus{background-color:#eff8ff;color:#333}#adminmenu .wp-submenu li.current,#adminmenu .wp-submenu li.current a,#adminmenu .wp-submenu li.current a:hover{color:#333}#adminmenu .wp-submenu,.folded #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.folded #adminmenu .wp-has-current-submenu .wp-submenu{background-color:#fff;border-color:#d0dfe9;-webkit-box-shadow:2px 3px 6px rgba(0,0,0,.4);box-shadow:2px 3px 6px rgba(0,0,0,.4)}#adminmenu .wp-submenu .wp-submenu-head{background-color:#e0f1ff;color:#333}#collapse-menu{color:#a0c3d5;border-top-color:#f9f9f9}#collapse-menu:hover{color:#5a8fad}#collapse-button{border-color:#d0dfe9;background:#eff8ff;background-image:-webkit-gradient(linear,left bottom,left top,from(#eff8ff),to(#fff));background-image:-webkit-linear-gradient(bottom,#eff8ff,#fff);background-image:-moz-linear-gradient(bottom,#eff8ff,#fff);background-image:-o-linear-gradient(bottom,#eff8ff,#fff);background-image:linear-gradient(to top,#eff8ff,#fff)}#collapse-menu:hover #collapse-button{border-color:#a0c3d5}#collapse-button div{background:transparent url(../images/arrows-vs.png) no-repeat 0 -72px}.folded #collapse-button div{background-position:0 -108px}@media only screen and (max-width:900px){.auto-fold #adminmenu li.wp-has-current-submenu,.auto-fold #adminmenu li.current.menu-top{background-color:#5589aa;background-image:-webkit-gradient(linear,left bottom,left top,from(#5589aa),to(#619bbb));background-image:-webkit-linear-gradient(bottom,#5589aa,#619bbb);background-image:-moz-linear-gradient(bottom,#5589aa,#619bbb);background-image:-o-linear-gradient(bottom,#5589aa,#619bbb);background-image:linear-gradient(bottom,#5589aa,#619bbb)}.auto-fold #adminmenu li.wp-has-current-submenu,.auto-fold #adminmenu li.current.menu-top{border-top-color:#5a8fad;border-bottom-color:#5589aa}.auto-fold #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu{background-color:#fff;border-color:#d0dfe9;-webkit-box-shadow:2px 3px 6px rgba(0,0,0,.4);box-shadow:2px 3px 6px rgba(0,0,0,.4)}.auto-fold #collapse-button div{background-position:0 -108px}}.icon16,.icon32,div.wp-menu-image{background-color:transparent;background-repeat:no-repeat}.icon16.icon-dashboard,.menu-icon-dashboard div.wp-menu-image,.icon16.icon-post,.menu-icon-post div.wp-menu-image,.icon16.icon-media,.menu-icon-media div.wp-menu-image,.icon16.icon-links,.menu-icon-links div.wp-menu-image,.icon16.icon-page,.menu-icon-page div.wp-menu-image,.icon16.icon-comments,.menu-icon-comments div.wp-menu-image,.icon16.icon-appearance,.menu-icon-appearance div.wp-menu-image,.icon16.icon-plugins,.menu-icon-plugins div.wp-menu-image,.icon16.icon-users,.menu-icon-users div.wp-menu-image,.icon16.icon-tools,.menu-icon-tools div.wp-menu-image,.icon16.icon-settings,.menu-icon-settings div.wp-menu-image,.icon16.icon-site,.menu-icon-site div.wp-menu-image,.icon16.icon-generic,.menu-icon-generic div.wp-menu-image{background-image:url(../images/menu-vs.png?ver=20121105)}.icon16.icon-dashboard,#adminmenu .menu-icon-dashboard div.wp-menu-image{background-position:-59px -33px}#adminmenu .menu-icon-dashboard:hover div.wp-menu-image,#adminmenu .menu-icon-dashboard.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-dashboard.current div.wp-menu-image{background-position:-59px -1px}.icon16.icon-post,#adminmenu .menu-icon-post div.wp-menu-image{background-position:-269px -33px}#adminmenu .menu-icon-post:hover div.wp-menu-image,#adminmenu .menu-icon-post.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-post.current div.wp-menu-image{background-position:-269px -1px}.icon16.icon-media,#adminmenu .menu-icon-media div.wp-menu-image{background-position:-119px -33px}#adminmenu .menu-icon-media:hover div.wp-menu-image,#adminmenu .menu-icon-media.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-media.current div.wp-menu-image{background-position:-119px -1px}.icon16.icon-links,#adminmenu .menu-icon-links div.wp-menu-image{background-position:-89px -33px}#adminmenu .menu-icon-links:hover div.wp-menu-image,#adminmenu .menu-icon-links.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-links.current div.wp-menu-image{background-position:-89px -1px}.icon16.icon-page,#adminmenu .menu-icon-page div.wp-menu-image{background-position:-149px -33px}#adminmenu .menu-icon-page:hover div.wp-menu-image,#adminmenu .menu-icon-page.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-page.current div.wp-menu-image{background-position:-149px -1px}.icon16.icon-comments,#adminmenu .menu-icon-comments div.wp-menu-image{background-position:-29px -33px}#adminmenu .menu-icon-comments:hover div.wp-menu-image,#adminmenu .menu-icon-comments.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-comments.current div.wp-menu-image{background-position:-29px -1px}.icon16.icon-appearance,#adminmenu .menu-icon-appearance div.wp-menu-image{background-position:1px -33px}#adminmenu .menu-icon-appearance:hover div.wp-menu-image,#adminmenu .menu-icon-appearance.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-appearance.current div.wp-menu-image{background-position:1px -1px}.icon16.icon-plugins,#adminmenu .menu-icon-plugins div.wp-menu-image{background-position:-179px -33px}#adminmenu .menu-icon-plugins:hover div.wp-menu-image,#adminmenu .menu-icon-plugins.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-plugins.current div.wp-menu-image{background-position:-179px -1px}.icon16.icon-users,#adminmenu .menu-icon-users div.wp-menu-image{background-position:-300px -33px}#adminmenu .menu-icon-users:hover div.wp-menu-image,#adminmenu .menu-icon-users.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-users.current div.wp-menu-image{background-position:-300px -1px}.icon16.icon-tools,#adminmenu .menu-icon-tools div.wp-menu-image{background-position:-209px -33px}#adminmenu .menu-icon-tools:hover div.wp-menu-image,#adminmenu .menu-icon-tools.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-tools.current div.wp-menu-image{background-position:-209px -1px}.icon16.icon-settings,#adminmenu .menu-icon-settings div.wp-menu-image{background-position:-239px -33px}#adminmenu .menu-icon-settings:hover div.wp-menu-image,#adminmenu .menu-icon-settings.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-settings.current div.wp-menu-image{background-position:-239px -1px}.icon16.icon-site,#adminmenu .menu-icon-site div.wp-menu-image{background-position:-359px -33px}#adminmenu .menu-icon-site:hover div.wp-menu-image,#adminmenu .menu-icon-site.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-site.current div.wp-menu-image{background-position:-359px -1px}.icon16.icon-generic,#adminmenu .menu-icon-generic div.wp-menu-image{background-position:-330px -33px}#adminmenu .menu-icon-generic:hover div.wp-menu-image,#adminmenu .menu-icon-generic.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-generic.current div.wp-menu-image{background-position:-330px -1px}.icon32.icon-post,#icon-edit,#icon-post,.icon32.icon-dashboard,#icon-index,.icon32.icon-media,#icon-upload,.icon32.icon-links,#icon-link-manager,#icon-link,#icon-link-category,.icon32.icon-page,#icon-edit-pages,#icon-page,.icon32.icon-comments,#icon-edit-comments,.icon32.icon-appearance,#icon-themes,.icon32.icon-plugins,#icon-plugins,.icon32.icon-users,#icon-users,#icon-profile,#icon-user-edit,.icon32.icon-tools,#icon-tools,#icon-admin,.icon32.icon-settings,#icon-options-general,.icon32.icon-site,#icon-ms-admin,.icon32.icon-generic,#icon-generic{background-image:url(../images/icons32-vs.png?ver=20121105)}.icon32.icon-post,#icon-edit,#icon-post{background-position:-552px -5px}.icon32.icon-dashboard,#icon-index{background-position:-137px -5px}.icon32.icon-media,#icon-upload{background-position:-251px -5px}.icon32.icon-links,#icon-link-manager,#icon-link,#icon-link-category{background-position:-190px -5px}.icon32.icon-page,#icon-edit-pages,#icon-page{background-position:-312px -5px}.icon32.icon-comments,#icon-edit-comments{background-position:-72px -5px}.icon32.icon-appearance,#icon-themes{background-position:-11px -5px}.icon32.icon-plugins,#icon-plugins{background-position:-370px -5px}.icon32.icon-users,#icon-users,#icon-profile,#icon-user-edit{background-position:-600px -5px}.icon32.icon-tools,#icon-tools,#icon-admin{background-position:-432px -5px}.icon32.icon-settings,#icon-options-general{background-position:-492px -5px}.icon32.icon-site,#icon-ms-admin{background-position:-659px -5px}.icon32.icon-generic,#icon-generic{background-position:-708px -5px}.post-format-icon{background:url(../images/post-formats-vs.png) no-repeat}table.diff .diff-deletedline{background-color:#ffe9e9}table.diff .diff-deletedline del{background-color:#faa}table.diff .diff-addedline{background-color:#e9ffe9}table.diff .diff-addedline ins{background-color:#afa}.revisions-meta{border:1px solid #d1e5ee}.revisions-controls{background:#fff;background:-webkit-gradient(linear,left bottom,left top,color-stop(0%,rgba(255,255,255,1)),color-stop(30px,rgba(255,255,255,1)),color-stop(100%,rgba(255,255,255,1)));background:-webkit-linear-gradient(bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%);background:-moz-linear-gradient(bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%);background:-o-linear-gradient(bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%);background:linear-gradient(to top,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%)}.revisions-tooltip,.revisions-tooltip-arrow span{border-color:#d1e5ee;background-color:#fff}.revisions-tickmarks>div{border-color:#d1e5ee}.wp-slider.ui-slider{border-color:#d1e5ee}.wp-slider .ui-slider-handle{color:#333;border-color:none}.wp-slider .ui-slider-handle{border-color:#d0dfe9;background:#eff8ff;background-image:-webkit-gradient(linear,left bottom,left top,from(#eff8ff),to(#fff));background-image:-webkit-linear-gradient(bottom,#eff8ff,#fff);background-image:-moz-linear-gradient(bottom,#eff8ff,#fff);background-image:-o-linear-gradient(bottom,#eff8ff,#fff);background-image:linear-gradient(to top,#eff8ff,#fff)}.wp-slider .ui-slider-handle:hover,.wp-slider .ui-slider-handle:focus{border-color:#a0c3d5}.wp-slider .ui-slider-handle.ui-state-hover,.wp-slider .ui-slider-handle.ui-state-focus{border-color:#a0c3d5;outline:0}#sidemenu a{background-color:#f9f9f9;border-color:#f9f9f9;border-bottom-color:#dfdfdf}#sidemenu a.current{background-color:#fff;border-color:#dfdfdf #dfdfdf #fff;color:#d54e21}#replyerror{border-color:#ddd;background-color:#f9f9f9}.vim-current,.vim-current th,.vim-current td{background-color:#e4f2fd!important}#plugin-information .fyi ul{background-color:#eaf3fa}#plugin-information .fyi h2.mainheader{background-color:#cee1ef}#plugin-information pre,#plugin-information code{background-color:#ededff}#plugin-information pre{border:1px solid #ccc}#bulk-titles{border-color:#ddd}.inline-editor div.title{background-color:#eaf3fa}.inline-editor ul.cat-checklist{background-color:#fff;border-color:#ddd}.inline-editor .quick-edit-save{background-color:#f1f1f1}fieldset.inline-edit-col-right .inline-edit-col{border-color:#dfdfdf}.attention{color:#d54e21}.js .meta-box-sortables .postbox:hover .handlediv{background:transparent url(../images/arrows-vs.png) no-repeat 6px 7px}.tablenav .tablenav-pages{color:#555}.tablenav .tablenav-pages a{border-color:#d1e5ee;background:#eee;-moz-box-shadow:inset 0 1px 0 #fff;-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.tablenav .tablenav-pages a:hover,.tablenav .tablenav-pages a:focus{color:#d54e21}.tablenav .tablenav-pages a.disabled,.tablenav .tablenav-pages a.disabled:hover,.tablenav .tablenav-pages a.disabled:focus{color:#aaa}.tablenav .tablenav-pages .current{background:#dfdfdf;border-color:#d3d3d3}#availablethemes,#availablethemes td{border-color:#acd}#current-theme img{border-color:#b0c8d7}#TB_window #TB_title a.tb-theme-preview-link,#TB_window #TB_title a.tb-theme-preview-link:visited{color:#999}#TB_window #TB_title a.tb-theme-preview-link:hover,#TB_window #TB_title a.tb-theme-preview-link:focus{color:#ccc}.misc-pub-section{border-top-color:#fff;border-bottom-color:#d1e5ee}#minor-publishing{border-bottom-color:#cae6ff}#post-body .misc-pub-section{border-left-color:#eee}.post-com-count span{background-color:#bbb}.form-table .color-palette td{border-color:#fff}.sortable-placeholder{border-color:#bbb;background-color:#f5f5f5}#post-body ul.category-tabs li.tabs a,#post-body ul.add-menu-item-tabs li.tabs a,body.press-this ul.category-tabs li.tabs a{color:#333}.view-switch #view-switch-list,.view-switch #view-switch-excerpt{background-color:transparent;background-image:url(../images/list.png);background-repeat:no-repeat}.view-switch #view-switch-list{background-position:0 0}.view-switch .current #view-switch-list{background-position:-40px 0}.view-switch #view-switch-excerpt{background-position:-20px 0}.view-switch .current #view-switch-excerpt{background-position:-60px 0}#header-logo{background:transparent url(../images/wp-logo-vs.png?ver=20101102) no-repeat scroll center center}.popular-tags,.feature-filter{background-color:#fff;border-color:#d1e5ee}div.widgets-sortables,#widgets-left .inactive,#available-widgets .widget-holder{background-color:#f7fcfe;border-color:#d0dfe9}#available-widgets .widget-description{color:#555}.sidebar-name{color:#464646;text-shadow:#fff 0 1px 0;border-color:#d0dfe9;-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.js .sidebar-name:hover,.js #removing-widget{color:#d54e21}#removing-widget span{color:#000}.js .sidebar-name-arrow{background:transparent url(../images/arrows-vs.png) no-repeat 5px 9px}.js .sidebar-name:hover .sidebar-name-arrow{background:transparent url(../images/arrows-dark-vs.png) no-repeat 5px 9px}.in-widget-title{color:#606060}.deleting .widget-title *{color:#aaa}.imgedit-menu div{border-color:#d5d5d5;background-color:#f1f1f1}.imgedit-menu div:hover{border-color:#c1c1c1;background-color:#eaeaea}.imgedit-menu div.disabled{border-color:#ccc;background-color:#ddd;filter:alpha(opacity=50);opacity:.5}#dashboard_recent_comments div.undo{border-top-color:#dfdfdf}.comment-ays,.comment-ays th{border-color:#ddd}.comment-ays th{background-color:#f1f1f1}#menu-management .menu-edit{border-color:#d0dfe9}#post-body{background:#fff;border-top-color:#fff;border-bottom-color:#d0dfe9}#nav-menu-header{border-bottom-color:#d0dfe9}#nav-menu-footer{border-top-color:#fff}#menu-management .nav-tabs-arrow a{color:#c1c1c1}#menu-management .nav-tabs-arrow a:hover{color:#d54e21}#menu-management .nav-tabs-arrow a:active{color:#464646}#menu-management .nav-tab-active{border-color:#dfdfdf}#menu-management .nav-tab{background:#f7fcfe;border-color:#d0dfe9}.js .input-with-default-title{color:#aaa}#cancel-save{color:red}#cancel-save:hover{background-color:red;color:#fff}.list-container{border-color:#dfdfdf}.menu-item-handle{border-color:#d0dfe9}.menu li.deleting .menu-item-handle{background-color:#f66;text-shadow:#ccc}.item-type{color:#999}.item-controls .menu-item-delete:hover{color:red}.nav-menus-php .item-edit{background:transparent url(../images/arrows-vs.png) no-repeat 8px 10px;border-bottom-color:#eff8ff}.nav-menus-php .item-edit:hover{background:transparent url(../images/arrows-dark-vs.png) no-repeat 8px 10px}.menu-item-settings{border-color:#d0dfe9}.link-to-original{color:#777;border-color:#d0dfe9}#cancel-save:hover{color:#fff!important}#update-menu-item{color:#fff!important}#update-menu-item:hover,#update-menu-item:active,#update-menu-item:focus{color:#eaf2fa!important;border-color:#13455b!important}.submitbox .submitcancel{color:#21759b;border-bottom-color:#21759b}.submitbox .submitcancel:hover{background:#21759b;color:#fff}.nav-tab{border-color:#d1e5ee #d1e5ee #fff}.nav-tab:hover,.nav-tab-active{border-color:#acd #acd #fff}h2.nav-tab-wrapper,h3.nav-tab-wrapper{border-bottom-color:#acd}#menu-management .nav-tab-active,.menu-item-handle,.menu-item-settings{-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}#menu-management .nav-tab-active{background:#f7fcfe;border-bottom-color:#f7fcfe}#upload-form label{color:#777}.fullscreen-overlay{background:#fff}.wp-fullscreen-focus #wp-fullscreen-title,.wp-fullscreen-focus #wp-fullscreen-container{border-color:#bed1dd}#fullscreen-topbar{border-bottom-color:#d1e5ee}.about-wrap h1{color:#333;text-shadow:1px 1px 1px #fff}.about-text{color:#777}.wp-badge{color:#fff;text-shadow:0 -1px 0 rgba(22,57,81,.3)}.about-wrap h2 .nav-tab{color:#21759b}.about-wrap h2 .nav-tab:hover{color:#d54e21}.about-wrap h2 .nav-tab-active,.about-wrap h2 .nav-tab-active:hover{color:#333}.about-wrap h2 .nav-tab-active{text-shadow:1px 1px 1px #fff;color:#464646}.about-wrap h3{color:#333;text-shadow:1px 1px 1px #fff}.about-wrap .feature-section h4{color:#464646}.about-wrap h4.wp-people-group{text-shadow:1px 1px 1px #fff}.about-wrap .point-releases{border-bottom:1px solid #dfdfdf}.about-wrap .point-releases h3{border-top:1px solid #dfdfdf}.about-wrap .point-releases h3:first-child{border:0}.about-wrap li.wp-person img.gravatar{-webkit-box-shadow:0 0 4px rgba(0,0,0,.4);box-shadow:0 0 4px rgba(0,0,0,.4)}.about-wrap li.wp-person .title{color:#464646;text-shadow:1px 1px 1px #fff}.freedoms-php .about-wrap ol li{color:#999}.freedoms-php .about-wrap ol p{color:#464646}.rtl .bar{border-right-color:transparent;border-left-color:#99d}.rtl #screen-meta-links a.show-settings{background-position:left 3px}.rtl #screen-meta-links a.show-settings.screen-meta-active{background-position:left -33px}.rtl #adminmenushadow,.rtl #adminmenuback{background-image:url(../images/menu-shadow-rtl.png);background-position:top left}.rtl #adminmenu .wp-submenu .wp-submenu-head{border-right-color:transparent;border-left-color:#d1e5ee}.rtl #adminmenu .wp-submenu,.rtl.folded #adminmenu .wp-has-current-submenu .wp-submenu{-webkit-box-shadow:-2px 2px 5px rgba(0,0,0,.4);box-shadow:-2px 2px 5px rgba(0,0,0,.4)}.rtl #adminmenu .wp-has-current-submenu .wp-submenu{-webkit-box-shadow:none;box-shadow:none}.rtl #collapse-button div{background-position:0 -108px}.rtl.folded #collapse-button div{background-position:0 -72px}@media only screen and (max-width:900px){.rtl.auto-fold #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.rtl.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu{-webkit-box-shadow:-2px 2px 5px rgba(0,0,0,.4);box-shadow:-2px 2px 5px rgba(0,0,0,.4)}.rtl.auto-fold #collapse-button div{background-position:0 -72px}}.js.rtl .meta-box-sortables .postbox:hover .handlediv{background:transparent url(../images/arrows-vs.png) no-repeat 6px 7px}.rtl #post-body .misc-pub-section{border-right-color:transparent;border-left-color:#d1e5ee}.js.rtl .sidebar-name-arrow{background:transparent url(../images/arrows-vs.png) no-repeat 5px 9px}.js.rtl .sidebar-name:hover .sidebar-name-arrow{background:transparent url(../images/arrows-dark-vs.png) no-repeat 5px 9px}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.curtime #timestamp{background-image:url(../images/date-button-2x.gif?ver=20120916);background-size:16px auto}.tagchecklist span a,#bulk-titles div a,.tagchecklist span a:hover,#bulk-titles div a:hover{background-image:url(../images/xit-2x.gif?ver=20120916);background-size:20px auto}#screen-meta-links a.show-settings,#screen-meta-links a.show-settings.screen-meta-active,#adminmenu .wp-has-submenu:hover .wp-menu-toggle,#adminmenu .wp-menu-open .wp-menu-toggle,#collapse-button div,.nav-menus-php .item-edit,.js .meta-box-sortables .postbox:hover .handlediv,.sidebar-name-arrow,.rtl #adminmenu .wp-has-submenu:hover .wp-menu-toggle,.rtl #adminmenu .wp-menu-open .wp-menu-toggle,.js.rtl .meta-box-sortables .postbox:hover .handlediv,.rtl .sidebar-name-arrow{background-image:url(../images/arrows-vs-2x.png?ver=20120916);background-size:15px 123px}#adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle,#adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle,.nav-menus-php .item-edit:hover,.sidebar-name:hover .sidebar-name-arrow,.rtl #adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle,.rtl #adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle,.rtl .sidebar-name:hover .sidebar-name-arrow{background-image:url(../images/arrows-dark-vs-2x.png?ver=20120916);background-size:15px 123px}.view-switch #view-switch-list,.view-switch #view-switch-excerpt{background-image:url(../images/list-2x.png?ver=20120916);background-size:80px 20px}.icon32.icon-post,#icon-edit,#icon-post,.icon32.icon-dashboard,#icon-index,.icon32.icon-media,#icon-upload,.icon32.icon-links,#icon-link-manager,#icon-link,#icon-link-category,.icon32.icon-page,#icon-edit-pages,#icon-page,.icon32.icon-comments,#icon-edit-comments,.icon32.icon-appearance,#icon-themes,.icon32.icon-plugins,#icon-plugins,.icon32.icon-users,#icon-users,#icon-profile,#icon-user-edit,.icon32.icon-tools,#icon-tools,#icon-admin,.icon32.icon-settings,#icon-options-general,.icon32.icon-site,#icon-ms-admin,.icon32.icon-generic,#icon-generic{background-image:url(../images/icons32-vs-2x.png?ver=20121105);background-size:756px 45px}.icon16.icon-dashboard,.menu-icon-dashboard div.wp-menu-image,.icon16.icon-post,.menu-icon-post div.wp-menu-image,.icon16.icon-media,.menu-icon-media div.wp-menu-image,.icon16.icon-links,.menu-icon-links div.wp-menu-image,.icon16.icon-page,.menu-icon-page div.wp-menu-image,.icon16.icon-comments,.menu-icon-comments div.wp-menu-image,.icon16.icon-appearance,.menu-icon-appearance div.wp-menu-image,.icon16.icon-plugins,.menu-icon-plugins div.wp-menu-image,.icon16.icon-users,.menu-icon-users div.wp-menu-image,.icon16.icon-tools,.menu-icon-tools div.wp-menu-image,.icon16.icon-settings,.menu-icon-settings div.wp-menu-image,.icon16.icon-site,.menu-icon-site div.wp-menu-image,.icon16.icon-generic,.menu-icon-generic div.wp-menu-image{background-image:url(../images/menu-vs-2x.png?ver=20121105);background-size:390px 64px}#header-logo{background-image:url(../images/wp-logo-vs-2x.png?ver=20120916);background-size:16px auto}.post-format-icon{background-image:url(../images/post-formats32-vs.png);background-size:16px 304px}} \ No newline at end of file diff --git a/sources/wp-admin/css/colors-fresh.css b/sources/wp-admin/css/colors-fresh.css new file mode 100644 index 0000000..547d6f4 --- /dev/null +++ b/sources/wp-admin/css/colors-fresh.css @@ -0,0 +1,2141 @@ +/*------------------------------------------------------------------------------ + + +Howdy! This is the CSS file that controls the +Gray (fresh) color style on the WordPress Dashboard. + +This file contains both LTR and RTL styles. + + +TABLE OF CONTENTS: +------------------ + 1.0 - Left to Right Styles + 2.0 - Right to Left Styles + + +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 1.0 - Left to Right Styles +------------------------------------------------------------------------------*/ + +.find-box-search, +.find-box-buttons { + background-color: #f7f7f7; + border-top: 1px solid #ddd; +} + +.find-box { + background-color: #444; +} + +.find-box-head { + color: #eee; +} + +.find-box-inside { + background-color: #fff; +} + +a.page-numbers:hover { + border-color: #999; +} + +body, +#wpbody, +.form-table .pre, +.ui-autocomplete li a { + color: #333; +} + +body > #upload-menu { + border-bottom-color: #fff; +} + +#postcustomstuff table, +#your-profile fieldset, +#rightnow, +div.dashboard-widget, +#dashboard-widgets p.dashboard-widget-links { + border-color: #ccc; +} + +#poststuff .inside label.spam, +#poststuff .inside label.deleted { + color: red; +} + +#poststuff .inside label.waiting { + color: orange; +} + +#poststuff .inside label.approved { + color: green; +} + +#postcustomstuff table { + border-color: #dfdfdf; + background-color: #f9f9f9; +} + +#postcustomstuff thead th { + background-color: #f1f1f1; +} + +table.widefat { + border-color: #dfdfdf; + background-color: #f9f9f9; +} + +div.dashboard-widget-error { + background-color: #c43; +} + +div.dashboard-widget-notice { + background-color: #cfe1ef; +} + +div.dashboard-widget-submit { + border-top-color: #ccc; +} + +ul.category-tabs li { + border-color: transparent; +} + +div.tabs-panel, +.wp-tab-panel, +ul.add-menu-item-tabs li.tabs, +.wp-tab-active { + border-color: #dfdfdf; + background-color: #fff; +} + +ul.category-tabs li.tabs { + border-color: #dfdfdf #dfdfdf #fff; +} + +ul.category-tabs li.tabs, +ul.add-menu-item-tabs li.tabs, +.wp-tab-active { + background-color: #fff; +} + +kbd, +code { + background: #eaeaea; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="file"], +input[type="email"], +input[type="number"], +input[type="search"], +input[type="tel"], +input[type="url"], +select { + border-color: #dfdfdf; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="file"]:focus, +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +select:focus { + border-color: #aaa; +} + +input.disabled, +textarea.disabled { + background-color: #ccc; +} + +#plugin-information .action-button a, +#plugin-information .action-button a:hover, +#plugin-information .action-button a:visited { + color: #fff; +} + +.revisions-meta, +.widget .widget-top, +.postbox h3, +.stuffbox h3, +.widefat thead tr th, +.widefat tfoot tr th, +h3.dashboard-widget-title, +h3.dashboard-widget-title span, +h3.dashboard-widget-title small, +.sidebar-name, +#nav-menu-header, +#nav-menu-footer, +.menu-item-handle { + background: #f1f1f1; + background-image: -webkit-gradient(linear, left bottom, left top, from(#ececec), to(#f9f9f9)); + background-image: -webkit-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: -moz-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: -o-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: linear-gradient(to top, #ececec, #f9f9f9); +} + + + +.widget .widget-top, +.postbox h3, +.stuffbox h3 { + border-bottom-color: #dfdfdf; + text-shadow: #fff 0 1px 0; + -webkit-box-shadow: 0 1px 0 #fff; + box-shadow: 0 1px 0 #fff; +} + +.form-table th, +.form-wrap label { + color: #222; + text-shadow: #fff 0 1px 0; +} + +.description, +.form-wrap p { + color: #666; +} + +strong .post-com-count span { + background-color: #21759b; +} + +.sorthelper { + background-color: #ccf3fa; +} + +.ac_match, +.subsubsub a.current { + color: #000; +} + +.wrap h2 { + color: #464646; +} + +.wrap .add-new-h2, +.wrap .add-new-h2:active { + background: #f1f1f1; +} + +.subtitle { + color: #777; +} + +.ac_over { + background-color: #f0f0b8; +} + +.ac_results { + background-color: #fff; + border-color: #808080; +} + +.ac_results li { + color: #101010; +} + +.alternate, +.alt { + background-color: #fcfcfc; +} + +.available-theme a.screenshot { + background-color: #f1f1f1; + border-color: #ddd; +} + +#current-theme { + border-bottom-color: #dfdfdf; +} + +.bar { + background-color: #e8e8e8; + border-right-color: #99d; +} + +#media-upload, +#media-upload .media-item .slidetoggle { + background: #fff; +} + +#media-upload .slidetoggle { + border-top-color: #dfdfdf; +} + +div.error, +.login #login_error { + background-color: #ffebe8; + border-color: #c00; +} + +div.error a { + color: #c00; +} + +.form-invalid { + background-color: #ffebe8 !important; +} + +.form-invalid input, +.form-invalid select { + border-color: #c00 !important; +} + +.submit, +#commentsdiv #add-new-comment { + border-color: #dfdfdf; +} + +.highlight { + background-color: #e4f2fd; + color: #000; +} + +.howto, +.nonessential, +#edit-slug-box, +.form-input-tip, +.subsubsub { + color: #666; +} + +.media-upload-form label.form-help, +td.help { + color: #9a9a9a; +} + +.ui-autocomplete { + border-color: #aaa; + background-color: #efefef; +} + +.ui-autocomplete li a.ui-state-focus { + background-color: #ddd; +} + +.post-com-count { + color: #fff; +} + +.post-com-count span { + background-color: #bbb; + color: #fff; +} + +.post-com-count:hover span { + background-color: #d54e21; +} + +.quicktags, .search { + background-color: #ccc; + color: #000; +} + +.side-info h5 { + border-bottom-color: #dadada; +} + +.side-info ul { + color: #666; +} + +a:hover, +a:active { + color: #d54e21; +} + +a:focus { + color: #124964; +} + +#adminmenu a:hover, +#adminmenu li.menu-top > a:focus, +#adminmenu .wp-submenu a:hover, +#the-comment-list .comment a:hover, +#rightnow a:hover, +#media-upload a.del-link:hover, +div.dashboard-widget-submit input:hover, +.subsubsub a:hover, +.subsubsub a.current:hover, +.ui-tabs-nav a:hover, +.plugins .inactive a:hover, +#all-plugins-table .plugins .inactive a:hover, +#search-plugins-table .plugins .inactive a:hover { + color: #d54e21; +} + +#the-comment-list .comment-item, +#dashboard-widgets #dashboard_quick_press form p.submit { + border-color: #dfdfdf; +} + +#side-sortables .category-tabs .tabs a, +#side-sortables .add-menu-item-tabs .tabs a, +.wp-tab-bar .wp-tab-active a { + color: #333; +} + +#rightnow .rbutton { + background-color: #ebebeb; + color: #264761; +} + +#dashboard_right_now .table_content, +#dashboard_right_now .table_discussion { + border-top-color: #ececec; +} + +.submitbox .submit { + background-color: #464646; + color: #ccc; +} + +.plugins a.delete:hover, +#all-plugins-table .plugins a.delete:hover, +#search-plugins-table .plugins a.delete:hover, +.submitbox .submitdelete { + color: #f00; + border-bottom-color: #f00; +} + +.submitbox .submitdelete:hover, +#media-items a.delete:hover, +#media-items a.delete-permanently:hover, +#nav-menu-footer .menu-delete:hover { + color: #fff; + background-color: #f00; + border-bottom-color: #f00; +} + +#normal-sortables .submitbox .submitdelete:hover { + color: #000; + background-color: #f00; + border-bottom-color: #f00; +} + +.tablenav .dots { + border-color: transparent; +} + +.tablenav .next, +.tablenav .prev { + border-color: transparent; + color: #21759b; +} + +.tablenav .next:hover, +.tablenav .prev:hover { + border-color: transparent; + color: #d54e21; +} + +div.updated, +.login .message { + background-color: #ffffe0; + border-color: #e6db55; +} + +.update-message { + color: #000; +} + +a.page-numbers { + border-bottom-color: #b8d3e2; +} + +.commentlist li { + border-bottom-color: #ccc; +} + +.widefat td, +.widefat th { + border-top-color: #fff; + border-bottom-color: #dfdfdf; +} + +.widefat th { + text-shadow: rgba(255,255,255,0.8) 0 1px 0; +} + +.widefat td { + color: #555; +} +.widefat p, +.widefat ol, +.widefat ul { + color: #333; +} + +.widefat thead tr th, +.widefat tfoot tr th, +h3.dashboard-widget-title, +h3.dashboard-widget-title span, +h3.dashboard-widget-title small { + color: #333; +} + +th.sortable a:hover, +th.sortable a:active, +th.sortable a:focus { + color: #333; +} + +th.sortable a:focus { + background: #e1e1e1; + background-image: -webkit-gradient(linear, left bottom, left top, from(#dcdcdc), to(#e9e9e9)); + background-image: -webkit-linear-gradient(bottom, #dcdcdc, #e9e9e9); + background-image: -moz-linear-gradient(bottom, #dcdcdc, #e9e9e9); + background-image: -o-linear-gradient(bottom, #dcdcdc, #e9e9e9); + background-image: linear-gradient(to top, #dcdcdc, #e9e9e9); +} + +h3.dashboard-widget-title small a { + color: #d7d7d7; +} + +h3.dashboard-widget-title small a:hover { + color: #fff; +} + +a, +#adminmenu a, +#the-comment-list p.comment-author strong a, +#media-upload a.del-link, +#media-items a.delete, +#media-items a.delete-permanently, +.plugins a.delete, +.ui-tabs-nav a { + color: #21759b; +} + +#adminmenu .awaiting-mod, +#adminmenu .update-plugins, +#sidemenu a .update-plugins, +#rightnow .reallynow { + background-color: #464646; + color: #fff; + -webkit-box-shadow: rgba(255,255,255,0.5) 0 1px 0; + box-shadow: rgba(255,255,255,0.5) 0 1px 0; +} +#plugin-information .action-button { + background-color: #d54e21; + color: #fff; +} + +#adminmenu li.current a .awaiting-mod, +#adminmenu li a.wp-has-current-submenu .update-plugins{ + background-color: #464646; + color: #fff; + -webkit-box-shadow: rgba(255,255,255,0.5) 0 1px 0; + box-shadow: rgba(255,255,255,0.5) 0 1px 0; +} + +div#media-upload-header, +div#plugin-information-header { + background-color: #f9f9f9; + border-bottom-color: #dfdfdf; +} + +#currenttheme img { + border-color: #666; +} + +#dashboard_secondary div.dashboard-widget-content ul li a { + background-color: #f9f9f9; +} + +input.readonly, textarea.readonly { + background-color: #ddd; +} + +#editable-post-name { + background-color: #fffbcc; +} + +#edit-slug-box strong, +.tablenav .displaying-num, +#submitted-on, +.submitted-on { + color: #777; +} + +.login #nav a, +.login #backtoblog a { + color: #21759b !important; +} + +.login #nav a:hover, +.login #backtoblog a:hover { + color: #d54e21 !important; +} + +#wpfooter { + color: #777; + border-color: #dfdfdf; +} + +.imgedit-group, +#media-items .media-item, +.media-item .describe { + border-color: #dfdfdf; +} + +.checkbox, +.side-info, +.plugins tr, +#your-profile #rich_editing { + background-color: #fcfcfc; +} + +.plugins .inactive, +.plugins .inactive th, +.plugins .inactive td, +tr.inactive + tr.plugin-update-tr .plugin-update { + background-color: #f4f4f4; +} + +.plugin-update-tr .update-message { + background-color: #fffbe4; + border-color: #dfdfdf; +} + +.plugins .active, +.plugins .active th, +.plugins .active td { + color: #000; +} + +.plugins .inactive a { + color: #579; +} + +#the-comment-list tr.undo, +#the-comment-list div.undo { + background-color: #f4f4f4; +} + +#the-comment-list .unapproved { + background-color: #ffffe0; +} + +#the-comment-list .approve a { + color: #006505; +} + +#the-comment-list .unapprove a { + color: #d98500; +} + +table.widefat span.delete a, +table.widefat span.trash a, +table.widefat span.spam a, +#dashboard_recent_comments .delete a, +#dashboard_recent_comments .trash a, +#dashboard_recent_comments .spam a { + color: #bc0b0b; +} + +.welcome-panel { + background: #f5f5f5; + background-image: -webkit-gradient(linear, left bottom, left top, from(#f5f5f5), to(#fafafa)); + background-image: -webkit-linear-gradient(bottom, #f5f5f5, #fafafa); + background-image: -moz-linear-gradient(bottom, #f5f5f5, #fafafa); + background-image: -o-linear-gradient(bottom, #f5f5f5, #fafafa); + background-image: linear-gradient(to top, #f5f5f5, #fafafa); + border-color: #dfdfdf; +} +.welcome-panel p { + color: #777; +} +.welcome-panel-column p { + color: #464646; +} +.welcome-panel h3 { + text-shadow: 1px 1px 1px #fff; +} + +.widget, +#widget-list .widget-top, +.postbox, +#titlediv, +#poststuff .postarea, +.stuffbox { + border-color: #dfdfdf; + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.widget, +#widget-list .widget-top, +.postbox, +.menu-item-settings { + background: #f5f5f5; + background-image: -webkit-gradient(linear, left bottom, left top, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(bottom, #f5f5f5, #f9f9f9); + background-image: -moz-linear-gradient(bottom, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(bottom, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to top, #f5f5f5, #f9f9f9); +} + +.postbox h3 { + color: #464646; +} + +.widget .widget-top { + color: #222; +} + +.js .sidebar-name:hover h3, +.js .postbox h3:hover { + color: #000; +} + +.curtime #timestamp { + background-image: url(../images/date-button.gif); +} + +#rightnow .youhave { + background-color: #f0f6fb; +} + +#rightnow a { + color: #448abd; +} + +.tagchecklist span a, +#bulk-titles div a { + background: url(../images/xit.gif) no-repeat; +} + +.tagchecklist span a:hover, +#bulk-titles div a:hover { + background: url(../images/xit.gif) no-repeat -10px 0; +} + +#update-nag, .update-nag { + background-color: #fffbcc; + border-color: #e6db55; + color: #555; +} + +#screen-meta { + background-color: #f1f1f1; + border-color: #ccc; + -webkit-box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.05 ); + box-shadow: 0 1px 3px rgba( 0, 0, 0, 0.05 ); +} + +#contextual-help-back { + background: #fff; +} + +.contextual-help-tabs a:hover { + color: #333; +} + +#contextual-help-back, +.contextual-help-tabs .active { + border-color: #ccc; +} + +.contextual-help-tabs .active, +.contextual-help-tabs .active a, +.contextual-help-tabs .active a:hover { + background: #fff; + color: #333; +} + +/* screen options and help tabs */ +#screen-options-link-wrap, +#contextual-help-link-wrap { + border-right: 1px solid #ccc; + border-left: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: #e3e3e3; + background-image: -webkit-gradient(linear, left bottom, left top, from(#dfdfdf), to(#f1f1f1)); + background-image: -webkit-linear-gradient(bottom, #dfdfdf, #f1f1f1); + background-image: -moz-linear-gradient(bottom, #dfdfdf, #f1f1f1); + background-image: -o-linear-gradient(bottom, #dfdfdf, #f1f1f1); + background-image: linear-gradient(to top, #dfdfdf, #f1f1f1); +} + +#screen-meta-links a { + color: #777; + background: transparent url(../images/arrows.png) no-repeat right 4px; +} + +#screen-meta-links a:hover, +#screen-meta-links a:active { + color: #333; + background-color: transparent; +} + +#screen-meta-links a.screen-meta-active { + background-position: right -31px; +} + +/* end screen options and help tabs */ + +.login #backtoblog a { + color: #464646; +} + +#wphead { + border-bottom: #dfdfdf 1px solid; +} + +#wphead h1 a { + color: #464646; +} + +#wpfooter a:link, +#wpfooter a:visited { + text-decoration: none; +} + +#wpfooter a:hover { + text-decoration: underline; +} + +.file-error, +abbr.required, +.widget-control-remove:hover, +table.widefat .delete a:hover, +table.widefat .trash a:hover, +table.widefat .spam a:hover, +#dashboard_recent_comments .delete a:hover, +#dashboard_recent_comments .trash a:hover +#dashboard_recent_comments .spam a:hover { + color: #f00; +} + +#pass-strength-result { + background-color: #eee; + border-color: #ddd !important; +} + +#pass-strength-result.bad { + background-color: #ffb78c; + border-color: #ff853c !important; +} + +#pass-strength-result.good { + background-color: #ffec8b; + border-color: #fc0 !important; +} + +#pass-strength-result.short { + background-color: #ffa0a0; + border-color: #f04040 !important; +} + +#pass-strength-result.strong { + background-color: #c3ff88; + border-color: #8dff1c !important; +} + +#post-status-info { + border-color: #dfdfdf #ccc #ccc; + background-color: #eaeaea; +} + +.editwidget .widget-inside { + border-color: #dfdfdf; +} + +#titlediv #title { + background-color: #fff; +} + +#tTips p#tTips_inside { + background-color: #ddd; + color: #333; +} + +#poststuff .inside .the-tagcloud { + border-color: #ddd; +} + +/* menu */ +#adminmenuback, +#adminmenuwrap { + background-color: #ececec; + border-color: #ccc; +} + +#adminmenushadow, +#adminmenuback { + background-image: url(../images/menu-shadow.png); + background-position: top right; + background-repeat: repeat-y; +} + +#adminmenu li.wp-menu-separator { + background: #dfdfdf; + border-color: #cfcfcf; +} + +#adminmenu div.separator { + border-color: #e1e1e1; +} + +#adminmenu a.menu-top, +#adminmenu .wp-submenu .wp-submenu-head { + border-top-color: #f9f9f9; + border-bottom-color: #dfdfdf; +} + +#adminmenu li.wp-menu-open { + border-color: #dfdfdf; +} + +#adminmenu li.menu-top:hover, +#adminmenu li.opensub > a.menu-top, +#adminmenu li > a.menu-top:focus { + background-color: #e4e4e4; + color: #d54e21; + text-shadow: 0 1px 0 rgba( 255, 255, 255, 0.4 ); +} + +/* So it doesn't get applied to the number spans (comments, updates, etc) */ +#adminmenu li.menu-top:hover > a span, +#adminmenu li.menu-top > a:focus span { + text-shadow: none; +} + +#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu, +#adminmenu li.current a.menu-top, +.folded #adminmenu li.wp-has-current-submenu, +.folded #adminmenu li.current.menu-top, +#adminmenu .wp-menu-arrow, +#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head { + background: #777; + background-image: -webkit-gradient(linear, left bottom, left top, from(#6d6d6d), to(#808080)); + background-image: -webkit-linear-gradient(bottom, #6d6d6d, #808080); + background-image: -moz-linear-gradient(bottom, #6d6d6d, #808080); + background-image: -o-linear-gradient(bottom, #6d6d6d, #808080); + background-image: linear-gradient(to top, #6d6d6d, #808080); +} + +#adminmenu .wp-menu-arrow div { + background: #777; + background-image: -webkit-gradient(linear, right bottom, left top, from(#6d6d6d), to(#808080)); + background-image: -webkit-linear-gradient(bottom right, #6d6d6d, #808080); + background-image: -moz-linear-gradient(bottom right, #6d6d6d, #808080); + background-image: -o-linear-gradient(bottom right, #6d6d6d, #808080); + background-image: linear-gradient(to top left, #6d6d6d, #808080); +} + +#adminmenu li.wp-not-current-submenu .wp-menu-arrow { + border-top-color: #f9f9f9; + border-bottom-color: #dfdfdf; + background: #e4e4e4; +} + +#adminmenu li.wp-not-current-submenu .wp-menu-arrow div { + background: #e4e4e4; + border-color: #ccc; +} + +.folded #adminmenu li.menu-top li:hover a { + background-image: none; +} + +#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu, +#adminmenu li.current a.menu-top, +#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head { + text-shadow: 0 -1px 0 #333; + color: #fff; + border-top-color: #808080; + border-bottom-color: #6d6d6d; +} + +.folded #adminmenu li.wp-has-current-submenu, +.folded #adminmenu li.current.menu-top { + border-top-color: #808080; + border-bottom-color: #6d6d6d; +} + +#adminmenu .wp-submenu a:hover, +#adminmenu .wp-submenu a:focus { + background-color: #eaf2fa; + color: #333; +} + +#adminmenu .wp-submenu li.current, +#adminmenu .wp-submenu li.current a, +#adminmenu .wp-submenu li.current a:hover { + color: #333; +} + +#adminmenu .wp-submenu, +.folded #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, +.folded #adminmenu .wp-has-current-submenu .wp-submenu { + background-color: #fff; + border-color: #dfdfdf; + -webkit-box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); + box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); +} + +#adminmenu .wp-submenu .wp-submenu-head { + background-color: #e4e4e4; + color: #333; +} + +/* collapse menu button */ +#collapse-menu { + color: #aaa; + border-top-color: #f9f9f9; +} + +#collapse-menu:hover { + color: #999; +} + +#collapse-button { + border-color: #ccc; + background: #f4f4f4; + background-image: -webkit-gradient(linear, left bottom, left top, from(#dfdfdf), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #dfdfdf, #fff); + background-image: -moz-linear-gradient(bottom, #dfdfdf, #fff); + background-image: -o-linear-gradient(bottom, #dfdfdf, #fff); + background-image: linear-gradient(to top, #dfdfdf, #fff); +} + +#collapse-menu:hover #collapse-button { + border-color: #aaa; +} + +#collapse-button div { + background: transparent url(../images/arrows.png) no-repeat 0 -72px; +} + +.folded #collapse-button div { + background-position: 0 -108px; +} + +/* Auto-folding of the admin menu */ +@media only screen and (max-width: 900px) { + .auto-fold #adminmenu li.wp-has-current-submenu, + .auto-fold #adminmenu li.current.menu-top { + background-color: #777; + background-image: -webkit-gradient(linear, left bottom, left top, from(#6d6d6d), to(#808080)); + background-image: -webkit-linear-gradient(bottom, #6d6d6d, #808080); + background-image: -moz-linear-gradient(bottom, #6d6d6d, #808080); + background-image: -o-linear-gradient(bottom, #6d6d6d, #808080); + background-image: linear-gradient(bottom, #6d6d6d, #808080); + } + + .auto-fold #adminmenu li.wp-has-current-submenu, + .auto-fold #adminmenu li.current.menu-top { + border-top-color: #808080; + border-bottom-color: #6d6d6d; + } + + .auto-fold #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu .wp-submenu { + background-color: #fff; + border-color: #dfdfdf; + -webkit-box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); + box-shadow: 2px 3px 6px rgba(0, 0, 0, 0.4); + } + + .auto-fold #collapse-button div { + background-position: 0 -108px; + } +} + +/* menu and screen icons */ +.icon16, +.icon32, +div.wp-menu-image { + background-color: transparent; + background-repeat: no-repeat; +} + +.icon16.icon-dashboard, +.menu-icon-dashboard div.wp-menu-image, +.icon16.icon-post, +.menu-icon-post div.wp-menu-image, +.icon16.icon-media, +.menu-icon-media div.wp-menu-image, +.icon16.icon-links, +.menu-icon-links div.wp-menu-image, +.icon16.icon-page, +.menu-icon-page div.wp-menu-image, +.icon16.icon-comments, +.menu-icon-comments div.wp-menu-image, +.icon16.icon-appearance, +.menu-icon-appearance div.wp-menu-image, +.icon16.icon-plugins, +.menu-icon-plugins div.wp-menu-image, +.icon16.icon-users, +.menu-icon-users div.wp-menu-image, +.icon16.icon-tools, +.menu-icon-tools div.wp-menu-image, +.icon16.icon-settings, +.menu-icon-settings div.wp-menu-image, +.icon16.icon-site, +.menu-icon-site div.wp-menu-image, +.icon16.icon-generic, +.menu-icon-generic div.wp-menu-image { + background-image: url(../images/menu.png?ver=20121105); +} + +.icon16.icon-dashboard, +#adminmenu .menu-icon-dashboard div.wp-menu-image { + background-position: -59px -33px; +} + +#adminmenu .menu-icon-dashboard:hover div.wp-menu-image, +#adminmenu .menu-icon-dashboard.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-dashboard.current div.wp-menu-image { + background-position: -59px -1px; +} + +.icon16.icon-post, +#adminmenu .menu-icon-post div.wp-menu-image { + background-position: -269px -33px; +} + +#adminmenu .menu-icon-post:hover div.wp-menu-image, +#adminmenu .menu-icon-post.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-post.current div.wp-menu-image { + background-position: -269px -1px; +} + +.icon16.icon-media, +#adminmenu .menu-icon-media div.wp-menu-image { + background-position: -119px -33px; +} + +#adminmenu .menu-icon-media:hover div.wp-menu-image, +#adminmenu .menu-icon-media.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-media.current div.wp-menu-image { + background-position: -119px -1px; +} + +.icon16.icon-links, +#adminmenu .menu-icon-links div.wp-menu-image { + background-position: -89px -33px; +} + +#adminmenu .menu-icon-links:hover div.wp-menu-image, +#adminmenu .menu-icon-links.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-links.current div.wp-menu-image { + background-position: -89px -1px; +} + +.icon16.icon-page, +#adminmenu .menu-icon-page div.wp-menu-image { + background-position: -149px -33px; +} + +#adminmenu .menu-icon-page:hover div.wp-menu-image, +#adminmenu .menu-icon-page.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-page.current div.wp-menu-image { + background-position: -149px -1px; +} + +.icon16.icon-comments, +#adminmenu .menu-icon-comments div.wp-menu-image { + background-position: -29px -33px; +} + +#adminmenu .menu-icon-comments:hover div.wp-menu-image, +#adminmenu .menu-icon-comments.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-comments.current div.wp-menu-image { + background-position: -29px -1px; +} + +.icon16.icon-appearance, +#adminmenu .menu-icon-appearance div.wp-menu-image { + background-position: 1px -33px; +} + +#adminmenu .menu-icon-appearance:hover div.wp-menu-image, +#adminmenu .menu-icon-appearance.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-appearance.current div.wp-menu-image { + background-position: 1px -1px; +} + +.icon16.icon-plugins, +#adminmenu .menu-icon-plugins div.wp-menu-image { + background-position: -179px -33px; +} + +#adminmenu .menu-icon-plugins:hover div.wp-menu-image, +#adminmenu .menu-icon-plugins.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-plugins.current div.wp-menu-image { + background-position: -179px -1px; +} + +.icon16.icon-users, +#adminmenu .menu-icon-users div.wp-menu-image { + background-position: -300px -33px; +} + +#adminmenu .menu-icon-users:hover div.wp-menu-image, +#adminmenu .menu-icon-users.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-users.current div.wp-menu-image { + background-position: -300px -1px; +} + +.icon16.icon-tools, +#adminmenu .menu-icon-tools div.wp-menu-image { + background-position: -209px -33px; +} + +#adminmenu .menu-icon-tools:hover div.wp-menu-image, +#adminmenu .menu-icon-tools.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-tools.current div.wp-menu-image { + background-position: -209px -1px; +} + +.icon16.icon-settings, +#adminmenu .menu-icon-settings div.wp-menu-image { + background-position: -239px -33px; +} + +#adminmenu .menu-icon-settings:hover div.wp-menu-image, +#adminmenu .menu-icon-settings.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-settings.current div.wp-menu-image { + background-position: -239px -1px; +} + +.icon16.icon-site, +#adminmenu .menu-icon-site div.wp-menu-image { + background-position: -359px -33px; +} + +#adminmenu .menu-icon-site:hover div.wp-menu-image, +#adminmenu .menu-icon-site.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-site.current div.wp-menu-image { + background-position: -359px -1px; +} + +.icon16.icon-generic, +#adminmenu .menu-icon-generic div.wp-menu-image { + background-position: -330px -33px; +} + +#adminmenu .menu-icon-generic:hover div.wp-menu-image, +#adminmenu .menu-icon-generic.wp-has-current-submenu div.wp-menu-image, +#adminmenu .menu-icon-generic.current div.wp-menu-image { + background-position: -330px -1px; +} + +/* end menu and screen icons */ + +/* Screen Icons */ +.icon32.icon-post, +#icon-edit, +#icon-post, +.icon32.icon-dashboard, +#icon-index, +.icon32.icon-media, +#icon-upload, +.icon32.icon-links, +#icon-link-manager, +#icon-link, +#icon-link-category, +.icon32.icon-page, +#icon-edit-pages, +#icon-page, +.icon32.icon-comments, +#icon-edit-comments, +.icon32.icon-appearance, +#icon-themes, +.icon32.icon-plugins, +#icon-plugins, +.icon32.icon-users, +#icon-users, +#icon-profile, +#icon-user-edit, +.icon32.icon-tools, +#icon-tools, +#icon-admin, +.icon32.icon-settings, +#icon-options-general, +.icon32.icon-site, +#icon-ms-admin, +.icon32.icon-generic, +#icon-generic { + background-image: url(../images/icons32.png?ver=20121105); +} + +.icon32.icon-post, +#icon-edit, +#icon-post { + background-position: -552px -5px; +} + +.icon32.icon-dashboard, +#icon-index { + background-position: -137px -5px; +} + +.icon32.icon-media, +#icon-upload { + background-position: -251px -5px; +} + +.icon32.icon-links, +#icon-link-manager, +#icon-link, +#icon-link-category { + background-position: -190px -5px; +} + +.icon32.icon-page, +#icon-edit-pages, +#icon-page { + background-position: -312px -5px; +} + +.icon32.icon-comments, +#icon-edit-comments { + background-position: -72px -5px; +} + +.icon32.icon-appearance, +#icon-themes { + background-position: -11px -5px; +} + +.icon32.icon-plugins, +#icon-plugins { + background-position: -370px -5px; +} + +.icon32.icon-users, +#icon-users, +#icon-profile, +#icon-user-edit { + background-position: -600px -5px; +} + +.icon32.icon-tools, +#icon-tools, +#icon-admin { + background-position: -432px -5px; +} + +.icon32.icon-settings, +#icon-options-general { + background-position: -492px -5px; +} + +.icon32.icon-site, +#icon-ms-admin { + background-position: -659px -5px; +} + +.icon32.icon-generic, +#icon-generic { + background-position: -708px -5px; +} + +/* end screen icons */ + +/* Post format icons */ + +.post-format-icon { + background: url(../images/post-formats.png) no-repeat; +} + +/* Diff */ +table.diff .diff-deletedline { + background-color: #ffe9e9; +} + +table.diff .diff-deletedline del { + background-color: #faa; +} + +table.diff .diff-addedline { + background-color: #e9ffe9; +} + +table.diff .diff-addedline ins { + background-color: #afa; +} + +.revisions-meta { + border: 1px solid #dfdfdf; +} + +.revisions-controls { + background: #fff; + background: -webkit-gradient(linear, left bottom, left top, color-stop(0%,rgba(255,255,255,1)), color-stop(30px,rgba(255,255,255,1)), color-stop(100%,rgba(255,255,255,1))); + background: -webkit-linear-gradient(bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); + background: -moz-linear-gradient(bottom, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); + background: -o-linear-gradient(bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); + background: linear-gradient(to top, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 30px, rgba(255,255,255,1) 100%); +} + +.revisions-tooltip, +.revisions-tooltip-arrow span { + border-color: #d7d7d7; + background-color: #fff; +} + +.revisions-tickmarks > div { + border-color: #aaa; +} + +/* jQuery UI Slider */ +.wp-slider.ui-slider { + border-color: #d7d7d7; +} + +.wp-slider .ui-slider-handle { + border-color: #ccc; + border-radius: 50%; + background: #f4f4f4; + background-image: -webkit-gradient(linear, left bottom, left top, from(#dfdfdf), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #dfdfdf, #fff); + background-image: -moz-linear-gradient(bottom, #dfdfdf, #fff); + background-image: -o-linear-gradient(bottom, #dfdfdf, #fff); + background-image: linear-gradient(to top, #dfdfdf, #fff); + color: #333; +} + +.wp-slider .ui-slider-handle:hover, +.wp-slider .ui-slider-handle:focus { + border-color: #aaa; +} + +.wp-slider .ui-slider-handle.ui-state-hover, +.wp-slider .ui-slider-handle.ui-state-focus { + border-color: #aaa; + outline: none; +} + +/* edit image */ +#sidemenu a { + background-color: #f9f9f9; + border-color: #f9f9f9; + border-bottom-color: #dfdfdf; +} + +#sidemenu a.current { + background-color: #fff; + border-color: #dfdfdf #dfdfdf #fff; + color: #d54e21; +} + +#replyerror { + border-color: #ddd; + background-color: #f9f9f9; +} + +/* table vim shortcuts */ +.vim-current, +.vim-current th, +.vim-current td { + background-color: #E4F2FD !important; +} + +/* Install Plugins */ +#plugin-information .fyi ul { + background-color: #eaf3fa; +} + +#plugin-information .fyi h2.mainheader { + background-color: #cee1ef; +} + +#plugin-information pre, +#plugin-information code { + background-color: #ededff; +} + +#plugin-information pre { + border: 1px solid #ccc; +} + +/* inline editor */ +#bulk-titles { + border-color: #ddd; +} + +.inline-editor div.title { + background-color: #eaf3fa; +} + +.inline-editor ul.cat-checklist { + background-color: #fff; + border-color: #ddd; +} + +.inline-editor .quick-edit-save { + background-color: #f1f1f1; +} + +fieldset.inline-edit-col-right .inline-edit-col { + border-color: #dfdfdf; +} + +.attention { + color: #d54e21; +} + +.js .meta-box-sortables .postbox:hover .handlediv { + background: transparent url(../images/arrows.png) no-repeat 6px 7px; +} + +.tablenav .tablenav-pages { + color: #555; +} + +.tablenav .tablenav-pages a { + border-color: #e3e3e3; + background: #eee; + -moz-box-shadow: inset 0 1px 0 #fff; + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; +} + +.tablenav .tablenav-pages a:hover, +.tablenav .tablenav-pages a:focus { + color: #d54e21; +} + +.tablenav .tablenav-pages a.disabled, +.tablenav .tablenav-pages a.disabled:hover, +.tablenav .tablenav-pages a.disabled:focus { + color: #aaa; +} + +.tablenav .tablenav-pages .current { + background: #dfdfdf; + border-color: #d3d3d3; +} + +#availablethemes, +#availablethemes td { + border-color: #ddd; +} + +#current-theme img { + border-color: #999; +} + +#TB_window #TB_title a.tb-theme-preview-link, +#TB_window #TB_title a.tb-theme-preview-link:visited { + color: #999; +} + +#TB_window #TB_title a.tb-theme-preview-link:hover, +#TB_window #TB_title a.tb-theme-preview-link:focus { + color: #ccc; +} + +.misc-pub-section { + border-top-color: #fff; + border-bottom-color: #dfdfdf; +} + +#minor-publishing { + border-bottom-color: #dfdfdf; +} + +#post-body .misc-pub-section { + border-left-color: #eee; +} + +.post-com-count span { + background-color: #bbb; +} + +.form-table .color-palette td { + border-color: #fff; +} + +.sortable-placeholder { + border-color: #bbb; + background-color: #f5f5f5; +} + +#post-body ul.category-tabs li.tabs a, +#post-body ul.add-menu-item-tabs li.tabs a, +body.press-this ul.category-tabs li.tabs a { + color: #333; +} + +.view-switch #view-switch-list, +.view-switch #view-switch-excerpt { + background-color: transparent; + background-image: url('../images/list.png'); + background-repeat: no-repeat; +} + +.view-switch #view-switch-list { + background-position: 0 0; +} + +.view-switch .current #view-switch-list { + background-position: -40px 0; +} + +.view-switch #view-switch-excerpt { + background-position: -20px 0; +} + +.view-switch .current #view-switch-excerpt { + background-position: -60px 0; +} + +#header-logo { + background: transparent url(../images/wp-logo.png?ver=20110504) no-repeat scroll center center; +} + +.popular-tags, +.feature-filter { + background-color: #fff; + border-color: #dfdfdf; +} + +div.widgets-sortables, +#widgets-left .inactive, +#available-widgets .widget-holder { + background-color: #fcfcfc; + border-color: #dfdfdf; +} + +#available-widgets .widget-description { + color: #555; +} + +.sidebar-name { + color: #464646; + text-shadow: #fff 0 1px 0; + border-color: #dfdfdf; + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; +} + +.js .sidebar-name:hover, +.js #removing-widget { + color: #d54e21; +} + +#removing-widget span { + color: black; +} + +.js .sidebar-name-arrow { + background: transparent url(../images/arrows.png) no-repeat 5px 9px; +} + +.js .sidebar-name:hover .sidebar-name-arrow { + background: transparent url(../images/arrows-dark.png) no-repeat 5px 9px; +} + +.in-widget-title { + color: #606060; +} + +.deleting .widget-title * { + color: #aaa; +} + +.imgedit-menu div { + border-color: #d5d5d5; + background-color: #f1f1f1; +} + +.imgedit-menu div:hover { + border-color: #c1c1c1; + background-color: #eaeaea; +} + +.imgedit-menu div.disabled { + border-color: #ccc; + background-color: #ddd; + filter: alpha(opacity=50); + opacity: 0.5; +} + +#dashboard_recent_comments div.undo { + border-top-color: #dfdfdf; +} + +.comment-ays, +.comment-ays th { + border-color: #ddd; +} + +.comment-ays th { + background-color: #f1f1f1; +} + +/* added from nav-menu.css */ +#menu-management .menu-edit { + border-color: #dfdfdf; +} + +#post-body { + background: #fff; + border-top-color: #fff; + border-bottom-color: #dfdfdf; +} + +#nav-menu-header { + border-bottom-color: #dfdfdf; +} + +#nav-menu-footer { + border-top-color: #fff; +} + +#menu-management .nav-tabs-arrow a { + color: #c1c1c1; +} + +#menu-management .nav-tabs-arrow a:hover { + color: #d54e21; +} + +#menu-management .nav-tabs-arrow a:active { + color: #464646; +} + +#menu-management .nav-tab-active { + border-color: #dfdfdf; +} + +#menu-management .nav-tab { + background: #fbfbfb; + border-color: #dfdfdf; +} + +.js .input-with-default-title { + color: #aaa; +} + +#cancel-save { + color: #f00; +} + +#cancel-save:hover { + background-color: #f00; + color: #fff; +} + +.list-container, +.menu-item-handle { + border-color: #dfdfdf; +} + +.menu li.deleting .menu-item-handle { + background-color: #f66; + text-shadow: #ccc; +} + +.item-type { /* Menu item controls */ + color: #999; +} + +.item-controls .menu-item-delete:hover { + color: #f00; +} + +.nav-menus-php .item-edit { + background: transparent url(../images/arrows.png) no-repeat 8px 10px; + border-bottom-color: #eee; +} + +.nav-menus-php .item-edit:hover { + background: transparent url(../images/arrows-dark.png) no-repeat 8px 10px; +} + +.menu-item-settings { /* Menu editing */ + border-color: #dfdfdf; +} + +.link-to-original { + color: #777; + border-color: #dfdfdf; +} + +#cancel-save:hover { + color: #fff !important; +} + +#update-menu-item { + color: #fff !important; +} + +#update-menu-item:hover, +#update-menu-item:active, +#update-menu-item:focus { + color: #eaf2fa !important; + border-color: #13455b !important; +} + +.submitbox .submitcancel { + color: #21759b; + border-bottom-color: #21759b; +} + +.submitbox .submitcancel:hover { + background: #21759b; + color: #fff; +} + +.manage-menus { + border: 1px solid #eeeeee; + background: #fbfbfb; +} + +.theme-location-set { + color: #999999; +} + +.nav-menus-php .delete-action a { + color: #bc0b0b; +} + +.is-submenu { + color: #999999; +} +/* end added from nav-menu.css */ + +.nav-tab { + border-color: #dfdfdf #dfdfdf #fff; +} + +.nav-tab:hover, +.nav-tab-active { + border-color: #ccc #ccc #fff; +} + +h2.nav-tab-wrapper, h3.nav-tab-wrapper { + border-bottom-color: #ccc; +} + +#menu-management .nav-tab-active, +.menu-item-handle, +.menu-item-settings { + -webkit-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff; +} + +#menu-management .nav-tab-active { + background: #f9f9f9; + border-bottom-color: #f9f9f9; +} + +#upload-form label { + color: #777; +} + +/* Begin About Pages */ + +.about-wrap h1 { + color: #333; + text-shadow: 1px 1px 1px #fff; +} + +.about-text { + color: #777; +} + +.wp-badge { + color: #fff; + text-shadow: 0 -1px 0 rgba(22, 57, 81, 0.3); +} + +.about-wrap h2 .nav-tab { + color: #21759b; +} + +.about-wrap h2 .nav-tab:hover { + color: #d54e21; +} + +.about-wrap h2 .nav-tab-active, +.about-wrap h2 .nav-tab-active:hover { + color: #333; +} + +.about-wrap h2 .nav-tab-active { + text-shadow: 1px 1px 1px #fff; + color: #464646; +} + +.about-wrap h3 { + color: #333; + text-shadow: 1px 1px 1px #fff; +} + +.about-wrap .feature-section h4 { + color: #464646; +} + +.about-wrap h4.wp-people-group { + text-shadow: 1px 1px 1px #fff; +} + +.about-wrap .point-releases { + border-bottom: 1px solid #dfdfdf; +} + +.about-wrap .point-releases h3 { + border-top: 1px solid #dfdfdf; +} + +.about-wrap .point-releases h3:first-child { + border: 0; +} + +.about-wrap li.wp-person img.gravatar { + -webkit-box-shadow: 0 0 4px rgba( 0, 0, 0, 0.4 ); + box-shadow: 0 0 4px rgba( 0, 0, 0, 0.4 ); +} + +.about-wrap li.wp-person .title { + color: #464646; + text-shadow: 1px 1px 1px #fff; +} + +.freedoms-php .about-wrap ol li { + color: #999; +} + +.freedoms-php .about-wrap ol p { + color: #464646; +} + +/* End About Pages */ + + +/*------------------------------------------------------------------------------ + 2.0 - Right to Left Styles +------------------------------------------------------------------------------*/ + +.rtl .bar { + border-right-color: transparent; + border-left-color: #99d; +} + +.rtl #screen-meta-links a.show-settings { + background-position: left 3px; +} + +.rtl #screen-meta-links a.show-settings.screen-meta-active { + background-position: left -33px; +} + +/* Menu */ +.rtl #adminmenushadow, +.rtl #adminmenuback { + background-image: url(../images/menu-shadow-rtl.png); + background-position: top left; +} + +.rtl #adminmenu .wp-submenu .wp-submenu-head { + border-right-color: transparent; + border-left-color: #dfdfdf; +} + +.rtl #adminmenu .wp-submenu, +.rtl.folded #adminmenu .wp-has-current-submenu .wp-submenu { + -webkit-box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); + box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); +} + +.rtl #adminmenu .wp-has-current-submenu .wp-submenu { + -webkit-box-shadow: none; + box-shadow: none; +} + +/* Collapse Menu Button */ +.rtl #collapse-button div { + background-position: 0 -108px; +} + +.rtl.folded #collapse-button div { + background-position: 0 -72px; +} + +/* Auto-folding of the admin menu for RTL */ +@media only screen and (max-width: 900px) { + .rtl.auto-fold #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, + .rtl.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu { + -webkit-box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); + box-shadow: -2px 2px 5px rgba( 0, 0, 0, 0.4 ); + } + + .rtl.auto-fold #collapse-button div { + background-position: 0 -72px; + } +} + +/* Edit Image */ +.js.rtl .meta-box-sortables .postbox:hover .handlediv { + background: transparent url(../images/arrows.png) no-repeat 6px 7px; +} + +.rtl #post-body .misc-pub-section { + border-right-color: transparent; + border-left-color: #eee; +} + +.js.rtl .sidebar-name-arrow { + background: transparent url(../images/arrows.png) no-repeat 5px 9px; +} + +.js.rtl .sidebar-name:hover .sidebar-name-arrow { + background: transparent url(../images/arrows-dark.png) no-repeat 5px 9px; +} + +/** + * HiDPI Displays + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + + .curtime #timestamp { + background-image: url("../images/date-button-2x.gif?ver=20120916"); + background-size: 16px auto; + } + + .tagchecklist span a, + #bulk-titles div a, + .tagchecklist span a:hover, + #bulk-titles div a:hover { + background-image: url("../images/xit-2x.gif?ver=20120916"); + background-size: 20px auto; + } + + #screen-meta-links a.show-settings, + #screen-meta-links a.show-settings.screen-meta-active, + #adminmenu .wp-has-submenu:hover .wp-menu-toggle, + #adminmenu .wp-menu-open .wp-menu-toggle, + #collapse-button div, + .nav-menus-php .item-edit, + .js .meta-box-sortables .postbox:hover .handlediv, + .sidebar-name-arrow, + .rtl #adminmenu .wp-has-submenu:hover .wp-menu-toggle, + .rtl #adminmenu .wp-menu-open .wp-menu-toggle, + .js.rtl .meta-box-sortables .postbox:hover .handlediv, + .rtl .sidebar-name-arrow { + background-image: url("../images/arrows-2x.png?ver=20120916"); + background-size: 15px 123px; + } + + #adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle, + #adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle, + .sidebar-name:hover .sidebar-name-arrow, + .nav-menus-php .item-edit:hover, + .rtl #adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle, + .rtl #adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle, + .rtl .sidebar-name:hover .sidebar-name-arrow { + background-image: url("../images/arrows-dark-2x.png?ver=20120916"); + background-size: 15px 123px; + } + + .view-switch #view-switch-list, + .view-switch #view-switch-excerpt { + background-image: url("../images/list-2x.png?ver=20120916"); + background-size: 80px 20px; + } + + .icon32.icon-post, + #icon-edit, + #icon-post, + .icon32.icon-dashboard, + #icon-index, + .icon32.icon-media, + #icon-upload, + .icon32.icon-links, + #icon-link-manager, + #icon-link, + #icon-link-category, + .icon32.icon-page, + #icon-edit-pages, + #icon-page, + .icon32.icon-comments, + #icon-edit-comments, + .icon32.icon-appearance, + #icon-themes, + .icon32.icon-plugins, + #icon-plugins, + .icon32.icon-users, + #icon-users, + #icon-profile, + #icon-user-edit, + .icon32.icon-tools, + #icon-tools, + #icon-admin, + .icon32.icon-settings, + #icon-options-general, + .icon32.icon-site, + #icon-ms-admin, + .icon32.icon-generic, + #icon-generic { + background-image: url(../images/icons32-2x.png?ver=20121105); + background-size: 756px 45px; + } + + .icon16.icon-dashboard, + .menu-icon-dashboard div.wp-menu-image, + .icon16.icon-post, + .menu-icon-post div.wp-menu-image, + .icon16.icon-media, + .menu-icon-media div.wp-menu-image, + .icon16.icon-links, + .menu-icon-links div.wp-menu-image, + .icon16.icon-page, + .menu-icon-page div.wp-menu-image, + .icon16.icon-comments, + .menu-icon-comments div.wp-menu-image, + .icon16.icon-appearance, + .menu-icon-appearance div.wp-menu-image, + .icon16.icon-plugins, + .menu-icon-plugins div.wp-menu-image, + .icon16.icon-users, + .menu-icon-users div.wp-menu-image, + .icon16.icon-tools, + .menu-icon-tools div.wp-menu-image, + .icon16.icon-settings, + .menu-icon-settings div.wp-menu-image, + .icon16.icon-site, + .menu-icon-site div.wp-menu-image, + .icon16.icon-generic, + .menu-icon-generic div.wp-menu-image { + background-image: url('../images/menu-2x.png?ver=20121105'); + background-size: 390px 64px; + } + + #header-logo { + background-image: url('../images/wp-logo-2x.png?ver=20120916'); + background-size: 16px auto; + } + + /* 16px post formats */ + .post-format-icon { + background-image: url(../images/post-formats32.png); + background-size: 16px 304px; + } + +} diff --git a/sources/wp-admin/css/colors-fresh.min.css b/sources/wp-admin/css/colors-fresh.min.css new file mode 100644 index 0000000..b51baf0 --- /dev/null +++ b/sources/wp-admin/css/colors-fresh.min.css @@ -0,0 +1 @@ +.find-box-search,.find-box-buttons{background-color:#f7f7f7;border-top:1px solid #ddd}.find-box{background-color:#444}.find-box-head{color:#eee}.find-box-inside{background-color:#fff}a.page-numbers:hover{border-color:#999}body,#wpbody,.form-table .pre,.ui-autocomplete li a{color:#333}body>#upload-menu{border-bottom-color:#fff}#postcustomstuff table,#your-profile fieldset,#rightnow,div.dashboard-widget,#dashboard-widgets p.dashboard-widget-links{border-color:#ccc}#poststuff .inside label.spam,#poststuff .inside label.deleted{color:red}#poststuff .inside label.waiting{color:orange}#poststuff .inside label.approved{color:green}#postcustomstuff table{border-color:#dfdfdf;background-color:#f9f9f9}#postcustomstuff thead th{background-color:#f1f1f1}table.widefat{border-color:#dfdfdf;background-color:#f9f9f9}div.dashboard-widget-error{background-color:#c43}div.dashboard-widget-notice{background-color:#cfe1ef}div.dashboard-widget-submit{border-top-color:#ccc}ul.category-tabs li{border-color:transparent}div.tabs-panel,.wp-tab-panel,ul.add-menu-item-tabs li.tabs,.wp-tab-active{border-color:#dfdfdf;background-color:#fff}ul.category-tabs li.tabs{border-color:#dfdfdf #dfdfdf #fff}ul.category-tabs li.tabs,ul.add-menu-item-tabs li.tabs,.wp-tab-active{background-color:#fff}kbd,code{background:#eaeaea}textarea,input[type=text],input[type=password],input[type=file],input[type=email],input[type=number],input[type=search],input[type=tel],input[type=url],select{border-color:#dfdfdf}textarea:focus,input[type=text]:focus,input[type=password]:focus,input[type=file]:focus,input[type=email]:focus,input[type=number]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=url]:focus,select:focus{border-color:#aaa}input.disabled,textarea.disabled{background-color:#ccc}#plugin-information .action-button a,#plugin-information .action-button a:hover,#plugin-information .action-button a:visited{color:#fff}.revisions-meta,.widget .widget-top,.postbox h3,.stuffbox h3,.widefat thead tr th,.widefat tfoot tr th,h3.dashboard-widget-title,h3.dashboard-widget-title span,h3.dashboard-widget-title small,.sidebar-name,#nav-menu-header,#nav-menu-footer,.menu-item-handle{background:#f1f1f1;background-image:-webkit-gradient(linear,left bottom,left top,from(#ececec),to(#f9f9f9));background-image:-webkit-linear-gradient(bottom,#ececec,#f9f9f9);background-image:-moz-linear-gradient(bottom,#ececec,#f9f9f9);background-image:-o-linear-gradient(bottom,#ececec,#f9f9f9);background-image:linear-gradient(to top,#ececec,#f9f9f9)}.widget .widget-top,.postbox h3,.stuffbox h3{border-bottom-color:#dfdfdf;text-shadow:#fff 0 1px 0;-webkit-box-shadow:0 1px 0 #fff;box-shadow:0 1px 0 #fff}.form-table th,.form-wrap label{color:#222;text-shadow:#fff 0 1px 0}.description,.form-wrap p{color:#666}strong .post-com-count span{background-color:#21759b}.sorthelper{background-color:#ccf3fa}.ac_match,.subsubsub a.current{color:#000}.wrap h2{color:#464646}.wrap .add-new-h2,.wrap .add-new-h2:active{background:#f1f1f1}.subtitle{color:#777}.ac_over{background-color:#f0f0b8}.ac_results{background-color:#fff;border-color:gray}.ac_results li{color:#101010}.alternate,.alt{background-color:#fcfcfc}.available-theme a.screenshot{background-color:#f1f1f1;border-color:#ddd}#current-theme{border-bottom-color:#dfdfdf}.bar{background-color:#e8e8e8;border-right-color:#99d}#media-upload,#media-upload .media-item .slidetoggle{background:#fff}#media-upload .slidetoggle{border-top-color:#dfdfdf}div.error,.login #login_error{background-color:#ffebe8;border-color:#c00}div.error a{color:#c00}.form-invalid{background-color:#ffebe8!important}.form-invalid input,.form-invalid select{border-color:#c00!important}.submit,#commentsdiv #add-new-comment{border-color:#dfdfdf}.highlight{background-color:#e4f2fd;color:#000}.howto,.nonessential,#edit-slug-box,.form-input-tip,.subsubsub{color:#666}.media-upload-form label.form-help,td.help{color:#9a9a9a}.ui-autocomplete{border-color:#aaa;background-color:#efefef}.ui-autocomplete li a.ui-state-focus{background-color:#ddd}.post-com-count{color:#fff}.post-com-count span{background-color:#bbb;color:#fff}.post-com-count:hover span{background-color:#d54e21}.quicktags,.search{background-color:#ccc;color:#000}.side-info h5{border-bottom-color:#dadada}.side-info ul{color:#666}a:hover,a:active{color:#d54e21}a:focus{color:#124964}#adminmenu a:hover,#adminmenu li.menu-top>a:focus,#adminmenu .wp-submenu a:hover,#the-comment-list .comment a:hover,#rightnow a:hover,#media-upload a.del-link:hover,div.dashboard-widget-submit input:hover,.subsubsub a:hover,.subsubsub a.current:hover,.ui-tabs-nav a:hover,.plugins .inactive a:hover,#all-plugins-table .plugins .inactive a:hover,#search-plugins-table .plugins .inactive a:hover{color:#d54e21}#the-comment-list .comment-item,#dashboard-widgets #dashboard_quick_press form p.submit{border-color:#dfdfdf}#side-sortables .category-tabs .tabs a,#side-sortables .add-menu-item-tabs .tabs a,.wp-tab-bar .wp-tab-active a{color:#333}#rightnow .rbutton{background-color:#ebebeb;color:#264761}#dashboard_right_now .table_content,#dashboard_right_now .table_discussion{border-top-color:#ececec}.submitbox .submit{background-color:#464646;color:#ccc}.plugins a.delete:hover,#all-plugins-table .plugins a.delete:hover,#search-plugins-table .plugins a.delete:hover,.submitbox .submitdelete{color:red;border-bottom-color:red}.submitbox .submitdelete:hover,#media-items a.delete:hover,#media-items a.delete-permanently:hover,#nav-menu-footer .menu-delete:hover{color:#fff;background-color:red;border-bottom-color:red}#normal-sortables .submitbox .submitdelete:hover{color:#000;background-color:red;border-bottom-color:red}.tablenav .dots{border-color:transparent}.tablenav .next,.tablenav .prev{border-color:transparent;color:#21759b}.tablenav .next:hover,.tablenav .prev:hover{border-color:transparent;color:#d54e21}div.updated,.login .message{background-color:#ffffe0;border-color:#e6db55}.update-message{color:#000}a.page-numbers{border-bottom-color:#b8d3e2}.commentlist li{border-bottom-color:#ccc}.widefat td,.widefat th{border-top-color:#fff;border-bottom-color:#dfdfdf}.widefat th{text-shadow:rgba(255,255,255,.8) 0 1px 0}.widefat td{color:#555}.widefat p,.widefat ol,.widefat ul{color:#333}.widefat thead tr th,.widefat tfoot tr th,h3.dashboard-widget-title,h3.dashboard-widget-title span,h3.dashboard-widget-title small{color:#333}th.sortable a:hover,th.sortable a:active,th.sortable a:focus{color:#333}th.sortable a:focus{background:#e1e1e1;background-image:-webkit-gradient(linear,left bottom,left top,from(#dcdcdc),to(#e9e9e9));background-image:-webkit-linear-gradient(bottom,#dcdcdc,#e9e9e9);background-image:-moz-linear-gradient(bottom,#dcdcdc,#e9e9e9);background-image:-o-linear-gradient(bottom,#dcdcdc,#e9e9e9);background-image:linear-gradient(to top,#dcdcdc,#e9e9e9)}h3.dashboard-widget-title small a{color:#d7d7d7}h3.dashboard-widget-title small a:hover{color:#fff}a,#adminmenu a,#the-comment-list p.comment-author strong a,#media-upload a.del-link,#media-items a.delete,#media-items a.delete-permanently,.plugins a.delete,.ui-tabs-nav a{color:#21759b}#adminmenu .awaiting-mod,#adminmenu .update-plugins,#sidemenu a .update-plugins,#rightnow .reallynow{background-color:#464646;color:#fff;-webkit-box-shadow:rgba(255,255,255,.5) 0 1px 0;box-shadow:rgba(255,255,255,.5) 0 1px 0}#plugin-information .action-button{background-color:#d54e21;color:#fff}#adminmenu li.current a .awaiting-mod,#adminmenu li a.wp-has-current-submenu .update-plugins{background-color:#464646;color:#fff;-webkit-box-shadow:rgba(255,255,255,.5) 0 1px 0;box-shadow:rgba(255,255,255,.5) 0 1px 0}div#media-upload-header,div#plugin-information-header{background-color:#f9f9f9;border-bottom-color:#dfdfdf}#currenttheme img{border-color:#666}#dashboard_secondary div.dashboard-widget-content ul li a{background-color:#f9f9f9}input.readonly,textarea.readonly{background-color:#ddd}#editable-post-name{background-color:#fffbcc}#edit-slug-box strong,.tablenav .displaying-num,#submitted-on,.submitted-on{color:#777}.login #nav a,.login #backtoblog a{color:#21759b!important}.login #nav a:hover,.login #backtoblog a:hover{color:#d54e21!important}#wpfooter{color:#777;border-color:#dfdfdf}.imgedit-group,#media-items .media-item,.media-item .describe{border-color:#dfdfdf}.checkbox,.side-info,.plugins tr,#your-profile #rich_editing{background-color:#fcfcfc}.plugins .inactive,.plugins .inactive th,.plugins .inactive td,tr.inactive+tr.plugin-update-tr .plugin-update{background-color:#f4f4f4}.plugin-update-tr .update-message{background-color:#fffbe4;border-color:#dfdfdf}.plugins .active,.plugins .active th,.plugins .active td{color:#000}.plugins .inactive a{color:#579}#the-comment-list tr.undo,#the-comment-list div.undo{background-color:#f4f4f4}#the-comment-list .unapproved{background-color:#ffffe0}#the-comment-list .approve a{color:#006505}#the-comment-list .unapprove a{color:#d98500}table.widefat span.delete a,table.widefat span.trash a,table.widefat span.spam a,#dashboard_recent_comments .delete a,#dashboard_recent_comments .trash a,#dashboard_recent_comments .spam a{color:#bc0b0b}.welcome-panel{background:#f5f5f5;background-image:-webkit-gradient(linear,left bottom,left top,from(#f5f5f5),to(#fafafa));background-image:-webkit-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:-moz-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:-o-linear-gradient(bottom,#f5f5f5,#fafafa);background-image:linear-gradient(to top,#f5f5f5,#fafafa);border-color:#dfdfdf}.welcome-panel p{color:#777}.welcome-panel-column p{color:#464646}.welcome-panel h3{text-shadow:1px 1px 1px #fff}.widget,#widget-list .widget-top,.postbox,#titlediv,#poststuff .postarea,.stuffbox{border-color:#dfdfdf;-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff;-webkit-border-radius:3px;border-radius:3px}.widget,#widget-list .widget-top,.postbox,.menu-item-settings{background:#f5f5f5;background-image:-webkit-gradient(linear,left bottom,left top,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(bottom,#f5f5f5,#f9f9f9);background-image:-moz-linear-gradient(bottom,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(bottom,#f5f5f5,#f9f9f9);background-image:linear-gradient(to top,#f5f5f5,#f9f9f9)}.postbox h3{color:#464646}.widget .widget-top{color:#222}.js .sidebar-name:hover h3,.js .postbox h3:hover{color:#000}.curtime #timestamp{background-image:url(../images/date-button.gif)}#rightnow .youhave{background-color:#f0f6fb}#rightnow a{color:#448abd}.tagchecklist span a,#bulk-titles div a{background:url(../images/xit.gif) no-repeat}.tagchecklist span a:hover,#bulk-titles div a:hover{background:url(../images/xit.gif) no-repeat -10px 0}#update-nag,.update-nag{background-color:#fffbcc;border-color:#e6db55;color:#555}#screen-meta{background-color:#f1f1f1;border-color:#ccc;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.05);box-shadow:0 1px 3px rgba(0,0,0,.05)}#contextual-help-back{background:#fff}.contextual-help-tabs a:hover{color:#333}#contextual-help-back,.contextual-help-tabs .active{border-color:#ccc}.contextual-help-tabs .active,.contextual-help-tabs .active a,.contextual-help-tabs .active a:hover{background:#fff;color:#333}#screen-options-link-wrap,#contextual-help-link-wrap{border-right:1px solid #ccc;border-left:1px solid #ccc;border-bottom:1px solid #ccc;background:#e3e3e3;background-image:-webkit-gradient(linear,left bottom,left top,from(#dfdfdf),to(#f1f1f1));background-image:-webkit-linear-gradient(bottom,#dfdfdf,#f1f1f1);background-image:-moz-linear-gradient(bottom,#dfdfdf,#f1f1f1);background-image:-o-linear-gradient(bottom,#dfdfdf,#f1f1f1);background-image:linear-gradient(to top,#dfdfdf,#f1f1f1)}#screen-meta-links a{color:#777;background:transparent url(../images/arrows.png) no-repeat right 4px}#screen-meta-links a:hover,#screen-meta-links a:active{color:#333;background-color:transparent}#screen-meta-links a.screen-meta-active{background-position:right -31px}.login #backtoblog a{color:#464646}#wphead{border-bottom:#dfdfdf 1px solid}#wphead h1 a{color:#464646}#wpfooter a:link,#wpfooter a:visited{text-decoration:none}#wpfooter a:hover{text-decoration:underline}.file-error,abbr.required,.widget-control-remove:hover,table.widefat .delete a:hover,table.widefat .trash a:hover,table.widefat .spam a:hover,#dashboard_recent_comments .delete a:hover,#dashboard_recent_comments .trash a:hover #dashboard_recent_comments .spam a:hover{color:red}#pass-strength-result{background-color:#eee;border-color:#ddd!important}#pass-strength-result.bad{background-color:#ffb78c;border-color:#ff853c!important}#pass-strength-result.good{background-color:#ffec8b;border-color:#fc0!important}#pass-strength-result.short{background-color:#ffa0a0;border-color:#f04040!important}#pass-strength-result.strong{background-color:#c3ff88;border-color:#8dff1c!important}#post-status-info{border-color:#dfdfdf #ccc #ccc;background-color:#eaeaea}.editwidget .widget-inside{border-color:#dfdfdf}#titlediv #title{background-color:#fff}#tTips p#tTips_inside{background-color:#ddd;color:#333}#poststuff .inside .the-tagcloud{border-color:#ddd}#adminmenuback,#adminmenuwrap{background-color:#ececec;border-color:#ccc}#adminmenushadow,#adminmenuback{background-image:url(../images/menu-shadow.png);background-position:top right;background-repeat:repeat-y}#adminmenu li.wp-menu-separator{background:#dfdfdf;border-color:#cfcfcf}#adminmenu div.separator{border-color:#e1e1e1}#adminmenu a.menu-top,#adminmenu .wp-submenu .wp-submenu-head{border-top-color:#f9f9f9;border-bottom-color:#dfdfdf}#adminmenu li.wp-menu-open{border-color:#dfdfdf}#adminmenu li.menu-top:hover,#adminmenu li.opensub>a.menu-top,#adminmenu li>a.menu-top:focus{background-color:#e4e4e4;color:#d54e21;text-shadow:0 1px 0 rgba(255,255,255,.4)}#adminmenu li.menu-top:hover>a span,#adminmenu li.menu-top>a:focus span{text-shadow:none}#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu,#adminmenu li.current a.menu-top,.folded #adminmenu li.wp-has-current-submenu,.folded #adminmenu li.current.menu-top,#adminmenu .wp-menu-arrow,#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head{background:#777;background-image:-webkit-gradient(linear,left bottom,left top,from(#6d6d6d),to(gray));background-image:-webkit-linear-gradient(bottom,#6d6d6d,gray);background-image:-moz-linear-gradient(bottom,#6d6d6d,gray);background-image:-o-linear-gradient(bottom,#6d6d6d,gray);background-image:linear-gradient(to top,#6d6d6d,gray)}#adminmenu .wp-menu-arrow div{background:#777;background-image:-webkit-gradient(linear,right bottom,left top,from(#6d6d6d),to(gray));background-image:-webkit-linear-gradient(bottom right,#6d6d6d,gray);background-image:-moz-linear-gradient(bottom right,#6d6d6d,gray);background-image:-o-linear-gradient(bottom right,#6d6d6d,gray);background-image:linear-gradient(to top left,#6d6d6d,gray)}#adminmenu li.wp-not-current-submenu .wp-menu-arrow{border-top-color:#f9f9f9;border-bottom-color:#dfdfdf;background:#e4e4e4}#adminmenu li.wp-not-current-submenu .wp-menu-arrow div{background:#e4e4e4;border-color:#ccc}.folded #adminmenu li.menu-top li:hover a{background-image:none}#adminmenu li.wp-has-current-submenu a.wp-has-current-submenu,#adminmenu li.current a.menu-top,#adminmenu .wp-has-current-submenu .wp-submenu .wp-submenu-head{text-shadow:0 -1px 0 #333;color:#fff;border-top-color:gray;border-bottom-color:#6d6d6d}.folded #adminmenu li.wp-has-current-submenu,.folded #adminmenu li.current.menu-top{border-top-color:gray;border-bottom-color:#6d6d6d}#adminmenu .wp-submenu a:hover,#adminmenu .wp-submenu a:focus{background-color:#eaf2fa;color:#333}#adminmenu .wp-submenu li.current,#adminmenu .wp-submenu li.current a,#adminmenu .wp-submenu li.current a:hover{color:#333}#adminmenu .wp-submenu,.folded #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.folded #adminmenu .wp-has-current-submenu .wp-submenu{background-color:#fff;border-color:#dfdfdf;-webkit-box-shadow:2px 3px 6px rgba(0,0,0,.4);box-shadow:2px 3px 6px rgba(0,0,0,.4)}#adminmenu .wp-submenu .wp-submenu-head{background-color:#e4e4e4;color:#333}#collapse-menu{color:#aaa;border-top-color:#f9f9f9}#collapse-menu:hover{color:#999}#collapse-button{border-color:#ccc;background:#f4f4f4;background-image:-webkit-gradient(linear,left bottom,left top,from(#dfdfdf),to(#fff));background-image:-webkit-linear-gradient(bottom,#dfdfdf,#fff);background-image:-moz-linear-gradient(bottom,#dfdfdf,#fff);background-image:-o-linear-gradient(bottom,#dfdfdf,#fff);background-image:linear-gradient(to top,#dfdfdf,#fff)}#collapse-menu:hover #collapse-button{border-color:#aaa}#collapse-button div{background:transparent url(../images/arrows.png) no-repeat 0 -72px}.folded #collapse-button div{background-position:0 -108px}@media only screen and (max-width:900px){.auto-fold #adminmenu li.wp-has-current-submenu,.auto-fold #adminmenu li.current.menu-top{background-color:#777;background-image:-webkit-gradient(linear,left bottom,left top,from(#6d6d6d),to(gray));background-image:-webkit-linear-gradient(bottom,#6d6d6d,gray);background-image:-moz-linear-gradient(bottom,#6d6d6d,gray);background-image:-o-linear-gradient(bottom,#6d6d6d,gray);background-image:linear-gradient(bottom,#6d6d6d,gray)}.auto-fold #adminmenu li.wp-has-current-submenu,.auto-fold #adminmenu li.current.menu-top{border-top-color:gray;border-bottom-color:#6d6d6d}.auto-fold #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu{background-color:#fff;border-color:#dfdfdf;-webkit-box-shadow:2px 3px 6px rgba(0,0,0,.4);box-shadow:2px 3px 6px rgba(0,0,0,.4)}.auto-fold #collapse-button div{background-position:0 -108px}}.icon16,.icon32,div.wp-menu-image{background-color:transparent;background-repeat:no-repeat}.icon16.icon-dashboard,.menu-icon-dashboard div.wp-menu-image,.icon16.icon-post,.menu-icon-post div.wp-menu-image,.icon16.icon-media,.menu-icon-media div.wp-menu-image,.icon16.icon-links,.menu-icon-links div.wp-menu-image,.icon16.icon-page,.menu-icon-page div.wp-menu-image,.icon16.icon-comments,.menu-icon-comments div.wp-menu-image,.icon16.icon-appearance,.menu-icon-appearance div.wp-menu-image,.icon16.icon-plugins,.menu-icon-plugins div.wp-menu-image,.icon16.icon-users,.menu-icon-users div.wp-menu-image,.icon16.icon-tools,.menu-icon-tools div.wp-menu-image,.icon16.icon-settings,.menu-icon-settings div.wp-menu-image,.icon16.icon-site,.menu-icon-site div.wp-menu-image,.icon16.icon-generic,.menu-icon-generic div.wp-menu-image{background-image:url(../images/menu.png?ver=20121105)}.icon16.icon-dashboard,#adminmenu .menu-icon-dashboard div.wp-menu-image{background-position:-59px -33px}#adminmenu .menu-icon-dashboard:hover div.wp-menu-image,#adminmenu .menu-icon-dashboard.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-dashboard.current div.wp-menu-image{background-position:-59px -1px}.icon16.icon-post,#adminmenu .menu-icon-post div.wp-menu-image{background-position:-269px -33px}#adminmenu .menu-icon-post:hover div.wp-menu-image,#adminmenu .menu-icon-post.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-post.current div.wp-menu-image{background-position:-269px -1px}.icon16.icon-media,#adminmenu .menu-icon-media div.wp-menu-image{background-position:-119px -33px}#adminmenu .menu-icon-media:hover div.wp-menu-image,#adminmenu .menu-icon-media.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-media.current div.wp-menu-image{background-position:-119px -1px}.icon16.icon-links,#adminmenu .menu-icon-links div.wp-menu-image{background-position:-89px -33px}#adminmenu .menu-icon-links:hover div.wp-menu-image,#adminmenu .menu-icon-links.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-links.current div.wp-menu-image{background-position:-89px -1px}.icon16.icon-page,#adminmenu .menu-icon-page div.wp-menu-image{background-position:-149px -33px}#adminmenu .menu-icon-page:hover div.wp-menu-image,#adminmenu .menu-icon-page.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-page.current div.wp-menu-image{background-position:-149px -1px}.icon16.icon-comments,#adminmenu .menu-icon-comments div.wp-menu-image{background-position:-29px -33px}#adminmenu .menu-icon-comments:hover div.wp-menu-image,#adminmenu .menu-icon-comments.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-comments.current div.wp-menu-image{background-position:-29px -1px}.icon16.icon-appearance,#adminmenu .menu-icon-appearance div.wp-menu-image{background-position:1px -33px}#adminmenu .menu-icon-appearance:hover div.wp-menu-image,#adminmenu .menu-icon-appearance.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-appearance.current div.wp-menu-image{background-position:1px -1px}.icon16.icon-plugins,#adminmenu .menu-icon-plugins div.wp-menu-image{background-position:-179px -33px}#adminmenu .menu-icon-plugins:hover div.wp-menu-image,#adminmenu .menu-icon-plugins.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-plugins.current div.wp-menu-image{background-position:-179px -1px}.icon16.icon-users,#adminmenu .menu-icon-users div.wp-menu-image{background-position:-300px -33px}#adminmenu .menu-icon-users:hover div.wp-menu-image,#adminmenu .menu-icon-users.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-users.current div.wp-menu-image{background-position:-300px -1px}.icon16.icon-tools,#adminmenu .menu-icon-tools div.wp-menu-image{background-position:-209px -33px}#adminmenu .menu-icon-tools:hover div.wp-menu-image,#adminmenu .menu-icon-tools.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-tools.current div.wp-menu-image{background-position:-209px -1px}.icon16.icon-settings,#adminmenu .menu-icon-settings div.wp-menu-image{background-position:-239px -33px}#adminmenu .menu-icon-settings:hover div.wp-menu-image,#adminmenu .menu-icon-settings.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-settings.current div.wp-menu-image{background-position:-239px -1px}.icon16.icon-site,#adminmenu .menu-icon-site div.wp-menu-image{background-position:-359px -33px}#adminmenu .menu-icon-site:hover div.wp-menu-image,#adminmenu .menu-icon-site.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-site.current div.wp-menu-image{background-position:-359px -1px}.icon16.icon-generic,#adminmenu .menu-icon-generic div.wp-menu-image{background-position:-330px -33px}#adminmenu .menu-icon-generic:hover div.wp-menu-image,#adminmenu .menu-icon-generic.wp-has-current-submenu div.wp-menu-image,#adminmenu .menu-icon-generic.current div.wp-menu-image{background-position:-330px -1px}.icon32.icon-post,#icon-edit,#icon-post,.icon32.icon-dashboard,#icon-index,.icon32.icon-media,#icon-upload,.icon32.icon-links,#icon-link-manager,#icon-link,#icon-link-category,.icon32.icon-page,#icon-edit-pages,#icon-page,.icon32.icon-comments,#icon-edit-comments,.icon32.icon-appearance,#icon-themes,.icon32.icon-plugins,#icon-plugins,.icon32.icon-users,#icon-users,#icon-profile,#icon-user-edit,.icon32.icon-tools,#icon-tools,#icon-admin,.icon32.icon-settings,#icon-options-general,.icon32.icon-site,#icon-ms-admin,.icon32.icon-generic,#icon-generic{background-image:url(../images/icons32.png?ver=20121105)}.icon32.icon-post,#icon-edit,#icon-post{background-position:-552px -5px}.icon32.icon-dashboard,#icon-index{background-position:-137px -5px}.icon32.icon-media,#icon-upload{background-position:-251px -5px}.icon32.icon-links,#icon-link-manager,#icon-link,#icon-link-category{background-position:-190px -5px}.icon32.icon-page,#icon-edit-pages,#icon-page{background-position:-312px -5px}.icon32.icon-comments,#icon-edit-comments{background-position:-72px -5px}.icon32.icon-appearance,#icon-themes{background-position:-11px -5px}.icon32.icon-plugins,#icon-plugins{background-position:-370px -5px}.icon32.icon-users,#icon-users,#icon-profile,#icon-user-edit{background-position:-600px -5px}.icon32.icon-tools,#icon-tools,#icon-admin{background-position:-432px -5px}.icon32.icon-settings,#icon-options-general{background-position:-492px -5px}.icon32.icon-site,#icon-ms-admin{background-position:-659px -5px}.icon32.icon-generic,#icon-generic{background-position:-708px -5px}.post-format-icon{background:url(../images/post-formats.png) no-repeat}table.diff .diff-deletedline{background-color:#ffe9e9}table.diff .diff-deletedline del{background-color:#faa}table.diff .diff-addedline{background-color:#e9ffe9}table.diff .diff-addedline ins{background-color:#afa}.revisions-meta{border:1px solid #dfdfdf}.revisions-controls{background:#fff;background:-webkit-gradient(linear,left bottom,left top,color-stop(0%,rgba(255,255,255,1)),color-stop(30px,rgba(255,255,255,1)),color-stop(100%,rgba(255,255,255,1)));background:-webkit-linear-gradient(bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%);background:-moz-linear-gradient(bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%);background:-o-linear-gradient(bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%);background:linear-gradient(to top,rgba(255,255,255,0) 0,rgba(255,255,255,1) 30px,rgba(255,255,255,1) 100%)}.revisions-tooltip,.revisions-tooltip-arrow span{border-color:#d7d7d7;background-color:#fff}.revisions-tickmarks>div{border-color:#aaa}.wp-slider.ui-slider{border-color:#d7d7d7}.wp-slider .ui-slider-handle{border-color:#ccc;border-radius:50%;background:#f4f4f4;background-image:-webkit-gradient(linear,left bottom,left top,from(#dfdfdf),to(#fff));background-image:-webkit-linear-gradient(bottom,#dfdfdf,#fff);background-image:-moz-linear-gradient(bottom,#dfdfdf,#fff);background-image:-o-linear-gradient(bottom,#dfdfdf,#fff);background-image:linear-gradient(to top,#dfdfdf,#fff);color:#333}.wp-slider .ui-slider-handle:hover,.wp-slider .ui-slider-handle:focus{border-color:#aaa}.wp-slider .ui-slider-handle.ui-state-hover,.wp-slider .ui-slider-handle.ui-state-focus{border-color:#aaa;outline:0}#sidemenu a{background-color:#f9f9f9;border-color:#f9f9f9;border-bottom-color:#dfdfdf}#sidemenu a.current{background-color:#fff;border-color:#dfdfdf #dfdfdf #fff;color:#d54e21}#replyerror{border-color:#ddd;background-color:#f9f9f9}.vim-current,.vim-current th,.vim-current td{background-color:#E4F2FD!important}#plugin-information .fyi ul{background-color:#eaf3fa}#plugin-information .fyi h2.mainheader{background-color:#cee1ef}#plugin-information pre,#plugin-information code{background-color:#ededff}#plugin-information pre{border:1px solid #ccc}#bulk-titles{border-color:#ddd}.inline-editor div.title{background-color:#eaf3fa}.inline-editor ul.cat-checklist{background-color:#fff;border-color:#ddd}.inline-editor .quick-edit-save{background-color:#f1f1f1}fieldset.inline-edit-col-right .inline-edit-col{border-color:#dfdfdf}.attention{color:#d54e21}.js .meta-box-sortables .postbox:hover .handlediv{background:transparent url(../images/arrows.png) no-repeat 6px 7px}.tablenav .tablenav-pages{color:#555}.tablenav .tablenav-pages a{border-color:#e3e3e3;background:#eee;-moz-box-shadow:inset 0 1px 0 #fff;-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.tablenav .tablenav-pages a:hover,.tablenav .tablenav-pages a:focus{color:#d54e21}.tablenav .tablenav-pages a.disabled,.tablenav .tablenav-pages a.disabled:hover,.tablenav .tablenav-pages a.disabled:focus{color:#aaa}.tablenav .tablenav-pages .current{background:#dfdfdf;border-color:#d3d3d3}#availablethemes,#availablethemes td{border-color:#ddd}#current-theme img{border-color:#999}#TB_window #TB_title a.tb-theme-preview-link,#TB_window #TB_title a.tb-theme-preview-link:visited{color:#999}#TB_window #TB_title a.tb-theme-preview-link:hover,#TB_window #TB_title a.tb-theme-preview-link:focus{color:#ccc}.misc-pub-section{border-top-color:#fff;border-bottom-color:#dfdfdf}#minor-publishing{border-bottom-color:#dfdfdf}#post-body .misc-pub-section{border-left-color:#eee}.post-com-count span{background-color:#bbb}.form-table .color-palette td{border-color:#fff}.sortable-placeholder{border-color:#bbb;background-color:#f5f5f5}#post-body ul.category-tabs li.tabs a,#post-body ul.add-menu-item-tabs li.tabs a,body.press-this ul.category-tabs li.tabs a{color:#333}.view-switch #view-switch-list,.view-switch #view-switch-excerpt{background-color:transparent;background-image:url(../images/list.png);background-repeat:no-repeat}.view-switch #view-switch-list{background-position:0 0}.view-switch .current #view-switch-list{background-position:-40px 0}.view-switch #view-switch-excerpt{background-position:-20px 0}.view-switch .current #view-switch-excerpt{background-position:-60px 0}#header-logo{background:transparent url(../images/wp-logo.png?ver=20110504) no-repeat scroll center center}.popular-tags,.feature-filter{background-color:#fff;border-color:#dfdfdf}div.widgets-sortables,#widgets-left .inactive,#available-widgets .widget-holder{background-color:#fcfcfc;border-color:#dfdfdf}#available-widgets .widget-description{color:#555}.sidebar-name{color:#464646;text-shadow:#fff 0 1px 0;border-color:#dfdfdf;-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.js .sidebar-name:hover,.js #removing-widget{color:#d54e21}#removing-widget span{color:#000}.js .sidebar-name-arrow{background:transparent url(../images/arrows.png) no-repeat 5px 9px}.js .sidebar-name:hover .sidebar-name-arrow{background:transparent url(../images/arrows-dark.png) no-repeat 5px 9px}.in-widget-title{color:#606060}.deleting .widget-title *{color:#aaa}.imgedit-menu div{border-color:#d5d5d5;background-color:#f1f1f1}.imgedit-menu div:hover{border-color:#c1c1c1;background-color:#eaeaea}.imgedit-menu div.disabled{border-color:#ccc;background-color:#ddd;filter:alpha(opacity=50);opacity:.5}#dashboard_recent_comments div.undo{border-top-color:#dfdfdf}.comment-ays,.comment-ays th{border-color:#ddd}.comment-ays th{background-color:#f1f1f1}#menu-management .menu-edit{border-color:#dfdfdf}#post-body{background:#fff;border-top-color:#fff;border-bottom-color:#dfdfdf}#nav-menu-header{border-bottom-color:#dfdfdf}#nav-menu-footer{border-top-color:#fff}#menu-management .nav-tabs-arrow a{color:#c1c1c1}#menu-management .nav-tabs-arrow a:hover{color:#d54e21}#menu-management .nav-tabs-arrow a:active{color:#464646}#menu-management .nav-tab-active{border-color:#dfdfdf}#menu-management .nav-tab{background:#fbfbfb;border-color:#dfdfdf}.js .input-with-default-title{color:#aaa}#cancel-save{color:red}#cancel-save:hover{background-color:red;color:#fff}.list-container,.menu-item-handle{border-color:#dfdfdf}.menu li.deleting .menu-item-handle{background-color:#f66;text-shadow:#ccc}.item-type{color:#999}.item-controls .menu-item-delete:hover{color:red}.nav-menus-php .item-edit{background:transparent url(../images/arrows.png) no-repeat 8px 10px;border-bottom-color:#eee}.nav-menus-php .item-edit:hover{background:transparent url(../images/arrows-dark.png) no-repeat 8px 10px}.menu-item-settings{border-color:#dfdfdf}.link-to-original{color:#777;border-color:#dfdfdf}#cancel-save:hover{color:#fff!important}#update-menu-item{color:#fff!important}#update-menu-item:hover,#update-menu-item:active,#update-menu-item:focus{color:#eaf2fa!important;border-color:#13455b!important}.submitbox .submitcancel{color:#21759b;border-bottom-color:#21759b}.submitbox .submitcancel:hover{background:#21759b;color:#fff}.manage-menus{border:1px solid #eee;background:#fbfbfb}.theme-location-set{color:#999}.nav-menus-php .delete-action a{color:#bc0b0b}.is-submenu{color:#999}.nav-tab{border-color:#dfdfdf #dfdfdf #fff}.nav-tab:hover,.nav-tab-active{border-color:#ccc #ccc #fff}h2.nav-tab-wrapper,h3.nav-tab-wrapper{border-bottom-color:#ccc}#menu-management .nav-tab-active,.menu-item-handle,.menu-item-settings{-webkit-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}#menu-management .nav-tab-active{background:#f9f9f9;border-bottom-color:#f9f9f9}#upload-form label{color:#777}.about-wrap h1{color:#333;text-shadow:1px 1px 1px #fff}.about-text{color:#777}.wp-badge{color:#fff;text-shadow:0 -1px 0 rgba(22,57,81,.3)}.about-wrap h2 .nav-tab{color:#21759b}.about-wrap h2 .nav-tab:hover{color:#d54e21}.about-wrap h2 .nav-tab-active,.about-wrap h2 .nav-tab-active:hover{color:#333}.about-wrap h2 .nav-tab-active{text-shadow:1px 1px 1px #fff;color:#464646}.about-wrap h3{color:#333;text-shadow:1px 1px 1px #fff}.about-wrap .feature-section h4{color:#464646}.about-wrap h4.wp-people-group{text-shadow:1px 1px 1px #fff}.about-wrap .point-releases{border-bottom:1px solid #dfdfdf}.about-wrap .point-releases h3{border-top:1px solid #dfdfdf}.about-wrap .point-releases h3:first-child{border:0}.about-wrap li.wp-person img.gravatar{-webkit-box-shadow:0 0 4px rgba(0,0,0,.4);box-shadow:0 0 4px rgba(0,0,0,.4)}.about-wrap li.wp-person .title{color:#464646;text-shadow:1px 1px 1px #fff}.freedoms-php .about-wrap ol li{color:#999}.freedoms-php .about-wrap ol p{color:#464646}.rtl .bar{border-right-color:transparent;border-left-color:#99d}.rtl #screen-meta-links a.show-settings{background-position:left 3px}.rtl #screen-meta-links a.show-settings.screen-meta-active{background-position:left -33px}.rtl #adminmenushadow,.rtl #adminmenuback{background-image:url(../images/menu-shadow-rtl.png);background-position:top left}.rtl #adminmenu .wp-submenu .wp-submenu-head{border-right-color:transparent;border-left-color:#dfdfdf}.rtl #adminmenu .wp-submenu,.rtl.folded #adminmenu .wp-has-current-submenu .wp-submenu{-webkit-box-shadow:-2px 2px 5px rgba(0,0,0,.4);box-shadow:-2px 2px 5px rgba(0,0,0,.4)}.rtl #adminmenu .wp-has-current-submenu .wp-submenu{-webkit-box-shadow:none;box-shadow:none}.rtl #collapse-button div{background-position:0 -108px}.rtl.folded #collapse-button div{background-position:0 -72px}@media only screen and (max-width:900px){.rtl.auto-fold #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.rtl.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu{-webkit-box-shadow:-2px 2px 5px rgba(0,0,0,.4);box-shadow:-2px 2px 5px rgba(0,0,0,.4)}.rtl.auto-fold #collapse-button div{background-position:0 -72px}}.js.rtl .meta-box-sortables .postbox:hover .handlediv{background:transparent url(../images/arrows.png) no-repeat 6px 7px}.rtl #post-body .misc-pub-section{border-right-color:transparent;border-left-color:#eee}.js.rtl .sidebar-name-arrow{background:transparent url(../images/arrows.png) no-repeat 5px 9px}.js.rtl .sidebar-name:hover .sidebar-name-arrow{background:transparent url(../images/arrows-dark.png) no-repeat 5px 9px}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.curtime #timestamp{background-image:url(../images/date-button-2x.gif?ver=20120916);background-size:16px auto}.tagchecklist span a,#bulk-titles div a,.tagchecklist span a:hover,#bulk-titles div a:hover{background-image:url(../images/xit-2x.gif?ver=20120916);background-size:20px auto}#screen-meta-links a.show-settings,#screen-meta-links a.show-settings.screen-meta-active,#adminmenu .wp-has-submenu:hover .wp-menu-toggle,#adminmenu .wp-menu-open .wp-menu-toggle,#collapse-button div,.nav-menus-php .item-edit,.js .meta-box-sortables .postbox:hover .handlediv,.sidebar-name-arrow,.rtl #adminmenu .wp-has-submenu:hover .wp-menu-toggle,.rtl #adminmenu .wp-menu-open .wp-menu-toggle,.js.rtl .meta-box-sortables .postbox:hover .handlediv,.rtl .sidebar-name-arrow{background-image:url(../images/arrows-2x.png?ver=20120916);background-size:15px 123px}#adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle,#adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle,.sidebar-name:hover .sidebar-name-arrow,.nav-menus-php .item-edit:hover,.rtl #adminmenu li.wp-has-current-submenu.wp-menu-open .wp-menu-toggle,.rtl #adminmenu li.wp-has-current-submenu:hover .wp-menu-toggle,.rtl .sidebar-name:hover .sidebar-name-arrow{background-image:url(../images/arrows-dark-2x.png?ver=20120916);background-size:15px 123px}.view-switch #view-switch-list,.view-switch #view-switch-excerpt{background-image:url(../images/list-2x.png?ver=20120916);background-size:80px 20px}.icon32.icon-post,#icon-edit,#icon-post,.icon32.icon-dashboard,#icon-index,.icon32.icon-media,#icon-upload,.icon32.icon-links,#icon-link-manager,#icon-link,#icon-link-category,.icon32.icon-page,#icon-edit-pages,#icon-page,.icon32.icon-comments,#icon-edit-comments,.icon32.icon-appearance,#icon-themes,.icon32.icon-plugins,#icon-plugins,.icon32.icon-users,#icon-users,#icon-profile,#icon-user-edit,.icon32.icon-tools,#icon-tools,#icon-admin,.icon32.icon-settings,#icon-options-general,.icon32.icon-site,#icon-ms-admin,.icon32.icon-generic,#icon-generic{background-image:url(../images/icons32-2x.png?ver=20121105);background-size:756px 45px}.icon16.icon-dashboard,.menu-icon-dashboard div.wp-menu-image,.icon16.icon-post,.menu-icon-post div.wp-menu-image,.icon16.icon-media,.menu-icon-media div.wp-menu-image,.icon16.icon-links,.menu-icon-links div.wp-menu-image,.icon16.icon-page,.menu-icon-page div.wp-menu-image,.icon16.icon-comments,.menu-icon-comments div.wp-menu-image,.icon16.icon-appearance,.menu-icon-appearance div.wp-menu-image,.icon16.icon-plugins,.menu-icon-plugins div.wp-menu-image,.icon16.icon-users,.menu-icon-users div.wp-menu-image,.icon16.icon-tools,.menu-icon-tools div.wp-menu-image,.icon16.icon-settings,.menu-icon-settings div.wp-menu-image,.icon16.icon-site,.menu-icon-site div.wp-menu-image,.icon16.icon-generic,.menu-icon-generic div.wp-menu-image{background-image:url(../images/menu-2x.png?ver=20121105);background-size:390px 64px}#header-logo{background-image:url(../images/wp-logo-2x.png?ver=20120916);background-size:16px auto}.post-format-icon{background-image:url(../images/post-formats32.png);background-size:16px 304px}} \ No newline at end of file diff --git a/sources/wp-admin/css/customize-controls-rtl.css b/sources/wp-admin/css/customize-controls-rtl.css new file mode 100644 index 0000000..236d85d --- /dev/null +++ b/sources/wp-admin/css/customize-controls-rtl.css @@ -0,0 +1,77 @@ +#customize-header-actions .button-primary { + float: left; +} + +#customize-header-actions .spinner { + float: left; + margin-right: 0; + margin-left: 4px; +} + +.customize-control { + float: right; +} + +.customize-control-radio input, +.customize-control-checkbox input { + margin-right: 0; + margin-left: 5px; +} + +/* + * Dropdowns + */ +.accordion-section .dropdown { + float: right; +} + +.accordion-section .dropdown-content { + float: right; + margin-right: 0px; + margin-left: 16px; + -webkit-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.customize-control .dropdown-arrow { + right: auto; + left: 0; + + border-color: #ccc; + border-style: solid; + border-width: 1px 0 1px 1px; + -webkit-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} + +.customize-control .dropdown-arrow:after { + right: auto; + left: 4px; +} + +/* + * Color Picker + */ +.customize-control-color .dropdown { + margin-right: 0; + margin-left: 5px; +} + +.accordion-section input[type="text"].color-picker-hex { + direction: ltr; +} + +/* + * Image Picker + */ +.accordion-section .customize-control-image .actions { + text-align: left; +} + +.customize-control-image .library, +.customize-control-image .actions, +.accordion-section .customize-control-image .library ul, +.accordion-section .customize-control-image .library li, +.accordion-section .customize-control-image .library-content { + float: right; +} diff --git a/sources/wp-admin/css/customize-controls-rtl.min.css b/sources/wp-admin/css/customize-controls-rtl.min.css new file mode 100644 index 0000000..80117e5 --- /dev/null +++ b/sources/wp-admin/css/customize-controls-rtl.min.css @@ -0,0 +1 @@ +#customize-header-actions .button-primary{float:left}#customize-header-actions .spinner{float:left;margin-right:0;margin-left:4px}.customize-control{float:right}.customize-control-radio input,.customize-control-checkbox input{margin-right:0;margin-left:5px}.accordion-section .dropdown{float:right}.accordion-section .dropdown-content{float:right;margin-right:0;margin-left:16px;-webkit-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.customize-control .dropdown-arrow{right:auto;left:0;border-color:#ccc;border-style:solid;border-width:1px 0 1px 1px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.customize-control .dropdown-arrow:after{right:auto;left:4px}.customize-control-color .dropdown{margin-right:0;margin-left:5px}.accordion-section input[type=text].color-picker-hex{direction:ltr}.accordion-section .customize-control-image .actions{text-align:left}.customize-control-image .library,.customize-control-image .actions,.accordion-section .customize-control-image .library ul,.accordion-section .customize-control-image .library li,.accordion-section .customize-control-image .library-content{float:right} \ No newline at end of file diff --git a/sources/wp-admin/css/customize-controls.css b/sources/wp-admin/css/customize-controls.css new file mode 100644 index 0000000..14f6f21 --- /dev/null +++ b/sources/wp-admin/css/customize-controls.css @@ -0,0 +1,440 @@ +body { + overflow: hidden; +} + +#customize-controls a { + text-decoration: none; +} + +#customize-info .accordion-section-content { + background: transparent; +} + +#customize-info .preview-notice { + font-size: 13px; + line-height: 24px; + color: #999; +} + +#customize-info .theme-name { + font-size: 20px; + font-weight: 200; + line-height: 24px; + color: #333; + display: block; + text-shadow: 0 1px 0 #fff; +} + +#customize-info .theme-screenshot { + width: 258px; + border: 1px solid #ccc; +} + +#customize-info .theme-description { + margin-top: 1em; + color: #777; + line-height: 20px; +} + +#customize-controls .submit { + text-align: center; +} + +#customize-theme-controls > ul, +#customize-theme-controls .accordion-section-content { + margin: 0; +} + +#customize-header-actions .button-primary { + float: right; + margin-top: 10px; +} + +#customize-header-actions .spinner { + margin-top: 16px; + margin-right: 4px; +} + +.saving #customize-header-actions .spinner { + display: block; +} + +.customize-control { + width: 100%; + float: left; + clear: both; + margin-bottom: 8px; +} + +.customize-control-title { + display: block; + line-height: 24px; + font-weight: bold; +} + +.customize-control select, +.customize-control input[type="text"], +.customize-control input[type="radio"], +.customize-control input[type="checkbox"], +.customize-control-color .color-picker, +.customize-control-checkbox label, +.customize-control-upload div { + line-height: 28px; +} + +.customize-control input[type="text"] { + width: 98%; + line-height: 18px; + margin: 0; +} + +.customize-control select { + min-width: 50%; + max-width: 100%; + height: 28px; + line-height: 28px; +} + +.customize-control-checkbox input { + margin-right: 5px; +} + +.customize-control-radio { + padding: 5px 0 10px; +} + +.customize-control-radio .customize-control-title { + margin-bottom: 0; + line-height: 22px; +} + +.customize-control-radio label { + line-height: 20px; +} + +.customize-control-radio input { + margin-right: 5px; +} + +#customize-preview iframe { + width: 100%; + height: 100%; +} + +#customize-theme-controls .accordion-section-title:hover:after, +#customize-theme-controls .accordion-section-title:focus:after { + border-color: #eee transparent; +} + +#customize-theme-controls .control-section:hover .accordion-section-title, +#customize-theme-controls .control-section .accordion-section-title:hover, +#customize-theme-controls .control-section.open .accordion-section-title, +#customize-theme-controls .control-section .accordion-section-title:focus { + color: #fff; + text-shadow: 0 -1px 0 #333; + background: #808080; + background-image: -webkit-gradient(linear, left bottom, left top, from(#6d6d6d), to(#808080)); + background-image: -webkit-linear-gradient(bottom, #6d6d6d, #808080); + background-image: -moz-linear-gradient(bottom, #6d6d6d, #808080); + background-image: -o-linear-gradient(bottom, #6d6d6d, #808080); + background-image: linear-gradient(to top, #6d6d6d, #808080); + border-left: 1px solid #808080; + border-right: 1px solid #808080; +} + +#customize-theme-controls .control-section.accordion-section:hover, +#customize-theme-controls .control-section.accordion-section.open { + border-top-color: #808080; +} + +#customize-theme-controls .control-section.open .accordion-section-title { + border-bottom: 1px solid #6d6d6d; +} + +/* + * Style for custom settings + */ + +/* + * Dropdowns + */ +.accordion-section .dropdown { + float: left; + display: block; + position: relative; + cursor: pointer; + + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.accordion-section .dropdown-content { + overflow: hidden; + float: left; + min-width: 30px; + height: 16px; + line-height: 16px; + margin-right: 16px; + padding: 4px 5px; + background-color: #eee; + border: 1px solid #ccc; + -webkit-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; + + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.customize-control .dropdown-arrow { + position: absolute; + top: 0; + bottom: 0; + right: 0; + width: 15px; + + border-color: #ccc; + border-style: solid; + border-width: 1px 1px 1px 0; + -webkit-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} + +.customize-control .dropdown-arrow:after { + content: ''; + width: 0; + height: 0; + border-color: #ccc transparent; + border-style: solid; + border-width: 4px 4px 0 4px; + position: absolute; + top: 50%; + margin-top: -1px; + right: 4px; + z-index: 1; +} + +.accordion-section .dropdown:hover .dropdown-content, +.customize-control .dropdown:hover .dropdown-arrow { + border-color: #aaa; +} + +.accordion-section .dropdown:hover .dropdown-arrow:after { + border-color: #aaa transparent; +} + +.customize-control .dropdown-status { + display: none; + max-width: 112px; + color: #777; +} + +/* + * Color Picker + */ +.customize-control-color .color-picker-hex { + display: none; +} + +.customize-control-color.open .color-picker-hex { + display: block; +} + +.customize-control-color .dropdown { + margin-right: 5px; + margin-bottom: 5px; +} + +.customize-control-color .dropdown .dropdown-content { + background-color: #fff; + border: 1px solid rgba( 0, 0, 0, 0.15 ); +} + +.customize-control-color .dropdown:hover .dropdown-content { + border-color: rgba( 0, 0, 0, 0.25 ); +} + +.accordion-section input[type="text"].color-picker-hex { + width: 65px; + font-family: monospace; + text-align: center; + line-height: 16px; +} + +/* The centered cursor overlaps the placeholder in webkit. Hide it when selected. */ +.accordion-section input[type="text"].color-picker-hex:focus::-webkit-input-placeholder { + color: transparent; +} +.accordion-section input[type="text"].color-picker-hex:-moz-placeholder { + color: #999; +} + +/* + * Image Picker + */ +.customize-control-image .library, +.customize-control-image .actions { + display: none; + float: left; + width: 100%; +} + +.customize-control-image.open .library, +.customize-control-image.open .actions { + display: block; +} + +.accordion-section .customize-control-image .dropdown-content { + height: auto; + min-height: 24px; + min-width: 40px; + padding: 0; +} + +.accordion-section .customize-control-image .dropdown-status { + padding: 4px 5px; +} + +.accordion-section .customize-control-image .preview-thumbnail img { + display: block; + width: 100%; + max-width: 122px; + max-height: 98px; + margin: 0 auto; +} + +.accordion-section .customize-control-image .actions { + text-align: right; +} + +.accordion-section .customize-control-image .library ul { + border-bottom: 1px solid #dfdfdf; + float: left; + width: 100%; + margin: 10px 0 0; +} + +.accordion-section .customize-control-image .library li { + color: #999; + float: left; + padding: 3px 5px; + margin: 0; + border-style: solid; + border-color: transparent; + border-width: 1px 1px 0 1px; +} + +.accordion-section .customize-control-image .library li.library-selected { + margin-bottom: -1px; + padding-bottom: 4px; + + color: #777; + background: #fdfdfd; + border-color: #dfdfdf; + -webkit-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0 ; +} + +.accordion-section .customize-control-image .library-content { + display: none; + width: 100%; + float: left; + padding: 10px 0; +} + +.accordion-section .customize-control-image .library-content.library-selected { + display: block; +} + +.accordion-section .customize-control-image .library .thumbnail { + display: block; + width: 100%; +} + +.accordion-section .customize-control-image .library .thumbnail:hover img { + border-color: #21759b; +} + +.accordion-section .customize-control-image .library .thumbnail img { + display: block; + max-width: 90%; + max-height: 80px; + + margin: 5px auto; + padding: 4px; + background: #fff; + border: 1px solid #dfdfdf; +} + +.accordion-section .customize-control-upload .upload-fallback, +.accordion-section .customize-control-image .upload-fallback { + display: none; +} + +.accordion-section .customize-control-upload .upload-dropzone, +.accordion-section .customize-control-image .upload-dropzone { + display: none; + padding: 15px 10px; + border: 3px dashed #dfdfdf; + margin: 5px auto; + text-align: center; + color: #777; + position: relative; + cursor: default; +} + +.accordion-section .customize-control-upload .upload-dropzone.supports-drag-drop, +.accordion-section .customize-control-image .upload-dropzone.supports-drag-drop { + display: block; + -webkit-transition: border-color 0.1s; + -moz-transition: border-color 0.1s; + -ms-transition: border-color 0.1s; + -o-transition: border-color 0.1s; + transition: border-color 0.1s; +} + +.accordion-section .customize-control-upload .library ul li, +.accordion-section .customize-control-image .library ul li { + cursor: pointer; +} + +.accordion-section .customize-control-upload .upload-dropzone.supports-drag-drop.drag-over, +.accordion-section .customize-control-image .upload-dropzone.supports-drag-drop.drag-over { + border-color: #83b4d8; +} + +/** + * iOS can't scroll iframes, + * instead it expands the iframe size to match the size of the content + */ +.ios .wp-full-overlay { + position: relative; +} + +.ios #customize-preview { + position: relative; +} + +.ios #customize-controls .wp-full-overlay-sidebar-content { + -webkit-overflow-scrolling: touch; +} + +/** + * Handle cheaters. + */ +body.cheatin { + min-width: 0; + background: #f9f9f9; + padding: 50px; +} + +body.cheatin p { + max-width: 700px; + margin: 0 auto; + padding: 2em; + font-size: 14px; + background: #fff; + border: 1px solid #dfdfdf; + -webkit-border-radius: 3px; + border-radius: 3px; +} diff --git a/sources/wp-admin/css/customize-controls.min.css b/sources/wp-admin/css/customize-controls.min.css new file mode 100644 index 0000000..a310000 --- /dev/null +++ b/sources/wp-admin/css/customize-controls.min.css @@ -0,0 +1 @@ +body{overflow:hidden}#customize-controls a{text-decoration:none}#customize-info .accordion-section-content{background:transparent}#customize-info .preview-notice{font-size:13px;line-height:24px;color:#999}#customize-info .theme-name{font-size:20px;font-weight:200;line-height:24px;color:#333;display:block;text-shadow:0 1px 0 #fff}#customize-info .theme-screenshot{width:258px;border:1px solid #ccc}#customize-info .theme-description{margin-top:1em;color:#777;line-height:20px}#customize-controls .submit{text-align:center}#customize-theme-controls>ul,#customize-theme-controls .accordion-section-content{margin:0}#customize-header-actions .button-primary{float:right;margin-top:10px}#customize-header-actions .spinner{margin-top:16px;margin-right:4px}.saving #customize-header-actions .spinner{display:block}.customize-control{width:100%;float:left;clear:both;margin-bottom:8px}.customize-control-title{display:block;line-height:24px;font-weight:700}.customize-control select,.customize-control input[type=text],.customize-control input[type=radio],.customize-control input[type=checkbox],.customize-control-color .color-picker,.customize-control-checkbox label,.customize-control-upload div{line-height:28px}.customize-control input[type=text]{width:98%;line-height:18px;margin:0}.customize-control select{min-width:50%;max-width:100%;height:28px;line-height:28px}.customize-control-checkbox input{margin-right:5px}.customize-control-radio{padding:5px 0 10px}.customize-control-radio .customize-control-title{margin-bottom:0;line-height:22px}.customize-control-radio label{line-height:20px}.customize-control-radio input{margin-right:5px}#customize-preview iframe{width:100%;height:100%}#customize-theme-controls .accordion-section-title:hover:after,#customize-theme-controls .accordion-section-title:focus:after{border-color:#eee transparent}#customize-theme-controls .control-section:hover .accordion-section-title,#customize-theme-controls .control-section .accordion-section-title:hover,#customize-theme-controls .control-section.open .accordion-section-title,#customize-theme-controls .control-section .accordion-section-title:focus{color:#fff;text-shadow:0 -1px 0 #333;background:gray;background-image:-webkit-gradient(linear,left bottom,left top,from(#6d6d6d),to(gray));background-image:-webkit-linear-gradient(bottom,#6d6d6d,gray);background-image:-moz-linear-gradient(bottom,#6d6d6d,gray);background-image:-o-linear-gradient(bottom,#6d6d6d,gray);background-image:linear-gradient(to top,#6d6d6d,gray);border-left:1px solid gray;border-right:1px solid gray}#customize-theme-controls .control-section.accordion-section:hover,#customize-theme-controls .control-section.accordion-section.open{border-top-color:gray}#customize-theme-controls .control-section.open .accordion-section-title{border-bottom:1px solid #6d6d6d}.accordion-section .dropdown{float:left;display:block;position:relative;cursor:pointer;-webkit-border-radius:3px;border-radius:3px}.accordion-section .dropdown-content{overflow:hidden;float:left;min-width:30px;height:16px;line-height:16px;margin-right:16px;padding:4px 5px;background-color:#eee;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.customize-control .dropdown-arrow{position:absolute;top:0;bottom:0;right:0;width:15px;border-color:#ccc;border-style:solid;border-width:1px 1px 1px 0;-webkit-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.customize-control .dropdown-arrow:after{content:'';width:0;height:0;border-color:#ccc transparent;border-style:solid;border-width:4px 4px 0;position:absolute;top:50%;margin-top:-1px;right:4px;z-index:1}.accordion-section .dropdown:hover .dropdown-content,.customize-control .dropdown:hover .dropdown-arrow{border-color:#aaa}.accordion-section .dropdown:hover .dropdown-arrow:after{border-color:#aaa transparent}.customize-control .dropdown-status{display:none;max-width:112px;color:#777}.customize-control-color .color-picker-hex{display:none}.customize-control-color.open .color-picker-hex{display:block}.customize-control-color .dropdown{margin-right:5px;margin-bottom:5px}.customize-control-color .dropdown .dropdown-content{background-color:#fff;border:1px solid rgba(0,0,0,.15)}.customize-control-color .dropdown:hover .dropdown-content{border-color:rgba(0,0,0,.25)}.accordion-section input[type=text].color-picker-hex{width:65px;font-family:monospace;text-align:center;line-height:16px}.accordion-section input[type=text].color-picker-hex:focus::-webkit-input-placeholder{color:transparent}.accordion-section input[type=text].color-picker-hex:-moz-placeholder{color:#999}.customize-control-image .library,.customize-control-image .actions{display:none;float:left;width:100%}.customize-control-image.open .library,.customize-control-image.open .actions{display:block}.accordion-section .customize-control-image .dropdown-content{height:auto;min-height:24px;min-width:40px;padding:0}.accordion-section .customize-control-image .dropdown-status{padding:4px 5px}.accordion-section .customize-control-image .preview-thumbnail img{display:block;width:100%;max-width:122px;max-height:98px;margin:0 auto}.accordion-section .customize-control-image .actions{text-align:right}.accordion-section .customize-control-image .library ul{border-bottom:1px solid #dfdfdf;float:left;width:100%;margin:10px 0 0}.accordion-section .customize-control-image .library li{color:#999;float:left;padding:3px 5px;margin:0;border-style:solid;border-color:transparent;border-width:1px 1px 0}.accordion-section .customize-control-image .library li.library-selected{margin-bottom:-1px;padding-bottom:4px;color:#777;background:#fdfdfd;border-color:#dfdfdf;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}.accordion-section .customize-control-image .library-content{display:none;width:100%;float:left;padding:10px 0}.accordion-section .customize-control-image .library-content.library-selected{display:block}.accordion-section .customize-control-image .library .thumbnail{display:block;width:100%}.accordion-section .customize-control-image .library .thumbnail:hover img{border-color:#21759b}.accordion-section .customize-control-image .library .thumbnail img{display:block;max-width:90%;max-height:80px;margin:5px auto;padding:4px;background:#fff;border:1px solid #dfdfdf}.accordion-section .customize-control-upload .upload-fallback,.accordion-section .customize-control-image .upload-fallback{display:none}.accordion-section .customize-control-upload .upload-dropzone,.accordion-section .customize-control-image .upload-dropzone{display:none;padding:15px 10px;border:3px dashed #dfdfdf;margin:5px auto;text-align:center;color:#777;position:relative;cursor:default}.accordion-section .customize-control-upload .upload-dropzone.supports-drag-drop,.accordion-section .customize-control-image .upload-dropzone.supports-drag-drop{display:block;-webkit-transition:border-color .1s;-moz-transition:border-color .1s;-ms-transition:border-color .1s;-o-transition:border-color .1s;transition:border-color .1s}.accordion-section .customize-control-upload .library ul li,.accordion-section .customize-control-image .library ul li{cursor:pointer}.accordion-section .customize-control-upload .upload-dropzone.supports-drag-drop.drag-over,.accordion-section .customize-control-image .upload-dropzone.supports-drag-drop.drag-over{border-color:#83b4d8}.ios .wp-full-overlay{position:relative}.ios #customize-preview{position:relative}.ios #customize-controls .wp-full-overlay-sidebar-content{-webkit-overflow-scrolling:touch}body.cheatin{min-width:0;background:#f9f9f9;padding:50px}body.cheatin p{max-width:700px;margin:0 auto;padding:2em;font-size:14px;background:#fff;border:1px solid #dfdfdf;-webkit-border-radius:3px;border-radius:3px} \ No newline at end of file diff --git a/sources/wp-admin/css/farbtastic.css b/sources/wp-admin/css/farbtastic.css new file mode 100644 index 0000000..ef1129c --- /dev/null +++ b/sources/wp-admin/css/farbtastic.css @@ -0,0 +1,52 @@ + +.farbtastic { + position: relative; +} + +.farbtastic * { + position: absolute; + cursor: crosshair; +} + +.farbtastic, +.farbtastic .wheel { + width: 195px; + height: 195px; +} + +.farbtastic .color, +.farbtastic .overlay { + top: 47px; + left: 47px; + width: 101px; + height: 101px; +} + +.farbtastic .wheel { + background: url(../images/wheel.png) no-repeat; + width: 195px; + height: 195px; +} + +.farbtastic .overlay { + background: url(../images/mask.png) no-repeat; +} + +.farbtastic .marker { + width: 17px; + height: 17px; + margin: -8px 0 0 -8px; + overflow: hidden; + background: url(../images/marker.png) no-repeat; +} + +/* farbtastic-rtl */ +.rtl .farbtastic .color, +.rtl .farbtastic .overlay { + left: 0; + right: 47px; +} + +.rtl .farbtastic .marker { + margin: -8px -8px 0 0; +} diff --git a/sources/wp-admin/css/ie-rtl.css b/sources/wp-admin/css/ie-rtl.css new file mode 100644 index 0000000..51dfdff --- /dev/null +++ b/sources/wp-admin/css/ie-rtl.css @@ -0,0 +1,236 @@ + +body { + direction: rtl; + width: 99.5%; +} + +.rtl #adminmenuback { + left: auto; + right: 0; + background-image: none; +} + +.rtl #adminmenuback, +.rtl #adminmenuwrap { + border-width: 0 0 0 1px; +} + +#plupload-upload-ui { + zoom: 1; +} + +.post-com-count-wrapper a.post-com-count { + float: none; +} + +#adminmenu .wp-submenu ul { + width: 99%; +} + +#adminmenu .wp-submenu .wp-submenu .wp-submenu, +#adminmenu .wp-menu-open .wp-submenu .wp-submenu { + border: 1px solid #dfdfdf; +} + +.folded #adminmenu .wp-submenu { + right: 30px; +} + +#wpcontent #adminmenu .wp-submenu li.wp-submenu-head { + padding: 3px 10px 4px 4px; +} + +div.quicktags-toolbar input { + min-width: 0; +} + +.inline-edit-row fieldset label span.title { + float: right; +} + +.inline-edit-row fieldset label span.input-text-wrap { + margin-right: 0; +} + +p.search-box { + float: left; +} + +#bh { + margin: 7px 10px 0 0; + float: left; +} + +.postbox div.inside, +.wp-editor-wrap .wp-editor-container .wp-editor-area, +#nav-menu-theme-locations .howto select { + width: 97.5%; +} + +/* without this dashboard widgets appear in one column for some screen widths */ +div#dashboard-widgets { + padding-right: 0; + padding-left: 1px; +} + +.widefat th input { + margin: 0 5px 0 0; +} + +/* ---------- add by navid */ +#TB_window { + width: 670px; + position: absolute; + top: 50%; + left: 50%; + margin-right: 335px !important; +} + +#dashboard_plugins { + direction: ltr; +} + +#dashboard_plugins h3.hndle { + direction: rtl; +} + +#dashboard_incoming_links ul li, +#dashboard_secondary ul li, +#dashboard_primary ul li, +p.row-actions { + width: 100%; +} + +#post-status-info { + height: 25px; +} + +p.submit { /* quick edit and reply in edit-comments.php */ + height:22px; +} + +.available-theme .action-links li { + padding-left: 7px; + margin-left: 7px; +} + +form#widgets-filter { /* fix widget page */ + position: static; +} + +/* nav menus +.menu-max-depth-0 #menu-management { width: 460px; } +.menu-max-depth-1 #menu-management { width: 490px; } +.menu-max-depth-2 #menu-management { width: 520px; } +.menu-max-depth-3 #menu-management { width: 550px; } +.menu-max-depth-4 #menu-management { width: 580px; } +.menu-max-depth-5 #menu-management { width: 610px; } +.menu-max-depth-6 #menu-management { width: 640px; } +.menu-max-depth-7 #menu-management { width: 670px; } +.menu-max-depth-8 #menu-management { width: 700px; } +.menu-max-depth-9 #menu-management { width: 730px; } +.menu-max-depth-10 #menu-management { width: 760px; } +.menu-max-depth-11 #menu-management { width: 790px; } +*/ +.menu-item-depth-0 { margin-left: 0px; } +.menu-item-depth-1 { margin-left: -30px; } +.menu-item-depth-2 { margin-left: -60px; } +.menu-item-depth-3 { margin-left: -90px; } +.menu-item-depth-4 { margin-left: -120px; } +.menu-item-depth-5 { margin-left: -150px; } +.menu-item-depth-6 { margin-left: -180px; } +.menu-item-depth-7 { margin-left: -210px; } +.menu-item-depth-8 { margin-left: -240px; } +.menu-item-depth-9 { margin-left: -270px; } +.menu-item-depth-10 { margin-left: -300px; } +.menu-item-depth-11 { margin-left: -330px; } + +/* +#menu-to-edit li dl { + padding: 0 !important; + margin: 0 !important; +} + +.ui-sortable-helper .menu-item-transport { + margin-top: 13px; +} + +.ui-sortable-helper .menu-item-transport .menu-item-transport { + margin-top: 0; +} +*/ + +#menu-management, +.nav-menus-php .menu-edit, +#nav-menu-header .submitbox { + zoom: 1; +} + +.nav-menus-php label { + max-width: 90% !important; +} + +p.button-controls, +.nav-menus-php .tabs-panel { + max-width: 90%; +} + +.nav-menus-php .major-publishing-actions .publishing-action { + float: none; +} + +#wpbody #nav-menu-header label { + float: none; +} + +#nav-menu-header { + margin-top: -10px; +} + +#nav-menu-footer { + margin-bottom: -20px; +} + +#update-nav-menu .publishing-action { + max-width: 200px; +} + +#nav-menus-frame #update-nav-menu .delete-action { + margin-top: -25px; + float: left; +} + +#menu-to-edit li { + margin-top: -10px; + margin-bottom: -10px; +} + +.sortable-placeholder { + margin-top: 0 !important; + margin-left: 0 !important; + margin-bottom: 13px !important; + padding: 0 !important; +} + +.auto-add-pages { + clear: both; + float: none; +} + +#nav-menus-frame .open-label span { + float: none; + display: inline-block; +} + +#nav-menus-frame .delete-action { + float: none; +} + +#title-wrap #title-prompt-text { + right: 0; +} + +.screen-reader-text { + right: auto; + text-indent: -1000em; +} \ No newline at end of file diff --git a/sources/wp-admin/css/ie-rtl.min.css b/sources/wp-admin/css/ie-rtl.min.css new file mode 100644 index 0000000..4467ebd --- /dev/null +++ b/sources/wp-admin/css/ie-rtl.min.css @@ -0,0 +1 @@ +body{direction:rtl;width:99.5%}.rtl #adminmenuback{left:auto;right:0;background-image:none}.rtl #adminmenuback,.rtl #adminmenuwrap{border-width:0 0 0 1px}#plupload-upload-ui{zoom:1}.post-com-count-wrapper a.post-com-count{float:none}#adminmenu .wp-submenu ul{width:99%}#adminmenu .wp-submenu .wp-submenu .wp-submenu,#adminmenu .wp-menu-open .wp-submenu .wp-submenu{border:1px solid #dfdfdf}.folded #adminmenu .wp-submenu{right:30px}#wpcontent #adminmenu .wp-submenu li.wp-submenu-head{padding:3px 10px 4px 4px}div.quicktags-toolbar input{min-width:0}.inline-edit-row fieldset label span.title{float:right}.inline-edit-row fieldset label span.input-text-wrap{margin-right:0}p.search-box{float:left}#bh{margin:7px 10px 0 0;float:left}.postbox div.inside,.wp-editor-wrap .wp-editor-container .wp-editor-area,#nav-menu-theme-locations .howto select{width:97.5%}div#dashboard-widgets{padding-right:0;padding-left:1px}.widefat th input{margin:0 5px 0 0}#TB_window{width:670px;position:absolute;top:50%;left:50%;margin-right:335px!important}#dashboard_plugins{direction:ltr}#dashboard_plugins h3.hndle{direction:rtl}#dashboard_incoming_links ul li,#dashboard_secondary ul li,#dashboard_primary ul li,p.row-actions{width:100%}#post-status-info{height:25px}p.submit{height:22px}.available-theme .action-links li{padding-left:7px;margin-left:7px}form#widgets-filter{position:static}.menu-item-depth-0{margin-left:0}.menu-item-depth-1{margin-left:-30px}.menu-item-depth-2{margin-left:-60px}.menu-item-depth-3{margin-left:-90px}.menu-item-depth-4{margin-left:-120px}.menu-item-depth-5{margin-left:-150px}.menu-item-depth-6{margin-left:-180px}.menu-item-depth-7{margin-left:-210px}.menu-item-depth-8{margin-left:-240px}.menu-item-depth-9{margin-left:-270px}.menu-item-depth-10{margin-left:-300px}.menu-item-depth-11{margin-left:-330px}#menu-management,.nav-menus-php .menu-edit,#nav-menu-header .submitbox{zoom:1}.nav-menus-php label{max-width:90%!important}p.button-controls,.nav-menus-php .tabs-panel{max-width:90%}.nav-menus-php .major-publishing-actions .publishing-action{float:none}#wpbody #nav-menu-header label{float:none}#nav-menu-header{margin-top:-10px}#nav-menu-footer{margin-bottom:-20px}#update-nav-menu .publishing-action{max-width:200px}#nav-menus-frame #update-nav-menu .delete-action{margin-top:-25px;float:left}#menu-to-edit li{margin-top:-10px;margin-bottom:-10px}.sortable-placeholder{margin-top:0!important;margin-left:0!important;margin-bottom:13px!important;padding:0!important}.auto-add-pages{clear:both;float:none}#nav-menus-frame .open-label span{float:none;display:inline-block}#nav-menus-frame .delete-action{float:none}#title-wrap #title-prompt-text{right:0}.screen-reader-text{right:auto;text-indent:-1000em} \ No newline at end of file diff --git a/sources/wp-admin/css/ie.css b/sources/wp-admin/css/ie.css new file mode 100644 index 0000000..7aa6685 --- /dev/null +++ b/sources/wp-admin/css/ie.css @@ -0,0 +1,622 @@ +/* Fixes for IE 7 bugs */ + +#dashboard-widgets form .input-text-wrap input, +#dashboard-widgets form .textarea-wrap textarea { + width: 99%; +} + +#dashboard-widgets form #title { + width: 98%; +} + +.wp-editor-wrap .wp-editor-container textarea.wp-editor-area { + width: 97%; +} + +#post-body.columns-2 #postbox-container-1 { + padding-left: 19px; +} + +.welcome-panel .wp-badge { + position: absolute; +} + +.welcome-panel .welcome-panel-column:first-child { + width: 35%; +} + +#wp-fullscreen-title { + width: 97%; +} + +#wp_mce_fullscreen_ifr { + background-color: #f9f9f9; +} + +#wp-fullscreen-tagline { + color: #888; + font-size: 14px; +} + +#adminmenushadow { + display: none; +} + +#adminmenuback { + left: 0; + background-image: none; +} + +#adminmenuwrap { + position: static; +} + +#adminmenu { + position: relative; +} + +#adminmenu, +#adminmenu a { + cursor: pointer; +} + +#adminmenu li.wp-menu-separator, +#adminmenu li.wp-menu-separator-last { + font-size: 1px; + line-height: 1; +} + +#adminmenu a.menu-top { + border-bottom: 0 none; + border-top: 1px solid #ddd; +} + +#adminmenu .separator { + font-size: 1px; + line-height: 1px; +} + +#adminmenu .wp-submenu ul { + margin: 0; +} + +.folded #adminmenu .wp-submenu { + border-top-color: transparent; +} + +#adminmenu .wp-submenu .wp-submenu-head { + border-top-color: #ddd; +} + +.folded #adminmenu .wp-submenu ul { + margin-left: 5px; +} + +#adminmenu li.menu-top { + margin-bottom: -2px; +} + +#adminmenu .wp-menu-arrow { + display: none !important; +} + +.js.folded #adminmenu li.menu-top { + display: block; + zoom: 100%; +} + +ul#adminmenu { + z-index: 99; +} + +#adminmenu li.menu-top a.menu-top { + min-width: auto; + width: auto; +} + +#wpcontent #adminmenu li.wp-has-current-submenu a.wp-has-submenu { + font-style: normal; +} + +#wpcontent #adminmenu .wp-submenu li { + padding: 0; +} + +#collapse-menu { + line-height: 23px; +} + +#wpadminbar .ab-comments-icon { + padding-top: 7px; +} + +table.fixed th, +table.fixed td { + border-top: 1px solid #ddd; +} + +#wpbody-content input.button, +#wpbody-content input.button-primary, +#wpbody-content input.button-secondary { + overflow: visible; +} + +#dashboard-widgets #dashboard_quick_press form p.submit #publish { + float: none; +} + +#dashboard-widgets h3 a { + height: 14px; + line-height: 14px; +} + +#dashboard_browser_nag { + color: #fff; +} + +#dashboard_browser_nag .browser-icon { + position: relative; +} + +.tablenav-pages .current-page { + vertical-align: middle; +} + +#wpbody-content .postbox { + border: 1px solid #dfdfdf; +} + +#wpbody-content .postbox h3 { + margin-bottom: -1px; +} + +.major-publishing-actions, +.wp-submenu, +.wp-submenu li, +#template, +#template div, +#editcat, +#addcat { + zoom: 100%; +} + +.wp-menu-arrow { + height: 28px; +} + +.submitbox { + margin-top: 10px; +} + +/* Inline Editor */ +#wpbody-content .quick-edit-row-post .inline-edit-col-left { + width: 39%; +} + +#wpbody-content .inline-edit-row-post .inline-edit-col-center { + width: 19%; +} + +#wpbody-content .quick-edit-row-page .inline-edit-col-left { + width: 49%; +} + +#wpbody-content .bulk-edit-row .inline-edit-col-left { + width: 29%; +} + +.inline-edit-row p.submit { + zoom: 100%; +} + +.inline-edit-row fieldset label span.title { + display: block; + float: left; + width: 5em; +} + +.inline-edit-row fieldset label span.input-text-wrap { + margin-left: 0; + zoom: 100%; +} + +#wpbody-content .inline-edit-row fieldset label span.input-text-wrap input { + line-height: 130%; +} + +#wpbody-content .inline-edit-row .input-text-wrap input { + width: 95%; +} + +#wpbody-content .inline-edit-row .input-text-wrap input.inline-edit-password-input { + width: 8em; +} +/* end Inline Editor */ + +#titlediv #title { + width: 98%; +} + +.button, +input[type="reset"], +input[type="button"], +input[type="submit"] { + padding: 0 8px; + line-height: 20px; + height: auto; +} + +.button.button-large, +input[type="reset"].button-large, +input[type="button"].button-large, +input[type="submit"].button-large { + padding: 0 10px; + line-height: 24px; + height: auto; +} + +.button.button-small, +input[type="reset"].button-small, +input[type="button"].button-small, +input[type="submit"].button-small { + padding: 0 6px; + line-height: 16px; + height: auto; +} + +a.button { + margin: 1px; + padding: 1px 9px 2px; +} + +a.button.button-large { + padding: 1px 11px 2px; +} + +a.button.button-small { + padding: 1px 7px 2px; +} + +#screen-options-wrap { + overflow: hidden; +} + +#the-comment-list .comment-item, +#post-status-info, +#wpwrap, +#wrap, +#postdivrich, +#postdiv, +#poststuff, +.metabox-holder, +#titlediv, +#post-body, +#editorcontainer, +.tablenav, +.widget-liquid-left, +.widget-liquid-right, +#widgets-left, +.widgets-sortables, +#dragHelper, +.widget .widget-top, +.widget-control-actions, +.tagchecklist, +#col-container, +#col-left, +#col-right, +.fileedit-sub { + display: block; + zoom: 100%; +} + +p.search-box { + position: static; + float: right; + margin: -3px 0 4px; +} + +#widget-list .widget, +.feature-filter .feature-group li { + display: inline; +} + +.feature-filter .feature-group li input { + vertical-align: middle; +} + +#editorcontainer #content { + overflow: auto; + margin: auto; + width: 98%; +} + +form#template div { + width: 100%; +} + +.wp-editor-container .quicktags-toolbar input { + overflow: visible; + padding: 0 4px; +} + +#poststuff h2 { + font-size: 1.6em; +} + +#poststuff .inside #parent_id, +#poststuff .inside #page_template, +.inline-edit-row #post_parent, +.inline-edit-row select[name="page_template"] { + width: 250px; +} + +#submitdiv input, +#submitdiv select, +#submitdiv a.button { + position: relative; +} + +#bh { + margin: 7px 10px 0 0; + float: right; +} + +/* without this dashboard widgets appear in one column for some screen widths */ +div#dashboard-widgets { + padding-right: 1px; +} + +.tagchecklist span, .tagchecklist span a { + display: inline-block; + display: block; +} + +.tablenav .button-secondary, +.nav .button-secondary { + padding-top: 2px; + padding-bottom: 2px; +} + +.tablenav select { + font-size: 13px; + display: inline-block; + vertical-align: top; + margin-top: 2px; +} + +.tablenav .actions select { + width: 155px; +} + +.subsubsub li { + display: inline; +} + +a.post-state-format { + text-indent: 0; + line-height: 0; + font-size: 0; +} + +table.ie-fixed { + table-layout: fixed; +} + +.widefat tr, +.widefat th { + margin-bottom: 0; + border-spacing: 0; +} + +.widefat th input { + margin: 0 0 0 5px; +} + +.widefat thead .check-column, +.widefat tfoot .check-column { + padding-top: 6px; +} + +.widefat tbody th.check-column, +.media.widefat tbody th.check-column { + padding: 4px 0 0; +} + +.widefat { + empty-cells: show; + border-collapse: collapse; +} + +.tablenav a.button-secondary { + display: inline-block; + padding: 2px 5px; +} + +.inactive-sidebar .widgets-sortables { + padding-bottom: 8px; +} + +#available-widgets .widget-holder { + padding-bottom: 65px; +} + +#widgets-left .inactive { + padding-bottom: 10px; +} + +.widget-liquid-right .widget, +.inactive-sidebar .widget { + position: relative; +} + +.inactive-sidebar .widget { + display: block; + float: left; +} + +#wpcontent .button-primary-disabled { + color: #9FD0D5; + background: #298CBA; +} + +#the-comment-list .unapproved tr, +#the-comment-list .unapproved td { + background-color: #ffffe0; +} + +.imgedit-submit { + width: 300px; +} + +#nav-menus-frame, +#wpbody, +.menu li { + zoom: 100%; +} + +#update-nav-menu #post-body { + overflow:hidden; +} + +.menu li { + min-width: 100%; +} + +.menu li.sortable-placeholder { + min-width: 400px; +} + +.available-theme { + display: inline; +} + +.available-theme ul { + margin: 0; +} + +.available-theme .action-links li { + padding-right: 7px; + margin-right: 7px; +} + +.about-wrap .three-col.about-updates .col-2 { + width: 15%; +} + +.about-wrap .about-password-meter input { + width: 98%; +} + +.revisions-tickmarks, +.revisions-tooltip { + display: none !important; +} + +.revisions.pinned .revisions-controls { + position: relative; +} + +/* IE6 leftovers */ +* html .row-actions { + visibility: visible; +} + +* html div.widget-liquid-left, +* html div.widget-liquid-right { + display: block; + position: relative; +} + +* html #editorcontainer { + padding: 0; +} + +* html #poststuff h2 { + margin-left: 0; +} + +* html .stuffbox, +* html .stuffbox input, +* html .stuffbox textarea { + border: 1px solid #DFDFDF; +} + +* html .feature-filter .feature-group li { + width: 145px; +} + +* html div.widget-liquid-left { + width: 99%; +} + +* html .widgets-sortables { + height: 50px; +} + +* html a#content_resize { + right: -2px; +} + +* html .widget-title h4 { + width: 205px; +} + +* html #removing-widget .in-widget-title { + display: none; +} + +* html .media-item .pinkynail { + height: 32px; + width: 40px; +} + +* html .describe .field input.text, +* html .describe .field textarea { + width: 440px; +} + +* html input { + border: 1px solid #dfdfdf; +} + +* html .edit-box { + display: inline; +} + +* html .postbox-container .meta-box-sortables { + height: 300px; +} + +* html #wpbody-content #screen-options-link-wrap { + display: inline-block; + width: 150px; + text-align: center; +} + +* html #wpbody-content #contextual-help-link-wrap { + display: inline-block; + width: 100px; + text-align: center; +} + +* html #adminmenu { + margin-left: -80px; +} + +* html .folded #adminmenu { + margin-left: -22px; +} + +* html #wpcontent #adminmenu li.menu-top { + display: inline; + padding: 0; + margin: 0; +} + +* html #wpfooter { + margin: 0; +} + +* html #adminmenu div.wp-menu-image { + height: 29px; +} diff --git a/sources/wp-admin/css/ie.min.css b/sources/wp-admin/css/ie.min.css new file mode 100644 index 0000000..32e50b1 --- /dev/null +++ b/sources/wp-admin/css/ie.min.css @@ -0,0 +1 @@ +#dashboard-widgets form .input-text-wrap input,#dashboard-widgets form .textarea-wrap textarea{width:99%}#dashboard-widgets form #title{width:98%}.wp-editor-wrap .wp-editor-container textarea.wp-editor-area{width:97%}#post-body.columns-2 #postbox-container-1{padding-left:19px}.welcome-panel .wp-badge{position:absolute}.welcome-panel .welcome-panel-column:first-child{width:35%}#wp-fullscreen-title{width:97%}#wp_mce_fullscreen_ifr{background-color:#f9f9f9}#wp-fullscreen-tagline{color:#888;font-size:14px}#adminmenushadow{display:none}#adminmenuback{left:0;background-image:none}#adminmenuwrap{position:static}#adminmenu{position:relative}#adminmenu,#adminmenu a{cursor:pointer}#adminmenu li.wp-menu-separator,#adminmenu li.wp-menu-separator-last{font-size:1px;line-height:1}#adminmenu a.menu-top{border-bottom:0 none;border-top:1px solid #ddd}#adminmenu .separator{font-size:1px;line-height:1px}#adminmenu .wp-submenu ul{margin:0}.folded #adminmenu .wp-submenu{border-top-color:transparent}#adminmenu .wp-submenu .wp-submenu-head{border-top-color:#ddd}.folded #adminmenu .wp-submenu ul{margin-left:5px}#adminmenu li.menu-top{margin-bottom:-2px}#adminmenu .wp-menu-arrow{display:none!important}.js.folded #adminmenu li.menu-top{display:block;zoom:100%}ul#adminmenu{z-index:99}#adminmenu li.menu-top a.menu-top{min-width:auto;width:auto}#wpcontent #adminmenu li.wp-has-current-submenu a.wp-has-submenu{font-style:normal}#wpcontent #adminmenu .wp-submenu li{padding:0}#collapse-menu{line-height:23px}#wpadminbar .ab-comments-icon{padding-top:7px}table.fixed th,table.fixed td{border-top:1px solid #ddd}#wpbody-content input.button,#wpbody-content input.button-primary,#wpbody-content input.button-secondary{overflow:visible}#dashboard-widgets #dashboard_quick_press form p.submit #publish{float:none}#dashboard-widgets h3 a{height:14px;line-height:14px}#dashboard_browser_nag{color:#fff}#dashboard_browser_nag .browser-icon{position:relative}.tablenav-pages .current-page{vertical-align:middle}#wpbody-content .postbox{border:1px solid #dfdfdf}#wpbody-content .postbox h3{margin-bottom:-1px}.major-publishing-actions,.wp-submenu,.wp-submenu li,#template,#template div,#editcat,#addcat{zoom:100%}.wp-menu-arrow{height:28px}.submitbox{margin-top:10px}#wpbody-content .quick-edit-row-post .inline-edit-col-left{width:39%}#wpbody-content .inline-edit-row-post .inline-edit-col-center{width:19%}#wpbody-content .quick-edit-row-page .inline-edit-col-left{width:49%}#wpbody-content .bulk-edit-row .inline-edit-col-left{width:29%}.inline-edit-row p.submit{zoom:100%}.inline-edit-row fieldset label span.title{display:block;float:left;width:5em}.inline-edit-row fieldset label span.input-text-wrap{margin-left:0;zoom:100%}#wpbody-content .inline-edit-row fieldset label span.input-text-wrap input{line-height:130%}#wpbody-content .inline-edit-row .input-text-wrap input{width:95%}#wpbody-content .inline-edit-row .input-text-wrap input.inline-edit-password-input{width:8em}#titlediv #title{width:98%}.button,input[type=reset],input[type=button],input[type=submit]{padding:0 8px;line-height:20px;height:auto}.button.button-large,input[type=reset].button-large,input[type=button].button-large,input[type=submit].button-large{padding:0 10px;line-height:24px;height:auto}.button.button-small,input[type=reset].button-small,input[type=button].button-small,input[type=submit].button-small{padding:0 6px;line-height:16px;height:auto}a.button{margin:1px;padding:1px 9px 2px}a.button.button-large{padding:1px 11px 2px}a.button.button-small{padding:1px 7px 2px}#screen-options-wrap{overflow:hidden}#the-comment-list .comment-item,#post-status-info,#wpwrap,#wrap,#postdivrich,#postdiv,#poststuff,.metabox-holder,#titlediv,#post-body,#editorcontainer,.tablenav,.widget-liquid-left,.widget-liquid-right,#widgets-left,.widgets-sortables,#dragHelper,.widget .widget-top,.widget-control-actions,.tagchecklist,#col-container,#col-left,#col-right,.fileedit-sub{display:block;zoom:100%}p.search-box{position:static;float:right;margin:-3px 0 4px}#widget-list .widget,.feature-filter .feature-group li{display:inline}.feature-filter .feature-group li input{vertical-align:middle}#editorcontainer #content{overflow:auto;margin:auto;width:98%}form#template div{width:100%}.wp-editor-container .quicktags-toolbar input{overflow:visible;padding:0 4px}#poststuff h2{font-size:1.6em}#poststuff .inside #parent_id,#poststuff .inside #page_template,.inline-edit-row #post_parent,.inline-edit-row select[name=page_template]{width:250px}#submitdiv input,#submitdiv select,#submitdiv a.button{position:relative}#bh{margin:7px 10px 0 0;float:right}div#dashboard-widgets{padding-right:1px}.tagchecklist span,.tagchecklist span a{display:inline-block;display:block}.tablenav .button-secondary,.nav .button-secondary{padding-top:2px;padding-bottom:2px}.tablenav select{font-size:13px;display:inline-block;vertical-align:top;margin-top:2px}.tablenav .actions select{width:155px}.subsubsub li{display:inline}a.post-state-format{text-indent:0;line-height:0;font-size:0}table.ie-fixed{table-layout:fixed}.widefat tr,.widefat th{margin-bottom:0;border-spacing:0}.widefat th input{margin:0 0 0 5px}.widefat thead .check-column,.widefat tfoot .check-column{padding-top:6px}.widefat tbody th.check-column,.media.widefat tbody th.check-column{padding:4px 0 0}.widefat{empty-cells:show;border-collapse:collapse}.tablenav a.button-secondary{display:inline-block;padding:2px 5px}.inactive-sidebar .widgets-sortables{padding-bottom:8px}#available-widgets .widget-holder{padding-bottom:65px}#widgets-left .inactive{padding-bottom:10px}.widget-liquid-right .widget,.inactive-sidebar .widget{position:relative}.inactive-sidebar .widget{display:block;float:left}#wpcontent .button-primary-disabled{color:#9FD0D5;background:#298CBA}#the-comment-list .unapproved tr,#the-comment-list .unapproved td{background-color:#ffffe0}.imgedit-submit{width:300px}#nav-menus-frame,#wpbody,.menu li{zoom:100%}#update-nav-menu #post-body{overflow:hidden}.menu li{min-width:100%}.menu li.sortable-placeholder{min-width:400px}.available-theme{display:inline}.available-theme ul{margin:0}.available-theme .action-links li{padding-right:7px;margin-right:7px}.about-wrap .three-col.about-updates .col-2{width:15%}.about-wrap .about-password-meter input{width:98%}.revisions-tickmarks,.revisions-tooltip{display:none!important}.revisions.pinned .revisions-controls{position:relative}* html .row-actions{visibility:visible}* html div.widget-liquid-left,* html div.widget-liquid-right{display:block;position:relative}* html #editorcontainer{padding:0}* html #poststuff h2{margin-left:0}* html .stuffbox,* html .stuffbox input,* html .stuffbox textarea{border:1px solid #DFDFDF}* html .feature-filter .feature-group li{width:145px}* html div.widget-liquid-left{width:99%}* html .widgets-sortables{height:50px}* html a#content_resize{right:-2px}* html .widget-title h4{width:205px}* html #removing-widget .in-widget-title{display:none}* html .media-item .pinkynail{height:32px;width:40px}* html .describe .field input.text,* html .describe .field textarea{width:440px}* html input{border:1px solid #dfdfdf}* html .edit-box{display:inline}* html .postbox-container .meta-box-sortables{height:300px}* html #wpbody-content #screen-options-link-wrap{display:inline-block;width:150px;text-align:center}* html #wpbody-content #contextual-help-link-wrap{display:inline-block;width:100px;text-align:center}* html #adminmenu{margin-left:-80px}* html .folded #adminmenu{margin-left:-22px}* html #wpcontent #adminmenu li.menu-top{display:inline;padding:0;margin:0}* html #wpfooter{margin:0}* html #adminmenu div.wp-menu-image{height:29px} \ No newline at end of file diff --git a/sources/wp-admin/css/install.css b/sources/wp-admin/css/install.css new file mode 100644 index 0000000..03c0e98 --- /dev/null +++ b/sources/wp-admin/css/install.css @@ -0,0 +1,263 @@ +html { + background: #f9f9f9; +} + +body { + background: #fff; + color: #333; + font-family: sans-serif; + margin: 2em auto; + padding: 1em 2em; + -webkit-border-radius: 3px; + border-radius: 3px; + border: 1px solid #dfdfdf; + max-width: 700px; +} + +a { + color: #21759b; + text-decoration: none; +} + +a:hover { + color: #d54e21; +} + +h1 { + border-bottom: 1px solid #dadada; + clear: both; + color: #666; + font: 24px Georgia, "Times New Roman", Times, serif; + margin: 30px 0 0 0; + padding: 0; + padding-bottom: 7px; +} + +h2 { + font-size: 16px; +} + +p, li, dd, dt { + padding-bottom: 2px; + font-size: 14px; + line-height: 1.5; +} + +code, .code { + font-size: 14px; +} + +ul, ol, dl { + padding: 5px 5px 5px 22px; +} + +a img { + border:0 +} +abbr { + border: 0; + font-variant: normal; +} +#logo { + margin: 6px 0 14px 0; + border-bottom: none; + text-align:center +} +#logo a { + background-image: url('../images/wordpress-logo.png?ver=20120216'); + background-size: 274px 63px; + background-position: top center; + background-repeat: no-repeat; + height: 67px; + text-indent: -9999px; + outline: none; + overflow: hidden; + display: block; +} +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + #logo a { + background-image: url('../images/wordpress-logo-2x.png?ver=20120412'); + background-size: 274px 63px; + } +} +.step { + margin: 20px 0 15px; +} +.step, th { + text-align: left; + padding: 0; +} +.step .button-large { + font-size: 14px; +} +textarea { + border: 1px solid #dfdfdf; + -webkit-border-radius: 3px; + border-radius: 3px; + font-family: sans-serif; + width: 695px; +} + +.form-table { + border-collapse: collapse; + margin-top: 1em; + width: 100%; +} + +.form-table td { + margin-bottom: 9px; + padding: 10px 20px 10px 0; + border-bottom: 8px solid #fff; + font-size: 14px; + vertical-align: top +} + +.form-table th { + font-size: 14px; + text-align: left; + padding: 16px 20px 10px 0; + border-bottom: 8px solid #fff; + width: 140px; + vertical-align: top; +} + +.form-table code { + line-height: 18px; + font-size: 14px; +} + +.form-table p { + margin: 4px 0 0 0; + font-size: 11px; +} + +.form-table input { + line-height: 20px; + font-size: 15px; + padding: 2px; + border: 1px #dfdfdf solid; + -webkit-border-radius: 3px; + border-radius: 3px; + font-family: sans-serif; +} + +.form-table input[type=text], +.form-table input[type=password] { + width: 206px; +} + +.form-table th p { + font-weight: normal; +} + +.form-table.install-success td { + vertical-align: middle; + padding: 16px 20px 10px 0; +} + +.form-table.install-success td p { + margin: 0; + font-size: 14px; +} + +.form-table.install-success td code { + margin: 0; + font-size: 18px; +} + +#error-page { + margin-top: 50px; +} + +#error-page p { + font-size: 14px; + line-height: 18px; + margin: 25px 0 20px; +} + +#error-page code, .code { + font-family: Consolas, Monaco, monospace; +} + +#pass-strength-result { + background-color: #eee; + border-color: #ddd !important; + border-style: solid; + border-width: 1px; + margin: 5px 5px 5px 0; + padding: 5px; + text-align: center; + width: 200px; + display: none; +} + +#pass-strength-result.bad { + background-color: #ffb78c; + border-color: #ff853c !important; +} + +#pass-strength-result.good { + background-color: #ffec8b; + border-color: #ffcc00 !important; +} + +#pass-strength-result.short { + background-color: #ffa0a0; + border-color: #f04040 !important; +} + +#pass-strength-result.strong { + background-color: #c3ff88; + border-color: #8dff1c !important; +} + +.message { + border: 1px solid #c00; + -webkit-border-radius: 3px; + border-radius: 3px; + padding: 0.5em 0.7em; + margin: 5px 0 15px; + background-color: #ffebe8; +} + +/* install-rtl */ +body.rtl { + font-family: Tahoma, arial; +} + +.rtl h1 { + font-family: arial; + margin: 5px -4px 0 0; +} + +.rtl ul, +.rtl ol { + padding: 5px 22px 5px 5px; +} + +.rtl .step, +.rtl th, +.rtl .form-table th { + text-align: right; +} + +.rtl .submit input, +.rtl .button, +.rtl .button-secondary { + margin-right: 0; +} + +.rtl #dbname, +.rtl #uname, +.rtl #pwd, +.rtl #dbhost, +.rtl #prefix, +.rtl #user_login, +.rtl #admin_email, +.rtl #pass1, +.rtl #pass2 { + direction: ltr; +} diff --git a/sources/wp-admin/css/install.min.css b/sources/wp-admin/css/install.min.css new file mode 100644 index 0000000..6c6dac1 --- /dev/null +++ b/sources/wp-admin/css/install.min.css @@ -0,0 +1 @@ +html{background:#f9f9f9}body{background:#fff;color:#333;font-family:sans-serif;margin:2em auto;padding:1em 2em;-webkit-border-radius:3px;border-radius:3px;border:1px solid #dfdfdf;max-width:700px}a{color:#21759b;text-decoration:none}a:hover{color:#d54e21}h1{border-bottom:1px solid #dadada;clear:both;color:#666;font:24px Georgia,"Times New Roman",Times,serif;margin:30px 0 0;padding:0;padding-bottom:7px}h2{font-size:16px}p,li,dd,dt{padding-bottom:2px;font-size:14px;line-height:1.5}code,.code{font-size:14px}ul,ol,dl{padding:5px 5px 5px 22px}a img{border:0}abbr{border:0;font-variant:normal}#logo{margin:6px 0 14px;border-bottom:0;text-align:center}#logo a{background-image:url(../images/wordpress-logo.png?ver=20120216);background-size:274px 63px;background-position:top center;background-repeat:no-repeat;height:67px;text-indent:-9999px;outline:0;overflow:hidden;display:block}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){#logo a{background-image:url(../images/wordpress-logo-2x.png?ver=20120412);background-size:274px 63px}}.step{margin:20px 0 15px}.step,th{text-align:left;padding:0}.step .button-large{font-size:14px}textarea{border:1px solid #dfdfdf;-webkit-border-radius:3px;border-radius:3px;font-family:sans-serif;width:695px}.form-table{border-collapse:collapse;margin-top:1em;width:100%}.form-table td{margin-bottom:9px;padding:10px 20px 10px 0;border-bottom:8px solid #fff;font-size:14px;vertical-align:top}.form-table th{font-size:14px;text-align:left;padding:16px 20px 10px 0;border-bottom:8px solid #fff;width:140px;vertical-align:top}.form-table code{line-height:18px;font-size:14px}.form-table p{margin:4px 0 0;font-size:11px}.form-table input{line-height:20px;font-size:15px;padding:2px;border:1px #dfdfdf solid;-webkit-border-radius:3px;border-radius:3px;font-family:sans-serif}.form-table input[type=text],.form-table input[type=password]{width:206px}.form-table th p{font-weight:400}.form-table.install-success td{vertical-align:middle;padding:16px 20px 10px 0}.form-table.install-success td p{margin:0;font-size:14px}.form-table.install-success td code{margin:0;font-size:18px}#error-page{margin-top:50px}#error-page p{font-size:14px;line-height:18px;margin:25px 0 20px}#error-page code,.code{font-family:Consolas,Monaco,monospace}#pass-strength-result{background-color:#eee;border-color:#ddd!important;border-style:solid;border-width:1px;margin:5px 5px 5px 0;padding:5px;text-align:center;width:200px;display:none}#pass-strength-result.bad{background-color:#ffb78c;border-color:#ff853c!important}#pass-strength-result.good{background-color:#ffec8b;border-color:#fc0!important}#pass-strength-result.short{background-color:#ffa0a0;border-color:#f04040!important}#pass-strength-result.strong{background-color:#c3ff88;border-color:#8dff1c!important}.message{border:1px solid #c00;-webkit-border-radius:3px;border-radius:3px;padding:.5em .7em;margin:5px 0 15px;background-color:#ffebe8}body.rtl{font-family:Tahoma,arial}.rtl h1{font-family:arial;margin:5px -4px 0 0}.rtl ul,.rtl ol{padding:5px 22px 5px 5px}.rtl .step,.rtl th,.rtl .form-table th{text-align:right}.rtl .submit input,.rtl .button,.rtl .button-secondary{margin-right:0}.rtl #dbname,.rtl #uname,.rtl #pwd,.rtl #dbhost,.rtl #prefix,.rtl #user_login,.rtl #admin_email,.rtl #pass1,.rtl #pass2{direction:ltr} \ No newline at end of file diff --git a/sources/wp-admin/css/media-rtl.css b/sources/wp-admin/css/media-rtl.css new file mode 100644 index 0000000..0c3ccb3 --- /dev/null +++ b/sources/wp-admin/css/media-rtl.css @@ -0,0 +1,71 @@ +body#media-upload ul#sidemenu { + left: auto; + right: 0; +} +#search-filter { + text-align: left; +} +/* specific to the image upload form */ +.align .field label { + padding: 0 23px 0 0; + margin: 0 3px 0 1em; +} +.image-align-none-label, .image-align-left-label, .image-align-center-label, .image-align-right-label { + background-position: center right; +} +tr.image-size label { + margin: 0 5px 0 0; +} +.file-error { + margin: 0 50px 5px 0; +} +.progress { + left: auto; + right: 0; +} +.describe td { + padding: 0 0 0 5px; +} + +/* Specific to Uploader */ +#media-upload .describe th.label { + text-align: right; +} +.menu_order { + float: left; +} +.media-upload-form label.form-help, td.help, #media-upload p.help, #media-upload label.help { + font-family: Tahoma, Arial; +} +#gallery-settings #basic th.label { + padding: 5px 0 5px 5px; +} +#gallery-settings .title, h3.media-title { + font-family: Tahoma, Arial; +} +#gallery-settings .describe th.label { + text-align: right; +} +#gallery-settings label, +#gallery-settings legend { + margin-right: 0; + margin-left: 15px; +} +#gallery-settings .align .field label { + margin: 0 3px 0 1em; +} +#sort-buttons { + margin: 3px 0 -8px 25px; + text-align: left; +} + +#sort-buttons #asc, +#sort-buttons #showall { + padding-left: 0; + padding-right: 5px; +} + +#sort-buttons span { + margin-right: 0; + margin-left: 25px; +} diff --git a/sources/wp-admin/css/media-rtl.min.css b/sources/wp-admin/css/media-rtl.min.css new file mode 100644 index 0000000..5f51b60 --- /dev/null +++ b/sources/wp-admin/css/media-rtl.min.css @@ -0,0 +1 @@ +body#media-upload ul#sidemenu{left:auto;right:0}#search-filter{text-align:left}.align .field label{padding:0 23px 0 0;margin:0 3px 0 1em}.image-align-none-label,.image-align-left-label,.image-align-center-label,.image-align-right-label{background-position:center right}tr.image-size label{margin:0 5px 0 0}.file-error{margin:0 50px 5px 0}.progress{left:auto;right:0}.describe td{padding:0 0 0 5px}#media-upload .describe th.label{text-align:right}.menu_order{float:left}.media-upload-form label.form-help,td.help,#media-upload p.help,#media-upload label.help{font-family:Tahoma,Arial}#gallery-settings #basic th.label{padding:5px 0 5px 5px}#gallery-settings .title,h3.media-title{font-family:Tahoma,Arial}#gallery-settings .describe th.label{text-align:right}#gallery-settings label,#gallery-settings legend{margin-right:0;margin-left:15px}#gallery-settings .align .field label{margin:0 3px 0 1em}#sort-buttons{margin:3px 0 -8px 25px;text-align:left}#sort-buttons #asc,#sort-buttons #showall{padding-left:0;padding-right:5px}#sort-buttons span{margin-right:0;margin-left:25px} \ No newline at end of file diff --git a/sources/wp-admin/css/media.css b/sources/wp-admin/css/media.css new file mode 100644 index 0000000..85adbf3 --- /dev/null +++ b/sources/wp-admin/css/media.css @@ -0,0 +1,353 @@ +/* Styles for the media library iframe (not used on the Library screen) */ + +div#media-upload-header { + margin: 0; + padding: 5px 5px 0; + font-weight: bold; + position: relative; + border-bottom-width: 1px; + border-bottom-style: solid; +} + +body#media-upload ul#sidemenu { + font-weight: normal; + margin: 0 5px; + left: 0; + bottom: -1px; + float: none; + overflow: hidden; +} + +form { + margin: 1em; +} + +#search-filter { + text-align: right; +} + +th { + position: relative; +} + +.media-upload-form label.form-help, td.help { + font-family: sans-serif; + font-style: italic; + font-weight: normal; +} + +.media-upload-form p.help { + margin: 0; + padding: 0; +} + +.media-upload-form fieldset { + width: 100%; + border: none; + text-align: justify; + margin: 0 0 1em 0; + padding: 0; +} + +/* specific to the image upload form */ + +.image-align-none-label { + background: url(../images/align-none.png) no-repeat center left; +} + +.image-align-left-label { + background: url(../images/align-left.png) no-repeat center left; +} + +.image-align-center-label { + background: url(../images/align-center.png) no-repeat center left; +} + +.image-align-right-label { + background: url(../images/align-right.png) no-repeat center left; +} + +tr.image-size td { + width: 460px; +} + +tr.image-size div.image-size-item { + margin: 0 0 5px; +} + +#library-form .progress, +#gallery-form .progress, +.insert-gallery, +.describe.startopen, +.describe.startclosed { + display: none; +} + +.media-item .thumbnail { + max-width: 128px; + max-height: 128px; +} + +thead.media-item-info tr { + background-color: transparent; +} + +.form-table thead.media-item-info { + border: 8px solid #fff; +} + +abbr.required { + text-decoration: none; + border: none; +} + +.describe label { + display: inline; +} + +.describe td.error { + padding: 2px 8px; +} + +.describe td.A1 { + width: 132px; +} + +.describe input[type="text"], +.describe textarea { + width: 460px; + border-width: 1px; + border-style: solid; +} + +/* Specific to Uploader */ + +#media-upload p.ml-submit { + padding: 1em 0; +} + +#media-upload p.help, +#media-upload label.help { + font-family: sans-serif; + font-style: italic; + font-weight: normal; +} + +#media-upload .ui-sortable .media-item { + cursor: move; +} + +#media-upload tr.image-size { + margin-bottom: 1em; + height: 3em; +} + +#media-upload #filter { + width: 623px; +} + +#media-upload #filter .subsubsub { + margin: 8px 0; +} + +#filter .tablenav select { + border-style: solid; + border-width: 1px; + padding: 2px; + vertical-align: top; + width: auto; +} + +#media-upload .del-attachment { + display: none; + margin: 5px 0; +} + +.menu_order { + float: right; + font-size: 11px; + margin: 10px 10px 0; +} + +.menu_order_input { + border: 1px solid #ddd; + font-size: 10px; + padding: 1px; + width: 23px; +} + +.ui-sortable-helper { + background-color: #fff; + border: 1px solid #aaa; + opacity: 0.6; + filter: alpha(opacity=60); +} + +#media-upload th.order-head { + width: 20%; + text-align: center; +} + +#media-upload th.actions-head { + width: 25%; + text-align: center; +} + +#media-upload a.wp-post-thumbnail { + margin: 0 20px; +} + +#media-upload .widefat { + width: 626px; + border-style: solid solid none; +} + +.sorthelper { + height: 37px; + width: 623px; + display: block; +} + +#gallery-settings th.label { + width: 160px; +} + +#gallery-settings #basic th.label { + padding: 5px 5px 5px 0; +} + +#gallery-settings .title { + clear: both; + padding: 0 0 3px; + font-size: 1.6em; + border-bottom: 1px solid #DADADA; +} + +h3.media-title { + font-size: 1.6em; +} + +h4.media-sub-title { + border-bottom: 1px solid #DADADA; + font-size: 1.3em; + margin: 12px; + padding: 0 0 3px; +} + +#gallery-settings .title, +h3.media-title, +h4.media-sub-title { + font-family: Georgia,"Times New Roman",Times,serif; + font-weight: normal; + color: #5A5A5A; +} + +#gallery-settings .describe td { + vertical-align: middle; + height: 3em; +} + +#gallery-settings .describe th.label { + padding-top: .5em; + text-align: left; +} + +#gallery-settings .describe { + padding: 5px; + width: 615px; + clear: both; + cursor: default; +} + +#gallery-settings .describe select { + width: 15em; +} + +#gallery-settings .describe select option, +#gallery-settings .describe td { + padding: 0; +} + +#gallery-settings label, +#gallery-settings legend { + font-size: 13px; + color: #464646; + margin-right: 15px; +} + +#gallery-settings .align .field label { + margin: 0 1em 0 3px; +} + +#gallery-settings p.ml-submit { + border-top: 1px solid #dfdfdf; +} + +#gallery-settings select#columns { + width: 6em; +} + +#sort-buttons { + font-size: 0.8em; + margin: 3px 25px -8px 0; + text-align: right; + max-width: 625px; +} + +#sort-buttons a { + text-decoration: none; +} + +#sort-buttons #asc, +#sort-buttons #showall { + padding-left: 5px; +} + +#sort-buttons span { + margin-right: 25px; +} + +p.media-types { + margin: 1em; +} + +tr.not-image { + display: none; +} + +table.not-image tr.not-image { + display: table-row; +} + +table.not-image tr.image-only { + display: none; +} + +/** + * HiDPI Displays + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + + .image-align-none-label { + background-image: url("../images/align-none-2x.png?ver=20120916"); + background-size: 21px 15px; + } + + .image-align-left-label { + background-image: url("../images/align-left-2x.png?ver=20120916"); + background-size: 22px 15px; + } + + .image-align-center-label { + background-image: url("../images/align-center-2x.png?ver=20120916"); + background-size: 21px 15px; + } + + .image-align-right-label { + background-image: url("../images/align-right-2x.png?ver=20120916"); + background-size: 22px 15px; + } +} diff --git a/sources/wp-admin/css/media.min.css b/sources/wp-admin/css/media.min.css new file mode 100644 index 0000000..fbdeea2 --- /dev/null +++ b/sources/wp-admin/css/media.min.css @@ -0,0 +1 @@ +div#media-upload-header{margin:0;padding:5px 5px 0;font-weight:700;position:relative;border-bottom-width:1px;border-bottom-style:solid}body#media-upload ul#sidemenu{font-weight:400;margin:0 5px;left:0;bottom:-1px;float:none;overflow:hidden}form{margin:1em}#search-filter{text-align:right}th{position:relative}.media-upload-form label.form-help,td.help{font-family:sans-serif;font-style:italic;font-weight:400}.media-upload-form p.help{margin:0;padding:0}.media-upload-form fieldset{width:100%;border:0;text-align:justify;margin:0 0 1em;padding:0}.image-align-none-label{background:url(../images/align-none.png) no-repeat center left}.image-align-left-label{background:url(../images/align-left.png) no-repeat center left}.image-align-center-label{background:url(../images/align-center.png) no-repeat center left}.image-align-right-label{background:url(../images/align-right.png) no-repeat center left}tr.image-size td{width:460px}tr.image-size div.image-size-item{margin:0 0 5px}#library-form .progress,#gallery-form .progress,.insert-gallery,.describe.startopen,.describe.startclosed{display:none}.media-item .thumbnail{max-width:128px;max-height:128px}thead.media-item-info tr{background-color:transparent}.form-table thead.media-item-info{border:8px solid #fff}abbr.required{text-decoration:none;border:0}.describe label{display:inline}.describe td.error{padding:2px 8px}.describe td.A1{width:132px}.describe input[type=text],.describe textarea{width:460px;border-width:1px;border-style:solid}#media-upload p.ml-submit{padding:1em 0}#media-upload p.help,#media-upload label.help{font-family:sans-serif;font-style:italic;font-weight:400}#media-upload .ui-sortable .media-item{cursor:move}#media-upload tr.image-size{margin-bottom:1em;height:3em}#media-upload #filter{width:623px}#media-upload #filter .subsubsub{margin:8px 0}#filter .tablenav select{border-style:solid;border-width:1px;padding:2px;vertical-align:top;width:auto}#media-upload .del-attachment{display:none;margin:5px 0}.menu_order{float:right;font-size:11px;margin:10px 10px 0}.menu_order_input{border:1px solid #ddd;font-size:10px;padding:1px;width:23px}.ui-sortable-helper{background-color:#fff;border:1px solid #aaa;opacity:.6;filter:alpha(opacity=60)}#media-upload th.order-head{width:20%;text-align:center}#media-upload th.actions-head{width:25%;text-align:center}#media-upload a.wp-post-thumbnail{margin:0 20px}#media-upload .widefat{width:626px;border-style:solid solid none}.sorthelper{height:37px;width:623px;display:block}#gallery-settings th.label{width:160px}#gallery-settings #basic th.label{padding:5px 5px 5px 0}#gallery-settings .title{clear:both;padding:0 0 3px;font-size:1.6em;border-bottom:1px solid #DADADA}h3.media-title{font-size:1.6em}h4.media-sub-title{border-bottom:1px solid #DADADA;font-size:1.3em;margin:12px;padding:0 0 3px}#gallery-settings .title,h3.media-title,h4.media-sub-title{font-family:Georgia,"Times New Roman",Times,serif;font-weight:400;color:#5A5A5A}#gallery-settings .describe td{vertical-align:middle;height:3em}#gallery-settings .describe th.label{padding-top:.5em;text-align:left}#gallery-settings .describe{padding:5px;width:615px;clear:both;cursor:default}#gallery-settings .describe select{width:15em}#gallery-settings .describe select option,#gallery-settings .describe td{padding:0}#gallery-settings label,#gallery-settings legend{font-size:13px;color:#464646;margin-right:15px}#gallery-settings .align .field label{margin:0 1em 0 3px}#gallery-settings p.ml-submit{border-top:1px solid #dfdfdf}#gallery-settings select#columns{width:6em}#sort-buttons{font-size:.8em;margin:3px 25px -8px 0;text-align:right;max-width:625px}#sort-buttons a{text-decoration:none}#sort-buttons #asc,#sort-buttons #showall{padding-left:5px}#sort-buttons span{margin-right:25px}p.media-types{margin:1em}tr.not-image{display:none}table.not-image tr.not-image{display:table-row}table.not-image tr.image-only{display:none}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.image-align-none-label{background-image:url(../images/align-none-2x.png?ver=20120916);background-size:21px 15px}.image-align-left-label{background-image:url(../images/align-left-2x.png?ver=20120916);background-size:22px 15px}.image-align-center-label{background-image:url(../images/align-center-2x.png?ver=20120916);background-size:21px 15px}.image-align-right-label{background-image:url(../images/align-right-2x.png?ver=20120916);background-size:22px 15px}} \ No newline at end of file diff --git a/sources/wp-admin/css/wp-admin-rtl.css b/sources/wp-admin/css/wp-admin-rtl.css new file mode 100644 index 0000000..5221a04 --- /dev/null +++ b/sources/wp-admin/css/wp-admin-rtl.css @@ -0,0 +1,2895 @@ +/*------------------------------------------------------------------------------ + + +Hello, this is the RTL version of the main WordPress admin CSS file. +All the important stuff is in here. + + +TABLE OF CONTENTS: +------------------ + 1.0 - Text Elements + 2.0 - Forms + 3.0 - Actions + 4.0 - Notifications + 5.0 - TinyMCE + 6.0 - Admin Header + 6.1 - Screen Options Tabs + 7.0 - Main Navigation + 8.0 - Layout Blocks + 9.0 - Dashboard +10.0 - List Posts + 10.1 - Inline Editing +11.0 - Write/Edit Post Screen + 11.1 - Custom Fields + 11.2 - Post Revisions + 11.3 - Featured Images + 11.4 - Post formats +12.0 - Categories +13.0 - Tags +14.0 - Media Screen + 14.1 - Media Uploader + 14.2 - Image Editor +15.0 - Comments Screen +16.0 - Themes + 16.1 - Custom Header + 16.2 - Custom Background + 16.3 - Tabbed Admin Screen Interface +17.0 - Plugins +18.0 - Users +19.0 - Tools +20.0 - Settings +21.0 - Admin Footer +22.0 - About Pages +23.0 - Misc +24.0 - Dead +25.0 - TinyMCE tweaks +26.0 - Full Overlay w/ Sidebar +27.0 - Customize Loader +28.0 - Nav Menus +29.0 - HiDPI + + +------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + 1.0 - Text Styles +------------------------------------------------------------------------------*/ + +ol { + margin-left: 0; + margin-right: 2em; +} + +.code, code { + font-family: monospace; + direction: ltr; +} + +.quicktags, .search { + font: 12px Tahoma, Arial, sans-serif; +} + +.icon32 { + float: right; + margin-right: 0; + margin-left: 8px; +} + +.icon16 { + float: right; + margin-right: -8px; + margin-left: 0; +} + +.howto { + font-style: normal; + font-family: Tahoma, Arial, sans-serif; +} + +p.install-help { + font-style: normal; +} + + +/*------------------------------------------------------------------------------ + 2.0 - Forms +------------------------------------------------------------------------------*/ + +#doaction, +#doaction2, +#post-query-submit { + margin-right: 0; + margin-left: 8px; +} + +#timezone_string option { + margin-left: 0; + margin-right: 1em; +} + +#pass-strength-result { + float: right; + margin: 13px 1px 5px 5px; +} + +p.search-box { + float: left; +} + +.search-box input[name="s"], +#search-plugins input[name="s"], +.tagsdiv .newtag { + float: right; + margin-right: 0; + margin-left: 4px; +} + +input[type=password] { + direction: ltr; +} + +input[type="text"].ui-autocomplete-loading { + background: transparent url('../images/loading.gif') no-repeat left center; +} + +ul#add-to-blog-users { + margin: 0 14px 0 0; +} + +.ui-autocomplete li { + text-align: right; +} + +/*------------------------------------------------------------------------------ + 3.0 - Actions +------------------------------------------------------------------------------*/ + +#delete-action { + float: right; +} + +#publishing-action { + float: left; + text-align: left; +} + +#publishing-action .spinner { + float: right; +} + +#post-body .misc-pub-section { + border-right: 0; + border-left-width: 1px; + border-left-style: solid; +} + +#post-body .misc-pub-section-last { + border-left: 0; +} + +#minor-publishing-actions { + padding: 10px 8px 2px 10px; + text-align: left; +} + +#save-post { + float: right; +} + +.preview { + float: left; +} + +#sticky-span { + margin-left: 0; + margin-right: 18px; +} + +.side-info ul { + padding-left: 0; + padding-right: 18px; +} + +td.action-links, +th.action-links { + text-align: left; +} + + +/*------------------------------------------------------------------------------ + 4.0 - Notifications +------------------------------------------------------------------------------*/ + +form.upgrade .hint { + font-style: normal; +} + +#ajax-response.alignleft { + margin-left: 0; + margin-right: 2em; +} + + +/*------------------------------------------------------------------------------ + 5.0 - TinyMCE +------------------------------------------------------------------------------*/ + +#quicktags { + background-position: right top; +} + +#ed_reply_toolbar input { + margin: 1px 1px 1px 2px; +} + +/*------------------------------------------------------------------------------ + 6.0 - Admin Header +------------------------------------------------------------------------------*/ +#wphead { + height: 32px; + margin-left: 15px; + margin-right: 2px; +} + +#header-logo { + float: right; +} + +#wphead h1 { + float: right; +} + +/*------------------------------------------------------------------------------ + 6.1 - Screen Options Tabs +------------------------------------------------------------------------------*/ + +#screen-meta-links { + margin-right: 0; + margin-left: 24px; +} + +#screen-meta { + margin-right: 5px; + margin-left: 15px; +} + +#screen-options-link-wrap, +#contextual-help-link-wrap { + float: left; + margin-left: 0; + margin-right: 6px; +} + +#screen-meta-links a.show-settings { + padding-right: 6px; + padding-left: 16px; +} + +.toggle-arrow { + background-position: top right; +} +.toggle-arrow-active { + background-position: bottom right; +} + +.metabox-prefs label { + padding-right: 0; + padding-left: 15px; +} + +.metabox-prefs label input { + margin-right: 2px; + margin-left: 5px; +} + +/*------------------------------------------------------------------------------ + 6.2 - Help Menu +------------------------------------------------------------------------------*/ + +#contextual-help-wrap { + margin-left: 0; + margin-right: -4px; +} + +#contextual-help-back { + left: 170px; + right: 150px; +} + +#contextual-help-wrap.no-sidebar #contextual-help-back { + left: 0; + right: 150px; + + border-right-width: 1px; + border-left-width: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 2px; + border-bottom-left-radius: 2px; +} + +.contextual-help-tabs { + float: right; +} + +.contextual-help-tabs a { + padding-left: 5px; + padding-right: 12px; +} + +.contextual-help-tabs .active { + margin-right: 0; + margin-left: -1px; +} + +.contextual-help-tabs .active, +.contextual-help-tabs-wrap { + border-left: 0; + border-right-width: 1px; +} + +.help-tab-content { + margin-right: 0; + margin-left: 22px; +} + +.help-tab-content li { + margin-left: 0; + margin-right: 18px; +} + +.contextual-help-sidebar { + float: left; + padding-right: 12px; + padding-left: 8px; +} + +/*------------------------------------------------------------------------------ + 7.0 - Main Navigation (Right Menu) (RTL: Left Menu) +------------------------------------------------------------------------------*/ + +.folded #wpcontent { + margin-left: 0; + margin-right: 52px; +} + +.folded.wp-admin #wpfooter { + margin-left: 15px; + margin-right: 52px; +} + +#adminmenuback, +#adminmenuwrap { + border-width: 0 0 0 1px; +} + +#adminmenushadow { + right: auto; + left: 0; +} + +#adminmenu li .wp-submenu { + left: auto; + right: 146px; +} + + +.folded #adminmenu .wp-submenu.sub-open, +.folded #adminmenu .opensub .wp-submenu, +.folded #adminmenu .wp-has-current-submenu .wp-submenu.sub-open, +.folded #adminmenu .wp-has-current-submenu.opensub .wp-submenu, +.folded #adminmenu a.menu-top:focus + .wp-submenu, +.folded #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu, +.no-js.folded #adminmenu .wp-has-submenu:hover .wp-submenu { + left: auto; + right: 32px; +} + +#adminmenu div.wp-menu-image, +.folded #adminmenu div.wp-menu-image { + float: right; + width: 30px; +} + +#adminmenu .wp-submenu a, +#adminmenu li li a, +.folded #adminmenu .wp-not-current-submenu li a { + padding-left: 0; + padding-right: 12px; +} + +#adminmenu .wp-not-current-submenu li a { + padding-left: 0; + padding-right: 18px; +} + +.wp-menu-arrow { + right: 0; + + -moz-transform: translate( -139px ); + -webkit-transform: translate( -139px ); + -o-transform: translate( -139px ); + -ms-transform: translate( -139px ); + transform: translate( -139px ); +} + +.ie8 .wp-menu-arrow { + right: -20px; +} + +#adminmenu .wp-menu-arrow div { + left: -8px; + width: 16px; +} + +#adminmenu li.wp-not-current-submenu .wp-menu-arrow { + -moz-transform: translate( -138px ); + -webkit-transform: translate( -138px ); + -o-transform: translate( -138px ); + -ms-transform: translate( -138px ); + transform: translate( -138px ); +} + +.folded #adminmenu li .wp-menu-arrow { + -moz-transform: translate( -26px ); + -webkit-transform: translate( -26px ); + -o-transform: translate( -26px ); + -ms-transform: translate( -26px ); + transform: translate( -26px ); +} + +#adminmenu .wp-not-current-submenu .wp-menu-arrow div { + border-style: solid solid none none; + border-width: 1px 1px 0 0; +} + +#adminmenu .wp-menu-image img { + padding: 7px 7px 0 0; +} + +#adminmenu .wp-submenu .wp-submenu-head { + padding: 5px 10px 5px 4px; + -webkit-border-top-right-radius: 0; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 0; + border-top-left-radius: 3px; +} + +.folded #adminmenu li.wp-has-current-submenu .wp-submenu { + border-width: 1px; + border-style: solid; + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-top-right-radius: 0; + -webkit-border-top-left-radius: 3px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 3px; + border-top-right-radius: 0; + border-top-left-radius: 3px; +} + +#adminmenu .awaiting-mod, +#adminmenu span.update-plugins, +#sidemenu li a span.update-plugins { + font-family: Tahoma, Arial, sans-serif; + margin-left: 0; + margin-right: 7px; +} + +#collapse-button { + float: right; +} + +/* Auto-folding of the admin menu */ +@media only screen and (max-width: 900px) { + .auto-fold #wpcontent { + margin-left: 0; + margin-right: 52px; + } + + .auto-fold.wp-admin #wpfooter { + margin-left: 15px; + margin-right: 52px; + } + + .auto-fold #adminmenu div.wp-menu-image { + float: right; + width: 30px; + } + + .auto-fold #adminmenu .wp-submenu.sub-open, + .auto-fold #adminmenu .opensub .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu .wp-submenu.sub-open, + .auto-fold #adminmenu .wp-has-current-submenu.opensub .wp-submenu, + .auto-fold #adminmenu a.menu-top:focus + .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu, + .no-js.auto-fold #adminmenu .wp-has-submenu:hover .wp-submenu { + left: auto; + right: 32px; + } + + .auto-fold #adminmenu .wp-not-current-submenu li a { + padding-left: 0; + padding-right: 12px; + } + + .auto-fold #adminmenu li .wp-menu-arrow { + -moz-transform: translate( -27px ); + -webkit-transform: translate( -27px ); + -o-transform: translate( -27px ); + -ms-transform: translate( -27px ); + transform: translate( -27px ); + } + + .auto-fold #adminmenu li.wp-has-current-submenu .wp-submenu { + border-width: 1px; + border-style: solid; + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-top-right-radius: 0; + -webkit-border-top-left-radius: 3px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 3px; + border-top-right-radius: 0; + border-top-left-radius: 3px; + } +} + +/* List table styles */ +.post-com-count-wrapper { + font-family: Tahoma, Arial, sans-serif; +} + +.post-com-count { + background-image: url('../images/bubble_bg-rtl.gif'); +} + +.column-response .post-com-count { + float: right; + margin-right: 0; + margin-left: 5px; +} + +.response-links { + float: right; +} + + +/*------------------------------------------------------------------------------ + 8.0 - Layout Blocks +------------------------------------------------------------------------------*/ + +.widefat th { + font-family: Tahoma, Arial, sans-serif; +} + +.postbox-container { + float: right; +} + +#post-body-content { + float: right; +} + +#poststuff #post-body.columns-2 { + margin-left: 300px; + margin-right: 0; +} + +#post-body.columns-2 #postbox-container-1 { + float: left; + margin-left: -300px; + margin-right: 0; +} + +@media only screen and (max-width: 850px) { + #wpbody-content #post-body.columns-2 #postbox-container-1 { + margin-left: 0; + } +} + +.postbox .handlediv { + float: left; +} + +/*------------------------------------------------------------------------------ + 9.0 - Dashboard +------------------------------------------------------------------------------*/ + +#the-comment-list p.comment-author img { + float: right; + margin-right: 0; + margin-left: 8px; +} + +/* Browser Nag */ +#dashboard_browser_nag p.browser-update-nag.has-browser-icon { + padding-right: 0; + padding-left: 125px; +} + +/* Welcome Panel */ +.welcome-panel .welcome-panel-close { + right: auto; + left: 10px; +} + +.welcome-panel .welcome-panel-close:before { + left: auto; + right: -12px; +} + +.welcome-panel-content { + margin-left: 0; + margin-right: 13px; +} + +.welcome-panel .welcome-panel-column { + float: right; +} + +.welcome-panel .welcome-panel-column ul { + margin-right: 0; + margin-left: 1em; +} + +.welcome-panel .welcome-panel-column li { + padding-left: 0; + padding-right: 2px; +} + +.welcome-panel .welcome-add-page { + background-position: right 2px; +} + +.welcome-panel .welcome-edit-page { + background-position: right -90px; +} + +.welcome-panel .welcome-learn-more { + background-position: right -136px; +} + +.welcome-panel .welcome-comments { + background-position: right -182px; +} + +.welcome-panel .welcome-view-site { + background-position: right -274px; +} + +.welcome-panel .welcome-widgets-menus { + background-position: right -229px; + line-height: 14px; +} + +.welcome-panel .welcome-write-blog { + background-position: right -44px; +} + +.welcome-panel .welcome-icon { + padding: 2px 32px 8px 0; +} + +@media screen and (max-width: 870px) { + .welcome-panel .welcome-panel-column li { + margin-right: 0; + margin-left: 13px; + } + + .welcome-panel .welcome-icon { + padding-right: 25px; + padding-left: 0; + } +} + +/*------------------------------------------------------------------------------ + 10.0 - List Posts (/Pages/etc) +------------------------------------------------------------------------------*/ + +.fixed .column-comments { + text-align: right; +} + +.fixed .column-comments .vers { + padding-left: 0; + padding-right: 3px; +} + +.fixed .column-comments a { + float: right; +} + +.fixed .column-menus { + text-align: right; +} + +.sorting-indicator { + margin-left: 0; + margin-right: 7px; +} + +tr.wp-locked .locked-indicator { + margin: -2px 6px 0 0; +} + +th.sortable a span, +th.sorted a span { + float: right; +} + +/* Bulk Actions */ + +.tablenav-pages a { + margin-right: 0; + margin-left: 1px; +} +.tablenav-pages .next-page { + margin-left: 0; + margin-right: 2px; +} + +.tablenav a.button-secondary { + margin: 3px 0 0 8px; +} + +.tablenav .tablenav-pages { + float: left; +} + +.tablenav .displaying-num { + margin-right: 0; + margin-left: 10px; + font-family: Tahoma, Arial, sans-serif; + font-style: normal; +} + +.tablenav .actions { + padding: 2px 0 0 8px; +} + +.tablenav .actions select { + float: right; + margin-right: 0; + margin-left: 6px; +} + +.tablenav .delete { + margin-right: 0; + margin-left: 20px; +} + +.view-switch { + float: left; +} + +.filter { + float: right; + margin: -5px 10px 0 0; +} + +.filter .subsubsub { + margin-left: 0; + margin-right: -10px; +} + +#posts-filter fieldset { + float: right; + margin: 0 0 1em 1.5ex; +} + +#posts-filter fieldset legend { + padding: 0 1px .2em 0; +} + +/*------------------------------------------------------------------------------ + 10.1 - Inline Editing +------------------------------------------------------------------------------*/ + +#wpbody-content .inline-edit-row fieldset { + float: right; +} + +#wpbody-content .quick-edit-row-page fieldset.inline-edit-col-right .inline-edit-col { + border-width: 0 1px 0 0; +} + +#wpbody-content .bulk-edit-row .inline-edit-col-bottom { + float: left; +} + +.inline-edit-row fieldset label span.title { + float: right; +} + +.inline-edit-row fieldset label span.input-text-wrap { + margin-left: 0; + margin-right: 5em; +} + +.quick-edit-row-post fieldset.inline-edit-col-right label span.title { + padding-right: 0; + padding-left: 0.5em; +} + +#wpbody-content .quick-edit-row fieldset .inline-edit-group label.alignleft:first-child { + margin-right: 0; + margin-left: 0.5em +} + +/* Styling */ + +.inline-edit-row fieldset span.title, +.inline-edit-row fieldset span.checkbox-title { + font-family: Tahoma, Arial, sans-serif; + font-style: normal; +} + +.inline-edit-row fieldset .inline-edit-date { + float: right; +} + +.inline-edit-row fieldset ul.cat-checklist label, +.inline-edit-row #bulk-titles div { + font-family: Tahoma, Arial, sans-serif; +} + +.quick-edit-row-post fieldset label.inline-edit-status { + float: right; +} + +#bulk-titles div a { + float: right; + margin: 3px -2px 0 3px; + overflow: hidden; + text-indent: -9999px; +} + + +/*------------------------------------------------------------------------------ + 11.0 - Write/Edit Post Screen +------------------------------------------------------------------------------*/ + +#save-action .spinner, +#show-comments a, +#show-comments .spinner { + float: right; +} + +#titlediv #title-prompt-text, +#wp-fullscreen-title-prompt-text { + right: 0; +} + +#sample-permalink { + direction: ltr; +} + +#sample-permalink #editable-post-name { + unicode-bidi: embed; +} + +#wp-fullscreen-title-prompt-text { + left: auto; + right: 0; +} + +#wp-fullscreen-save .spinner, +#wp-fullscreen-save .fs-saved { + float: left; +} + +#edit-slug-box .cancel { + margin-right: 0; + margin-left: 10px; +} + +.postarea h3 label { + float: right; +} + +.submitbox .submit { + text-align: right; +} + +.inside-submitbox #post_status { + margin: 2px -2px 2px 0; +} + +.submitbox .submit input { + margin-right: 0; + margin-left: 4px; +} + +#normal-sortables .postbox .submit { + float: left; +} + +.taxonomy div.tabs-panel { + margin: 0 125px 0 5px; +} + +#side-sortables .comments-box thead th, +#normal-sortables .comments-box thead th { + font-style: normal; +} + +#commentsdiv .spinner { + padding-left: 0; + padding-right: 5px; +} + +#post-body .add-menu-item-tabs li.tabs { + border-width: 1px 1px 1px 0; + margin-right: 0; + margin-left: -1px; +} + +/* Global classes */ + +#post-body .tagsdiv #newtag { + margin-right: 0; + margin-left: 5px; +} + +.autosave-info { + padding: 2px 2px 2px 15px; + text-align: left; +} + +#post-body .wp_themeSkin .mceStatusbar a.mceResize { + background: transparent url('../images/resize-rtl.gif') no-repeat scroll left bottom; + cursor: sw-resize; +} + +.curtime #timestamp { + background-position: right top; + padding-left: 0; + padding-right: 18px; +} + +.compat-attachment-fields th { + padding-right: 0; + padding-left: 10px; +} + +#post-lock-dialog .post-locked-message a.button { + margin-right: 0; + margin-left: 10px; +} + +#post-lock-dialog .post-locked-avatar { + float: right; + margin: 0 0 20px 20px; +} + +#post-lock-dialog .locked-saving img { + float: right; + margin-right: 0; + margin-left: 3px; +} + + +/*------------------------------------------------------------------------------ + 11.1 - Custom Fields +------------------------------------------------------------------------------*/ + +/* No RTL for now, this space intentionally left blank */ + +/*------------------------------------------------------------------------------ + 11.2 - Post Revisions +------------------------------------------------------------------------------*/ +.wp-slider .ui-slider-handle.from-handle:before, +.wp-slider .ui-slider-handle.to-handle:before { + height: 8px; + width: 7px; +} + +.wp-slider .ui-slider-handle.from-handle:before { + background-position: -5px -10px; + left: 6px; +} + +.wp-slider .ui-slider-handle.to-handle:before { + background-position: -4px -29px; + left: 6px; +} + +.revision-toggle-compare-mode { + right: auto; + left: 0; +} + +.revisions .loading-indicator { + margin-right: -90px; +} + +body.folded .revisions .loading-indicator { + margin-right: -32px; +} + +.revisions-next { + float: left; +} + +.revisions-previous { + float: right; +} + +.diff-title strong { + text-align: left; + float: right; + margin-right: 0; + margin-left: 5px; +} + +.revisions-controls .author-card .avatar, +.revisions-controls .author-card .author-info { + float: right; +} + +.diff-meta input.restore-revision { + float: left; +} + +.diff-col-title-added, +.diff-col-title-removed { + text-align: right; + float: right; +} + +.revisions-tooltip { + margin-left: 0; + margin-right: -69px; +} + +.revisions-tooltip.flipped { + margin-right: 0; + margin-left: -70px; +} + +.ie8 .revisions-tooltip { + margin-right: -75px; +} + +.ie8 .revisions-tooltip.flipped { + margin-left: -63px; +} + +.revisions-tooltip-arrow { + right: 0; + margin-left: 0; + margin-right: 35px; +} + +.revisions-tooltip.flipped .revisions-tooltip-arrow { + margin-right: 0; + margin-left: 35px; + right: auto; + left: 0; +} + +.revisions-tooltip-arrow > span { + left: auto; + right: 20px; +} + +.revisions-tooltip.flipped .revisions-tooltip-arrow > span { + right: auto; + left: 20px; +} + +.ie8 .revisions-tooltip-arrow > span { + right: 21px; +} + +.revisions-tickmarks > div { + float: right; + border-width: 0 0 0 1px; +} + +/*------------------------------------------------------------------------------ + 11.3 - Featured Images +------------------------------------------------------------------------------*/ + +#select-featured-image a { + float: right; +} + +/*------------------------------------------------------------------------------ + 11.4 - Post formats +------------------------------------------------------------------------------*/ + +a.post-state-format { + margin-right: 0; + margin-left: 5px; +} + +label.post-format-icon { + margin-left: 0; + margin-right: 5px; + padding-left: 0px; + padding-right: 21px; +} + +.post-format-icon.post-format-standard { + background-position: 100% 0; +} + +.post-format-icon.post-format-image { + background-position: 100% -32px; +} + +.post-format-icon.post-format-gallery { + background-position: 100% -64px; +} + +.post-format-icon.post-format-audio { + background-position: 100% -96px; +} + +.post-format-icon.post-format-video { + background-position: 100% -128px; +} + +.post-format-icon.post-format-chat { + background-position: 100% -160px; +} + +.post-format-icon.post-format-status { + background-position: 100% -192px; +} + +.post-format-icon.post-format-aside { + background-position: 100% -224px; +} + +.post-format-icon.post-format-quote { + background-position: 100% -256px; +} + +.post-format-icon.post-format-link { + background-position: 100% -288px; +} + +/*------------------------------------------------------------------------------ + 12.0 - Categories +------------------------------------------------------------------------------*/ + +.category-adder { + margin-left: 0; + margin-right: 120px; +} + +#post-body ul.add-menu-item-tabs { + float: right; + text-align: left; + /* Negative margin for the sake of those without JS: all tabs display */ + margin: 0 5px 0 -120px; +} + +#post-body ul.add-menu-item-tabs li.tabs { + -webkit-border-top-left-radius: 0; + -webkit-border-top-right-radius: 3px; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 3px; + border-top-left-radius: 0; + border-top-right-radius: 3px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 3px; +} + +#front-page-warning, +#front-static-pages ul, +ul.export-filters, +.inline-editor ul.cat-checklist ul, +.categorydiv ul.categorychecklist ul, +.customlinkdiv ul.categorychecklist ul, +.posttypediv ul.categorychecklist ul, +.taxonomydiv ul.categorychecklist ul { + margin-left: 0; + margin-right: 18px; +} + +#post-body .add-menu-item-tabs li.tabs { + border-style: solid solid solid none; + border-width: 1px 1px 1px 0; + margin-right: 0; + margin-left: -1px; +} + +p.help, +p.description, +span.description, +.form-wrap p { + font-style: normal; + font-family: Tahoma, Arial, sans-serif; +} + +/*------------------------------------------------------------------------------ + 13.0 - Tags +------------------------------------------------------------------------------*/ + +.taghint { + margin: 15px 12px -24px 0; +} + +#poststuff .tagsdiv .howto { + margin: 0 8px 6px 0; +} + +.ac_results li { + text-align: right; +} + +.links-table th { + text-align: right; +} + +/*------------------------------------------------------------------------------ + 14.0 - Media Screen +------------------------------------------------------------------------------*/ + +#wpbody-content .describe th { + text-align: right; + +} + +.describe .media-item-info .A1B1 { + padding: 0 10px 0 0; +} + +.media-upload-form td label { + margin-left: 6px; + margin-right: 2px; +} + +.media-upload-form .align .field label { + padding: 0 23px 0 0; + margin: 0 3px 0 1em; +} + +.media-upload-form tr.image-size label { + margin: 0 5px 0 0; +} + +#wpbody-content .describe p.help { + padding: 0 5px 0 0; +} + +.media-item .edit-attachment, +.media-item .error-div a.dismiss, +.describe-toggle-on, +.describe-toggle-off { + float: left; + margin-right: 0; + margin-left: 15px; +} + +.media-item .error-div a.dismiss { + padding: 0 15px 0 0; +} + +.media-item .error-div { + padding-left: 0; + padding-right: 10px; +} + +.media-item .pinkynail { + float: right; +} + +.media-item .describe td { + padding: 0 0 8px 8px; +} + +.media-item .progress { + float: left; + margin: 6px 0 0 10px; +} + +/*------------------------------------------------------------------------------ + 14.1 - Media Uploader +------------------------------------------------------------------------------*/ + +#find-posts-input { + float: right; +} + +#find-posts-search { + float: right; + margin-right: 3px; + margin-left: 4px; +} + +.find-box-search .spinner { + left: auto; + right: 115px; +} + +#find-posts-response .found-radio { + padding: 5px 8px 0 0; +} + +.find-box-search label { + padding-right: 0; + padding-left: 6px; +} + +.find-box #resize-se { + right: auto; + left: 1px; +} + +form.upgrade .hint { + font-style: normal; +} + + +/*------------------------------------------------------------------------------ + 14.2 - Image Editor +------------------------------------------------------------------------------*/ + +.wp_attachment_image .button, +.A1B1 .button { + float: right; +} + +.wp_attachment_image .spinner, +.A1B1 .spinner { + float: right; +} + +.imgedit-menu div { + float: right; +} + +.imgedit-crop { + margin: 0; +} + +.imgedit-rleft, +.imgedit-flipv, +.imgedit-undo { + margin: 0 8px 0 3px; +} + +.imgedit-rright, +.imgedit-fliph, +.imgedit-redo { + margin: 0 3px; +} + +.imgedit-applyto img { + margin: 0 0 0 8px; +} + +.imgedit-help { + font-style: normal; +} + +.imgedit-submit-btn { + margin-left: 0; + margin-right: 20px; +} + + +/*------------------------------------------------------------------------------ + 15.0 - Comments Screen +------------------------------------------------------------------------------*/ + +.form-table th { + text-align: right; +} + +.form-table input.tog { + margin-right: 0; + margin-left: 2px; + float: right; +} + +.form-table table.color-palette { + float: right; +} + +/* reply to comments */ + +#replysubmit .spinner, +.inline-edit-save .spinner { + float: left; +} + +#replysubmit .button { + margin-right: 0; + margin-left: 5px; +} + +#edithead .inside { + float: right; + padding: 3px 5px 2px 0; +} + +.comment-ays th { + border-right-style: none; + border-left-style: solid; + border-right-width: 0; + border-left-width: 1px; +} + +.spam-undo-inside .avatar, +.trash-undo-inside .avatar { + margin-left: 8px; +} + +#comment-status-radio input { + margin: 2px 0 5px 3px; +} + +/*------------------------------------------------------------------------------ + 16.0 - Themes +------------------------------------------------------------------------------*/ + +h3.available-themes { + float: right; +} + +.available-theme { + margin-right: 0; + margin-left: 10px; + padding: 20px 0 20px 20px; +} + +#current-theme .theme-info li, +.theme-options li, +.available-theme .action-links li { + float: right; + padding-right: 0; + padding-left: 10px; + margin-right: 0; + margin-left: 10px; + border-right: none; + border-left: 1px solid #dfdfdf; +} + +.available-theme .action-links li { + padding-left: 8px; + margin-left: 8px; +} + +.ie8 .available-theme .action-links li { + padding-left: 7px; + margin-left: 7px; +} + +#current-theme .theme-info li:last-child, +.theme-options li:last-child, +.available-theme .action-links li:last-child { + padding-left: 0; + margin-right: 0; + border-left: 0; +} + +.available-theme .action-links .delete-theme { + float: left; + margin-left: 0; + margin-right: 8px; +} + +.available-theme .action-links p { + float: right; +} + +#current-theme.has-screenshot { + padding-left: 0; + padding-right: 330px; +} + +#current-theme h4 span { + margin-left: 0; + margin-right: 20px; +} + +#current-theme img { + float: right; + width: 300px; + margin-left: 0; + margin-right: -330px; +} + +.theme-options .load-customize { + margin-right: 0; + margin-left: 30px; + float: right; +} + +.theme-options span { + float: right; + margin-right: 0; + margin-left: 10px; +} + +.theme-options ul { + float: right; +} + +/* Allow for three-up on 1024px wide screens, e.g. tablets */ +@media only screen and (max-width: 1200px) { + #current-theme.has-screenshot { + padding-right: 270px; + } + + #current-theme img { + margin-right: -270px; + width: 240px; + } +} + +#broken-themes { + text-align: right; +} + +/*------------------------------------------------------------------------------ + 16.1 - Custom Header Screen +------------------------------------------------------------------------------*/ + +.appearance_page_custom-header .available-headers .default-header { + float: right; + margin: 0 0 20px 20px; +} + +.appearance_page_custom-header .random-header { + margin: 0 0 20px 20px; +} + +.appearance_page_custom-header .available-headers label input, +.appearance_page_custom-header .random-header label input { + margin-right: 0; + margin-left: 10px; +} + +/*------------------------------------------------------------------------------ + 16.2 - Custom Background Screen +------------------------------------------------------------------------------*/ + +/* No RTL for now, this space intentionally left blank */ + + +/*------------------------------------------------------------------------------ + 16.3 - Tabbed Admin Screen Interface (Experimental) +------------------------------------------------------------------------------*/ + +.nav-tab { + margin: 0 0 -1px 6px; +} + +h2 .nav-tab { + font-family: Tahoma, Arial, sans-serif; +} + + +/*------------------------------------------------------------------------------ + 17.0 - Plugins +------------------------------------------------------------------------------*/ + +.plugins .desc ul, +.plugins .desc ol { + margin: 0 2em 0 0; +} + +#wpbody-content .plugins .plugin-title, #wpbody-content .plugins .theme-title { + padding-right: 0; + padding-left: 12px; +} + + +/*------------------------------------------------------------------------------ + 18.0 - Users +------------------------------------------------------------------------------*/ + +#profile-page .form-table #rich_editing { + margin-right: 0; + margin-left: 5px +} + +#profile-page #pass1, +#profile-page #pass2, +#profile-page #user_login { + direction: ltr; +} + +#your-profile legend { + font-family: Tahoma, Arial, sans-serif; +} + +/*------------------------------------------------------------------------------ + 19.0 - Tools +------------------------------------------------------------------------------*/ + +.pressthis a span { + background-position: right 5px; + padding: 8px 27px 8px 11px; +} + +.pressthis a:after { + right: auto; + left: 10px; + background: transparent; + transform: skew(-20deg) rotate(-6deg); + -webkit-transform: skew(-20deg) rotate(-6deg); + -moz-transform: skew(-20deg) rotate(-6deg); +} + + +.pressthis a:hover:after { + transform: skew(-20deg) rotate(-9deg); + -webkit-transform: skew(-20deg) rotate(-9deg); + -moz-transform: skew(-20deg) rotate(-9deg); +} + +/*------------------------------------------------------------------------------ + 20.0 - Settings +------------------------------------------------------------------------------*/ + +#utc-time, #local-time { + padding-left: 0; + padding-right: 25px; + font-style: normal; + font-family: Tahoma, Arial, sans-serif; +} + +#permalink_structure { + float: right; +} + +.options-permalink-php code { + unicode-bidi: embed; +} + +.options-permalink-php #rules { + direction: ltr; +} + +/*------------------------------------------------------------------------------ + 21.0 - Admin Footer +------------------------------------------------------------------------------*/ + +#wpfooter { + margin-left: 20px; +} + +#wpcontent, +#wpfooter { + margin-right: 165px; +} + +/*------------------------------------------------------------------------------ + 22.0 - About Pages +------------------------------------------------------------------------------*/ + +.wrap.about-wrap { + margin-left: 40px; + margin-right: 20px; +} + +.about-wrap h1, +.about-text { + margin-right: 0; + margin-left: 200px; +} + +.about-wrap h2.nav-tab-wrapper { + padding-left: 0px; + padding-right: 6px; +} + +.about-wrap .wp-badge { + right: auto; + left: 0; +} + +.about-wrap h2 .nav-tab { + margin-right: 0; + margin-left: 3px; +} + +.about-wrap .changelog li { + margin-left: 0; + margin-right: 3em; +} + +.about-wrap .three-col-images .last-feature { + float: left; +} + +.about-wrap .three-col-images .first-feature { + float: right; +} + +.about-wrap .feature-section.two-col div, +.about-wrap .feature-section.three-col div { + margin-right: 0; + margin-left: 4.999999999%; + float: right; +} + +.about-wrap .feature-section.col .last-feature { + margin-left: 0; +} + +.about-wrap .feature-section div p img { + float: left; + margin-left: 0; + margin-right: 10px; +} + +.about-wrap li.wp-person, +.about-wrap li.wp-person img.gravatar { + float: right; + margin-right: 0; + margin-left: 10px; +} + + +/*------------------------------------------------------------------------------ + 23.0 - Misc +------------------------------------------------------------------------------*/ + +#template div { + margin-right: 0; + margin-left: 190px; +} + +.column-author img, .column-username img { + float: right; + margin-right: 0; + margin-left: 10px; +} + +.tagchecklist { + margin-left: 0; + margin-right: 14px; +} + +.tagchecklist strong { + margin-left: 0; + margin-right: -8px; +} + +.tagchecklist span { + margin-right: 0; + margin-left: 25px; + float: right; + +} +.tagchecklist span a { + margin: 4px -10px 0 0; + float: right; +} + +#poststuff h2 { + clear: right; +} + +#poststuff h3, +.metabox-holder h3 { + font-family: Tahoma, Arial, sans-serif; +} + +.tool-box .title { + font-family: Tahoma, Arial, sans-serif; +} + +#sidemenu { + margin: -30px 315px 0 15px; + float: left; + padding-left: 0; + padding-right: 10px; +} +#sidemenu a { + float: right; +} + +table .vers, +table .column-visible, +table .column-rating { + text-align: right; +} + +.screen-meta-toggle { + right: auto; + left: 15px; +} + +.screen-reader-text, +.screen-reader-text span, +.ui-helper-hidden-accessible { + left: auto; + right: -1000em; +} + +.screen-reader-shortcut:focus { + left: auto; + right: 6px; +} + +/*------------------------------------------------------------------------------ + 24.0 - Dead +------------------------------------------------------------------------------*/ + +/* - Not used anywhere in WordPress - verify and then deprecate +------------------------------------------------------------------------------*/ + +/* No RTL for now, this space intentionally left blank */ + + +/* - Only used once or twice in all of WP - deprecate for global style +------------------------------------------------------------------------------*/ + +* html #template div {margin-left: 0;} + +/* - Used - but could/should be deprecated with a CSS reset +------------------------------------------------------------------------------*/ +/* No RTL for now, this space intentionally left blank */ + + +/*------------------------------------------------------------------------------ + 25.0 - TinyMCE tweaks + Small tweaks for until tinymce css files are proprely RTLized +------------------------------------------------------------------------------*/ +#editorcontainer .wp_themeSkin .mceStatusbar { + padding-left: 0; + padding-right: 5px; +} + +#editorcontainer .wp_themeSkin .mceStatusbar div { + float: right; +} + +#editorcontainer .wp_themeSkin .mceStatusbar a.mceResize { + float: left; +} + +#content-resize-handle { + background: transparent url('../images/resize-rtl.gif') no-repeat scroll left bottom; + right: auto; + left: 2px; + cursor: sw-resize; +} + +/*------------------------------------------------------------------------------ + 26.0 - Full Overlay w/ Sidebar +------------------------------------------------------------------------------*/ +.wp-full-overlay .wp-full-overlay-sidebar { + margin: 0; + left: auto; + right: 0; + border-right: 0; + border-left: 1px solid rgba( 0, 0, 0, 0.2 ); +} + +.wp-full-overlay-sidebar:after { + right: auto; + left: 0; + box-shadow: inset 5px 0 4px -4px rgba(0, 0, 0, 0.1); +} + +.wp-full-overlay.collapsed, +.wp-full-overlay.expanded .wp-full-overlay-sidebar { + margin-right: 0 !important; +} + +.wp-full-overlay.expanded { + margin-right: 300px; + margin-left: 0; +} + +.wp-full-overlay.collapsed .wp-full-overlay-sidebar { + margin-right: -300px; + margin-left: 0; +} + +/* Collapse Button */ +.wp-full-overlay a.collapse-sidebar { + left: auto; + right: 0; + margin-left: 0; + margin-right: 15px; +} + +.wp-full-overlay.collapsed .collapse-sidebar { + right: 100%; +} + +.wp-full-overlay .collapse-sidebar-arrow { + margin-right: 2px; + margin-left: 0; + background: transparent url('../images/arrows.png') no-repeat 1px -108px; +} + +.wp-full-overlay.collapsed .collapse-sidebar-arrow { + background-position: 0 -72px; +} + +.wp-full-overlay .collapse-sidebar-label { + right: 100%; + left: auto; + margin-right: 10px; + margin-left: 0; +} + +/*------------------------------------------------------------------------------ + 27.0 - Customize Loader +------------------------------------------------------------------------------*/ +.install-theme-info .theme-install { + float: left; +} + +/* MERGED */ + +/* global */ + +/* 2 column liquid layout */ + +#wpcontent { + margin-left: 0; + margin-right: 165px; +} + +#wpbody-content { + float: right; +} + +#adminmenuwrap { + float: right; +} + +#adminmenu { + clear: right; +} + +/* inner 2 column liquid layout */ +.inner-sidebar { + float: left; + clear: left; +} + +.has-right-sidebar #post-body { + float: right; + clear: right; + margin-right: 0; + margin-left: -340px; +} + +.has-right-sidebar #post-body-content { + margin-right: 0; + margin-left: 300px; +} + +/* 2 columns main area */ + +#col-right { + float: left; + clear: left; +} + +/* utility classes*/ +.alignleft { + float: right; +} + +.alignright { + float: left; +} + +.textleft { + text-align: right; +} + +.textright { + text-align: left; +} + +/* styles for use by people extending the WordPress interface */ + +body, +td, +textarea, +input, +select { + font-family: Tahoma, Arial, sans-serif; +} + +ul.ul-disc, +ul.ul-square, +ol.ol-decimal { + margin-left: 0; + margin-right: 1.8em; +} + +.subsubsub { + float: right; +} + +.widefat thead th:first-of-type { + -webkit-border-top-left-radius: 0; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 0; + border-top-right-radius: 3px; +} + +.widefat thead th:last-of-type { + -webkit-border-top-right-radius: 0; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 0; + border-top-left-radius: 3px; +} +.widefat tfoot th:first-of-type { + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 3px; +} +.widefat tfoot th:last-of-type { + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 3px; +} + +.widefat th { + text-align: right; +} + +.widefat th input { + margin: 0 8px 0 0; +} + +.wrap { + margin-right: 0; + margin-left: 15px; +} + +.wrap h2, +.subtitle { + font-family: Tahoma, Arial, sans-serif; +} + +.wrap h2 { + padding-right: 0; + padding-left: 15px; +} + +.subtitle { + padding-left: 0; + padding-right: 25px; +} + +.wrap .add-new-h2 { + font-family: Tahoma, Arial, sans-serif; + margin-left: 0; + margin-right: 4px; +} + +.wrap h2.long-header { + padding-left: 0; +} + +/* dashboard */ +#dashboard-widgets-wrap .has-sidebar { + margin-right: 0; + margin-left: -51%; +} + +#dashboard-widgets-wrap .has-sidebar .has-sidebar-content { + margin-right: 0; + margin-left: 51%; +} + +.view-all { + right: auto; + left: 0; +} + +#dashboard_right_now p.sub, +#dashboard-widgets h4, +a.rsswidget, +#dashboard_plugins h4, +#dashboard_plugins h5, +#dashboard_recent_comments .comment-meta .approve, +#dashboard_right_now td.b, +#dashboard_right_now .versions a { + font-family: Tahoma, Arial, sans-serif; +} + +#dashboard_right_now p.sub { + left:auto; + right:15px; +} + +#dashboard_right_now td.b { + padding-right: 0; + padding-left: 6px; + text-align: left; +} + +#dashboard_right_now .t { + padding-right: 0; + padding-left: 12px; +} + +#dashboard_right_now .table_content { + float:right; +} + +#dashboard_right_now .table_discussion { + float:left; +} + +#dashboard_right_now a.button { + float: left; + clear: left; +} + +#dashboard_plugins .inside span { + padding-left: 0; + padding-right: 5px; +} + +#dashboard-widgets h3 .postbox-title-action { + right: auto; + left: 10px; +} + +.js #dashboard-widgets h3 .postbox-title-action { + right: auto; + left: 30px; +} + +#the-comment-list .pingback { + padding-left: 0 !important; + padding-right: 9px !important; +} + +/* Recent Comments */ +#the-comment-list .comment-item { + padding: 1em 70px 1em 10px; +} + +#the-comment-list .comment-item .avatar { + float: right; + margin-left: 0; + margin-right: -60px; +} + +/* Feeds */ +.rss-widget cite { + text-align: left; +} + +.rss-widget span.rss-date { + font-family: Tahoma, Arial, sans-serif; + margin-left: 0; + margin-right: 3px; +} + +/* QuickPress */ +#dashboard-widgets #dashboard_quick_press form p.submit input { + float: right; +} + +#dashboard-widgets #dashboard_quick_press form p.submit #save-post { + margin: 0 1px 0 0.7em; +} + +#dashboard-widgets #dashboard_quick_press form p.submit #publish { + float: left; +} + +#dashboard-widgets #dashboard_quick_press form p.submit .spinner { + margin: 4px 0 0 6px; +} + +/* Recent Drafts */ +#dashboard_recent_drafts h4 abbr { + font-family: Tahoma, Arial, sans-serif; + margin-left:0; + margin-right: 3px; +} + +/* login */ +body.login { + font-family: Tahoma, Arial, sans-serif; +} + +.login form { + margin-right: 8px; + margin-left: 0; +} + +.login form .forgetmenot { + float: right; +} + +.login form .submit { + float: left; +} + +#login form .submit input { + font-family: Tahoma, Arial, sans-serif; +} + +.login #nav, +.login #backtoblog { + margin: 0 16px 0 0; +} + +#login_error, +.login .message { + margin: 0 8px 16px 0; +} + +.login #user_pass, +.login #user_login, +.login #user_email { + margin-left: 6px; + margin-right: 0; + direction: ltr; +} + +.login h1 a { + text-decoration: none; +} + +.login .button-primary { + float: left; +} + +/* nav-menu */ +#nav-menus-frame { + margin-right: 300px; + margin-left: 0; +} + +#wpbody-content #menu-settings-column { + margin-right: -300px; + margin-left: 0; + float: right; +} + +.menu-location-menus select { + float: right; +} + +.locations-row-links { + float: right; + margin: 4px 6px 0 0; +} + +.locations-add-menu-link { + direction: rtl; +} + +.locations-edit-menu-link { + border-left: 1px solid #CCCCCC; + border-right: 0; + padding-left: 6px; + padding-right: 0; + float: right; +} + +/* Menu Container */ +#menu-management-liquid { + float: right; +} + +#menu-management { + margin-left: 20px; + margin-right: 0; +} + +.post-body-plain { + padding: 10px 0 0 10px; +} + +/* Menu Tabs */ + +#menu-management .nav-tabs-arrow-left { + right: 0; + left:auto; +} + +#menu-management .nav-tabs-arrow-right { + left: 0; + right:auto; + text-align: left; + font-family: Tahoma, Arial, sans-serif; +} + +#menu-management .nav-tabs { + padding-right: 20px; + padding-left: 10px; +} + +.js #menu-management .nav-tabs { + float: right; + margin-right: 0px; + margin-left: -400px; +} + +#select-nav-menu-container { + text-align: left; +} + +#wpbody .open-label { + float:right; +} + +#wpbody .open-label span { + padding-left: 10px; + padding-right:0; +} + +.js .input-with-default-title { + font-style: normal; + font-weight: bold; +} + +/* Add Menu Item Boxes */ +.postbox .howto input, +.accordion-container .howto input { + float: left; +} + +#nav-menu-theme-locations .button-controls { + text-align: left; +} + +/* Button Primary Actions */ + +.meta-sep, +.submitcancel { + float: right; +} + +#cancel-save { + margin-left: 0; + margin-right: 20px; +} + +.button.right, .button-secondary.right, .button-primary.right { + float: left; +} + +/* Button Secondary Actions */ +.list-controls { + float: right; +} +.add-to-menu { + float: left; +} + +/* Custom Links */ +#add-custom-link label span { + float: right; + padding-left: 5px; + padding-right: 0; +} + +.nav-menus-php .howto span { + float: right; +} + +.list li .menu-item-title input { + margin-left: 3px; + margin-right: 0; +} + +/* Nav Menu */ +.menu-item-handle { + padding-right: 10px; + padding-left: 0; +} +.menu-item-edit-active .menu-item-handle { + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.menu-item-handle .item-title { + margin-left:13em; + margin-right:0; + overflow: hidden; +} +.menu-item-handle .item-edit { + right: auto; + left: -20px; +} + +.menu-item-handle .menu-item-title { + float: right; +} + +.menu-item-settings .field-move a, +.menu-item-settings .field-move span { + float: right; + margin-left: 4px; +} + +/* WARNING: The factor of 30px is hardcoded into the nav-menus javascript. */ +.menu-item-depth-0 { margin-right: 0px; margin-left:0;} +.menu-item-depth-1 { margin-right: 30px; margin-left:0;} +.menu-item-depth-2 { margin-right: 60px; margin-left:0;} +.menu-item-depth-3 { margin-right: 90px; margin-left:0;} +.menu-item-depth-4 { margin-right: 120px; margin-left:0;} +.menu-item-depth-5 { margin-right: 150px; margin-left:0;} +.menu-item-depth-6 { margin-right: 180px; margin-left:0;} +.menu-item-depth-7 { margin-right: 210px; margin-left:0;} +.menu-item-depth-8 { margin-right: 240px; margin-left:0;} +.menu-item-depth-9 { margin-right: 270px; margin-left:0;} +.menu-item-depth-10 { margin-right: 300px; margin-left:0;} +.menu-item-depth-11 { margin-right: 330px; margin-left:0;} + +.menu-item-depth-0 .menu-item-transport { margin-right: 0px; margin-left:0;} +.menu-item-depth-1 .menu-item-transport { margin-right: -30px; margin-left:0;} +.menu-item-depth-2 .menu-item-transport { margin-right: -60px; margin-left:0;} +.menu-item-depth-3 .menu-item-transport { margin-right: -90px; margin-left:0;} +.menu-item-depth-4 .menu-item-transport { margin-right: -120px; margin-left:0;} +.menu-item-depth-5 .menu-item-transport { margin-right: -150px; margin-left:0;} +.menu-item-depth-6 .menu-item-transport { margin-right: -180px; margin-left:0;} +.menu-item-depth-7 .menu-item-transport { margin-right: -210px; margin-left:0;} +.menu-item-depth-8 .menu-item-transport { margin-right: -240px; margin-left:0;} +.menu-item-depth-9 .menu-item-transport { margin-right: -270px; margin-left:0;} +.menu-item-depth-10 .menu-item-transport { margin-right: -300px; margin-left:0;} +.menu-item-depth-11 .menu-item-transport { margin-right: -330px; margin-left:0;} + +/* Menu item controls */ +.item-type { + padding-left: 10px; + padding-right:0; +} + +.item-controls { + left: 20px; + right: auto; +} + +.item-controls .item-order { + padding-left: 10px; + padding-right: 0; +} + +.item-edit { + left: -20px; + right:auto; + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 0; +} + +/* Menu editing */ +.menu-item-settings { + padding: 10px 10px 10px 0; + border-width: 0 1px 1px 1px; +} + +#custom-menu-item-url { + direction: ltr; +} + +.link-to-original { + font-style: normal; + font-weight: bold; +} + +.link-to-original a { + padding-right: 4px; + padding-left:0; +} + +.menu-item-settings .description-thin, +.menu-item-settings .description-wide { + margin-left: 10px; + margin-right:0; + float: right; +} + +/* Major/minor publishing actions (classes) */ +.major-publishing-actions .publishing-action { + text-align: left; + float: left; +} + +.major-publishing-actions .delete-action { + text-align: right; + float: right; + padding-left: 15px; + padding-right:0; +} + +.menu-name-label { + margin-left: 15px; + margin-right:0; +} + +/* Star ratings */ +div.star-holder { + background: url('../images/stars-rtl.png?ver=20121108') repeat-x bottom right; +} +div.star-holder .star-rating { + background: url('../images/stars-rtl.png?ver=20121108') repeat-x top right; + float: right; +} + +#plugin-information .wrap { + margin: 4px 15px 0 0; +} + +#plugin-information ul#sidemenu { + left: auto; + right: 0; +} + +#plugin-information .fyi { + float: right; +} + +#plugin-information #section-screenshots li p { + padding-left: 0; + padding-right: 20px; +} + +#plugin-information .updated, +#plugin-information .error { + clear: none; + direction: rtl; +} + +#plugin-information #section-holder .section { + direction: ltr; +} + +/* Editor/Main Column */ +.posting { + margin-left: 212px; + margin-right: 0; + position: relative; +} + +h3.tb { + margin-left: 0; + margin-right: 5px; +} + +#publish { + float: left; +} + +.postbox .handlediv { + float: left; +} + +.actions li { + float: right; + margin-right: 0; + margin-left: 10px; +} + +#extra-fields .actions { + margin: -23px 0 0 -7px; +} + +/* Photo Styles */ +#img_container a { + float: right; +} + +#category-add input, +#category-add select { + font-family: Tahoma, Arial, sans-serif; +} + +/* Tags */ +#tagsdiv #newtag { + margin-right: 0; + margin-left: 5px; +} + +#tagadd { + margin-left: 0; + margin-right: 3px; +} + +#tagchecklist span { + margin-left: .5em; + margin-right: 10px; + float: right; +} +#tagchecklist span a { + margin: 6px -9px 0 0; + float: right; +} + +.submit input, +.button, +.button-primary, +.button-secondary, +#postcustomstuff .submit input { + font-family: Tahoma, Arial, sans-serif; +} + +.ac_results li { + text-align: right; +} + +#TB_ajaxContent #options { + right: auto; + left: 25px; +} + +#TB_closeAjaxWindow { + float: left; +} + +#TB_ajaxWindowTitle { + float: right; +} + +#post_status { + margin-left: 0; + margin-right: 10px; +} + +/* theme-editor, plugin-editor */ +#templateside { + float: left; +} + +#template textarea, +#docs-list { + direction: ltr; +} + +/* theme-install */ +.theme-details .theme-version { + float: right; +} + +.theme-details .star-holder { + float: left; +} + +.feature-filter .feature-group { + float: right; +} + +.feature-filter .feature-group li { + padding-right: 0; + padding-left: 25px; +} + +/* widgets */ +/* 2 column liquid layout */ +div.widget-liquid-left { + float: right; + clear: right; + margin-right: 0; + margin-left: -325px; +} + +div#widgets-left { + margin-right: 5px; + margin-left: 325px; +} + +div.widget-liquid-right { + float: left; + clear: left; +} + +.inactive-sidebar .widget { + float: right; +} + +div.sidebar-name h3 { + font-family: Tahoma, Arial, sans-serif; +} + +#widget-list .widget { + float: right; +} + +.inactive-sidebar .widget-placeholder { + float: right; +} + +.widget-top .widget-title-action { + float: left; +} + +.widget-control-edit { + padding: 0 0 0 8px; +} + +.sidebar-name-arrow { + float: left; +} + +/* Press This */ +.press-this-sidebar { + float: left; +} + +.press-this #header-logo, +.press-this #wphead h1 { + float: right; +} + +/* RTL */ +.ltr { + direction: ltr; +} + +.control-section .accordion-section-title { + font-family: Tahoma, Arial, sans-serif; +} + +.js .accordion-section-title:after { + right: auto; + left: 20px; +} + +/*------------------------------------------------------------------------------ + 28.0 - Nav Menus +------------------------------------------------------------------------------*/ +.nav-menus-php .major-publishing-actions .publishing-action { + float: left; +} + +.menu-settings dd { + float: right; +} + +.manage-menus span { + float: right; +} + +.manage-menus select { + float: right; + margin-right: 0; + margin-left: 6px; +} + +.manage-menus .submit-btn { + float: right; +} + +.manage-menus .selected-menu { + float: right; + margin: 5px 0 0 6px; +} + +.nav-menus-php .add-new-menu-action { + float: right; + margin: 4px 6px 0 0; +} + +.nav-menus-php .meta-sep, +.nav-menus-php .submitdelete, +.nav-menus-php .submitcancel { + float: right; +} + +.is-submenu { + float: right; + margin-right: 8px; +} + +/*------------------------------------------------------------------------------ + 29.0 - HiDPI +------------------------------------------------------------------------------*/ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + .post-com-count { + background-image: url('../images/bubble_bg-rtl-2x.gif'); + background-size: 18px 100px; + } + + #content-resize-handle, #post-body .wp_themeSkin .mceStatusbar a.mceResize { + background: transparent url('../images/resize-rtl-2x.gif') no-repeat scroll right bottom; + background-size: 11px 11px; + } + + .wp-full-overlay .collapse-sidebar-arrow { + background-image: url('../images/arrows-2x.png'); + background-size: 15px 123px; + } + + div.star-holder { + background: url('../images/stars-rtl-2x.png?ver=20121108') repeat-x bottom right; + background-size: 21px 37px; + } + + div.star-holder .star-rating { + background: url('../images/stars-rtl-2x.png?ver=20121108') repeat-x top right; + background-size: 21px 37px; + } + + #post-body .wp_themeSkin .mceStatusbar a.mceResize, + #content-resize-handle { + background: transparent url('../images/resize-rtl-2x.gif') no-repeat scroll left bottom; + } + + .wp-slider .ui-slider-handle:before { + background-image: url(../images/arrows-pr-2x.png); + background-size: 16px 102px; + } + +} + +/* =Localized CSS +-------------------------------------------------------------- */ + +/* he_IL: Remove Tahoma from the font stack. Arial is best for Hebrew. */ +body.locale-he-il, +.locale-he-il .quicktags, .locale-he-il .search, +.locale-he-il .howto, +.locale-he-il #adminmenu .awaiting-mod, +.locale-he-il #adminmenu span.update-plugins, +.locale-he-il #sidemenu li a span.update-plugins, +.locale-he-il .post-com-count-wrapper, +.locale-he-il .widefat th, +.locale-he-il .tablenav .displaying-num, +.locale-he-il .inline-edit-row fieldset span.title, +.locale-he-il .inline-edit-row fieldset span.checkbox-title, +.locale-he-il .inline-edit-row fieldset ul.cat-checklist label, +.locale-he-il .inline-edit-row #bulk-titles div, +.locale-he-il p.help, +.locale-he-il p.description, +.locale-he-il span.description, +.locale-he-il .form-wrap p, +.locale-he-il h2 .nav-tab, +.locale-he-il #your-profile legend, +.locale-he-il #utc-time, .locale-he-il #local-time, +.locale-he-il #poststuff h3, +.locale-he-il .metabox-holder h3, +.locale-he-il .tool-box .title, +.locale-he-il td, +.locale-he-il textarea, +.locale-he-il input, +.locale-he-il select, +.locale-he-il .wrap h2, +.locale-he-il .subtitle, +.locale-he-il .wrap .add-new-h2, +.locale-he-il #dashboard_right_now p.sub, +.locale-he-il #dashboard-widgets h4, +.locale-he-il a.rsswidget, +.locale-he-il #dashboard_plugins h4, +.locale-he-il #dashboard_plugins h5, +.locale-he-il #dashboard_recent_comments .comment-meta .approve, +.locale-he-il #dashboard_right_now td.b, +.locale-he-il #dashboard_right_now .versions a, +.locale-he-il .rss-widget span.rss-date, +.locale-he-il #dashboard_recent_drafts h4 abbr, +body.login.locale-he-il, +.locale-he-il #login form .submit input, +.locale-he-il #menu-management .nav-tabs-arrow-right, +.locale-he-il #category-add input, +.locale-he-il #category-add select, +.locale-he-il .submit input, +.locale-he-il .button, +.locale-he-il .button-primary, +.locale-he-il .button-secondary, +.locale-he-il #postcustomstuff .submit input, +.locale-he-il div.sidebar-name h3 { + font-family: Arial, sans-serif; +} + +/* he_IL: Have be bold rather than italic. */ +.locale-he-il em { + font-style: normal; + font-weight: bold; +} diff --git a/sources/wp-admin/css/wp-admin-rtl.min.css b/sources/wp-admin/css/wp-admin-rtl.min.css new file mode 100644 index 0000000..4da46f6 --- /dev/null +++ b/sources/wp-admin/css/wp-admin-rtl.min.css @@ -0,0 +1 @@ +ol{margin-left:0;margin-right:2em}.code,code{font-family:monospace;direction:ltr}.quicktags,.search{font:12px Tahoma,Arial,sans-serif}.icon32{float:right;margin-right:0;margin-left:8px}.icon16{float:right;margin-right:-8px;margin-left:0}.howto{font-style:normal;font-family:Tahoma,Arial,sans-serif}p.install-help{font-style:normal}#doaction,#doaction2,#post-query-submit{margin-right:0;margin-left:8px}#timezone_string option{margin-left:0;margin-right:1em}#pass-strength-result{float:right;margin:13px 1px 5px 5px}p.search-box{float:left}.search-box input[name="s"],#search-plugins input[name="s"],.tagsdiv .newtag{float:right;margin-right:0;margin-left:4px}input[type=password]{direction:ltr}input[type=text].ui-autocomplete-loading{background:transparent url(../images/loading.gif) no-repeat left center}ul#add-to-blog-users{margin:0 14px 0 0}.ui-autocomplete li{text-align:right}#delete-action{float:right}#publishing-action{float:left;text-align:left}#publishing-action .spinner{float:right}#post-body .misc-pub-section{border-right:0;border-left-width:1px;border-left-style:solid}#post-body .misc-pub-section-last{border-left:0}#minor-publishing-actions{padding:10px 8px 2px 10px;text-align:left}#save-post{float:right}.preview{float:left}#sticky-span{margin-left:0;margin-right:18px}.side-info ul{padding-left:0;padding-right:18px}td.action-links,th.action-links{text-align:left}form.upgrade .hint{font-style:normal}#ajax-response.alignleft{margin-left:0;margin-right:2em}#quicktags{background-position:right top}#ed_reply_toolbar input{margin:1px 1px 1px 2px}#wphead{height:32px;margin-left:15px;margin-right:2px}#header-logo{float:right}#wphead h1{float:right}#screen-meta-links{margin-right:0;margin-left:24px}#screen-meta{margin-right:5px;margin-left:15px}#screen-options-link-wrap,#contextual-help-link-wrap{float:left;margin-left:0;margin-right:6px}#screen-meta-links a.show-settings{padding-right:6px;padding-left:16px}.toggle-arrow{background-position:top right}.toggle-arrow-active{background-position:bottom right}.metabox-prefs label{padding-right:0;padding-left:15px}.metabox-prefs label input{margin-right:2px;margin-left:5px}#contextual-help-wrap{margin-left:0;margin-right:-4px}#contextual-help-back{left:170px;right:150px}#contextual-help-wrap.no-sidebar #contextual-help-back{left:0;right:150px;border-right-width:1px;border-left-width:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-webkit-border-bottom-left-radius:2px;border-bottom-left-radius:2px}.contextual-help-tabs{float:right}.contextual-help-tabs a{padding-left:5px;padding-right:12px}.contextual-help-tabs .active{margin-right:0;margin-left:-1px}.contextual-help-tabs .active,.contextual-help-tabs-wrap{border-left:0;border-right-width:1px}.help-tab-content{margin-right:0;margin-left:22px}.help-tab-content li{margin-left:0;margin-right:18px}.contextual-help-sidebar{float:left;padding-right:12px;padding-left:8px}.folded #wpcontent{margin-left:0;margin-right:52px}.folded.wp-admin #wpfooter{margin-left:15px;margin-right:52px}#adminmenuback,#adminmenuwrap{border-width:0 0 0 1px}#adminmenushadow{right:auto;left:0}#adminmenu li .wp-submenu{left:auto;right:146px}.folded #adminmenu .wp-submenu.sub-open,.folded #adminmenu .opensub .wp-submenu,.folded #adminmenu .wp-has-current-submenu .wp-submenu.sub-open,.folded #adminmenu .wp-has-current-submenu.opensub .wp-submenu,.folded #adminmenu a.menu-top:focus+.wp-submenu,.folded #adminmenu .wp-has-current-submenu a.menu-top:focus+.wp-submenu,.no-js.folded #adminmenu .wp-has-submenu:hover .wp-submenu{left:auto;right:32px}#adminmenu div.wp-menu-image,.folded #adminmenu div.wp-menu-image{float:right;width:30px}#adminmenu .wp-submenu a,#adminmenu li li a,.folded #adminmenu .wp-not-current-submenu li a{padding-left:0;padding-right:12px}#adminmenu .wp-not-current-submenu li a{padding-left:0;padding-right:18px}.wp-menu-arrow{right:0;-moz-transform:translate(-139px);-webkit-transform:translate(-139px);-o-transform:translate(-139px);-ms-transform:translate(-139px);transform:translate(-139px)}.ie8 .wp-menu-arrow{right:-20px}#adminmenu .wp-menu-arrow div{left:-8px;width:16px}#adminmenu li.wp-not-current-submenu .wp-menu-arrow{-moz-transform:translate(-138px);-webkit-transform:translate(-138px);-o-transform:translate(-138px);-ms-transform:translate(-138px);transform:translate(-138px)}.folded #adminmenu li .wp-menu-arrow{-moz-transform:translate(-26px);-webkit-transform:translate(-26px);-o-transform:translate(-26px);-ms-transform:translate(-26px);transform:translate(-26px)}#adminmenu .wp-not-current-submenu .wp-menu-arrow div{border-style:solid solid none none;border-width:1px 1px 0 0}#adminmenu .wp-menu-image img{padding:7px 7px 0 0}#adminmenu .wp-submenu .wp-submenu-head{padding:5px 10px 5px 4px;-webkit-border-top-right-radius:0;-webkit-border-top-left-radius:3px;border-top-right-radius:0;border-top-left-radius:3px}.folded #adminmenu li.wp-has-current-submenu .wp-submenu{border-width:1px;border-style:solid;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:3px;border-top-right-radius:0;border-top-left-radius:3px}#adminmenu .awaiting-mod,#adminmenu span.update-plugins,#sidemenu li a span.update-plugins{font-family:Tahoma,Arial,sans-serif;margin-left:0;margin-right:7px}#collapse-button{float:right}@media only screen and (max-width:900px){.auto-fold #wpcontent{margin-left:0;margin-right:52px}.auto-fold.wp-admin #wpfooter{margin-left:15px;margin-right:52px}.auto-fold #adminmenu div.wp-menu-image{float:right;width:30px}.auto-fold #adminmenu .wp-submenu.sub-open,.auto-fold #adminmenu .opensub .wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu.sub-open,.auto-fold #adminmenu .wp-has-current-submenu.opensub .wp-submenu,.auto-fold #adminmenu a.menu-top:focus+.wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu a.menu-top:focus+.wp-submenu,.no-js.auto-fold #adminmenu .wp-has-submenu:hover .wp-submenu{left:auto;right:32px}.auto-fold #adminmenu .wp-not-current-submenu li a{padding-left:0;padding-right:12px}.auto-fold #adminmenu li .wp-menu-arrow{-moz-transform:translate(-27px);-webkit-transform:translate(-27px);-o-transform:translate(-27px);-ms-transform:translate(-27px);transform:translate(-27px)}.auto-fold #adminmenu li.wp-has-current-submenu .wp-submenu{border-width:1px;border-style:solid;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-right-radius:0;-webkit-border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:3px;border-top-right-radius:0;border-top-left-radius:3px}}.post-com-count-wrapper{font-family:Tahoma,Arial,sans-serif}.post-com-count{background-image:url(../images/bubble_bg-rtl.gif)}.column-response .post-com-count{float:right;margin-right:0;margin-left:5px}.response-links{float:right}.widefat th{font-family:Tahoma,Arial,sans-serif}.postbox-container{float:right}#post-body-content{float:right}#poststuff #post-body.columns-2{margin-left:300px;margin-right:0}#post-body.columns-2 #postbox-container-1{float:left;margin-left:-300px;margin-right:0}@media only screen and (max-width:850px){#wpbody-content #post-body.columns-2 #postbox-container-1{margin-left:0}}.postbox .handlediv{float:left}#the-comment-list p.comment-author img{float:right;margin-right:0;margin-left:8px}#dashboard_browser_nag p.browser-update-nag.has-browser-icon{padding-right:0;padding-left:125px}.welcome-panel .welcome-panel-close{right:auto;left:10px}.welcome-panel .welcome-panel-close:before{left:auto;right:-12px}.welcome-panel-content{margin-left:0;margin-right:13px}.welcome-panel .welcome-panel-column{float:right}.welcome-panel .welcome-panel-column ul{margin-right:0;margin-left:1em}.welcome-panel .welcome-panel-column li{padding-left:0;padding-right:2px}.welcome-panel .welcome-add-page{background-position:right 2px}.welcome-panel .welcome-edit-page{background-position:right -90px}.welcome-panel .welcome-learn-more{background-position:right -136px}.welcome-panel .welcome-comments{background-position:right -182px}.welcome-panel .welcome-view-site{background-position:right -274px}.welcome-panel .welcome-widgets-menus{background-position:right -229px;line-height:14px}.welcome-panel .welcome-write-blog{background-position:right -44px}.welcome-panel .welcome-icon{padding:2px 32px 8px 0}@media screen and (max-width:870px){.welcome-panel .welcome-panel-column li{margin-right:0;margin-left:13px}.welcome-panel .welcome-icon{padding-right:25px;padding-left:0}}.fixed .column-comments{text-align:right}.fixed .column-comments .vers{padding-left:0;padding-right:3px}.fixed .column-comments a{float:right}.fixed .column-menus{text-align:right}.sorting-indicator{margin-left:0;margin-right:7px}tr.wp-locked .locked-indicator{margin:-2px 6px 0 0}th.sortable a span,th.sorted a span{float:right}.tablenav-pages a{margin-right:0;margin-left:1px}.tablenav-pages .next-page{margin-left:0;margin-right:2px}.tablenav a.button-secondary{margin:3px 0 0 8px}.tablenav .tablenav-pages{float:left}.tablenav .displaying-num{margin-right:0;margin-left:10px;font-family:Tahoma,Arial,sans-serif;font-style:normal}.tablenav .actions{padding:2px 0 0 8px}.tablenav .actions select{float:right;margin-right:0;margin-left:6px}.tablenav .delete{margin-right:0;margin-left:20px}.view-switch{float:left}.filter{float:right;margin:-5px 10px 0 0}.filter .subsubsub{margin-left:0;margin-right:-10px}#posts-filter fieldset{float:right;margin:0 0 1em 1.5ex}#posts-filter fieldset legend{padding:0 1px .2em 0}#wpbody-content .inline-edit-row fieldset{float:right}#wpbody-content .quick-edit-row-page fieldset.inline-edit-col-right .inline-edit-col{border-width:0 1px 0 0}#wpbody-content .bulk-edit-row .inline-edit-col-bottom{float:left}.inline-edit-row fieldset label span.title{float:right}.inline-edit-row fieldset label span.input-text-wrap{margin-left:0;margin-right:5em}.quick-edit-row-post fieldset.inline-edit-col-right label span.title{padding-right:0;padding-left:.5em}#wpbody-content .quick-edit-row fieldset .inline-edit-group label.alignleft:first-child{margin-right:0;margin-left:.5em}.inline-edit-row fieldset span.title,.inline-edit-row fieldset span.checkbox-title{font-family:Tahoma,Arial,sans-serif;font-style:normal}.inline-edit-row fieldset .inline-edit-date{float:right}.inline-edit-row fieldset ul.cat-checklist label,.inline-edit-row #bulk-titles div{font-family:Tahoma,Arial,sans-serif}.quick-edit-row-post fieldset label.inline-edit-status{float:right}#bulk-titles div a{float:right;margin:3px -2px 0 3px;overflow:hidden;text-indent:-9999px}#save-action .spinner,#show-comments a,#show-comments .spinner{float:right}#titlediv #title-prompt-text,#wp-fullscreen-title-prompt-text{right:0}#sample-permalink{direction:ltr}#sample-permalink #editable-post-name{unicode-bidi:embed}#wp-fullscreen-title-prompt-text{left:auto;right:0}#wp-fullscreen-save .spinner,#wp-fullscreen-save .fs-saved{float:left}#edit-slug-box .cancel{margin-right:0;margin-left:10px}.postarea h3 label{float:right}.submitbox .submit{text-align:right}.inside-submitbox #post_status{margin:2px -2px 2px 0}.submitbox .submit input{margin-right:0;margin-left:4px}#normal-sortables .postbox .submit{float:left}.taxonomy div.tabs-panel{margin:0 125px 0 5px}#side-sortables .comments-box thead th,#normal-sortables .comments-box thead th{font-style:normal}#commentsdiv .spinner{padding-left:0;padding-right:5px}#post-body .add-menu-item-tabs li.tabs{border-width:1px 1px 1px 0;margin-right:0;margin-left:-1px}#post-body .tagsdiv #newtag{margin-right:0;margin-left:5px}.autosave-info{padding:2px 2px 2px 15px;text-align:left}#post-body .wp_themeSkin .mceStatusbar a.mceResize{background:transparent url(../images/resize-rtl.gif) no-repeat scroll left bottom;cursor:sw-resize}.curtime #timestamp{background-position:right top;padding-left:0;padding-right:18px}.compat-attachment-fields th{padding-right:0;padding-left:10px}#post-lock-dialog .post-locked-message a.button{margin-right:0;margin-left:10px}#post-lock-dialog .post-locked-avatar{float:right;margin:0 0 20px 20px}#post-lock-dialog .locked-saving img{float:right;margin-right:0;margin-left:3px}.wp-slider .ui-slider-handle.from-handle:before,.wp-slider .ui-slider-handle.to-handle:before{height:8px;width:7px}.wp-slider .ui-slider-handle.from-handle:before{background-position:-5px -10px;left:6px}.wp-slider .ui-slider-handle.to-handle:before{background-position:-4px -29px;left:6px}.revision-toggle-compare-mode{right:auto;left:0}.revisions .loading-indicator{margin-right:-90px}body.folded .revisions .loading-indicator{margin-right:-32px}.revisions-next{float:left}.revisions-previous{float:right}.diff-title strong{text-align:left;float:right;margin-right:0;margin-left:5px}.revisions-controls .author-card .avatar,.revisions-controls .author-card .author-info{float:right}.diff-meta input.restore-revision{float:left}.diff-col-title-added,.diff-col-title-removed{text-align:right;float:right}.revisions-tooltip{margin-left:0;margin-right:-69px}.revisions-tooltip.flipped{margin-right:0;margin-left:-70px}.ie8 .revisions-tooltip{margin-right:-75px}.ie8 .revisions-tooltip.flipped{margin-left:-63px}.revisions-tooltip-arrow{right:0;margin-left:0;margin-right:35px}.revisions-tooltip.flipped .revisions-tooltip-arrow{margin-right:0;margin-left:35px;right:auto;left:0}.revisions-tooltip-arrow>span{left:auto;right:20px}.revisions-tooltip.flipped .revisions-tooltip-arrow>span{right:auto;left:20px}.ie8 .revisions-tooltip-arrow>span{right:21px}.revisions-tickmarks>div{float:right;border-width:0 0 0 1px}#select-featured-image a{float:right}a.post-state-format{margin-right:0;margin-left:5px}label.post-format-icon{margin-left:0;margin-right:5px;padding-left:0;padding-right:21px}.post-format-icon.post-format-standard{background-position:100% 0}.post-format-icon.post-format-image{background-position:100% -32px}.post-format-icon.post-format-gallery{background-position:100% -64px}.post-format-icon.post-format-audio{background-position:100% -96px}.post-format-icon.post-format-video{background-position:100% -128px}.post-format-icon.post-format-chat{background-position:100% -160px}.post-format-icon.post-format-status{background-position:100% -192px}.post-format-icon.post-format-aside{background-position:100% -224px}.post-format-icon.post-format-quote{background-position:100% -256px}.post-format-icon.post-format-link{background-position:100% -288px}.category-adder{margin-left:0;margin-right:120px}#post-body ul.add-menu-item-tabs{float:right;text-align:left;margin:0 5px 0 -120px}#post-body ul.add-menu-item-tabs li.tabs{-webkit-border-top-left-radius:0;-webkit-border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-radius:3px;border-top-left-radius:0;border-top-right-radius:3px;border-bottom-left-radius:0;border-bottom-right-radius:3px}#front-page-warning,#front-static-pages ul,ul.export-filters,.inline-editor ul.cat-checklist ul,.categorydiv ul.categorychecklist ul,.customlinkdiv ul.categorychecklist ul,.posttypediv ul.categorychecklist ul,.taxonomydiv ul.categorychecklist ul{margin-left:0;margin-right:18px}#post-body .add-menu-item-tabs li.tabs{border-style:solid solid solid none;border-width:1px 1px 1px 0;margin-right:0;margin-left:-1px}p.help,p.description,span.description,.form-wrap p{font-style:normal;font-family:Tahoma,Arial,sans-serif}.taghint{margin:15px 12px -24px 0}#poststuff .tagsdiv .howto{margin:0 8px 6px 0}.ac_results li{text-align:right}.links-table th{text-align:right}#wpbody-content .describe th{text-align:right}.describe .media-item-info .A1B1{padding:0 10px 0 0}.media-upload-form td label{margin-left:6px;margin-right:2px}.media-upload-form .align .field label{padding:0 23px 0 0;margin:0 3px 0 1em}.media-upload-form tr.image-size label{margin:0 5px 0 0}#wpbody-content .describe p.help{padding:0 5px 0 0}.media-item .edit-attachment,.media-item .error-div a.dismiss,.describe-toggle-on,.describe-toggle-off{float:left;margin-right:0;margin-left:15px}.media-item .error-div a.dismiss{padding:0 15px 0 0}.media-item .error-div{padding-left:0;padding-right:10px}.media-item .pinkynail{float:right}.media-item .describe td{padding:0 0 8px 8px}.media-item .progress{float:left;margin:6px 0 0 10px}#find-posts-input{float:right}#find-posts-search{float:right;margin-right:3px;margin-left:4px}.find-box-search .spinner{left:auto;right:115px}#find-posts-response .found-radio{padding:5px 8px 0 0}.find-box-search label{padding-right:0;padding-left:6px}.find-box #resize-se{right:auto;left:1px}form.upgrade .hint{font-style:normal}.wp_attachment_image .button,.A1B1 .button{float:right}.wp_attachment_image .spinner,.A1B1 .spinner{float:right}.imgedit-menu div{float:right}.imgedit-crop{margin:0}.imgedit-rleft,.imgedit-flipv,.imgedit-undo{margin:0 8px 0 3px}.imgedit-rright,.imgedit-fliph,.imgedit-redo{margin:0 3px}.imgedit-applyto img{margin:0 0 0 8px}.imgedit-help{font-style:normal}.imgedit-submit-btn{margin-left:0;margin-right:20px}.form-table th{text-align:right}.form-table input.tog{margin-right:0;margin-left:2px;float:right}.form-table table.color-palette{float:right}#replysubmit .spinner,.inline-edit-save .spinner{float:left}#replysubmit .button{margin-right:0;margin-left:5px}#edithead .inside{float:right;padding:3px 5px 2px 0}.comment-ays th{border-right-style:none;border-left-style:solid;border-right-width:0;border-left-width:1px}.spam-undo-inside .avatar,.trash-undo-inside .avatar{margin-left:8px}#comment-status-radio input{margin:2px 0 5px 3px}h3.available-themes{float:right}.available-theme{margin-right:0;margin-left:10px;padding:20px 0 20px 20px}#current-theme .theme-info li,.theme-options li,.available-theme .action-links li{float:right;padding-right:0;padding-left:10px;margin-right:0;margin-left:10px;border-right:0;border-left:1px solid #dfdfdf}.available-theme .action-links li{padding-left:8px;margin-left:8px}.ie8 .available-theme .action-links li{padding-left:7px;margin-left:7px}#current-theme .theme-info li:last-child,.theme-options li:last-child,.available-theme .action-links li:last-child{padding-left:0;margin-right:0;border-left:0}.available-theme .action-links .delete-theme{float:left;margin-left:0;margin-right:8px}.available-theme .action-links p{float:right}#current-theme.has-screenshot{padding-left:0;padding-right:330px}#current-theme h4 span{margin-left:0;margin-right:20px}#current-theme img{float:right;width:300px;margin-left:0;margin-right:-330px}.theme-options .load-customize{margin-right:0;margin-left:30px;float:right}.theme-options span{float:right;margin-right:0;margin-left:10px}.theme-options ul{float:right}@media only screen and (max-width:1200px){#current-theme.has-screenshot{padding-right:270px}#current-theme img{margin-right:-270px;width:240px}}#broken-themes{text-align:right}.appearance_page_custom-header .available-headers .default-header{float:right;margin:0 0 20px 20px}.appearance_page_custom-header .random-header{margin:0 0 20px 20px}.appearance_page_custom-header .available-headers label input,.appearance_page_custom-header .random-header label input{margin-right:0;margin-left:10px}.nav-tab{margin:0 0 -1px 6px}h2 .nav-tab{font-family:Tahoma,Arial,sans-serif}.plugins .desc ul,.plugins .desc ol{margin:0 2em 0 0}#wpbody-content .plugins .plugin-title,#wpbody-content .plugins .theme-title{padding-right:0;padding-left:12px}#profile-page .form-table #rich_editing{margin-right:0;margin-left:5px}#profile-page #pass1,#profile-page #pass2,#profile-page #user_login{direction:ltr}#your-profile legend{font-family:Tahoma,Arial,sans-serif}.pressthis a span{background-position:right 5px;padding:8px 27px 8px 11px}.pressthis a:after{right:auto;left:10px;background:transparent;transform:skew(-20deg) rotate(-6deg);-webkit-transform:skew(-20deg) rotate(-6deg);-moz-transform:skew(-20deg) rotate(-6deg)}.pressthis a:hover:after{transform:skew(-20deg) rotate(-9deg);-webkit-transform:skew(-20deg) rotate(-9deg);-moz-transform:skew(-20deg) rotate(-9deg)}#utc-time,#local-time{padding-left:0;padding-right:25px;font-style:normal;font-family:Tahoma,Arial,sans-serif}#permalink_structure{float:right}.options-permalink-php code{unicode-bidi:embed}.options-permalink-php #rules{direction:ltr}#wpfooter{margin-left:20px}#wpcontent,#wpfooter{margin-right:165px}.wrap.about-wrap{margin-left:40px;margin-right:20px}.about-wrap h1,.about-text{margin-right:0;margin-left:200px}.about-wrap h2.nav-tab-wrapper{padding-left:0;padding-right:6px}.about-wrap .wp-badge{right:auto;left:0}.about-wrap h2 .nav-tab{margin-right:0;margin-left:3px}.about-wrap .changelog li{margin-left:0;margin-right:3em}.about-wrap .three-col-images .last-feature{float:left}.about-wrap .three-col-images .first-feature{float:right}.about-wrap .feature-section.two-col div,.about-wrap .feature-section.three-col div{margin-right:0;margin-left:4.999999999%;float:right}.about-wrap .feature-section.col .last-feature{margin-left:0}.about-wrap .feature-section div p img{float:left;margin-left:0;margin-right:10px}.about-wrap li.wp-person,.about-wrap li.wp-person img.gravatar{float:right;margin-right:0;margin-left:10px}#template div{margin-right:0;margin-left:190px}.column-author img,.column-username img{float:right;margin-right:0;margin-left:10px}.tagchecklist{margin-left:0;margin-right:14px}.tagchecklist strong{margin-left:0;margin-right:-8px}.tagchecklist span{margin-right:0;margin-left:25px;float:right}.tagchecklist span a{margin:4px -10px 0 0;float:right}#poststuff h2{clear:right}#poststuff h3,.metabox-holder h3{font-family:Tahoma,Arial,sans-serif}.tool-box .title{font-family:Tahoma,Arial,sans-serif}#sidemenu{margin:-30px 315px 0 15px;float:left;padding-left:0;padding-right:10px}#sidemenu a{float:right}table .vers,table .column-visible,table .column-rating{text-align:right}.screen-meta-toggle{right:auto;left:15px}.screen-reader-text,.screen-reader-text span,.ui-helper-hidden-accessible{left:auto;right:-1000em}.screen-reader-shortcut:focus{left:auto;right:6px}* html #template div{margin-left:0}#editorcontainer .wp_themeSkin .mceStatusbar{padding-left:0;padding-right:5px}#editorcontainer .wp_themeSkin .mceStatusbar div{float:right}#editorcontainer .wp_themeSkin .mceStatusbar a.mceResize{float:left}#content-resize-handle{background:transparent url(../images/resize-rtl.gif) no-repeat scroll left bottom;right:auto;left:2px;cursor:sw-resize}.wp-full-overlay .wp-full-overlay-sidebar{margin:0;left:auto;right:0;border-right:0;border-left:1px solid rgba(0,0,0,.2)}.wp-full-overlay-sidebar:after{right:auto;left:0;box-shadow:inset 5px 0 4px -4px rgba(0,0,0,.1)}.wp-full-overlay.collapsed,.wp-full-overlay.expanded .wp-full-overlay-sidebar{margin-right:0!important}.wp-full-overlay.expanded{margin-right:300px;margin-left:0}.wp-full-overlay.collapsed .wp-full-overlay-sidebar{margin-right:-300px;margin-left:0}.wp-full-overlay a.collapse-sidebar{left:auto;right:0;margin-left:0;margin-right:15px}.wp-full-overlay.collapsed .collapse-sidebar{right:100%}.wp-full-overlay .collapse-sidebar-arrow{margin-right:2px;margin-left:0;background:transparent url(../images/arrows.png) no-repeat 1px -108px}.wp-full-overlay.collapsed .collapse-sidebar-arrow{background-position:0 -72px}.wp-full-overlay .collapse-sidebar-label{right:100%;left:auto;margin-right:10px;margin-left:0}.install-theme-info .theme-install{float:left}#wpcontent{margin-left:0;margin-right:165px}#wpbody-content{float:right}#adminmenuwrap{float:right}#adminmenu{clear:right}.inner-sidebar{float:left;clear:left}.has-right-sidebar #post-body{float:right;clear:right;margin-right:0;margin-left:-340px}.has-right-sidebar #post-body-content{margin-right:0;margin-left:300px}#col-right{float:left;clear:left}.alignleft{float:right}.alignright{float:left}.textleft{text-align:right}.textright{text-align:left}body,td,textarea,input,select{font-family:Tahoma,Arial,sans-serif}ul.ul-disc,ul.ul-square,ol.ol-decimal{margin-left:0;margin-right:1.8em}.subsubsub{float:right}.widefat thead th:first-of-type{-webkit-border-top-left-radius:0;-webkit-border-top-right-radius:3px;border-top-left-radius:0;border-top-right-radius:3px}.widefat thead th:last-of-type{-webkit-border-top-right-radius:0;-webkit-border-top-left-radius:3px;border-top-right-radius:0;border-top-left-radius:3px}.widefat tfoot th:first-of-type{-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-radius:3px;border-bottom-left-radius:0;border-bottom-right-radius:3px}.widefat tfoot th:last-of-type{-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:3px}.widefat th{text-align:right}.widefat th input{margin:0 8px 0 0}.wrap{margin-right:0;margin-left:15px}.wrap h2,.subtitle{font-family:Tahoma,Arial,sans-serif}.wrap h2{padding-right:0;padding-left:15px}.subtitle{padding-left:0;padding-right:25px}.wrap .add-new-h2{font-family:Tahoma,Arial,sans-serif;margin-left:0;margin-right:4px}.wrap h2.long-header{padding-left:0}#dashboard-widgets-wrap .has-sidebar{margin-right:0;margin-left:-51%}#dashboard-widgets-wrap .has-sidebar .has-sidebar-content{margin-right:0;margin-left:51%}.view-all{right:auto;left:0}#dashboard_right_now p.sub,#dashboard-widgets h4,a.rsswidget,#dashboard_plugins h4,#dashboard_plugins h5,#dashboard_recent_comments .comment-meta .approve,#dashboard_right_now td.b,#dashboard_right_now .versions a{font-family:Tahoma,Arial,sans-serif}#dashboard_right_now p.sub{left:auto;right:15px}#dashboard_right_now td.b{padding-right:0;padding-left:6px;text-align:left}#dashboard_right_now .t{padding-right:0;padding-left:12px}#dashboard_right_now .table_content{float:right}#dashboard_right_now .table_discussion{float:left}#dashboard_right_now a.button{float:left;clear:left}#dashboard_plugins .inside span{padding-left:0;padding-right:5px}#dashboard-widgets h3 .postbox-title-action{right:auto;left:10px}.js #dashboard-widgets h3 .postbox-title-action{right:auto;left:30px}#the-comment-list .pingback{padding-left:0!important;padding-right:9px!important}#the-comment-list .comment-item{padding:1em 70px 1em 10px}#the-comment-list .comment-item .avatar{float:right;margin-left:0;margin-right:-60px}.rss-widget cite{text-align:left}.rss-widget span.rss-date{font-family:Tahoma,Arial,sans-serif;margin-left:0;margin-right:3px}#dashboard-widgets #dashboard_quick_press form p.submit input{float:right}#dashboard-widgets #dashboard_quick_press form p.submit #save-post{margin:0 1px 0 .7em}#dashboard-widgets #dashboard_quick_press form p.submit #publish{float:left}#dashboard-widgets #dashboard_quick_press form p.submit .spinner{margin:4px 0 0 6px}#dashboard_recent_drafts h4 abbr{font-family:Tahoma,Arial,sans-serif;margin-left:0;margin-right:3px}body.login{font-family:Tahoma,Arial,sans-serif}.login form{margin-right:8px;margin-left:0}.login form .forgetmenot{float:right}.login form .submit{float:left}#login form .submit input{font-family:Tahoma,Arial,sans-serif}.login #nav,.login #backtoblog{margin:0 16px 0 0}#login_error,.login .message{margin:0 8px 16px 0}.login #user_pass,.login #user_login,.login #user_email{margin-left:6px;margin-right:0;direction:ltr}.login h1 a{text-decoration:none}.login .button-primary{float:left}#nav-menus-frame{margin-right:300px;margin-left:0}#wpbody-content #menu-settings-column{margin-right:-300px;margin-left:0;float:right}.menu-location-menus select{float:right}.locations-row-links{float:right;margin:4px 6px 0 0}.locations-add-menu-link{direction:rtl}.locations-edit-menu-link{border-left:1px solid #CCC;border-right:0;padding-left:6px;padding-right:0;float:right}#menu-management-liquid{float:right}#menu-management{margin-left:20px;margin-right:0}.post-body-plain{padding:10px 0 0 10px}#menu-management .nav-tabs-arrow-left{right:0;left:auto}#menu-management .nav-tabs-arrow-right{left:0;right:auto;text-align:left;font-family:Tahoma,Arial,sans-serif}#menu-management .nav-tabs{padding-right:20px;padding-left:10px}.js #menu-management .nav-tabs{float:right;margin-right:0;margin-left:-400px}#select-nav-menu-container{text-align:left}#wpbody .open-label{float:right}#wpbody .open-label span{padding-left:10px;padding-right:0}.js .input-with-default-title{font-style:normal;font-weight:700}.postbox .howto input,.accordion-container .howto input{float:left}#nav-menu-theme-locations .button-controls{text-align:left}.meta-sep,.submitcancel{float:right}#cancel-save{margin-left:0;margin-right:20px}.button.right,.button-secondary.right,.button-primary.right{float:left}.list-controls{float:right}.add-to-menu{float:left}#add-custom-link label span{float:right;padding-left:5px;padding-right:0}.nav-menus-php .howto span{float:right}.list li .menu-item-title input{margin-left:3px;margin-right:0}.menu-item-handle{padding-right:10px;padding-left:0}.menu-item-edit-active .menu-item-handle{-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.menu-item-handle .item-title{margin-left:13em;margin-right:0;overflow:hidden}.menu-item-handle .item-edit{right:auto;left:-20px}.menu-item-handle .menu-item-title{float:right}.menu-item-settings .field-move a,.menu-item-settings .field-move span{float:right;margin-left:4px}.menu-item-depth-0{margin-right:0;margin-left:0}.menu-item-depth-1{margin-right:30px;margin-left:0}.menu-item-depth-2{margin-right:60px;margin-left:0}.menu-item-depth-3{margin-right:90px;margin-left:0}.menu-item-depth-4{margin-right:120px;margin-left:0}.menu-item-depth-5{margin-right:150px;margin-left:0}.menu-item-depth-6{margin-right:180px;margin-left:0}.menu-item-depth-7{margin-right:210px;margin-left:0}.menu-item-depth-8{margin-right:240px;margin-left:0}.menu-item-depth-9{margin-right:270px;margin-left:0}.menu-item-depth-10{margin-right:300px;margin-left:0}.menu-item-depth-11{margin-right:330px;margin-left:0}.menu-item-depth-0 .menu-item-transport{margin-right:0;margin-left:0}.menu-item-depth-1 .menu-item-transport{margin-right:-30px;margin-left:0}.menu-item-depth-2 .menu-item-transport{margin-right:-60px;margin-left:0}.menu-item-depth-3 .menu-item-transport{margin-right:-90px;margin-left:0}.menu-item-depth-4 .menu-item-transport{margin-right:-120px;margin-left:0}.menu-item-depth-5 .menu-item-transport{margin-right:-150px;margin-left:0}.menu-item-depth-6 .menu-item-transport{margin-right:-180px;margin-left:0}.menu-item-depth-7 .menu-item-transport{margin-right:-210px;margin-left:0}.menu-item-depth-8 .menu-item-transport{margin-right:-240px;margin-left:0}.menu-item-depth-9 .menu-item-transport{margin-right:-270px;margin-left:0}.menu-item-depth-10 .menu-item-transport{margin-right:-300px;margin-left:0}.menu-item-depth-11 .menu-item-transport{margin-right:-330px;margin-left:0}.item-type{padding-left:10px;padding-right:0}.item-controls{left:20px;right:auto}.item-controls .item-order{padding-left:10px;padding-right:0}.item-edit{left:-20px;right:auto;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:0;border-bottom-right-radius:3px;border-bottom-left-radius:0}.menu-item-settings{padding:10px 10px 10px 0;border-width:0 1px 1px}#custom-menu-item-url{direction:ltr}.link-to-original{font-style:normal;font-weight:700}.link-to-original a{padding-right:4px;padding-left:0}.menu-item-settings .description-thin,.menu-item-settings .description-wide{margin-left:10px;margin-right:0;float:right}.major-publishing-actions .publishing-action{text-align:left;float:left}.major-publishing-actions .delete-action{text-align:right;float:right;padding-left:15px;padding-right:0}.menu-name-label{margin-left:15px;margin-right:0}div.star-holder{background:url(../images/stars-rtl.png?ver=20121108) repeat-x bottom right}div.star-holder .star-rating{background:url(../images/stars-rtl.png?ver=20121108) repeat-x top right;float:right}#plugin-information .wrap{margin:4px 15px 0 0}#plugin-information ul#sidemenu{left:auto;right:0}#plugin-information .fyi{float:right}#plugin-information #section-screenshots li p{padding-left:0;padding-right:20px}#plugin-information .updated,#plugin-information .error{clear:none;direction:rtl}#plugin-information #section-holder .section{direction:ltr}.posting{margin-left:212px;margin-right:0;position:relative}h3.tb{margin-left:0;margin-right:5px}#publish{float:left}.postbox .handlediv{float:left}.actions li{float:right;margin-right:0;margin-left:10px}#extra-fields .actions{margin:-23px 0 0 -7px}#img_container a{float:right}#category-add input,#category-add select{font-family:Tahoma,Arial,sans-serif}#tagsdiv #newtag{margin-right:0;margin-left:5px}#tagadd{margin-left:0;margin-right:3px}#tagchecklist span{margin-left:.5em;margin-right:10px;float:right}#tagchecklist span a{margin:6px -9px 0 0;float:right}.submit input,.button,.button-primary,.button-secondary,#postcustomstuff .submit input{font-family:Tahoma,Arial,sans-serif}.ac_results li{text-align:right}#TB_ajaxContent #options{right:auto;left:25px}#TB_closeAjaxWindow{float:left}#TB_ajaxWindowTitle{float:right}#post_status{margin-left:0;margin-right:10px}#templateside{float:left}#template textarea,#docs-list{direction:ltr}.theme-details .theme-version{float:right}.theme-details .star-holder{float:left}.feature-filter .feature-group{float:right}.feature-filter .feature-group li{padding-right:0;padding-left:25px}div.widget-liquid-left{float:right;clear:right;margin-right:0;margin-left:-325px}div#widgets-left{margin-right:5px;margin-left:325px}div.widget-liquid-right{float:left;clear:left}.inactive-sidebar .widget{float:right}div.sidebar-name h3{font-family:Tahoma,Arial,sans-serif}#widget-list .widget{float:right}.inactive-sidebar .widget-placeholder{float:right}.widget-top .widget-title-action{float:left}.widget-control-edit{padding:0 0 0 8px}.sidebar-name-arrow{float:left}.press-this-sidebar{float:left}.press-this #header-logo,.press-this #wphead h1{float:right}.ltr{direction:ltr}.control-section .accordion-section-title{font-family:Tahoma,Arial,sans-serif}.js .accordion-section-title:after{right:auto;left:20px}.nav-menus-php .major-publishing-actions .publishing-action{float:left}.menu-settings dd{float:right}.manage-menus span{float:right}.manage-menus select{float:right;margin-right:0;margin-left:6px}.manage-menus .submit-btn{float:right}.manage-menus .selected-menu{float:right;margin:5px 0 0 6px}.nav-menus-php .add-new-menu-action{float:right;margin:4px 6px 0 0}.nav-menus-php .meta-sep,.nav-menus-php .submitdelete,.nav-menus-php .submitcancel{float:right}.is-submenu{float:right;margin-right:8px}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.post-com-count{background-image:url(../images/bubble_bg-rtl-2x.gif);background-size:18px 100px}#content-resize-handle,#post-body .wp_themeSkin .mceStatusbar a.mceResize{background:transparent url(../images/resize-rtl-2x.gif) no-repeat scroll right bottom;background-size:11px 11px}.wp-full-overlay .collapse-sidebar-arrow{background-image:url(../images/arrows-2x.png);background-size:15px 123px}div.star-holder{background:url(../images/stars-rtl-2x.png?ver=20121108) repeat-x bottom right;background-size:21px 37px}div.star-holder .star-rating{background:url(../images/stars-rtl-2x.png?ver=20121108) repeat-x top right;background-size:21px 37px}#post-body .wp_themeSkin .mceStatusbar a.mceResize,#content-resize-handle{background:transparent url(../images/resize-rtl-2x.gif) no-repeat scroll left bottom}.wp-slider .ui-slider-handle:before{background-image:url(../images/arrows-pr-2x.png);background-size:16px 102px}}body.locale-he-il,.locale-he-il .quicktags,.locale-he-il .search,.locale-he-il .howto,.locale-he-il #adminmenu .awaiting-mod,.locale-he-il #adminmenu span.update-plugins,.locale-he-il #sidemenu li a span.update-plugins,.locale-he-il .post-com-count-wrapper,.locale-he-il .widefat th,.locale-he-il .tablenav .displaying-num,.locale-he-il .inline-edit-row fieldset span.title,.locale-he-il .inline-edit-row fieldset span.checkbox-title,.locale-he-il .inline-edit-row fieldset ul.cat-checklist label,.locale-he-il .inline-edit-row #bulk-titles div,.locale-he-il p.help,.locale-he-il p.description,.locale-he-il span.description,.locale-he-il .form-wrap p,.locale-he-il h2 .nav-tab,.locale-he-il #your-profile legend,.locale-he-il #utc-time,.locale-he-il #local-time,.locale-he-il #poststuff h3,.locale-he-il .metabox-holder h3,.locale-he-il .tool-box .title,.locale-he-il td,.locale-he-il textarea,.locale-he-il input,.locale-he-il select,.locale-he-il .wrap h2,.locale-he-il .subtitle,.locale-he-il .wrap .add-new-h2,.locale-he-il #dashboard_right_now p.sub,.locale-he-il #dashboard-widgets h4,.locale-he-il a.rsswidget,.locale-he-il #dashboard_plugins h4,.locale-he-il #dashboard_plugins h5,.locale-he-il #dashboard_recent_comments .comment-meta .approve,.locale-he-il #dashboard_right_now td.b,.locale-he-il #dashboard_right_now .versions a,.locale-he-il .rss-widget span.rss-date,.locale-he-il #dashboard_recent_drafts h4 abbr,body.login.locale-he-il,.locale-he-il #login form .submit input,.locale-he-il #menu-management .nav-tabs-arrow-right,.locale-he-il #category-add input,.locale-he-il #category-add select,.locale-he-il .submit input,.locale-he-il .button,.locale-he-il .button-primary,.locale-he-il .button-secondary,.locale-he-il #postcustomstuff .submit input,.locale-he-il div.sidebar-name h3{font-family:Arial,sans-serif}.locale-he-il em{font-style:normal;font-weight:700} \ No newline at end of file diff --git a/sources/wp-admin/css/wp-admin.css b/sources/wp-admin/css/wp-admin.css new file mode 100644 index 0000000..2f5b5c7 --- /dev/null +++ b/sources/wp-admin/css/wp-admin.css @@ -0,0 +1,9424 @@ +/*------------------------------------------------------------------------------ + + +Hello, this is the main WordPress admin CSS file. +All the important stuff is in here. + + +TABLE OF CONTENTS: +------------------ + 1.0 - Text Elements + 2.0 - Forms + 3.0 - Actions + 4.0 - Notifications + 5.0 - TinyMCE + 6.0 - Admin Header + 6.1 - Screen Options Tabs + 6.2 - Help Menu + 7.0 - Main Navigation + 8.0 - Layout Blocks + 9.0 - Dashboard +10.0 - List Posts + 10.1 - Inline Editing +11.0 - Write/Edit Post Screen + 11.1 - Custom Fields + 11.2 - Post Revisions + 11.3 - Featured Images + 11.4 - Post Format Selection +12.0 - Categories +13.0 - Tags +14.0 - Media Screen + 14.1 - Media Library + 14.2 - Image Editor +15.0 - Comments Screen +16.0 - Themes + 16.1 - Custom Header + 16.2 - Custom Background + 16.3 - Tabbed Admin Screen Interface +17.0 - Plugins +18.0 - Users +19.0 - Tools +20.0 - Settings +21.0 - Admin Footer +22.0 - About Pages +23.0 - Full Overlay w/ Sidebar +24.0 - Customize Loader +25.0 - Misc + +------------------------------------------------------------------------*/ + +/* 2 column liquid layout */ +#wpwrap { + height: auto; + min-height: 100%; + width: 100%; + position: relative; +} + +#wpcontent { + height: 100%; +} + +#wpcontent, +#wpfooter { + margin-left: 165px; +} + +.folded #wpcontent, +.folded #wpfooter { + margin-left: 52px; +} + +#wpbody-content { + padding-bottom: 65px; + float: left; + width: 100%; +} + +#adminmenuback, +#adminmenuwrap, +#adminmenu, +#adminmenu .wp-submenu { + width: 145px; +} + +#adminmenuback { + position: absolute; + top: 0; + bottom: 0; + z-index: -1; +} + +#adminmenu { + clear: left; + margin: 0; + padding: 0; + list-style: none; +} + +.folded #adminmenuback, +.folded #adminmenuwrap, +.folded #adminmenu, +.folded #adminmenu li.menu-top { + width: 32px; +} + +/* inner 2 column liquid layout */ + +.inner-sidebar { + float: right; + clear: right; + display: none; + width: 281px; + position: relative; +} + +.columns-2 .inner-sidebar { + margin-right: auto; + width: 286px; + display: block; +} + +.inner-sidebar #side-sortables, +.columns-2 .inner-sidebar #side-sortables { + min-height: 300px; + width: 280px; + padding: 0; +} + +.has-right-sidebar .inner-sidebar { + display: block; +} + +.has-right-sidebar #post-body { + float: left; + clear: left; + width: 100%; + margin-right: -2000px; +} + +.has-right-sidebar #post-body-content { + margin-right: 300px; + float: none; + width: auto; +} + +/* 2 columns main area */ + +#col-container, +#col-left, +#col-right { + overflow: hidden; + padding: 0; + margin: 0; +} + +#col-left { + width: 35%; +} + +#col-right { + float: right; + clear: right; + width: 65%; +} + +.col-wrap { + padding: 0 7px; +} + +/* utility classes */ +.alignleft { + float: left; +} + +.alignright { + float: right; +} + +.textleft { + text-align: left; +} + +.textright { + text-align: right; +} + +.clear { + clear: both; +} + +/* Hide visually but not from screen readers */ +.screen-reader-text, +.screen-reader-text span, +.ui-helper-hidden-accessible { + position: absolute; + left: -1000em; + top: -1000em; + height: 1px; + width: 1px; + overflow: hidden; +} + +.screen-reader-shortcut { + position: absolute; + top: -1000em; +} + +.screen-reader-shortcut:focus { + left: 6px; + top: -21px; + height: auto; + width: auto; + display: block; + font-size: 14px; + font-weight: bold; + padding: 15px 23px 14px; + background: #f1f1f1; + color: #21759b; + border-radius: 3px; + z-index: 100000; + line-height: normal; + -webkit-box-shadow: 0 0 2px 2px rgba(0,0,0,.6); + box-shadow: 0 0 2px 2px rgba(0,0,0,.6); + text-decoration: none; +} + +.hidden, +.js .closed .inside, +.js .hide-if-js, +.no-js .hide-if-no-js, +.js.wp-core-ui .hide-if-js, +.js .wp-core-ui .hide-if-js, +.no-js.wp-core-ui .hide-if-no-js, +.no-js .wp-core-ui .hide-if-no-js { + display: none; +} + +/* include margin and padding in the width calculation of input and textarea */ +input[type="text"], +input[type="password"], +input[type="number"], +input[type="search"], +input[type="email"], +input[type="url"], +textarea { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; /* ie8 only */ + box-sizing: border-box; +} + +input[type="checkbox"], +input[type="radio"] { + vertical-align: text-top; + padding: 0; + margin: 1px 0 0; +} + +input[type="search"] { + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration { + display: none; +} + +/* general */ +html, +body { + height: 100%; + margin: 0; + padding: 0; +} + +body { + font-family: sans-serif; + font-size: 12px; + line-height: 1.4em; + min-width: 600px; +} + +body.iframe { + min-width: 0; + padding-top: 1px; +} + +body.login { + background: #fbfbfb; + min-width: 0; +} + +iframe, +img { + border: 0; +} + +td, +textarea, +input, +select, +button { + font-family: inherit; + font-size: inherit; + font-weight: inherit; +} + +td, +textarea { + line-height: inherit; +} + +input, +select { + line-height: 15px; +} + +a, +input[type="text"], +input[type="password"], +input[type="number"], +input[type="search"], +input[type="email"], +input[type="url"], +select, +textarea, +div { + outline: 0; +} + +a:focus, +a:active { + outline: thin dotted; +} + +#adminmenu a:focus, +#adminmenu a:active, +.screen-reader-text:focus { + outline: none; +} + +blockquote, +q { + quotes: none; +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} + +p { + margin: 1em 0; +} + +blockquote { + margin: 1em; +} + +label { + cursor: pointer; +} + +li, +dd { + margin-bottom: 6px; +} + +textarea, +input, +select { + margin: 1px; + padding: 3px; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + display: block; + font-weight: bold; +} + +h1 { + font-size: 2em; + margin: .67em 0; +} + +h2 { + font-size: 1.5em; + margin: .83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.67em; + margin: 2.33em 0; +} + +ul, +ol { + padding: 0; +} + +ul { + list-style: none; +} + +ol { + list-style-type: decimal; + margin-left: 2em; +} + +ul.ul-disc { + list-style: disc outside; +} + +ul.ul-square { + list-style: square outside; +} + +ol.ol-decimal { + list-style: decimal outside; +} + +ul.ul-disc, +ul.ul-square, +ol.ol-decimal { + margin-left: 1.8em; +} + +ul.ul-disc > li, +ul.ul-square > li, +ol.ol-decimal > li { + margin: 0 0 0.5em; +} + +.code, +code { + font-family: Consolas, Monaco, monospace; +} + +kbd, +code { + padding: 1px 3px; + margin: 0 1px; + font-size: 11px; +} + +.subsubsub { + list-style: none; + margin: 8px 0 5px; + padding: 0; + font-size: 12px; + float: left; +} + +.subsubsub a { + line-height: 2; + padding: .2em; + text-decoration: none; +} + +.subsubsub a .count, +.subsubsub a.current .count { + color: #999; + font-weight: normal; +} + +.subsubsub a.current { + font-weight: bold; + border: none; +} + +.subsubsub li { + display: inline-block; + margin: 0; + padding: 0; + white-space: nowrap; +} + +.widefat, +div.updated, +div.error, +.wrap .add-new-h2, +textarea, +input[type="text"], +input[type="password"], +input[type="file"], +input[type="email"], +input[type="number"], +input[type="search"], +input[type="tel"], +input[type="url"], +select, +.tablenav .tablenav-pages a, +.tablenav-pages span.current, +#titlediv #title, +.postbox, +#postcustomstuff table, +#postcustomstuff input, +#postcustomstuff textarea, +.imgedit-menu div, +.plugin-update-tr .update-message, +#poststuff .inside .the-tagcloud, +.login form, +#login_error, +.login .message, +#menu-management .menu-edit, +.nav-menus-php .list-container, +.menu-item-handle, +.link-to-original, +.nav-menus-php .major-publishing-actions .form-invalid, +.press-this #message, +#TB_window, +.tbtitle, +.highlight, +.feature-filter, +#widget-list .widget-top, +.editwidget .widget-inside { + -webkit-border-radius: 3px; + border-radius: 3px; + border-width: 1px; + border-style: solid; +} + +/* .widefat - main style for tables */ +.widefat { + border-spacing: 0; + width: 100%; + clear: both; + margin: 0; +} + +.widefat * { + word-wrap: break-word; +} + +.widefat a { + text-decoration: none; +} + +.widefat thead th:first-of-type { + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; +} +.widefat thead th:last-of-type { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} +.widefat tfoot th:first-of-type { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.widefat tfoot th:last-of-type { + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +.widefat td, +.widefat th { + border-width: 1px 0; + border-style: solid; +} +.widefat tfoot th { + border-bottom: none; +} + +.widefat .no-items td { + border-bottom-width: 0; +} + +.widefat td { + font-size: 12px; + padding: 4px 7px 2px; + vertical-align: top; +} + +.widefat td p, +.widefat td ol, +.widefat td ul { + font-size: 12px; +} + +.widefat th { + padding: 7px 7px 8px; + text-align: left; + line-height: 1.3em; + font-size: 14px; +} + +.widefat th input { + margin: 0 0 0 8px; + padding: 0; + vertical-align: text-top; +} + +.widefat .check-column { + width: 2.2em; + padding: 6px 0 25px; + vertical-align: top; +} + +.widefat tbody th.check-column { + padding: 9px 0 22px; +} + +.widefat.media .check-column { + padding-top: 8px; +} + +.widefat thead .check-column, +.widefat tfoot .check-column { + padding: 10px 0 0; +} + +.no-js .widefat thead .check-column input, +.no-js .widefat tfoot .check-column input { + display: none; +} + +.widefat .num, +.column-comments, +.column-links, +.column-posts { + text-align: center; +} + +.widefat th#comments { + vertical-align: middle; +} + +.wrap { + margin: 4px 15px 0 0; +} + +div.updated, +div.error { + padding: 0 0.6em; + margin: 5px 15px 2px; +} + +div.updated p, +div.error p { + margin: 0.5em 0; + padding: 2px; +} + +.wrap div.updated, +.wrap div.error, +.media-upload-form div.error { + margin: 5px 0 15px; +} + +.wrap h2, +.subtitle { + font-weight: normal; + margin: 0; + text-shadow: #fff 0 1px 0; +} + +.wrap h2 { + font-size: 23px; + padding: 9px 15px 4px 0; + line-height: 29px; +} + +.subtitle { + font-size: 14px; + padding-left: 25px; +} + +.wrap .add-new-h2 { + font-family: sans-serif; + margin-left: 4px; + padding: 3px 8px; + position: relative; + top: -3px; + text-decoration: none; + font-size: 12px; + border: 0 none; +} + +.wrap h2.long-header { + padding-right: 0; +} + +html, +.wp-dialog { + background-color: #fff; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="file"], +input[type="email"], +input[type="number"], +input[type="search"], +input[type="tel"], +input[type="url"], +select { + background-color: #fff; + color: #333; +} + +select { + color: #000; +} + +select[disabled] { + color: #7f7f7f; +} + +select:focus { + border-color: #aaa; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="file"]:focus, +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +select:focus { + -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.1); + box-shadow: 1px 1px 2px rgba(0,0,0,0.1); +} + +input[readonly] { + background-color: #eee; +} + +:-moz-placeholder, +.wp-core-ui :-moz-placeholder { + color: #a9a9a9; +} + +/*------------------------------------------------------------------------------ + 1.0 - Text Styles +------------------------------------------------------------------------------*/ + +div.sidebar-name h3, +#menu-management .nav-tab, +#dashboard_plugins h5, +a.rsswidget, +#dashboard_right_now td.b, +#dashboard-widgets h4, +.tool-box .title, +#poststuff h3, +.metabox-holder h3, +.pressthis a, +#your-profile legend, +.inline-edit-row fieldset span.title, +.inline-edit-row fieldset span.checkbox-title, +.tablenav .displaying-num, +.widefat th, +.quicktags, +.search { + font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; +} + +h2 .nav-tab, +.wrap h2, +.subtitle, +.login form .input { + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; +} + +.quicktags, +.search { + font-size: 12px; +} + +.icon32 { + float: left; + height: 34px; + margin: 7px 8px 0 0; + width: 36px; +} + +.icon16 { + height: 18px; + width: 18px; + padding: 6px 6px; + margin: -6px 0 0 -8px; + float: left; +} + +.key-labels label { + line-height: 24px; +} + +.pre { + /* https://developer.mozilla.org/en-US/docs/CSS/white-space */ + white-space: pre-wrap; /* css-3 */ + word-wrap: break-word; /* IE 5.5 - 7 */ +} + +.howto { + font-style: italic; + display: block; + font-family: sans-serif; +} + +p.install-help { + margin: 8px 0; + font-style: italic; +} + +.no-break { + white-space: nowrap; +} + +/*------------------------------------------------------------------------------ + 2.0 - Forms +------------------------------------------------------------------------------*/ + + +.wp-admin select { + padding: 2px; + height: 2em; +} + +.wp-admin select[multiple] { + height: auto; +} + +.submit { + padding: 1.5em 0; + margin: 5px 0; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} + +form p.submit a.cancel:hover { + text-decoration: none; +} + +#minor-publishing-actions input, +#major-publishing-actions input, +#minor-publishing-actions .preview { + text-align: center; +} + +textarea.all-options, +input.all-options { + width: 250px; +} + +input.large-text, +textarea.large-text { + width: 99%; +} + +input.regular-text, +#adduser .form-field input { + width: 25em; +} + +input.small-text { + width: 50px; +} + +input[type="number"].small-text { + width: 60px; +} + +#doaction, +#doaction2, +#post-query-submit { + margin: 1px 8px 0 0; +} + +.tablenav #changeit, +.tablenav #delete_all, +.tablenav #clear-recent-list { + margin-top: 1px; +} + +.tablenav .actions select { + float: left; + margin-right: 6px; + max-width: 200px; +} + +.ie8 .tablenav .actions select { + width: 155px; +} + +.ie8 .tablenav .actions select#cat { + width: 200px; +} + +#timezone_string option { + margin-left: 1em; +} + +label, +#your-profile label + a { + vertical-align: middle; +} + +#misc-publishing-actions label { + vertical-align: baseline; +} + +#pass-strength-result { + border-style: solid; + border-width: 1px; + float: left; + margin: 13px 5px 5px 1px; + padding: 3px 5px; + text-align: center; + width: 200px; + display: none; +} +.indicator-hint { + padding-top: 8px; +} + +p.search-box { + float: right; + margin: 0; +} + +.search-box input[name="s"], +#search-plugins input[name="s"], +.tagsdiv .newtag { + float: left; + height: 2em; + margin: 0 4px 0 0; +} + +input[type="text"].ui-autocomplete-loading { + background: transparent url('../images/loading.gif') no-repeat right center; + visibility: visible; +} + +ul#add-to-blog-users { + margin: 0 0 0 14px; +} + +.ui-autocomplete-input.open { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.ui-autocomplete { + padding: 0; + margin: 0; + list-style: none; + position: absolute; + z-index: 10000; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + border-width: 1px; + border-style: solid; +} + +.ui-autocomplete li { + margin-bottom: 0; + white-space: nowrap; + text-align: left; +} + +.ui-autocomplete li a { + display: block; + height: 100%; + padding: 4px 10px; +} + +.ui-autocomplete li a.ui-state-focus { + cursor: pointer; +} + +/*------------------------------------------------------------------------------ + 3.0 - Actions +------------------------------------------------------------------------------*/ + +#major-publishing-actions { + padding: 10px 10px 8px; + clear: both; + border-top: 1px solid #f5f5f5; + margin-top: -2px; +} + +#delete-action { + line-height: 25px; + vertical-align: middle; + text-align: left; + float: left; +} + +#publishing-action { + text-align: right; + float: right; + line-height: 23px; +} + +#publishing-action .spinner { + float: left; +} + +#misc-publishing-actions { + padding: 6px 0 0; +} + +.misc-pub-section { + padding: 6px 10px 8px; + border-width: 1px 0; + border-style: solid; +} + +.misc-pub-section:first-child { + border-top-width: 0; +} + +.misc-pub-section-last { + border-bottom-width: 0; +} + +#minor-publishing-actions { + padding: 10px 10px 2px 8px; + text-align: right; +} + +#minor-publishing { + border-bottom-width: 1px; + border-bottom-style: solid; + -webkit-box-shadow: 0 1px 0 #fff; + box-shadow: 0 1px 0 #fff; +} + +#save-post { + float: left; +} + +.preview { + float: right; +} + +#sticky-span { + margin-left: 18px; +} + +.side-info { + margin: 0; + padding: 4px; + font-size: 11px; +} + +.side-info h5 { + padding-bottom: 7px; + font-size: 14px; + margin: 12px 2px 5px; + border-bottom-width: 1px; + border-bottom-style: solid; +} + +.side-info ul { + margin: 0; + padding-left: 18px; + list-style: square; +} + +.approve, +.unapproved .unapprove { + display: none; +} + +.unapproved .approve, +.spam .approve, +.trash .approve { + display: inline; +} + +td.action-links, +th.action-links { + text-align: right; +} + + +/*------------------------------------------------------------------------------ + 4.0 - Notifications +------------------------------------------------------------------------------*/ + +#update-nag, +.update-nag { + line-height: 19px; + padding: 5px 0; + font-size: 12px; + text-align: center; + margin: -1px 15px 0 5px; + border-width: 1px; + border-style: solid; + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.plugins .plugin-update { + padding: 0; +} + +.plugin-update .update-message { + margin: 0 10px 8px 31px; + font-weight: bold; +} + +ul#dismissed-updates { + display: none; +} + +form.upgrade { + margin-top: 8px; +} + +form.upgrade .hint { + font-style: italic; + font-size: 85%; + margin: -0.5em 0 2em 0; +} + +.update-php .spinner { + float: none; + margin: -4px 0; +} + +#ajax-loading, +.ajax-loading, +.ajax-feedback, +.imgedit-wait-spin, +.list-ajax-loading { /* deprecated */ + visibility: hidden; +} + +#ajax-response.alignleft { + margin-left: 2em; +} + + +/*------------------------------------------------------------------------------ + 6.0 - Admin Header +------------------------------------------------------------------------------*/ +#adminmenu a, +#sidemenu a, +#taglist a, +#catlist a { + text-decoration: none; +} + +/*------------------------------------------------------------------------------ + 6.1 - Screen Options Tabs +------------------------------------------------------------------------------*/ + +#screen-options-wrap, +#contextual-help-wrap { + margin: 0; + padding: 8px 20px 12px; + position: relative; +} + +#contextual-help-wrap { + overflow: auto; +} + +#screen-meta .screen-reader-text { + visibility: hidden; +} + +#screen-meta-links { + margin: 0 24px 0 0; +} + +#screen-meta-links a:focus { + -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.4); + box-shadow: 1px 1px 1px rgba(0,0,0,0.4); + outline: none; +} + +/* screen options and help tabs revert */ +#screen-meta { + display: none; + position: relative; + margin: 0 15px 0 5px; + border-width: 0 1px 1px; + border-style: none solid solid; +} + +#screen-options-link-wrap, +#contextual-help-link-wrap { + float: right; + height: 23px; + padding: 0; + margin: 0 0 0 6px; + font-family: sans-serif; +} + +#screen-options-link-wrap, +#contextual-help-link-wrap, +#screen-meta { + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} + +#screen-meta-links .screen-meta-toggle { + position: relative; + top: -1px; +} + +#screen-meta-links a.show-settings { + text-decoration: none; + z-index: 1; + padding: 1px 16px 0 6px; + height: 22px; + line-height: 22px; + font-size: 12px; + display: block; + text-shadow: rgba(255,255,255,0.7) 0 1px 0; +} + +#screen-meta-links a.show-settings:hover { + text-decoration: none; +} +/* end screen options and help tabs */ + +.toggle-arrow { + background-repeat: no-repeat; + background-position: top left; + background-color: transparent; + height: 22px; + line-height: 22px; + display: block; +} + +.toggle-arrow-active { + background-position: bottom left; +} + +#screen-options-wrap h5, +#contextual-help-wrap h5 { + margin: 8px 0; + font-size: 13px; +} + +.metabox-prefs label { + display: inline-block; + padding-right: 15px; + white-space: nowrap; + line-height: 30px; +} + +.metabox-prefs label input { + margin: 0 5px 0 2px; +} + +.metabox-prefs .columns-prefs label input { + margin: 0 2px; +} + +.metabox-prefs label a { + display: none; +} + +/*------------------------------------------------------------------------------ + 6.2 - Help Menu +------------------------------------------------------------------------------*/ + +#contextual-help-wrap { + padding: 0; + margin-left: -4px; +} + +#contextual-help-columns { + position: relative; +} + +#contextual-help-back { + position: absolute; + top: 0; + bottom: 0; + left: 150px; + right: 170px; + border-width: 0 1px; + border-style: solid; +} + +#contextual-help-wrap.no-sidebar #contextual-help-back { + right: 0; + + border-right-width: 0; + -webkit-border-bottom-right-radius: 2px; + border-bottom-right-radius: 2px; +} + +.contextual-help-tabs { + float: left; + width: 150px; + margin: 0; +} + +.contextual-help-tabs ul { + margin: 1em 0; +} + +.contextual-help-tabs li { + margin-bottom: 0; + list-style-type: none; + border-style: solid; + border-width: 1px 0; + border-color: transparent; +} + +.contextual-help-tabs a { + display: block; + padding: 5px 5px 5px 12px; + line-height: 18px; + text-decoration: none; +} + +.contextual-help-tabs .active { + padding: 0; + margin: 0 -1px 0 0; + border-width: 1px 0 1px 1px; + border-style: solid; +} + +.contextual-help-tabs-wrap { + padding: 0 20px; + overflow: auto; +} + +.help-tab-content { + display: none; + margin: 0 22px 12px 0; + line-height: 1.6em; +} + +.help-tab-content.active { + display: block; +} + +.help-tab-content ul li { + list-style-type: disc; + margin-left: 18px; +} + +.contextual-help-sidebar { + width: 150px; + float: right; + padding: 0 8px 0 12px; + overflow: auto; +} + + +/*------------------------------------------------------------------------------ + 7.0 - Main Navigation (Left Menu) +------------------------------------------------------------------------------*/ + +#adminmenuback, +#adminmenuwrap { + border-width: 0 1px 0 0; + border-style: solid; +} + +#adminmenuwrap { + position: relative; + float: left; +} + +#adminmenushadow { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 6px; + z-index: 20; +} + +/* side admin menu */ +#adminmenu * { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +#adminmenu li { + margin: 0; + padding: 0; + cursor: pointer; +} + +#adminmenu a { + display: block; + line-height: 18px; + padding: 2px 5px; +} + +#adminmenu li.menu-top { + min-height: 28px; + position: relative; +} + +#adminmenu .wp-submenu { + list-style: none; + padding: 4px 0; + margin: 0; + position: absolute; + top: -1000em; + left: 146px; + z-index: 1000; + overflow: visible; + border-width: 1px; + border-style: solid; + -webkit-border-bottom-right-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} + +.js #adminmenu .sub-open, +.js #adminmenu .opensub .wp-submenu, +#adminmenu a.menu-top:focus + .wp-submenu, +.no-js li.wp-has-submenu:hover .wp-submenu { + top: -1px; +} + +#adminmenu .wp-has-current-submenu .wp-submenu, +.no-js li.wp-has-current-submenu:hover .wp-submenu, +#adminmenu a.wp-has-current-submenu:focus + .wp-submenu, +#adminmenu .wp-has-current-submenu .wp-submenu.sub-open, +#adminmenu .wp-has-current-submenu.opensub .wp-submenu { + position: relative; + z-index: 3; + top: auto; + left: auto; + right: auto; + bottom: auto; + border: 0 none; + + -webkit-box-shadow: none; + box-shadow: none; +} + +.folded #adminmenu .wp-submenu.sub-open, +.folded #adminmenu .opensub .wp-submenu, +.folded #adminmenu .wp-has-current-submenu .wp-submenu.sub-open, +.folded #adminmenu .wp-has-current-submenu.opensub .wp-submenu, +.folded #adminmenu a.menu-top:focus + .wp-submenu, +.folded #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu, +.no-js.folded #adminmenu .wp-has-submenu:hover .wp-submenu { + top: -1px; + left: 32px; +} + +.folded #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, +.folded #adminmenu .wp-has-current-submenu .wp-submenu { + border-width: 1px; + border-style: solid; + position: absolute; + top: -1000em; +} + +#adminmenu .wp-submenu a { + font-size: 12px; + line-height: 18px; + margin: 0; + padding-left: 12px; +} + +#adminmenu .wp-not-current-submenu li > a { + padding-left: 16px; +} + +#adminmenu .wp-has-current-submenu ul > li > a, +.folded #adminmenu li.menu-top .wp-submenu > li > a { + padding-left: 12px; +} + +#adminmenu a.menu-top, +#adminmenu .wp-submenu-head { + font-size: 13px; + font-weight: bold; + line-height: 18px; + padding: 0; +} + +#adminmenu .wp-submenu-head, +.folded #adminmenu .wp-menu-name { + display: none; +} + +.folded #adminmenu .wp-submenu-head { + display: block; +} + +#adminmenu .wp-submenu li { + padding: 0; + margin: 0; + overflow: hidden; +} + +#adminmenu a.menu-top { + border-width: 1px 0; + border-style: solid none; +} + +#adminmenu .wp-menu-image img { + padding: 7px 0 0 7px; + opacity: 0.6; + filter: alpha(opacity=60); +} + +#adminmenu div.wp-menu-name { + padding: 5px; +} + +#adminmenu div.wp-menu-image { + float: left; + width: 28px; + height: 28px; +} + +.folded #adminmenu div.wp-menu-image { + width: 32px; + position: absolute; + z-index: 25; +} + +.folded #adminmenu a.menu-top { + height: 28px; +} + +.wp-menu-arrow { + z-index: 25; + position: absolute; + right: 100%; + margin: 0; + height: 30px; + width: 6px; + + -moz-transform: translate( 146px ); + -webkit-transform: translate( 146px ); + -o-transform: translate( 146px ); + -ms-transform: translate( 146px ); + transform: translate( 146px ); +} + +#adminmenu .wp-menu-arrow div { + display: none; + position: absolute; + top: 7px; + left: -1px; + width: 14px; + height: 15px; + + -moz-transform: matrix( -0.6, 1, 0.6, 1, 0, 0 ); + -webkit-transform: matrix( -0.6, 1, 0.6, 1, 0, 0 ); + -o-transform: matrix( -0.6, 1, 0.6, 1, 0, 0 ); + -ms-transform: matrix( -0.6, 1, 0.6, 1, 0, 0 ); + transform: matrix( -0.6, 1, 0.6, 1, 0, 0 ); +} + +#adminmenu li.wp-not-current-submenu .wp-menu-arrow { + -moz-transform: translate( 145px ); + -webkit-transform: translate( 145px ); + -o-transform: translate( 145px ); + -ms-transform: translate( 145px ); + transform: translate( 145px ); + height: 28px; + border-width: 1px 0; + border-style: solid; + top: 0; +} + +.folded #adminmenu li .wp-menu-arrow { + -moz-transform: translate( 32px ); + -webkit-transform: translate( 32px ); + -o-transform: translate( 32px ); + -ms-transform: translate( 32px ); + transform: translate( 32px ); +} + +#adminmenu li.current .wp-menu-arrow, +#adminmenu li.wp-has-current-submenu .wp-menu-arrow, +#adminmenu li.wp-has-current-submenu .wp-menu-arrow div, +#adminmenu li.wp-has-submenu .wp-menu-arrow div, +#adminmenu li.current .wp-menu-arrow div, +.no-js #adminmenu li.wp-has-submenu:hover .wp-menu-arrow, +#adminmenu li.wp-has-submenu.opensub .wp-menu-arrow, +#adminmenu a.wp-has-submenu:focus .wp-menu-arrow, +#adminmenu a:hover .wp-menu-arrow { + display: block; +} + +#adminmenu li.current .wp-menu-arrow, +#adminmenu li.wp-menu-open .wp-menu-arrow { + top: 0; +} + +.no-js #adminmenu li.wp-has-submenu:hover .wp-menu-arrow, +#adminmenu li.wp-has-submenu.opensub .wp-menu-arrow, +#adminmenu a.wp-has-submenu:focus .wp-menu-arrow { + z-index: 1001; +} + +.ie8 #adminmenu li.menu-top:hover .wp-menu-arrow { + display: none; +} + +#adminmenu .wp-not-current-submenu .wp-menu-arrow div { + width: 15px; + top: 6px; + border-width: 0 0 1px 1px; + border-style: solid; +} + +.wp-menu-arrow, +.folded #adminmenu li .wp-menu-arrow div, +.no-js #adminmenu li.wp-not-current-submenu:hover .wp-menu-arrow { + display: none; +} + +.folded #adminmenu li.current .wp-menu-arrow, +.folded #adminmenu li.current .wp-menu-arrow div, +.folded #adminmenu li.wp-has-current-submenu .wp-menu-arrow div, +.folded #adminmenu li.wp-menu-open .wp-menu-arrow, +.folded #adminmenu li a:focus .wp-menu-arrow { + display: block; +} + +#adminmenu li.menu-top:hover .wp-menu-image img, +#adminmenu li.wp-has-current-submenu .wp-menu-image img { + opacity: 1; + filter: alpha(opacity=100); +} + +#adminmenu li.wp-menu-separator { + height: 3px; + padding: 0; + margin: 0; + border-width: 1px 0; + border-style: solid; + cursor: inherit; +} + +#adminmenu div.separator { + height: 1px; + padding: 0; + border-width: 1px 0 0 0; + border-style: solid; +} + +#adminmenu .wp-submenu .wp-submenu-head { + padding: 5px 4px 5px 10px; + margin: -4px -1px 4px; + border-width: 1px 0; + border-style: solid; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} + +#adminmenu li.wp-menu-open { + border-width: 0 0 1px; + border-style: solid; +} + +#adminmenu li.current, +.folded #adminmenu li.wp-menu-open { + border: 0 none; +} + +.folded #adminmenu li.wp-has-current-submenu { + margin-bottom: 1px; +} + +.folded #adminmenu .wp-has-current-submenu.menu-top-last { + margin-bottom: 0; +} + +#adminmenu .awaiting-mod, +#adminmenu span.update-plugins, +#sidemenu li a span.update-plugins { + position: absolute; + font-family: sans-serif; + font-size: 9px; + line-height: 17px; + font-weight: bold; + margin-top: 1px; + margin-left: 7px; + -webkit-border-radius: 10px; + border-radius: 10px; + z-index: 26; +} + +#adminmenu li .awaiting-mod span, +#adminmenu li span.update-plugins span, +#sidemenu li a span.update-plugins span { + display: block; + padding: 0 6px; +} + +#adminmenu li span.count-0, +#sidemenu li a .count-0 { + display: none; +} + +#collapse-menu { + font-size: 12px; + line-height: 34px; + border-width: 1px 0 0; + border-style: solid; +} + +.folded #collapse-menu span { + display: none; +} + +#collapse-button, +#collapse-button div { + width: 15px; + height: 15px; +} + +#collapse-button { + float: left; + margin: 8px 6px; + border-width: 1px; + border-style: solid; + -webkit-border-radius: 10px; + border-radius: 10px; +} + +/* Auto-folding of the admin menu */ +@media only screen and (max-width: 900px) { + .auto-fold #wpcontent, + .auto-fold #wpfooter { + margin-left: 52px; + } + + .auto-fold #adminmenuback, + .auto-fold #adminmenuwrap, + .auto-fold #adminmenu, + .auto-fold #adminmenu li.menu-top { + width: 32px; + } + + .auto-fold #adminmenu .wp-submenu.sub-open, + .auto-fold #adminmenu .opensub .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu .wp-submenu.sub-open, + .auto-fold #adminmenu .wp-has-current-submenu.opensub .wp-submenu, + .auto-fold #adminmenu a.menu-top:focus + .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu a.menu-top:focus + .wp-submenu { + top: -1px; + left: 32px; + } + + .auto-fold #adminmenu a.wp-has-current-submenu:focus + .wp-submenu, + .auto-fold #adminmenu .wp-has-current-submenu .wp-submenu { + border-width: 1px; + border-style: solid; + position: absolute; + top: -1000em; + } + + .auto-fold #adminmenu li.menu-top .wp-submenu > li > a { + padding-left: 12px; + } + + .auto-fold #adminmenu .wp-menu-name { + display: none; + } + + .auto-fold #adminmenu .wp-submenu-head { + display: block; + } + + .auto-fold #adminmenu div.wp-menu-image { + width: 32px; + position: absolute; + z-index: 25; + } + + .auto-fold #adminmenu a.menu-top { + height: 28px; + } + + .auto-fold #adminmenu li .wp-menu-arrow { + -moz-transform: translate( 32px ); + -webkit-transform: translate( 32px ); + -o-transform: translate( 32px ); + -ms-transform: translate( 32px ); + transform: translate( 32px ); + } + + .auto-fold #adminmenu li .wp-menu-arrow div { + display: none; + } + + .auto-fold #adminmenu li.current .wp-menu-arrow, + .auto-fold #adminmenu li.current .wp-menu-arrow div, + .auto-fold #adminmenu li.wp-has-current-submenu .wp-menu-arrow div, + .auto-fold #adminmenu li.wp-menu-open .wp-menu-arrow, + .auto-fold #adminmenu li a:focus .wp-menu-arrow { + display: block; + } + + .auto-fold #adminmenu li.wp-menu-open { + border: 0 none; + } + + .auto-fold #adminmenu li.wp-has-current-submenu { + margin-bottom: 1px; + } + + .auto-fold #adminmenu .wp-has-current-submenu.menu-top-last { + margin-bottom: 0; + } + + .auto-fold #collapse-menu span { + display: none; + } + +} + +/* List table styles */ +.post-com-count-wrapper { + min-width: 22px; + font-family: sans-serif; +} + +.post-com-count { + background-image: url('../images/bubble_bg.gif'); + height: 1.3em; + line-height: 1.1em; + display: block; + text-decoration: none; + padding: 0 0 6px; + cursor: pointer; + background-position: center -80px; + background-repeat: no-repeat; +} + +.post-com-count span { + font-size: 11px; + font-weight: bold; + height: 1.4em; + line-height: 1.4em; + min-width: 0.7em; + padding: 0 6px; + display: inline-block; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +strong .post-com-count { + background-position: center -55px; +} + +.post-com-count:hover { + background-position: center -3px; +} + +.column-response .post-com-count { + float: left; + margin-right: 5px; + text-align: center; +} + +.response-links { + float: left; +} + +#the-comment-list .attachment-80x60 { + padding: 4px 8px; +} + +th .comment-grey-bubble { + background-image: url('../images/comment-grey-bubble.png'); + background-repeat: no-repeat; + height: 12px; + width: 12px; +} + +/*------------------------------------------------------------------------------ + 8.0 - Layout Blocks +------------------------------------------------------------------------------*/ + +html.wp-toolbar { + padding-top: 28px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.narrow { + width: 70%; + margin-bottom: 40px; +} + +.narrow p { + line-height: 150%; +} + +.widefat th, +.widefat td { + overflow: hidden; +} + +.widefat th { + font-weight: normal; +} + +.widefat td p { + margin: 2px 0 0.8em; +} + +.widefat .column-comment p { + margin: 0.6em 0; +} + +/* Screens with postboxes */ +.postbox-container { + float: left; +} + +#dashboard-widgets.columns-1 .postbox-container { + width: 100%; +} + +#dashboard-widgets.columns-2 .postbox-container { + width: 49.5%; +} + +#dashboard-widgets.columns-2 #postbox-container-2, +#dashboard-widgets.columns-2 #postbox-container-3, +#dashboard-widgets.columns-2 #postbox-container-4 { + float: right; + width: 50.5%; +} + +#dashboard-widgets.columns-3 .postbox-container { + width: 33.5%; +} + +#dashboard-widgets.columns-3 #postbox-container-1 { + width: 33%; +} + +#dashboard-widgets.columns-3 #postbox-container-3, +#dashboard-widgets.columns-3 #postbox-container-4 { + float: right; +} + +#dashboard-widgets.columns-4 .postbox-container { + width: 25%; +} + +.postbox-container .meta-box-sortables { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} + +.metabox-holder .postbox-container .empty-container { + border: 3px dashed #CCCCCC; + height: 250px; +} + +.metabox-holder.columns-1 .postbox-container .empty-container, +.columns-2 #postbox-container-3 .empty-container, +.columns-2 #postbox-container-4 .empty-container, +.columns-3 #postbox-container-4 .empty-container { + border: 0 none; + height: 0; + min-height: 0; +} + +#poststuff { + padding-top: 10px; +} + +#poststuff #post-body { + padding: 0; +} + +#post-body-content { + width: 100%; + float: left; +} + +#poststuff .postbox-container { + width: 100%; +} + +#poststuff #post-body.columns-2 { + margin-right: 300px; +} + +#post-body.columns-2 #postbox-container-1 { + float: right; + margin-right: -300px; + width: 280px; +} + +#post-body.columns-2 #side-sortables { + min-height: 250px; +} + +/* one column on the dash */ +@media only screen and (max-width: 799px) { + #wpbody-content #dashboard-widgets .postbox-container { + width: 100%; + } + + #wpbody-content .metabox-holder .postbox-container .empty-container { + border: 0 none; + height: 0; + min-height: 0; + } +} + +/* two columns on the dash, but keep the setting if one is selected */ +@media only screen and (min-width: 800px) and (max-width: 1200px) { + #wpbody-content #dashboard-widgets .postbox-container { + width: 49.5%; + } + + #wpbody-content #dashboard-widgets #postbox-container-2, + #wpbody-content #dashboard-widgets #postbox-container-3, + #wpbody-content #dashboard-widgets #postbox-container-4 { + float: right; + width: 50.5%; + } + + #dashboard-widgets #postbox-container-3 .empty-container, + #dashboard-widgets #postbox-container-4 .empty-container { + border: 0 none; + height: 0; + min-height: 0; + } + + #wpbody #wpbody-content #dashboard-widgets.columns-1 .postbox-container { + width: 100%; + } + + #wpbody #wpbody-content .metabox-holder.columns-1 .postbox-container .empty-container { + border: 0 none; + height: 0; + min-height: 0; + } + + /* show the radio buttons for column prefs only for one or two columns */ + .index-php .screen-layout, + .index-php .columns-prefs { + display: block; + } + + .columns-prefs .columns-prefs-3, + .columns-prefs .columns-prefs-4 { + display: none; + } +} + +/* one column on the post write/edit screen */ +@media only screen and (max-width: 960px) { + #wpbody-content #poststuff #post-body { + margin: 0; + } + + #wpbody-content #post-body.columns-2 #postbox-container-1 { + margin-right: 0; + width: 100%; + } + + #poststuff #postbox-container-1 .empty-container, + #poststuff #postbox-container-1 #side-sortables:empty { + border: 0 none; + height: 0; + min-height: 0; + } + + #poststuff #post-body.columns-2 #side-sortables { + min-height: 0; + } + + /* hide the radio buttons for column prefs */ + .screen-layout, + .columns-prefs { + display: none; + } +} + +.postbox .hndle { + -webkit-border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +.js .postbox .hndle { + cursor: move; +} + +.postbox.closed .hndle { + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.hndle a { + font-size: 11px; + font-weight: normal; +} + +.postbox .handlediv { + float: right; + width: 27px; + height: 30px; +} + +.js .postbox .handlediv { + cursor: pointer; +} + +.sortable-placeholder { + border-width: 1px; + border-style: dashed; + margin-bottom: 20px; +} + +.widget, +.postbox, +.stuffbox { + margin-bottom: 20px; + padding: 0; + border-width: 1px; + border-style: solid; + line-height: 1; +} + +.widget .widget-top, +.postbox h3, +.stuffbox h3 { + margin-top: 1px; + border-bottom-width: 1px; + border-bottom-style: solid; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.js .widget .widget-top, +.js .postbox h3 { + cursor: move; +} + +.postbox .inside, +.stuffbox .inside { + padding: 0 12px 0 10px; + line-height: 1.4em; +} + +.postbox .inside { + margin: 10px 0; + position: relative; +} + +.postbox.closed h3 { + border: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +.postbox table.form-table { + margin-bottom: 0; +} + +.temp-border { + border: 1px dotted #ccc; +} + +.columns-prefs label { + padding: 0 5px; +} + + +/*------------------------------------------------------------------------------ + 9.0 - Dashboard +------------------------------------------------------------------------------*/ + +#dashboard-widgets-wrap { + margin: 0 -8px; +} + +#wpbody-content .metabox-holder { + padding-top: 10px; +} + +#dashboard-widgets .meta-box-sortables { + margin: 0 8px; +} + +#dashboard_recent_comments div.undo { + border-top-style: solid; + border-top-width: 1px; + margin: 0 -10px; + padding: 3px 8px; + font-size: 11px; +} + +#the-comment-list td.comment p.comment-author { + margin-top: 0; + margin-left: 0; +} + +#the-comment-list p.comment-author img { + float: left; + margin-right: 8px; +} + +#the-comment-list p.comment-author strong a { + border: none; +} + +#the-comment-list td { + vertical-align: top; +} + +#the-comment-list td.comment { + word-wrap: break-word; +} + +/* Welcome Panel */ +.welcome-panel { + position: relative; + overflow: auto; + margin: 20px 0; + padding: 23px 10px 12px; + border-width: 1px; + border-style: solid; + border-radius: 3px; + font-size: 13px; + line-height: 2.1em; +} + +.welcome-panel h3 { + margin: 0; + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-size: 21px; + font-weight: normal; + line-height: 1.2; +} +.welcome-panel h4 { + margin: 1.33em 0 0; + font-size: 13px; +} + +.welcome-panel .about-description { + font-size: 16px; + margin: 0; +} + +.welcome-panel .welcome-panel-close { + position: absolute; + top: 5px; + right: 10px; + padding: 8px 3px; + font-size: 13px; + text-decoration: none; + line-height: 1; +} + +.welcome-panel .welcome-panel-close:before { + content: ' '; + position: absolute; + left: -12px; + width: 10px; + height: 100%; + background: url('../images/xit.gif') 0 17% no-repeat; +} + +.welcome-panel .welcome-panel-close:hover:before { + background-position: 100% 17%; +} + +.wp-core-ui .welcome-panel .button.button-hero { + margin: 15px 0 3px; +} + +.welcome-panel-content { + margin-left: 13px; + max-width: 1500px; +} + +.welcome-panel .welcome-panel-column-container { + clear: both; + overflow: hidden; + position: relative; +} + +.welcome-panel .welcome-panel-column { + width: 32%; + min-width: 200px; + float: left; +} + +.ie8 .welcome-panel .welcome-panel-column { + min-width: 230px; +} + +.welcome-panel .welcome-panel-column:first-child { + width: 36%; +} + +.welcome-panel-column p { + margin-top: 7px; +} + +.welcome-panel .welcome-icon { + display: block; + padding: 2px 0 8px 32px; + background-image: url('../images/welcome-icons.png'); + background-repeat: no-repeat; + background-size: 16px; +} + +.welcome-panel .welcome-add-page { + background-position: 0 2px; +} + +.welcome-panel .welcome-edit-page { + background-position: 0 -90px; +} + +.welcome-panel .welcome-learn-more { + background-position: 0 -136px; +} + +.welcome-panel .welcome-comments { + background-position: 0 -182px; +} + +.welcome-panel .welcome-view-site { + background-position: 0 -274px; +} + +.welcome-panel .welcome-widgets-menus { + background-position: 1px -229px; + line-height: 14px; +} + +.welcome-panel .welcome-write-blog { + background-position: 0 -44px; +} + +.welcome-panel .welcome-panel-column ul { + margin: 0.8em 1em 1em 0; +} + +.welcome-panel .welcome-panel-column li { + line-height: 16px; + list-style-type: none; +} + +@media screen and (max-width: 870px) { + .welcome-panel .welcome-panel-column, + .welcome-panel .welcome-panel-column:first-child { + display: block; + float: none; + width: 100%; + } + + .welcome-panel .welcome-panel-column li { + display: inline-block; + margin-right: 13px; + } + + .welcome-panel .welcome-panel-column ul { + margin: 0.4em 0 0; + } + + .welcome-panel .welcome-icon { + padding-left: 25px; + } +} + +/*------------------------------------------------------------------------------ + 10.0 - List Posts (/Pages/etc) +------------------------------------------------------------------------------*/ + +table.fixed { + table-layout: fixed; +} + +.fixed .column-rating, +.fixed .column-visible { + width: 8%; +} + +.fixed .column-posts, +.fixed .column-date, +.fixed .column-parent, +.fixed .column-links, +.fixed .column-author, +.fixed .column-format { + width: 10%; +} + +.fixed .column-response, +.fixed .column-categories, +.fixed .column-tags, +.fixed .column-rel, +.fixed .column-role { + width: 15%; +} + +.fixed .column-slug { + width: 25%; +} + +.fixed .column-locations { + width: 35%; +} + +.fixed .column-comments { + width: 4em; + padding: 8px 0; + text-align: left; +} + +.fixed .column-comments .vers { + padding-left: 3px; +} + +.fixed .column-comments a { + float: left; +} + +.fixed .column-icon { + width: 80px; +} + +#comments-form .fixed .column-author { + width: 20%; +} + +#commentsdiv.postbox .inside { + margin: 0; + padding: 0; +} + +#commentsdiv .inside .row-actions { + line-height:18px; +} + +#commentsdiv .inside .column-author { + width: 25%; +} + +#commentsdiv .column-comment p { + margin: 0.6em 0; + padding: 0; +} + +#commentsdiv #replyrow td { + padding: 0; +} + +#commentsdiv p { + padding: 8px 10px; + margin: 0; +} + +#commentsdiv #add-new-comment { + border-width: 0 0 1px; + border-style: none none solid; +} + +#commentsdiv .comments-box { + border: 0 none; +} + +#commentsdiv .comments-box thead th { + background: transparent; + padding: 0 7px 4px; + font-style: italic; +} + +#commentsdiv .comments-box tr:last-child td { + border-bottom: 0 none; +} + +#commentsdiv .spinner { + padding-left: 5px; +} + +.sorting-indicator { + display: none; + width: 7px; + height: 4px; + margin-top: 8px; + margin-left: 7px; + background-image: url('../images/sort.gif'); + background-repeat: no-repeat; +} + +tr.wp-locked .locked-indicator { + background: url('../images/lock.png') no-repeat; + margin: -2px 0 0 6px; + height: 20px; + width: 16px; +} + +tr.wp-locked .check-column label, +tr.wp-locked .check-column input[type="checkbox"], +tr.wp-locked .row-actions .inline, +tr.wp-locked .row-actions .trash { + display: none; +} + +tr .locked-info { + height: 0; + opacity: 0; +} + +tr.wp-locked .locked-info { + height: auto; + opacity: 1; +} + +tr.locked-info, tr.wp-locked .locked-info { + -webkit-transition: height 1s, opacity 500ms; + -moz-transition: height 1s, opacity 500ms; + -ms-transition: height 1s, opacity 500ms; + -o-transition: height 1s, opacity 500ms; + transition: height 1s, opacity 500ms; +} + +.fixed .column-comments .sorting-indicator { + margin-top: 3px; +} + +#menu-locations-wrap .widefat { + width: 60%; +} + +.widefat th.sortable, +.widefat th.sorted { + padding: 0; +} + +th.sortable a, +th.sorted a { + display: block; + overflow: hidden; + padding: 7px 7px 8px; +} + +.fixed .column-comments.sortable a, +.fixed .column-comments.sorted a { + padding: 8px 0; +} + +th.sortable a span, +th.sorted a span { + float: left; + cursor: pointer; +} + +th.sorted.asc .sorting-indicator, +th.desc:hover span.sorting-indicator { + display: block; + background-position: 0 0; +} + +th.sorted.desc .sorting-indicator, +th.asc:hover span.sorting-indicator { + display: block; + background-position: -7px 0; +} + +/* Bulk Actions */ +.tablenav-pages a { + border-bottom-style: solid; + border-bottom-width: 2px; + font-weight: bold; + margin-right: 1px; + padding: 0 2px; +} +.tablenav-pages .current-page { + text-align: center; +} +.tablenav-pages .next-page { + margin-left: 2px; +} + +.tablenav a.button-secondary { + display: block; + margin: 3px 8px 0 0; +} + +.tablenav { + clear: both; + height: 30px; + margin: 6px 0 4px; + vertical-align: middle; +} + +.tablenav.themes { + max-width: 98%; +} + +.tablenav .tablenav-pages { + float: right; + display: block; + cursor: default; + height: 30px; + line-height: 30px; + font-size: 12px; +} + +.tablenav .no-pages, +.tablenav .one-page .pagination-links { + display: none; +} + +.tablenav .tablenav-pages a, +.tablenav-pages span.current { + text-decoration: none; + padding: 3px 6px; +} + +.tablenav .tablenav-pages a.disabled:hover , +.tablenav .tablenav-pages a.disabled:active { + cursor: default; +} + +.tablenav .displaying-num { + margin-right: 10px; + font-size: 12px; + font-style: italic; +} + +.tablenav .actions { + overflow: hidden; + padding: 2px 8px 0 0; +} + +.tablenav .delete { + margin-right: 20px; +} + +.view-switch { + float: right; + margin: 6px 8px 0; +} + +.view-switch a { + text-decoration: none; +} + +.filter { + float: left; + margin: -5px 0 0 10px; +} + +.filter .subsubsub { + margin-left: -10px; + margin-top: 13px; +} +.screen-per-page { + width: 4em; +} + +#posts-filter fieldset { + float: left; + margin: 0 1.5ex 1em 0; + padding: 0; +} + +#posts-filter fieldset legend { + padding: 0 0 .2em 1px; +} + + +/*------------------------------------------------------------------------------ + 10.1 - Inline Editing +------------------------------------------------------------------------------*/ + +/* +.quick-edit* is for Quick Edit +.bulk-edit* is for Bulk Edit +.inline-edit* is for everything +*/ + +/* Layout */ + +#wpbody-content .inline-edit-row fieldset { + font-size: 12px; + float: left; + margin: 0; + padding: 0; + width: 100%; +} + +tr.inline-edit-row td, +#wpbody-content .inline-edit-row fieldset .inline-edit-col { + padding: 0 0.5em; +} + +#wpbody-content .quick-edit-row-page fieldset.inline-edit-col-right .inline-edit-col { + border-width: 0 0 0 1px; + border-style: none none none solid; +} + +#wpbody-content .quick-edit-row-post .inline-edit-col-left { + width: 40%; +} + +#wpbody-content .quick-edit-row-post .inline-edit-col-right { + width: 39%; +} + +#wpbody-content .inline-edit-row-post .inline-edit-col-center { + width: 20%; +} + +#wpbody-content .quick-edit-row-page .inline-edit-col-left { + width: 50%; +} + +#wpbody-content .quick-edit-row-page .inline-edit-col-right, +#wpbody-content .bulk-edit-row-post .inline-edit-col-right { + width: 49%; +} + +#wpbody-content .bulk-edit-row .inline-edit-col-left { + width: 30%; +} + +#wpbody-content .bulk-edit-row-page .inline-edit-col-right { + width: 69%; +} + +#wpbody-content .bulk-edit-row .inline-edit-col-bottom { + float: right; + width: 69%; +} + +#wpbody-content .inline-edit-row-page .inline-edit-col-right { + margin-top: 27px; +} + +.inline-edit-row fieldset .inline-edit-group { + clear: both; +} + +.inline-edit-row fieldset .inline-edit-group:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +.inline-edit-row p.submit { + clear: both; + padding: 0.5em; + margin: 0.5em 0 0; +} + +.inline-edit-row span.error { + line-height: 22px; + margin: 0 15px; + padding: 3px 5px; +} + +/* Positioning */ +.inline-edit-row h4 { + margin: .2em 0; + padding: 0; + line-height: 23px; +} +.inline-edit-row fieldset span.title, +.inline-edit-row fieldset span.checkbox-title { + margin: 0; + padding: 0; + line-height: 27px; +} + +.inline-edit-row fieldset label, +.inline-edit-row fieldset span.inline-edit-categories-label { + display: block; + margin: .2em 0; +} + +.inline-edit-row fieldset label.inline-edit-tags { + margin-top: 0; +} + +.inline-edit-row fieldset label.inline-edit-tags span.title { + margin: .2em 0; + width: auto; +} + +.inline-edit-row fieldset label span.title { + display: block; + float: left; + width: 5em; +} + +.inline-edit-row fieldset label span.input-text-wrap { + display: block; + margin-left: 5em; +} + +.quick-edit-row-post fieldset.inline-edit-col-right label span.title { + width: auto; + padding-right: 0.5em; +} + +.inline-edit-row .input-text-wrap input[type=text] { + width: 100%; +} + +.inline-edit-row fieldset label input[type=checkbox] { + vertical-align: text-bottom; +} + +.inline-edit-row fieldset label textarea { + width: 100%; + height: 4em; +} + +#wpbody-content .bulk-edit-row fieldset .inline-edit-group label { + max-width: 50%; +} + +#wpbody-content .quick-edit-row fieldset .inline-edit-group label.alignleft:first-child { + margin-right: 0.5em +} + +.inline-edit-col-right .input-text-wrap input.inline-edit-menu-order-input { + width: 6em; +} + +.inline-edit-save .spinner { + padding: 4px 10px 0; + vertical-align: top; + float: right; +} + +/* Styling */ +.inline-edit-row h4 { + text-transform: uppercase; +} + +.inline-edit-row fieldset span.title, +.inline-edit-row fieldset span.checkbox-title { + font-style: italic; + line-height: 1.8em; +} + +/* Specific Elements */ +.inline-edit-row fieldset input[type="text"], +.inline-edit-row fieldset textarea { + border-style: solid; + border-width: 1px; +} + +.inline-edit-row fieldset .inline-edit-date { + float: left; +} + +.inline-edit-row fieldset input[name=jj], +.inline-edit-row fieldset input[name=hh], +.inline-edit-row fieldset input[name=mn] { + font-size: 12px; + width: 2.1em; +} + +.inline-edit-row fieldset input[name=aa] { + font-size: 12px; + width: 3.5em; +} + +.inline-edit-row fieldset label input.inline-edit-password-input { + width: 8em; +} + +ul.cat-checklist { + height: 12em; + border-style: solid; + border-width: 1px; + overflow-y: scroll; + padding: 0 5px; + margin: 0; +} + +#bulk-titles { + display: block; + height: 12em; + border-style: solid; + border-width: 1px; + overflow-y: scroll; + padding: 0 5px; + margin: 0 0 5px; +} + +.inline-edit-row fieldset ul.cat-checklist li, +.inline-edit-row fieldset ul.cat-checklist input { + margin: 0; +} + +.inline-edit-row fieldset ul.cat-checklist label, +.inline-edit-row #bulk-titles div { + font-family: sans-serif; + font-style: normal; + font-size: 11px; +} + +.inline-edit-row fieldset label input.inline-edit-menu-order-input { + width: 3em; +} + +.inline-edit-row fieldset label input.inline-edit-slug-input { + width: 75%; +} + +.quick-edit-row-post fieldset label.inline-edit-status { + float: left; +} + +#bulk-titles { + line-height: 140%; +} +#bulk-titles div { + margin: 0.2em 0.3em; +} + +#bulk-titles div a { + cursor: pointer; + display: block; + float: left; + height: 10px; + margin: 3px 3px 0 -2px; + overflow: hidden; + position: relative; + text-indent: -9999px; + width: 10px; +} + + +/*------------------------------------------------------------------------------ + 11.0 - Write/Edit Post Screen +------------------------------------------------------------------------------*/ + +#show-comments { + overflow: hidden; +} + +#save-action .spinner, +#show-comments a, +#show-comments .spinner { + float: left; +} + +#lost-connection-notice .spinner { + display: block; + float: left; + margin: 0 5px 0 0; +} + +.rtl #lost-connection-notice .spinner { + float: right; + margin: 0 0 0 5px; +} + +#titlediv { + position: relative; + margin-bottom: 5px; +} + +#titlediv label { + cursor: text; +} + +#titlediv div.inside { + margin: 0; +} + +#poststuff #titlewrap { + border: 0; + padding: 0; +} + +#titlediv #title { + padding: 3px 8px; + font-size: 1.7em; + line-height: 100%; + height: 1.7em; + width: 100%; + outline: none; + margin: 1px 0; +} + +#titlediv #title-prompt-text, +#wp-fullscreen-title-prompt-text { + color: #bbb; + position: absolute; + font-size: 1.7em; + padding: 11px 10px; +} + +#wp-fullscreen-save .fs-saved { + color: #999; + float: right; + margin-top: 4px; +} + +#wp-fullscreen-title-prompt-text { + padding: 11px; +} + +#poststuff .inside-submitbox, +#side-sortables .inside-submitbox { + margin: 0 3px; + font-size: 11px; +} + +input#link_description, +input#link_url { + width: 98%; +} + +#pending { + background: 0 none; + border: 0 none; + padding: 0; + font-size: 11px; + margin-top: -1px; +} + +#edit-slug-box { + line-height: 24px; + min-height: 25px; /* Yes, line-height + 1 */ + margin-top: 5px; + padding-right: 6px; +} + +#edit-slug-box .cancel { + margin-right: 10px; + font-size: 11px; +} + +#editable-post-name-full { + display: none; +} + +#editable-post-name input { + width: 16em; +} + +.postarea h3 label { + float: left; +} + +.submitbox .submit { + text-align: left; + padding: 12px 10px 10px; + font-size: 11px; +} + +.submitbox .submitdelete { + text-decoration: none; + padding: 1px 2px; +} + +.submitbox .submitdelete, +.submitbox .submit a:hover { + border-bottom-width: 1px; + border-bottom-style: solid; +} + +.submitbox .submit input { + margin-bottom: 8px; + margin-right: 4px; + padding: 6px; +} + +.inside-submitbox #post_status { + margin: 2px 0 2px -2px; +} + +#post-status-select { + line-height: 2.5em; + margin-top: 3px; +} + +/* Post Screen */ +#post-body #normal-sortables { + min-height: 50px; +} + +.postbox { + position: relative; + min-width: 255px; +} + +#trackback_url { + width: 99%; +} + +#normal-sortables .postbox .submit { + background: transparent none; + border: 0 none; + float: right; + padding: 0 12px; + margin:0; +} + +.category-add input[type="text"], +.category-add select { + width: 100%; + max-width: 260px; +} + +.press-this #side-sortables .category-tabs li, +ul.category-tabs li, +#side-sortables .add-menu-item-tabs li, +.wp-tab-bar li { + display: inline; + line-height: 1.35em; +} + +.no-js .category-tabs li.hide-if-no-js { + display: none; +} + +.category-tabs a, +#side-sortables .add-menu-item-tabs a, +.wp-tab-bar a { + text-decoration: none; +} + +.category-tabs { + margin: 8px 0 3px; +} + +#category-adder h4 { + margin: 10px 0; +} + +#side-sortables .add-menu-item-tabs, +.wp-tab-bar { + margin-bottom: 3px; +} + +#normal-sortables .postbox #replyrow .submit { + float: none; + margin: 0; + padding: 0 7px 5px; +} + +#side-sortables .submitbox .submit input, +#side-sortables .submitbox .submit .preview, +#side-sortables .submitbox .submit a.preview:hover { + border: 0 none; +} + +#side-sortables .inside-submitbox .insidebox, +.stuffbox .insidebox { + margin: 11px 0; +} + +ul.category-tabs, +ul.add-menu-item-tabs, +ul.wp-tab-bar { + margin-top: 12px; +} + +ul.category-tabs li { + border-style: solid; + border-width: 1px; + position: relative; +} + +ul.add-menu-item-tabs li.tabs, +.wp-tab-active { + border-style: solid solid none; + border-width: 1px 1px 0; +} + +#post-body .add-menu-item-tabs li.tabs { + border-style: solid none solid solid; + border-width: 1px 0 1px 1px; + margin-right: -1px; +} + +ul.category-tabs li, +ul.add-menu-item-tabs li, +ul.wp-tab-bar li { + padding: 3px 5px 5px; + -webkit-border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +/* positioning etc. */ +form#tags-filter { + position: relative; +} + +/* Edit posts */ +td.post-title strong, +td.plugin-title strong { + display: block; + margin-bottom: .2em; +} + +td.post-title p, +td.plugin-title p { + margin: 6px 0; +} + +/* Global classes */ +.wp-hidden-children .wp-hidden-child, +.ui-tabs-hide { + display: none; +} + +.commentlist .avatar { + vertical-align: text-top; +} + +#post-body .tagsdiv #newtag { + margin-right: 5px; + width: 16em; +} + +#side-sortables input#post_password { + width: 94% +} + +#side-sortables .tagsdiv #newtag { + width: 68%; +} + +#post-status-info { + border-width: 0 1px 1px; + border-style: none solid solid; + width: 100%; + -webkit-border-bottom-left-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} + +#post-status-info td { + font-size: 12px; +} + +.autosave-info { + padding: 2px 15px; + text-align: right; +} + +#editorcontent #post-status-info { + border: none; +} + +#post-body .wp_themeSkin .mceStatusbar a.mceResize { + display: block; + background: transparent url('../images/resize.gif') no-repeat scroll right bottom; + width: 12px; + cursor: se-resize; + margin: 0 1px; + position: relative; + top: -2px; +} + +#post-body .postarea .wp_themeSkin .mceStatusbar a.mceResize { + top: 20px; +} + +#content-resize-handle { + background: transparent url('../images/resize.gif') no-repeat scroll right bottom; + width: 12px; + cursor: se-resize; + position: absolute; + right: 2px; + height: 19px; +} + +.press-this #content-resize-handle { + bottom: 2px; +} + +.tmce-active #content-resize-handle { + display: none; +} + +#wp-word-count { + display: block; + padding: 2px 10px; +} + +#timestampdiv select { + height: 20px; + line-height: 14px; + padding: 0; + vertical-align: top; +} + +#aa, #jj, #hh, #mn { + padding: 1px; + font-size: 12px; +} + +#jj, #hh, #mn { + width: 2em; +} + +#aa { + width: 3.4em; +} + +.curtime #timestamp { + background-repeat: no-repeat; + background-position: left center; + padding: 2px 0 1px 20px; +} + +#timestampdiv { + padding-top: 5px; + line-height: 23px; +} + +#timestampdiv p { + margin: 8px 0 6px; +} + +#timestampdiv input { + border-width: 1px; + border-style: solid; +} + +.notification-dialog { + position: fixed; + top: 30%; + left: 50%; + width: 450px; + margin-left: -225px; + background: #fff; + line-height: 1.5; + z-index: 1000005; +} + +.notification-dialog-background { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: #000; + opacity: 0.5; + filter: alpha(opacity=50); + z-index: 1000000; +} + +#post-lock-dialog .post-locked-message, +#post-lock-dialog .post-taken-over { + margin: 25px; +} + +#post-lock-dialog .post-locked-message a.button { + margin-right: 10px; +} + +#post-lock-dialog .post-locked-avatar { + float: left; + margin: 0 20px 20px 0; +} + +#post-lock-dialog .wp-tab-first { + outline: 0; +} + +#post-lock-dialog .locked-saving img { + float: left; + margin-right: 3px; +} + +#post-lock-dialog.saving .locked-saving, +#post-lock-dialog.saved .locked-saved { + display: inline; +} + +/*------------------------------------------------------------------------------ + 11.1 - Custom Fields +------------------------------------------------------------------------------*/ + +#postcustomstuff thead th { + padding: 5px 8px 8px; +} + +#postcustom #postcustomstuff .submit { + border: 0 none; + float: none; + padding: 0 8px 8px; +} + +#side-sortables #postcustom #postcustomstuff .submit { + margin: 0; + padding: 0; +} + +#side-sortables #postcustom #postcustomstuff #the-list textarea { + height: 85px; +} + +#side-sortables #postcustom #postcustomstuff td.left input, +#side-sortables #postcustom #postcustomstuff td.left select, +#side-sortables #postcustomstuff #newmetaleft a { + margin: 3px 3px 0; +} + +#postcustomstuff table { + margin: 0; + width: 100%; + border-width: 1px; + border-style: solid; + border-spacing: 0; +} + +#postcustomstuff tr { + vertical-align: top; +} + +#postcustomstuff table input, +#postcustomstuff table select, +#postcustomstuff table textarea { + width: 96%; + margin: 8px; +} + +#side-sortables #postcustomstuff table input, +#side-sortables #postcustomstuff table select, +#side-sortables #postcustomstuff table textarea { + margin: 3px; +} + +#postcustomstuff th.left, +#postcustomstuff td.left { + width: 38%; +} + +#postcustomstuff .submit input { + margin: 0; + width: auto; +} + +#postcustomstuff #newmetaleft a { + display: inline-block; + margin: 0 8px 8px; + text-decoration: none; +} + +.no-js #postcustomstuff #enternew { + display: none; +} + +#post-body-content .compat-attachment-fields { + margin-bottom: 20px; +} + +.compat-attachment-fields th { + padding-top: 5px; + padding-right: 10px; +} + +/*------------------------------------------------------------------------------ + 11.2 - Post Revisions +------------------------------------------------------------------------------*/ +.revisions-control-frame, +.revisions-diff-frame { + position: relative; +} + +.revisions-controls { + padding-top: 40px; + height: 100px; + z-index: 1; +} + +.revisions-controls input[type="checkbox"] { + position: relative; + top: -1px; + vertical-align: text-bottom; +} + +.revisions.pinned .revisions-controls { + position: fixed; + top: 0; + padding-bottom: 10px; +} + +.revisions-tickmarks { + position: relative; + margin: 0 auto; + height: 0.8em; + top: 7px; + max-width: 70%; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.revisions-tickmarks > div { + position: absolute; + height: 100%; + border-style: solid; + border-width: 0 1px 0 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.revisions-tickmarks > div:first-child { + border-width: 0; +} + +.comparing-two-revisions .revisions-controls { + height: 140px; +} + +.revisions .diff-error { + position: absolute; + text-align: center; + margin: 0 auto; + width: 100%; + display: none; +} + +.revisions.diff-error .diff-error { + display: block; +} + +.revisions .loading-indicator { + position: fixed; + vertical-align: middle; + opacity: 0; + width: 100%; + top: 50%; + margin-left: -90px; + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -ms-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; + filter: alpha(opacity=0); /* ie8 and earlier */ +} + +body.folded .revisions .loading-indicator { + margin-left: -32px; +} + +.revisions .loading-indicator span.spinner { + display: block; + margin: 0 auto; + float: none; +} + +.revisions.loading .loading-indicator { + opacity: 1; + filter: alpha(opacity=100); /* ie8 and earlier */ +} + +.revisions .diff { + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -ms-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} + +.revisions.loading .diff { + opacity: 0.5; + filter: alpha(opacity=50); /* ie8 and earlier */ +} + +.revisions.diff-error .diff { + visibility: hidden; +} + +.revisions-meta { + margin-top: 15px; +} + +.revision-toggle-compare-mode { + position: absolute; + top: 0; + right: 0; +} + +.comparing-two-revisions .revisions-previous, +.comparing-two-revisions .revisions-next, +.revisions-meta .diff-meta-to strong { + display: none; +} + +.revisions-controls .author-card .date { + color: #777; +} + +.revisions-controls .author-card.autosave { + color: #d54e21; +} + +.revisions-controls .author-card .author-name { + font-weight: bold; +} + +.comparing-two-revisions .diff-meta-to strong { + display: block; +} + +.revisions-previous, +.revisions-next { + position: relative; + z-index: 1; +} + +.revisions-previous { + float: left; +} + +.revisions-next { + float: right; +} + +.revisions-controls .wp-slider { + max-width: 70%; + margin: 0 auto; + top: -3px; +} + +/* Revision meta box */ +.post-revisions li img, +#revisions-meta-restored img { + vertical-align: middle; +} + +table.diff { + table-layout: fixed; + width: 100%; + white-space: pre-wrap; + word-wrap: break-word; +} + +table.diff col.content { + width: auto; +} + +table.diff col.content.diffsplit { + width: 48%; +} + +table.diff col.diffsplit.middle { + width: auto; +} + +table.diff col.ltype { + width: 30px; +} + +table.diff tr { + background-color: transparent; +} + +table.diff td, +table.diff th { + padding: .5em; + font-family: Consolas, Monaco, monospace; +} + +table.diff .diff-deletedline del, +table.diff .diff-addedline ins { + text-decoration: none; +} + +.diff-meta { + -webkit-border-radius: 3px; + border-radius: 3px; + padding: 5px; + clear: both; + min-height: 32px; +} + +.diff-title strong { + line-height: 32px; + min-width: 60px; + text-align: right; + float: left; + margin-right: 5px; +} + +.revisions-controls .author-card .avatar, +.revisions-controls .author-card .author-info { + float: left; + margin-left: 6px; + margin-right: 6px; +} + +.revisions-controls .author-card .byline { + display: block; + font-size: 12px; +} + +.revisions-controls .author-card .avatar { + vertical-align: middle; +} + +.diff-meta input.restore-revision { + float: right; + margin-left: 6px; + margin-right: 6px; + margin-top: 4px; +} + +.diff-meta-from { + display: none; +} + +.comparing-two-revisions .diff-meta-from { + display: block; +} + +.revisions-tooltip { + position: absolute; + bottom: 105px; + margin-right: 0; + margin-left: -69px; + z-index: 0; + max-width: 350px; + min-width: 130px; + padding: 8px 4px; + display: none; + opacity: 0; +} + +.revisions-tooltip.flipped { + margin-left: 0; + margin-right: -70px; +} + +.revisions.pinned .revisions-tooltip { + display: none !important; +} + +.comparing-two-revisions .revisions-tooltip { + bottom: 145px; +} + +.revisions-tooltip-arrow { + width: 70px; + height: 15px; + overflow: hidden; + position: absolute; + left: 0; + margin-left: 35px; + bottom: -15px; +} + +.revisions-tooltip.flipped .revisions-tooltip-arrow { + margin-left: 0; + margin-right: 35px; + left: auto; + right: 0; +} + +.revisions-tooltip-arrow > span { + content: ""; + position: absolute; + left: 20px; + top: -20px; + width: 25px; + height: 25px; + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); +} + +.revisions-tooltip.flipped .revisions-tooltip-arrow > span { + left: auto; + right: 20px; +} + +.ie8 .revisions-tooltip-arrow > span { + left: 15px; + top: -25px; + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; +} + +.ie8 .revisions-tooltip.flipped .revisions-tooltip-arrow > span { + right: 25px; +} + +.revisions-tooltip, +.revisions-tooltip-arrow > span { + border-width: 1px; + border-style: solid; +} + +div.revisions-controls > .wp-slider > .ui-slider-handle { + margin-left: -10px; +} + + /* jQuery UI Slider */ +.wp-slider.ui-slider { + position: relative; + border-width: 1px; + border-style: solid; + border-radius: 3px; + text-align: left; + cursor: pointer; +} + +.wp-slider .ui-slider-handle { + position: absolute; + z-index: 2; + margin-top: -3px; + width: 19px; + height: 19px; + border-width: 1px; + border-style: solid; + border-radius: 50%; +} + +.wp-slider .ui-slider-handle:before { + content: ""; + position: absolute; + top: 6px; + left: 3px; + height: 8px; + width: 13px; + background: url(../images/arrows-pr.png) no-repeat -2px -47px; +} + +.wp-slider .ui-slider-handle.from-handle:before, +.wp-slider .ui-slider-handle.to-handle:before { + height: 8px; + width: 7px; +} + +.wp-slider .ui-slider-handle.from-handle:before { + background-position: -5px -84px; + left: 7px; +} + +.wp-slider .ui-slider-handle.to-handle:before { + background-position: -4px -65px; + left: 5px; +} + +.wp-slider .ui-slider-range { + position: absolute; + font-size: .7em; + display: block; + border: 0; + background-color: transparent; + background-image: none; +} + +.wp-slider.ui-slider-horizontal { + height: .8em; +} + +.wp-slider.ui-slider-horizontal .ui-slider-handle { + top: -.25em; + margin-left: -.6em; +} + +.wp-slider.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} + +.wp-slider.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} + +.wp-slider.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + + +/*------------------------------------------------------------------------------ + 11.3 - Featured Images +------------------------------------------------------------------------------*/ + +#select-featured-image { + padding: 4px 0; + overflow: hidden; +} + +#select-featured-image img { + max-width: 100%; + height: auto; + margin-bottom: 10px; +} + +#select-featured-image a { + float: left; + clear: both; +} + +#select-featured-image .remove { + display: none; + margin-top: 10px; +} + +.js #select-featured-image.has-featured-image .remove { + display: inline-block; +} + +.no-js #select-featured-image .choose { + display: none; +} + +/*------------------------------------------------------------------------------ + 11.4 - Post formats +------------------------------------------------------------------------------*/ + +a.post-state-format { + overflow: hidden; + display: inline-block; + vertical-align: middle; + height: 16px; + width: 16px; + margin-right: 5px; + background-repeat: no-repeat; + text-indent: -999em; +} + +#post-formats-select { + line-height: 2em; +} + +label.post-format-icon { + margin-left: 5px; + padding: 2px 0 2px 21px; +} + +.post-format-icon.post-format-standard { + background-position: 0 0; +} + +.post-format-icon.post-format-image { + background-position: 0 -32px; +} + +.post-format-icon.post-format-gallery { + background-position: 0 -64px; +} + +.post-format-icon.post-format-audio { + background-position: 0 -96px; +} + +.post-format-icon.post-format-video { + background-position: 0 -128px; +} + +.post-format-icon.post-format-chat { + background-position: 0 -160px; +} + +.post-format-icon.post-format-status { + background-position: 0 -192px; +} + +.post-format-icon.post-format-aside { + background-position: 0 -224px; +} + +.post-format-icon.post-format-quote { + background-position: 0 -256px; +} + +.post-format-icon.post-format-link { + background-position: 0 -288px; +} + + +/*------------------------------------------------------------------------------ + 12.0 - Categories +------------------------------------------------------------------------------*/ + +.category-adder { + margin-left: 120px; + padding: 4px 0; +} + +.category-adder h4 { + margin: 0 0 8px; +} + +#side-sortables .category-adder { + margin: 0; +} + +#post-body ul.add-menu-item-tabs { + float: left; + width: 120px; + text-align: right; + /* Negative margin for the sake of those without JS: all tabs display */ + margin: 0 -120px 0 5px; + padding: 0; +} + +#post-body ul.add-menu-item-tabs li { + padding: 8px; +} + +#post-body ul.add-menu-item-tabs li.tabs { + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +.wp-tab-panel, +.categorydiv div.tabs-panel, +.customlinkdiv div.tabs-panel, +.posttypediv div.tabs-panel, +.taxonomydiv div.tabs-panel { + min-height: 42px; + max-height: 200px; + overflow: auto; + padding: 0 0.9em; + border-style: solid; + border-width: 1px; +} + +div.tabs-panel-active { + display:block; +} + +div.tabs-panel-inactive { + display:none; +} + +#front-page-warning, +#front-static-pages ul, +ul.export-filters, +.inline-editor ul.cat-checklist ul, +.categorydiv ul.categorychecklist ul, +.customlinkdiv ul.categorychecklist ul, +.posttypediv ul.categorychecklist ul, +.taxonomydiv ul.categorychecklist ul { + margin-left: 18px; +} + +ul.categorychecklist li { + margin: 0; + padding: 0; + line-height: 19px; + word-wrap: break-word; +} + +.categorydiv .tabs-panel, +.customlinkdiv .tabs-panel, +.posttypediv .tabs-panel, +.taxonomydiv .tabs-panel { + border-width: 3px; + border-style: solid; +} + +.form-wrap p, +.form-wrap label { + font-size: 11px; +} + +.form-wrap label { + display: block; + padding: 2px; + font-size: 12px; +} + +.form-field input, +.form-field textarea { + border-style: solid; + border-width: 1px; + width: 95%; +} + +p.description, +.form-wrap p { + margin: 2px 0 5px; +} + +p.help, +p.description, +span.description, +.form-wrap p { + font-size: 12px; + font-style: italic; + font-family: sans-serif; +} + +.form-wrap .form-field { + margin: 0 0 10px; + padding: 8px 0; +} + +.form-wrap .form-field #parent { + max-width: 100%; +} + +.col-wrap h3 { + margin: 12px 0; + font-size: 1.1em; +} + +.col-wrap p.submit { + margin-top: -10px; +} + + +/*------------------------------------------------------------------------------ + 13.0 - Tags +------------------------------------------------------------------------------*/ + +#poststuff .taghint { + color: #aaa; + margin: 15px 0 -24px 12px; +} + +#poststuff .tagsdiv .howto { + margin: 0 0 6px 8px; +} + +.ajaxtag .newtag { + position: relative; +} + +.tagsdiv .newtag { + width: 180px; +} + +.tagsdiv .the-tags { + display: block; + height: 60px; + margin: 0 auto; + overflow: auto; + width: 260px; +} + +#post-body-content .tagsdiv .the-tags { + margin: 0 5px; +} + +p.popular-tags { + -webkit-border-radius: 8px; + border-radius: 8px; + border-width: 1px; + border-style: solid; + line-height: 2em; + max-width: 1000px; + padding: 8px 12px 12px; + text-align: justify; +} + +p.popular-tags a { + padding: 0 3px; +} + +.tagcloud { + width: 97%; + margin: 0 0 40px; + text-align: justify; +} + +.tagcloud h3 { + margin: 2px 0 12px; +} + +.ac_results { + padding: 0; + margin: 0; + list-style: none; + position: absolute; + z-index: 10000; + display: none; + border-width: 1px; + border-style: solid; +} + +.ac_results li { + padding: 2px 5px; + white-space: nowrap; + text-align: left; +} + +.ac_over { + cursor: pointer; +} + +.ac_match { + text-decoration: underline; +} + +/* links tables */ +table.links-table { + width: 100%; +} + +.links-table th { + font-weight: normal; + text-align: left; + vertical-align: top; + min-width: 80px; + width: 20%; + word-wrap: break-word; +} + +.links-table th, +.links-table td { + padding: 5px 0; +} + +.links-table td label { + margin-right: 8px; +} + +.links-table td input[type="text"], +.links-table td textarea { + width: 100%; +} + +.links-table #link_rel { + max-width: 280px; +} + +/*------------------------------------------------------------------------------ + 14.0 - Media Screen +------------------------------------------------------------------------------*/ + +.media-item .describe { + border-collapse: collapse; + width: 100%; + border-top-style: solid; + border-top-width: 1px; + clear: both; + cursor: default; +} + +.media-item.media-blank .describe { + border: 0; +} + +.media-item .describe th { + vertical-align: top; + text-align: left; + padding: 5px 10px 10px; + width: 140px; +} + +.media-item .describe .align th { + padding-top: 0; +} + +.media-item .media-item-info tr { + background-color: transparent; +} + +.media-item .describe td { + padding: 0 8px 8px 0; + vertical-align: top; +} + +.media-item thead.media-item-info td { + padding: 4px 10px 0; +} + +.media-item .media-item-info .A1B1 { + padding: 0 0 0 10px; +} + +.media-item td.savesend { + padding-bottom: 15px; +} + +.media-item .thumbnail { + max-height: 128px; + max-width: 128px; +} + +#wpbody-content #async-upload-wrap a { + display: none; +} + +.media-upload-form { + margin-top: 20px; +} + +.media-upload-form td label { + margin-right: 6px; + margin-left: 2px; +} + +.media-upload-form .align .field label { + display: inline; + padding: 0 0 0 23px; + margin: 0 1em 0 3px; + font-weight: bold; +} + +.media-upload-form tr.image-size label { + margin: 0 0 0 5px; + font-weight: bold; +} + +.media-upload-form th.label label { + font-weight: bold; + margin: 0.5em; + font-size: 13px; +} + +.media-upload-form th.label label span { + padding: 0 5px; +} + +abbr.required { + border: medium none; + text-decoration: none; +} + +.media-item .describe input[type="text"], +.media-item .describe textarea { + width: 460px; +} + +.media-item .describe p.help { + margin: 0; + padding: 0 0 0 5px; +} + +.media-item .edit-attachment, +.describe-toggle-on, +.describe-toggle-off { + display: block; + line-height: 36px; + float: right; + margin-right: 15px; +} + +.media-item .describe-toggle-off, +.media-item.open .describe-toggle-on { + display: none; +} + +.media-item.open .describe-toggle-off { + display: block; +} + +#media-items .media-item { + border-style: solid; + border-width: 1px; + min-height: 36px; + position: relative; + margin-top: -1px; + width: 100%; +} + +#media-items { + width: 623px; +} + +.media-new-php #media-items { + margin: 1em 0; +} + +#media-items:empty { + border: 0 none; +} + +.media-item .filename { + line-height: 36px; + overflow: hidden; + padding: 0 10px; +} + +.media-item .error-div { + padding-left: 10px; +} + +.media-item .pinkynail { + float: left; + margin: 2px 2px 0; + max-width: 40px; + max-height: 32px; +} + +.media-item .startopen, +.media-item .startclosed { + display: none; +} + +.media-item .original { + position: relative; + height: 34px; +} + +.media-item .progress { + float: right; + height: 22px; + margin: 6px 10px 0 0; + width: 200px; + line-height: 2em; + padding: 0; + overflow: hidden; + margin-bottom: 2px; + border: 1px solid #d1d1d1; + background: #f7f7f7; + background-image: -webkit-gradient(linear, left bottom, left top, from(#fff), to(#f7f7f7)); + background-image: -webkit-linear-gradient(bottom, #fff, #f7f7f7); + background-image: -moz-linear-gradient(bottom, #fff, #f7f7f7); + background-image: -o-linear-gradient(bottom, #fff, #f7f7f7); + background-image: linear-gradient(to top, #fff, #f7f7f7); + -webkit-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 0 3px rgba(0,0,0,0.1); + box-shadow: inset 0 0 3px rgba(0,0,0,0.1); +} + +.media-item .bar { + z-index: 9; + width: 0; + height: 100%; + margin-top: -24px; + background-color: #8cc1e9; + background-image: -webkit-gradient(linear, left bottom, left top, from(#72a7cf), to(#8cc1e9)); + background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -moz-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -o-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: linear-gradient(to top, #72a7cf, #8cc1e9); + -webkit-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: 0 0 3px rgba(0,0,0,0.3); + box-shadow: 0 0 3px rgba(0,0,0,0.3); +} + +.media-item .progress .percent { + z-index: 10; + position: relative; + width: 200px; + padding: 0 8px; + text-shadow: 0 1px 0 rgba(255,255,255,0.4); + color: rgba(0,0,0,0.6); +} + +.upload-php .fixed .column-parent { + width: 15%; +} + +.js .html-uploader #plupload-upload-ui { + display: none; +} + +.js .html-uploader #html-upload-ui { + display: block; +} + +.media-upload-form .media-item.error { + margin: 0; + padding: 0; +} + +.media-upload-form .media-item.error p, +.media-item .error-div { + line-height: 16px; + margin: 5px 10px; + padding: 0; +} + +.media-item .error-div a.dismiss { + display: block; + float: right; + margin: 5px 4px 0 15px; +} + +/*------------------------------------------------------------------------------ + 14.1 - Media Library +------------------------------------------------------------------------------*/ + +.find-box { + width: 600px; + height: 300px; + overflow: hidden; + padding: 33px 0 51px; + position: absolute; + z-index: 1000; +} + +.find-box-head { + cursor: move; + font-weight: bold; + height: 2em; + line-height: 2em; + padding: 1px 12px; + position: absolute; + top: 5px; + width: 100%; +} + +.find-box-inside { + overflow: auto; + padding: 6px; + height: 100%; +} + +.find-box-search { + overflow: hidden; + padding: 9px; + position: relative; +} + +.find-box-search .spinner { + float: none; + left: 125px; + position: absolute; + top: 9px; +} + +#find-posts-input { + float: left; + width: 140px; + height: 24px; +} + +#find-posts-search { + float: left; + margin: 1px 4px 0 3px; +} + +#find-posts-response { + margin: 8px 0; + padding: 0 1px 6px; +} + +#find-posts-response table { + width: 100%; +} + +#find-posts-response .found-radio { + padding: 3px 0 0 8px; + width: 15px; +} + +.find-box-buttons { + padding: 8px; + overflow: hidden; +} + +.find-box #resize-se { + position: absolute; + right: 1px; + bottom: 1px; +} + +.ui-find-overlay { + position: absolute; + top: 0; + left: 0; + background-color: #000; + opacity: 0.6; + filter: alpha(opacity=60); +} + +ul#dismissed-updates { + display: none; +} + +form.upgrade { + margin-top: 8px; +} + +form.upgrade .hint { + font-style: italic; + font-size: 85%; + margin: -0.5em 0 2em 0; +} + +#poststuff .inside .the-tagcloud { + margin: 5px 0 10px; + padding: 8px; + border-width: 1px; + border-style: solid; + line-height: 1.8em; + word-spacing: 3px; + -webkit-border-radius: 6px; + border-radius: 6px; +} + +.drag-drop #drag-drop-area { + border: 4px dashed #DDDDDD; + height: 200px; +} + +.drag-drop .drag-drop-inside { + margin: 70px auto 0; + width: 250px; +} + +.drag-drop-inside p { + color: #aaa; + font-size: 14px; + margin: 5px 0; + display: none; +} + +.drag-drop .drag-drop-inside p { + text-align: center; +} + +.drag-drop-inside p.drag-drop-info { + font-size: 20px; +} + +.drag-drop .drag-drop-inside p, +.drag-drop-inside p.drag-drop-buttons { + display: block; +} + +/* +#drag-drop-area:-moz-drag-over { + border-color: #83b4d8; +} +borger color while dragging a file over the uploader drop area */ +.drag-drop.drag-over #drag-drop-area { + border-color: #83b4d8; +} + +#plupload-upload-ui { + position: relative; +} + + +/*------------------------------------------------------------------------------ + 14.2 - Image Editor +------------------------------------------------------------------------------*/ + +.describe .image-editor { + vertical-align: top; +} + +.imgedit-wrap { + position: relative; +} + +.imgedit-settings p { + margin: 8px 0; +} + +.post-php .imgedit-wrap table { + width: 100%; +} + +.describe .imgedit-wrap table td, +.wp_attachment_holder .imgedit-wrap table td { + vertical-align: top; + padding-top: 0; +} + +.describe .imgedit-wrap table td.imgedit-settings { + padding: 0 5px; +} + +.wp_attachment_holder .imgedit-wrap table td.imgedit-settings { + width: 250px; +} + +td.imgedit-settings input { + margin-top: 0; + vertical-align: middle; +} + +.imgedit-wait { + position: absolute; + top: 0; + background: #fff url(../images/wpspin_light.gif) no-repeat scroll 22px 10px; + background-size: 16px 16px; + opacity: 0.7; + filter: alpha(opacity=70); + width: 100%; + height: 500px; + display: none; +} + +.spinner { + background: url(../images/wpspin_light.gif) no-repeat; + background-size: 16px 16px; + display: none; + float: right; + opacity: 0.7; + filter: alpha(opacity=70); + width: 16px; + height: 16px; + margin: 5px 5px 0; +} + +.no-float { + float: none; +} + +.media-disabled, +.imgedit-settings .disabled { + color: grey; +} + +.wp_attachment_image, +.A1B1 { + overflow: hidden; +} + +.wp_attachment_image .button, +.A1B1 .button { + float: left; +} + +.no-js .wp_attachment_image .button { + display: none; +} + +.wp_attachment_image .spinner, +.A1B1 .spinner { + float: left; + padding: 0 4px 4px; + vertical-align: bottom; +} + +.imgedit-menu { + margin: 0 0 12px; + min-width: 300px; +} + +.imgedit-menu div { + float: left; + width: 32px; + height: 32px; +} + +.imgedit-crop-wrap { + position: relative; +} + +.imgedit-crop { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -9px -31px; + margin: 0 8px 0 0; +} + +.imgedit-crop.disabled:hover { + background-position: -9px -31px; +} + +.imgedit-crop:hover { + background-position: -9px -1px; +} + +.imgedit-rleft { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -46px -31px; + margin: 0 3px; +} + +.imgedit-rleft.disabled:hover { + background-position: -46px -31px; +} + +.imgedit-rleft:hover { + background-position: -46px -1px; +} + +.imgedit-rright { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -77px -31px; + margin: 0 8px 0 3px; +} + +.imgedit-rright.disabled:hover { + background-position: -77px -31px; +} + +.imgedit-rright:hover { + background-position: -77px -1px; +} + +.imgedit-flipv { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -115px -31px; + margin: 0 3px; +} + +.imgedit-flipv.disabled:hover { + background-position: -115px -31px; +} + +.imgedit-flipv:hover { + background-position: -115px -1px; +} + +.imgedit-fliph { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -147px -31px; + margin: 0 8px 0 3px; +} + +.imgedit-fliph.disabled:hover { + background-position: -147px -31px; +} + +.imgedit-fliph:hover { + background-position: -147px -1px; +} + +.imgedit-undo { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -184px -31px; + margin: 0 3px; +} + +.imgedit-undo.disabled:hover { + background-position: -184px -31px; +} + +.imgedit-undo:hover { + background-position: -184px -1px; +} + +.imgedit-redo { + background: transparent url('../images/imgedit-icons.png') no-repeat scroll -215px -31px; + margin: 0 8px 0 3px; +} + +.imgedit-redo.disabled:hover { + background-position: -215px -31px; +} + +.imgedit-redo:hover { + background-position: -215px -1px; +} + +.imgedit-applyto img { + margin: 0 8px 0 0; +} + +.imgedit-group-top { + margin: 5px 0; +} + +.imgedit-applyto .imgedit-label { + padding: 2px 0 0; + display: block; +} + +.imgedit-help { + display: none; + font-style: italic; + margin-bottom: 8px; +} + +a.imgedit-help-toggle { + text-decoration: none; +} + +.form-table td.imgedit-response { + padding: 0; +} + +.imgedit-submit { + margin: 8px 0; +} + +.imgedit-submit-btn { + margin-left: 20px; +} + +.imgedit-wrap .nowrap { + white-space: nowrap; +} + +span.imgedit-scale-warn { + color: red; + font-size: 20px; + font-style: normal; + visibility: hidden; + vertical-align: middle; +} + +.imgedit-group { + border-width: 1px; + border-style: solid; + -webkit-border-radius: 3px; + border-radius: 3px; + margin-bottom: 8px; + padding: 2px 10px; +} + +/*------------------------------------------------------------------------------ + 15.0 - Comments Screen +------------------------------------------------------------------------------*/ + +.form-table { + border-collapse: collapse; + margin-top: 0.5em; + width: 100%; + margin-bottom: -8px; + clear: both; +} + +.form-table td { + margin-bottom: 9px; + padding: 8px 10px; + line-height: 20px; + font-size: 12px; +} + +.form-table th, +.form-wrap label { + font-weight: normal; + text-shadow: #fff 0 1px 0; +} + +.form-table th { + vertical-align: top; + text-align: left; + padding: 10px; + width: 200px; +} + +.form-table th.th-full { + width: auto; +} + +.form-table div.color-option { + display: block; + clear: both; + margin-top: 12px; +} + +.form-table input.tog { + margin-top: 2px; + margin-right: 2px; + float: left; +} + +.form-table td p { + margin-top: 4px; +} + +.form-table table.color-palette { + vertical-align: bottom; + float: left; + margin: -12px 3px 11px; +} + +.form-table .color-palette td { + border-width: 1px 1px 0; + border-style: solid solid none; + height: 10px; + line-height: 20px; + width: 10px; +} + +.commentlist li { + padding: 1em 1em .2em; + margin: 0; + border-bottom-width: 1px; + border-bottom-style: solid; +} + +.commentlist li li { + border-bottom: 0; + padding: 0; +} + +.commentlist p { + padding: 0; + margin: 0 0 .8em; +} + +/* reply to comments */ +#replyrow input { + border-width: 1px; + border-style: solid; +} + +#replyrow td { + padding: 2px; +} + +#replysubmit { + margin: 0; + padding: 0 5px 3px; + text-align: center; +} + +#replysubmit .spinner { + padding: 2px 0 0; + vertical-align: top; + float: right; +} + +#replysubmit .button { + margin-right: 5px; +} + +#replysubmit .error { + color: red; + line-height: 21px; + text-align: center; +} + +#replyrow h5 { + margin: .2em 0 0; + padding: 0 5px; + line-height: 1.4em; + font-size: 1em; +} + +#edithead .inside { + float: left; + padding: 3px 0 2px 5px; + margin: 0; + text-align: center; +} + +#edithead .inside input { + width: 180px; +} + +#edithead label { + padding: 2px 0; +} + +#replycontainer { + padding: 5px; +} + +#replycontent { + height: 120px; + -webkit-box-shadow: none; + box-shadow: none; +} + +.comment-php .wp-editor-area { + height: 200px; +} + +.comment-ays { + margin-bottom: 0; + border-style: solid; + border-width: 1px; +} + +.comment-ays th { + border-right-style: solid; + border-right-width: 1px; +} + +.trash-undo-inside, +.spam-undo-inside { + margin: 1px 8px 1px 0; + line-height: 16px; +} + +.spam-undo-inside .avatar, +.trash-undo-inside .avatar { + height: 20px; + width: 20px; + margin-right: 8px; + vertical-align: middle; +} + +.stuffbox .editcomment { + clear: none; +} + +#comment-status-radio p { + margin: 3px 0 5px; +} + +#comment-status-radio input { + margin: 2px 3px 5px 0; + vertical-align: middle; +} + +#comment-status-radio label { + padding: 5px 0; +} + +.commentlist .avatar { + vertical-align: text-top; +} + + +/*------------------------------------------------------------------------------ + 16.0 - Themes +------------------------------------------------------------------------------*/ + +.theme-install-php .tablenav { + height: auto; +} + +.theme-install-php .spinner { + margin-top: 9px; +} + +h3.available-themes { + margin: 0.3em 0 1em; + float: left; +} + +.available-theme { + display: inline-block; + margin-right: 10px; + overflow: hidden; + padding: 20px 20px 20px 0; + vertical-align: top; + width: 300px; +} + +.available-theme .screenshot { + width: 300px; + height: 225px; + display: block; + border-width: 1px; + border-style: solid; + margin-bottom: 10px; + overflow: hidden; +} + +.available-theme img { + width: 300px; +} + +.available-theme h3 { + margin: 15px 0 0; +} + +.available-theme .theme-author { + line-height: 18px; +} + +.available-theme .action-links { + margin-top: 10px; + overflow: hidden; +} + +.available-theme a.screenshot:focus { + border-color: #777; +} + +#current-theme .theme-info li, +.theme-options li, +.available-theme .action-links li { + float: left; + padding-right: 10px; + margin-right: 10px; + border-right: 1px solid #dfdfdf; +} + +.available-theme .action-links li { + padding-right: 8px; + margin-right: 8px; +} + +.ie8 .available-theme .action-links li { + padding-right: 7px; + margin-right: 7px; +} + +#current-theme .theme-info li:last-child, +.theme-options li:last-child, +.available-theme .action-links li:last-child { + padding-right: 0; + margin-right: 0; + border-right: 0; +} + +.available-theme .action-links .delete-theme { + float: right; + margin-left: 8px; + margin-right: 0; +} + +.available-theme .action-links .delete-theme a { + color: red; + padding: 2px; +} + +.available-theme .action-links .delete-theme a:hover { + background: red; + color: #fff; + text-decoration: none; +} + +.available-theme .action-links p { + float: left; +} + +#current-theme { + margin: 20px 0 10px; + padding: 0 0 20px; + border-bottom-width: 1px; + border-bottom-style: solid; + overflow: hidden; +} + +#current-theme.has-screenshot { + padding-left: 330px; +} + +#current-theme h3 { + margin: 0; + font-size: 12px; + font-weight: normal; + color: #999; +} + +#current-theme h4 { + margin: 3px 0 16px; + font-size: 20px; +} + +#current-theme h4 span { + margin-left: 20px; + font-size: 12px; + font-weight: normal; +} + +#current-theme a { + border-bottom: none; +} + +#current-theme .theme-info { + margin: 1em 0; + overflow: hidden; +} + +#current-theme .theme-description { + margin-top: 5px; + max-width: 600px; + line-height: 1.6em; +} + +#current-theme img { + float: left; + width: 300px; + margin-left: -330px; + + border-width: 1px; + border-style: solid; +} + +.theme-options { + overflow: hidden; + font-size: 14px; + padding-bottom: 10px; +} + +.theme-options .load-customize { + margin-right: 30px; + float: left; +} + +.theme-options span { + float: left; + margin-right: 10px; + text-transform: uppercase; + font-size: 11px; + line-height: 18px; + color: #999; +} + +.theme-options ul { + float: left; + margin: 0; +} + +/* Allow for three-up in small windows when sidebar is collapsed */ +@media only screen and (max-width: 1200px) { + .folded .available-theme, + .folded .available-theme .screenshot { + width: 300px; + } + + .folded .available-theme .screenshot { + height: 225px; + } + + .folded #current-theme img { + width: 300px; + } + + .folded #current-theme.has-screenshot { + padding-left: 330px; + } + + .folded #current-theme img { + margin-left: -330px; + } +} + +/* Adjust three-up display in smaller windows when sidebar is collapsed */ +@media only screen and (max-width: 1079px) { + .folded .available-theme, + .folded .available-theme .screenshot { + width: 270px; + } + + .folded .available-theme .screenshot { + height: 203px; + } + + .folded #current-theme img { + width: 270px; + } + + .folded #current-theme.has-screenshot { + padding-left: 300px; + } + + .folded #current-theme img { + margin-left: -300px; + } +} + +/* Allow for three-up on 1024px wide screens, e.g. tablets */ +@media only screen and (max-width: 1200px) { + .available-theme, + .available-theme .screenshot, + #current-theme img { + width: 240px; + } + + .available-theme .screenshot { + height: 180px; + } + + .available-theme img { + width: 100%; + } + + #current-theme.has-screenshot { + padding-left: 270px; + } + + #current-theme img { + margin-left: -270px; + } +} + +#post-body ul.add-menu-item-tabs li.tabs a, +#TB_window #TB_title a.tb-theme-preview-link, +#TB_window #TB_title a.tb-theme-preview-link:visited { + font-weight: bold; + text-decoration: none; +} + +#TB_window #TB_title { + background-color: #222; + color: #cfcfcf; +} + +#broken-themes { + text-align: left; + width: 50%; + border-spacing: 3px; + padding: 3px; +} + +.theme-install-php h4 { + margin: 2.5em 0 8px; +} + + +/*------------------------------------------------------------------------------ + 16.1 - Custom Header Screen +------------------------------------------------------------------------------*/ + +.appearance_page_custom-header #headimg { + border: 1px solid #DFDFDF; + overflow: hidden; + width: 100%; +} + +.appearance_page_custom-header #upload-form p label { + font-size: 12px; +} + +.appearance_page_custom-header .available-headers .default-header { + float: left; + margin: 0 20px 20px 0; +} + +.appearance_page_custom-header .random-header { + clear: both; + margin: 0 20px 20px 0; + vertical-align: middle; +} + +.appearance_page_custom-header .available-headers label input, +.appearance_page_custom-header .random-header label input { + margin-right: 10px; +} + +.appearance_page_custom-header .available-headers label img { + vertical-align: middle; +} + + +/*------------------------------------------------------------------------------ + 16.2 - Custom Background Screen +------------------------------------------------------------------------------*/ + +div#custom-background-image { + min-height: 100px; + border: 1px solid #dfdfdf; +} + +div#custom-background-image img { + max-width: 400px; + max-height: 300px; +} + + +/*------------------------------------------------------------------------------ + 16.3 - Tabbed Admin Screen Interface (Experimental) +------------------------------------------------------------------------------*/ + +.nav-tab { + border-style: solid; + border-width: 1px 1px 0; + color: #aaa; + text-shadow: #fff 0 1px 0; + font-size: 12px; + line-height: 16px; + display: inline-block; + padding: 4px 14px 6px; + text-decoration: none; + margin: 0 6px -1px 0; + -webkit-border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +.nav-tab-active { + border-width: 1px; + color: #464646; +} + +h2.nav-tab-wrapper, h3.nav-tab-wrapper { + border-bottom-width: 1px; + border-bottom-style: solid; + padding-bottom: 0; +} + +h2 .nav-tab { + padding: 4px 10px 6px; + font-weight: 200; + font-size: 20px; + line-height: 24px; + +} + + +/*------------------------------------------------------------------------------ + 17.0 - Plugins +------------------------------------------------------------------------------*/ + +#dashboard_right_now .versions .b, +#post-status-display, +#post-visibility-display, +#adminmenu .wp-submenu li.current, +#adminmenu .wp-submenu li.current a, +#adminmenu .wp-submenu li.current a:hover, +.media-item .percent, +.plugins .name, +#pass-strength-result.strong, +#pass-strength-result.short, +#ed_reply_toolbar #ed_reply_strong, +.item-controls .item-order a, +.feature-filter .feature-name { + font-weight: bold; +} + +.plugins p { + margin: 0 4px; + padding: 0; +} + +.plugins .desc p { + margin: 0 0 8px; +} + +.plugins td.desc { + line-height: 1.5em; +} + +.plugins .desc ul, +.plugins .desc ol { + margin: 0 0 0 2em; +} + +.plugins .desc ul { + list-style-type: disc; +} + +.plugins .row-actions { + padding: 0; +} + +.plugins tbody th.check-column { + padding: 7px 0; +} + +.plugins .inactive td, +.plugins .inactive th, +.plugins .active td, +.plugins .active th { + border-top-style: solid; + border-top-width: 1px; + padding: 5px 7px 0; +} + +.plugins .update th, +.plugins .update td { + border-bottom: 0; +} +.plugin-update-tr td { + border-top: 0; +} + +#wpbody-content .plugins .plugin-title, +#wpbody-content .plugins .theme-title { + padding-right: 12px; + white-space:nowrap; +} + +.plugins .second, +.plugins .row-actions { + padding: 0 0 5px; +} + +.plugins .update .second, +.plugins .update .row-actions { + padding-bottom: 0; +} + +.plugins-php .widefat tfoot th, +.plugins-php .widefat tfoot td { + border-top-style: solid; + border-top-width: 1px; +} + +.plugin-update-tr .update-message { + margin: 5px; + padding: 3px 5px; +} + +.plugin-install-php h4 { + margin: 2.5em 0 8px; +} + + +/*------------------------------------------------------------------------------ + 18.0 - Users +------------------------------------------------------------------------------*/ + +#profile-page .form-table textarea { + width: 500px; + margin-bottom: 6px; +} + +#profile-page .form-table #rich_editing { + margin-right: 5px +} + +#your-profile legend { + font-size: 22px; +} + +#your-profile #rich_editing { + border: none; +} + +#display_name { + width: 15em; +} + +#createuser .form-field input { + width: 25em; +} + +/*------------------------------------------------------------------------------ + 19.0 - Tools +------------------------------------------------------------------------------*/ + +.pressthis { + margin: 20px 0; +} + +.pressthis a, +.pressthis a:hover, +.pressthis a:focus, +.pressthis a:active { + display: inline-block; + position: relative; + cursor: move; + color: #333; + background: #e6e6e6; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(7%, #e6e6e6), color-stop(77%, #d8d8d8)); + background-image: -webkit-linear-gradient(bottom, #e6e6e6 7%, #d8d8d8 77%); + background-image: -moz-linear-gradient(bottom, #e6e6e6 7%, #d8d8d8 77%); + background-image: -o-linear-gradient(bottom, #e6e6e6 7%, #d8d8d8 77%); + background-image: linear-gradient(to top, #e6e6e6 7%, #d8d8d8 77%); + -webkit-border-radius: 5px; + border-radius: 5px; + border: 1px solid #b4b4b4; + font-style: normal; + line-height: 16px; + font-size: 14px; + text-decoration: none; + text-shadow: 0 1px 0px #fff; +} + +.pressthis a:active { + outline: none; +} + +.pressthis a:hover:after { + -webkit-transform: skew(20deg) rotate(9deg); + -moz-transform: skew(20deg) rotate(9deg); + transform: skew(20deg) rotate(9deg); + -webkit-box-shadow: 0 10px 8px rgba(0, 0, 0, 0.7); + box-shadow: 0 10px 8px rgba(0, 0, 0, 0.7); +} + +.pressthis a span { + background: url(../images/press-this.png?v=20120502) no-repeat 0px 5px; + background-size: 24px 20px; + padding: 8px 11px 8px 27px; + margin: 0 5px; + display: inline-block; +} + +.pressthis a:after { + content: ''; + width: 70%; + height: 55%; + z-index: -1; + position: absolute; + right: 10px; + bottom: 9px; + background: transparent; + + -webkit-transform: skew(20deg) rotate(6deg); + -moz-transform: skew(20deg) rotate(6deg); + transform: skew(20deg) rotate(6deg); + -webkit-box-shadow: 0 10px 8px rgba(0, 0, 0, 0.6); + box-shadow: 0 10px 8px rgba(0, 0, 0, 0.6); +} + +/*------------------------------------------------------------------------------ + 20.0 - Settings +------------------------------------------------------------------------------*/ + +#utc-time, #local-time { + padding-left: 25px; + font-style: italic; + font-family: sans-serif; +} + +.defaultavatarpicker .avatar { + margin: 2px 0; + vertical-align: middle; +} + +.options-general-php .spinner { + float: none; + margin: -3px 3px; +} + +/*------------------------------------------------------------------------------ + 21.0 - Admin Footer +------------------------------------------------------------------------------*/ + +#wpfooter { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 10px 0; + margin-right: 20px; + border-top-width: 1px; + border-top-style: solid; +} + +#wpfooter p { + margin: 0; + line-height: 20px; +} + +#wpfooter a { + text-decoration: none; +} + +#wpfooter a:hover { + text-decoration: underline; +} + +/*------------------------------------------------------------------------------ + 22.0 - About Pages +------------------------------------------------------------------------------*/ + +.about-wrap { + position: relative; + margin: 25px 40px 0 20px; + max-width: 1050px; /* readability */ + + font-size: 15px; +} + +.about-wrap div.updated, +.about-wrap div.error { + display: none !important; +} + +.about-wrap p.about-notice { + background-color: #ffffe0; + border: 1px solid #e6db55; + margin: 5px 0 15px; + padding: 0.4em 0.8em; + border-radius: 3px; + -webkit-border-radius: 3px; +} + + +/* Typography */ + +.about-wrap p { + line-height: 1.6em; +} + +.about-wrap h1 { + margin: 0.2em 200px 0 0; + line-height: 1.2em; + font-size: 2.8em; + font-weight: 200; +} + +.about-text, +.about-description, +.about-wrap li.wp-person a.web { + font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif; + font-weight: normal; + line-height: 1.6em; + font-size: 20px; +} + +.about-description { + margin-top: 1.4em; +} + +.about-text { + margin: 1em 200px 1.4em 0; + min-height: 60px; + font-size: 24px; +} + +.about-wrap h3 { + font-size: 1.5em; + line-height: 1.5em; + padding-top: 20px; +} + +.about-wrap .feature-section { + padding-bottom: 20px; +} + +.about-wrap .feature-section h4 { + margin-bottom: 0.6em; +} + +.about-wrap .feature-section p { + margin-top: 0.6em; +} + +.about-wrap code { + font-size: 14px; +} + +/* Point Releases */ + +.about-wrap .point-releases { + margin-top: 5px; +} + +.about-wrap .changelog.point-releases h3 { + padding-top: 35px; +} + +.about-wrap .changelog.point-releases h3:first-child { + padding-top: 7px; +} + +/* WordPress Version Badge */ + +.wp-badge { + padding-top: 142px; + height: 50px; + width: 173px; + font-weight: bold; + font-size: 14px; + text-align: center; + margin: 0 -5px; + background: url('../images/wp-badge.png?ver=20111120') no-repeat; +} + +.about-wrap .wp-badge { + position: absolute; + top: 0; + right: 0; +} + +/* Tabs */ + +.about-wrap h2.nav-tab-wrapper { + padding-left: 6px; +} + +.about-wrap h2 .nav-tab { + padding: 4px 10px 6px; + margin: 0 3px -1px 0; + font-size: 18px; + vertical-align: top; +} + +.about-wrap h2 .nav-tab-active { + font-weight: bold; + padding-top: 3px; +} + +/* Changelog / Update screen */ + +.about-wrap .feature-section.three-col img { + margin: 0.5em 0 0.5em 5px; + max-width: 100%; + float: none; +} + +.about-wrap .feature-section.col { + margin-bottom: 0; +} + +.about-wrap .feature-section.col h4 { + margin: 0 0 0.6em 0; +} + +.about-wrap .feature-section.two-col div { + width: 47%; + margin-right: 4.999999999%; + float: left; +} + +.about-wrap .feature-section.three-col div { + width: 30%; + margin-right: 4.999999999%; + float: left; +} + +.about-wrap .three-col.about-updates .col-1, +.about-wrap .three-col.about-updates .col-3 { + width: 37%; + margin: 0; +} + +.about-wrap .three-col.about-updates .col-2 { + width: 16%; + margin: 0 5%; +} + +.about-wrap .feature-section.col .last-feature { + margin-right: 0; +} + +.about-wrap .three-col.about-updates img { + margin: 0; +} + +.about-wrap .changelog .feature-section { + overflow: hidden; +} + +.about-wrap .about-passwords { + margin: 20px 0; + padding: 1px 20px 10px; + background-color: #f9f9f9; +} + +.about-wrap .about-auto-update { + text-align: center; + background-color: #f9f9ef; + clear: both; + padding: 10px; +} + +.about-wrap .about-auto-update.cool { + background-color: #eff9ef; +} + +.about-wrap .about-password-meter input { + font-size: 250%; + line-height: 1; + width: 100%; + display: block; + padding: 5px; +} + +.about-wrap .about-password-meter #pass-strength-result { + display: block !important; + font-size: 150%; + font-weight: normal !important; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + padding: 17px 0; + margin-bottom: 15px; +} + +.about-wrap .feature-section div p img { + float: right; + margin-left: 10px; + max-width: 20%; +} + +.about-wrap .changelog li { + list-style-type: disc; + margin-left: 3em; +} + + +/* Return to Dashboard Home link */ + +.about-wrap .return-to-dashboard { + margin: 30px 0 0 -5px; + font-size: 14px; + font-weight: bold; +} + +.about-wrap .return-to-dashboard a { + text-decoration: none; + padding: 0 5px; +} + +/* Credits */ + +.about-wrap h4.wp-people-group { + margin-top: 2.6em; + font-size: 16px; +} + +.about-wrap ul.wp-people-group { + overflow: hidden; + padding: 0 5px; + margin: 0 -15px 0 -5px; +} + +.about-wrap ul.compact { + margin-bottom: 0 +} + +.about-wrap li.wp-person { + float: left; + margin-right: 10px; +} + +.about-wrap li.wp-person img.gravatar { + float: left; + margin: 0 10px 10px 0; + padding: 2px; + width: 60px; + height: 60px; +} + +.about-wrap ul.compact li.wp-person img.gravatar { + width: 30px; + height: 30px; +} + +.about-wrap li.wp-person { + height: 70px; + width: 280px; + padding-bottom: 15px; +} + +.about-wrap ul.compact li.wp-person { + height: auto; + width: 180px; + padding-bottom: 0; + margin-bottom: 0; +} + +.about-wrap #wp-people-group-validators + p.wp-credits-list { + margin-top: 0; +} + +.about-wrap li.wp-person a.web { + display: block; + margin: 6px 0 2px; + font-size: 16px; + text-decoration: none; +} + +.about-wrap p.wp-credits-list a { + white-space: nowrap; +} + +/* Freedoms */ + +.freedoms-php .about-wrap ol { + margin: 40px 60px; +} + +.freedoms-php .about-wrap ol li { + list-style-type: decimal; + font-weight: bold; +} + +.freedoms-php .about-wrap ol p { + font-weight: normal; + margin: 0.6em 0; +} + +/*------------------------------------------------------------------------------ + 23.0 - Full Overlay w/ Sidebar +------------------------------------------------------------------------------*/ + +body.full-overlay-active { + overflow: hidden; +} + +.wp-full-overlay { + background: #fff; + z-index: 500000; + position: fixed; + overflow: visible; + top: 0; + bottom: 0; + left: 0; + right: 0; + height: 100%; + min-width: 0; +} + +.wp-full-overlay-sidebar { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + + position: fixed; + width: 300px; + height: 100%; + top: 0; + bottom: 0; + left: 0; + padding: 0; + margin: 0; + z-index: 10; + overflow: auto; + background: #f5f5f5; + border-right: 1px solid rgba( 0, 0, 0, 0.2 ); +} + +.wp-full-overlay.collapsed .wp-full-overlay-sidebar { + overflow: visible; +} + +.wp-full-overlay.collapsed, +.wp-full-overlay.expanded .wp-full-overlay-sidebar { + margin-left: 0 !important; +} + +.wp-full-overlay.expanded { + margin-left: 300px; +} + +.wp-full-overlay.collapsed .wp-full-overlay-sidebar { + margin-left: -300px; +} + +.wp-full-overlay-sidebar:after { + content: ''; + display: block; + position: absolute; + top: 0; + bottom: 0; + right: 0; + width: 3px; + box-shadow: -5px 0 4px -4px rgba(0, 0, 0, 0.1) inset; + z-index: 1000; +} + +.wp-full-overlay-main { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + height: 100%; +} + +.wp-full-overlay-sidebar .wp-full-overlay-header { + position: absolute; + left: 0; + right: 0; + height: 45px; + padding: 0 20px; + line-height: 45px; + z-index: 10; + margin: 0; +} + +.wp-full-overlay-sidebar .wp-full-overlay-header { + border-top: 0; + border-bottom: 1px solid #fff; + box-shadow: inset 0 -1px 0 0px #dfdfdf; +} + +.wp-full-overlay-sidebar .wp-full-overlay-footer { + bottom: 0; + border-bottom: 0; + border-top: 1px solid #dfdfdf; + box-shadow: inset 0 1px 0 0px #fff; +} + +.wp-full-overlay-sidebar .wp-full-overlay-sidebar-content { + position: absolute; + top: 45px; + bottom: 45px; + left: 0; + right: 0; + overflow: auto; +} + +.wp-full-overlay-sidebar-content .accordion-section:first-child { + border-top: 1px solid #fff; +} + +/* Close Link */ +.wp-full-overlay .close-full-overlay { + text-decoration: none; +} + +/* Collapse Button */ +.wp-full-overlay a.collapse-sidebar { + position: absolute; + bottom: 12px; + left: 0; + z-index: 50; + display: block; + width: 19px; + height: 19px; + margin-left: 15px; + padding: 0; + border-radius: 50%; + text-decoration: none; +} + +.wp-full-overlay.collapsed .collapse-sidebar { + position: absolute; + left: 100%; +} + +.wp-full-overlay .collapse-sidebar-arrow { + position: absolute; + margin-top: 2px; + margin-left: 2px; + display: block; + width: 15px; + height: 15px; + background: transparent url('../images/arrows.png') no-repeat -1px -73px; +} + +.wp-full-overlay.collapsed .collapse-sidebar-arrow { + background-position: -1px -109px; +} + +.wp-full-overlay .collapse-sidebar-label { + position: absolute; + left: 100%; + color: #808080; + line-height: 20px; + margin-left: 10px; +} + +.wp-full-overlay.collapsed .collapse-sidebar-label { + display: none; +} + +.wp-full-overlay .collapse-sidebar:hover .collapse-sidebar-label { + color: #666; +} + +/* Animations */ +.wp-full-overlay, +.wp-full-overlay-sidebar, +.wp-full-overlay .collapse-sidebar, +.wp-full-overlay-main { + -webkit-transition-property: left, right, top, bottom, width, margin; + -moz-transition-property: left, right, top, bottom, width, margin; + -ms-transition-property: left, right, top, bottom, width, margin; + -o-transition-property: left, right, top, bottom, width, margin; + transition-property: left, right, top, bottom, width, margin; + + -webkit-transition-duration: 0.2s; + -moz-transition-duration: 0.2s; + -ms-transition-duration: 0.2s; + -o-transition-duration: 0.2s; + transition-duration: 0.2s; +} + + +/*------------------------------------------------------------------------------ + 24.0 - Customize Loader +------------------------------------------------------------------------------*/ + +.no-customize-support .hide-if-no-customize, +.customize-support .hide-if-customize, +.no-customize-support.wp-core-ui .hide-if-no-customize, +.no-customize-support .wp-core-ui .hide-if-no-customize, +.customize-support.wp-core-ui .hide-if-customize, +.customize-support .wp-core-ui .hide-if-customize { + display: none; +} + +#customize-container { + display: none; + background: #fff; + z-index: 500000; + position: fixed; + overflow: visible; + top: 0; + bottom: 0; + left: 0; + right: 0; + height: 100%; +} + +.customize-active #customize-container { + display: block; +} + +.customize-loading #customize-container iframe { + opacity: 0; +} + +.customize-loading #customize-container { + background: #fff url("../images/wpspin_light.gif") no-repeat fixed center center; + background-size: 16px 16px; +} + +#customize-container iframe, +#theme-installer iframe { + height: 100%; + width: 100%; + z-index: 20; + + -webkit-transition: opacity 0.3s; + -moz-transition: opacity 0.3s; + -ms-transition: opacity 0.3s; + -o-transition: opacity 0.3s; + transition: opacity 0.3s; +} + +#customize-container .collapse-sidebar { + bottom: 16px; +} + +#theme-installer { + display: none; +} + +#theme-installer.single-theme { + display: block; +} + +.install-theme-info { + display: none; + padding: 10px 20px 20px; +} + +.single-theme .install-theme-info { + padding-top: 15px; +} + +#theme-installer .install-theme-info { + display: block; +} + +.install-theme-info .theme-install { + float: right; + margin-top: 18px; +} + +.install-theme-info .theme-name { + font-size: 16px; + line-height: 24px; + margin-bottom: 0; +} + +.install-theme-info .theme-screenshot { + margin-top: 15px; + width: 258px; + border: 1px solid #ccc; +} + +.install-theme-info .theme-details { + overflow: hidden; +} + +.theme-details .theme-version { + margin: 15px 0; + float: left; +} + +.theme-details .star-holder { + margin: 14px 0; + float: right; +} + +.theme-details .theme-description { + float: left; + color: #777; + line-height: 20px; +} + +/*------------------------------------------------------------------------------ + 25.0 - Misc +------------------------------------------------------------------------------*/ + +#excerpt, +.attachmentlinks { + margin: 0; + height: 4em; + width: 98%; +} + +#template div { + margin-right: 190px; +} + +p.pagenav { + margin: 0; + display: inline; +} + +.pagenav span { + font-weight: bold; + margin: 0 6px; +} + +.row-title { + font-size: 13px !important; + font-weight: bold; +} + +.column-author img, .column-username img { + float: left; + margin-right: 10px; + margin-top: 1px; +} + +.row-actions { + visibility: hidden; + padding: 2px 0 0; +} + +tr:hover .row-actions, +.mobile .row-actions, +.row-actions.visible, +div.comment-item:hover .row-actions { + visibility: visible; +} + +/* deprecated */ +.row-actions-visible { + padding: 2px 0 0; +} + +.form-table .pre { + padding: 8px; + margin: 0; +} + +table.form-table td .updated { + font-size: 13px; +} + +.tagchecklist { + margin-left: 14px; + font-size: 12px; + overflow: auto; +} +.tagchecklist strong { + margin-left: -8px; + position: absolute; +} +.tagchecklist span { + margin-right: 25px; + display: block; + float: left; + font-size: 11px; + line-height: 1.8em; + white-space: nowrap; + cursor: default; +} +.tagchecklist span a { + margin: 4px 0 0 -10px; + cursor: pointer; + width: 10px; + height: 10px; + display: block; + float: left; + text-indent: -9999px; + overflow: hidden; + position: absolute; +} + +#poststuff h2 { + margin-top: 20px; + font-size: 1.5em; + margin-bottom: 15px; + padding: 0 0 3px; + clear: left; +} + +#poststuff h3, +.metabox-holder h3 { + font-size: 15px; + font-weight: normal; + padding: 7px 10px; + margin: 0; + line-height: 1; +} + +#poststuff .inside { + margin: 6px 0 8px; +} + +#poststuff .inside #parent_id, +#poststuff .inside #page_template { + max-width: 100%; +} + +.inline-edit-row #post_parent, +.inline-edit-row select[name="page_template"] { + max-width: 80%; +} + +.ie8 #poststuff .inside #parent_id, +.ie8 #poststuff .inside #page_template, +.ie8 .inline-edit-row #post_parent, +.ie8 .inline-edit-row select[name="page_template"] { + width: 250px; +} + +#post-visibility-select { + line-height: 1.5em; + margin-top: 3px; +} + +#poststuff #submitdiv .inside { + margin: 0; + padding: 0; +} + +.edit-form-section { + margin-bottom: 20px; +} + +#templateside ul li a { + text-decoration: none; +} + +.tool-box .title { + margin: 8px 0; + font-size: 18px; + font-weight: normal; + line-height: 24px; +} + +#sidemenu { + margin: -30px 15px 0 315px; + list-style: none; + position: relative; + float: right; + padding-left: 10px; + font-size: 12px; +} + +#sidemenu a { + padding: 0 7px; + display: block; + float: left; + line-height: 28px; + border-top-width: 1px; + border-top-style: solid; + border-bottom-width: 1px; + border-bottom-style: solid; +} + +#sidemenu li { + display: inline; + line-height: 200%; + list-style: none; + text-align: center; + white-space: nowrap; + margin: 0; + padding: 0; +} + +#sidemenu a.current { + font-weight: normal; + padding-left: 6px; + padding-right: 6px; + -webkit-border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-width: 1px; + border-style: solid; +} + +#sidemenu li a .count-0 { + display: none; +} + +.plugin-install #description, +.plugin-install-network #description { + width: 60%; +} + +table .vers, +table .column-visible, +table .column-rating { + text-align: left; +} + +.error-message { + color: red; + font-weight: bold; +} + +/* Scrollbar fix for bulk upgrade iframe */ +body.iframe { + height: 98%; +} + +/* Upgrader styles, Specific to Language Packs */ +.lp-show-latest p { + display: none; +} +.lp-show-latest p:last-child, +.lp-show-latest .lp-error p { + display: block; +} + +/* - Only used once or twice in all of WP - deprecate for global style +------------------------------------------------------------------------------*/ +td.media-icon { + text-align: center; + width: 80px; + padding-top: 8px; + padding-bottom: 8px; +} + +td.media-icon img { + max-width: 80px; + max-height: 60px; +} + +#howto { + font-size: 11px; + margin: 0 5px; + display: block; +} + +.importers td { + padding-right: 14px; +} + +.importers { + font-size: 16px; + width: auto; +} + +#namediv table { + width: 100%; +} + +#namediv td.first { + width: 10px; + white-space: nowrap; +} + +#namediv input { + width: 98%; +} + +#namediv p { + margin: 10px 0; +} + +#submitdiv h3 { + margin-bottom: 0 !important; +} + +/* - Used - but could/should be deprecated with a CSS reset +------------------------------------------------------------------------------*/ +.zerosize { + height: 0; + width: 0; + margin: 0; + border: 0; + padding: 0; + overflow: hidden; + position: absolute; +} + +br.clear { + height: 2px; + line-height: 2px; +} + +.checkbox { + border: none; + margin: 0; + padding: 0; +} + +fieldset { + border: 0; + padding: 0; + margin: 0; +} + +.post-categories { + display: inline; + margin: 0; + padding: 0; +} + +.post-categories li { + display: inline; +} + + +/*----------------------------------------------------------------------------- + MERGED +-------------------------------------------------------------------------------*/ + +/* dashboard */ +.edit-box { + display: none; +} + +h3:hover .edit-box { + display: inline; +} + +#dashboard-widgets form .input-text-wrap input { + width: 100%; +} + +#dashboard-widgets form .textarea-wrap textarea { + width: 100%; +} + +#dashboard-widgets .postbox form .submit { + float: none; + margin: .5em 0 0; + padding: 0; + border: none; +} + +#dashboard-widgets-wrap #dashboard-widgets .postbox form .submit #publish { + min-width: 0; +} + +#dashboard-widgets a { + text-decoration: none; +} + +#dashboard-widgets h3 a { + text-decoration: underline; +} + +#dashboard-widgets h3 .postbox-title-action { + position: absolute; + right: 10px; + padding: 0; + top: 5px; +} + +.js #dashboard-widgets h3 .postbox-title-action { + right: 30px; +} + +#dashboard-widgets h4 { + font-weight: normal; + font-size: 13px; + margin: 0 0 .2em; + padding: 0; +} + +/* Right Now */ +#dashboard_right_now p.sub, +#dashboard_right_now .table, #dashboard_right_now .versions { + margin: -12px; +} + +#dashboard_right_now .inside { + font-size: 12px; + padding-top: 20px; +} + +#dashboard_right_now p.sub { + padding: 5px 0 15px; + color: #8f8f8f; + font-size: 14px; + position: absolute; + top: -17px; + left: 15px; +} + +#dashboard_right_now .table { + margin: 0; + padding: 0; + position: relative; +} + +#dashboard_right_now .table_content { + float: left; + border-top-width: 1px; + border-top-style: solid; + width: 45%; +} + +#dashboard_right_now .table_discussion { + float: right; + border-top-width: 1px; + border-top-style: solid; + width: 45%; +} + +#dashboard_right_now table td { + padding: 3px 0; + white-space: nowrap; +} + +#dashboard_right_now table tr.first td { + border-top: none; +} + +#dashboard_right_now td.b { + padding-right: 6px; + text-align: right; + font-size: 14px; + width: 1%; +} + +#dashboard_right_now td.b a { + font-size: 18px; +} + +#dashboard_right_now td.b a:hover { + color: #d54e21; +} + +#dashboard_right_now .t { + font-size: 12px; + padding-right: 12px; + padding-top: 6px; + color: #777; +} + +#dashboard_right_now .t a { + white-space: nowrap; +} + +#dashboard_right_now .spam { + color: red; +} + +#dashboard_right_now .waiting { + color: #e66f00; +} + +#dashboard_right_now .approved { + color: green; +} + +#dashboard_right_now .versions { + padding: 6px 10px 12px; + clear: both; +} + +#dashboard_right_now a.button { + float: right; + clear: right; + position: relative; + top: -5px; +} + +/* Recent Comments */ +#dashboard_recent_comments h3 { + margin-bottom: 0; +} + +#dashboard_recent_comments .inside { + margin-top: 0; +} + +#dashboard_recent_comments .comment-meta .approve { + font-style: italic; + font-family: sans-serif; + font-size: 10px; +} + +#dashboard_recent_comments .subsubsub { + float: none; + white-space: normal; +} + +#the-comment-list { + position: relative; +} + +#the-comment-list .comment-item { + padding: 1em 10px; + border-top: 1px solid; +} + +#the-comment-list .pingback { + padding-left: 9px !important; +} + +#the-comment-list .comment-item, +#the-comment-list #replyrow { + margin: 0 -10px; +} + +#the-comment-list .comment-item:first-child { + border-top: none; +} + +#the-comment-list .comment-item .avatar { + float: left; + margin: 0 10px 5px 0; +} + +#the-comment-list .comment-item h4 { + line-height: 1.7em; + margin-top: -0.4em; + color: #777; +} + +#the-comment-list .comment-item h4 cite { + font-style: normal; + font-weight: normal; +} + +#the-comment-list .comment-item blockquote, +#the-comment-list .comment-item blockquote p { + margin: 0; + padding: 0; + display: inline; +} + +#dashboard_recent_comments #the-comment-list .trackback blockquote, +#dashboard_recent_comments #the-comment-list .pingback blockquote { + display: block; +} + +#the-comment-list .comment-item p.row-actions { + margin: 3px 0 0; + padding: 0; + font-size: 12px; +} + +/* QuickPress */ +.no-js #dashboard_quick_press { + display: none; +} + +#dashboard_quick_press .easy-blogging { + padding: 0 8px; + text-align: left; +} + +#dashboard_quick_press .input-text-wrap { + position: relative; +} + +#dashboard_quick_press .prompt { + color: #bbb; + position: absolute; +} + +#dashboard_quick_press div.updated { + padding: 0 5px; +} + +#title-wrap label, +#tags-input-wrap label { + cursor: text; +} + +#title-wrap #title { + padding: 2px 6px; + font-size: 1.3em; + line-height: 100%; + outline: none; +} + +#tags-input-wrap #tags-input { + outline: none; +} + +#title-wrap #title-prompt-text { + font-size: 1.3em; + padding: 5px 8px; +} + +#tags-input-wrap #tags-input-prompt-text { + font-size: 1em; + padding: 4px 8px; +} + +#dashboard_quick_press .input-text-wrap, +#dashboard_quick_press .textarea-wrap { + margin: 0 0 1em 0; +} + +#dashboard_quick_press .wp-media-buttons { + margin: 0 0 .2em 1px; + padding: 0; +} + +#dashboard_quick_press .wp-media-buttons a { + color: #777; +} + +#dashboard-widgets #dashboard_quick_press form p.submit input { + float: left; +} + +#dashboard-widgets #dashboard_quick_press form p.submit #save-post { + margin: 0 0.7em 0 1px; +} + +#dashboard-widgets #dashboard_quick_press form p.submit #publish { + float: right; +} + +#dashboard-widgets #dashboard_quick_press form p.submit .spinner { + vertical-align: middle; + margin: 4px 6px 0 0; +} + +/* Recent Drafts */ +#dashboard_recent_drafts ul, +#dashboard_recent_drafts p { + margin: 0; + padding: 0; + word-wrap: break-word; +} + +#dashboard_recent_drafts ul { + list-style: none; +} + +#dashboard_recent_drafts ul li { + margin-bottom: 1em; +} + +#dashboard_recent_drafts h4 { + line-height: 1.7em; + word-wrap: break-word; +} + +#dashboard_recent_drafts h4 abbr { + font-weight: normal; + font-family: sans-serif; + font-size: 12px; + color: #999; + margin-left: 3px; +} + +/* Feeds */ +.rss-widget ul { + margin: 0; + padding: 0; + list-style: none; +} + +a.rsswidget { + font-size: 13px; + line-height: 1.7em; +} + +.rss-widget ul li { + line-height: 1.5em; + margin-bottom: 12px; +} + +.rss-widget span.rss-date { + color: #999; + font-size: 12px; + margin-left: 3px; +} + +.rss-widget cite { + display: block; + text-align: right; + margin: 0 0 1em; + padding: 0; +} + +.rss-widget cite:before { + content: '\2014'; +} + +/* Plugins */ +#dashboard_plugins h4 { + line-height: 1.7em; +} + +#dashboard_plugins h5 { + font-weight: normal; + font-size: 13px; + margin: 0; + display: inline; + line-height: 1.4em; +} + +#dashboard_plugins h5 a { + line-height: 1.4em; +} + +#dashboard_plugins .inside span { + font-size: 12px; + padding-left: 5px; +} + +#dashboard_plugins p { + margin: 0.3em 0 1.4em; + line-height: 1.4em; +} + +.dashboard-comment-wrap { + overflow: hidden; + word-wrap: break-word; +} + +/* Browser Nag */ +#dashboard_browser_nag a.update-browser-link { + font-size: 1.2em; + font-weight: bold; +} + +#dashboard_browser_nag a { + text-decoration: underline; +} + +#dashboard_browser_nag p.browser-update-nag.has-browser-icon { + padding-right: 125px; +} + +#dashboard_browser_nag .browser-icon { + margin-top: -35px; +} + +#dashboard_browser_nag.postbox.browser-insecure { + background-color: #ac1b1b; + border-color: #ac1b1b; +} + +#dashboard_browser_nag.postbox { + background-color: #e29808; + background-image: none; + border-color: #edc048; + color: #fff; + -webkit-box-shadow: none; + box-shadow: none; +} + +#dashboard_browser_nag.postbox.browser-insecure h3 { + border-bottom-color: #cd5a5a; + color: #fff; +} + +#dashboard_browser_nag.postbox h3 { + border-bottom-color: #f6e2ac; + text-shadow: none; + background: transparent none; + color: #fff; + -webkit-box-shadow: none; + box-shadow: none; +} + +#dashboard_browser_nag a { + color: #fff; +} + +#dashboard_browser_nag.browser-insecure a.browse-happy-link, +#dashboard_browser_nag.browser-insecure a.update-browser-link { + text-shadow: #871b15 0 1px 0; +} + +#dashboard_browser_nag a.browse-happy-link, +#dashboard_browser_nag a.update-browser-link { + text-shadow: #d29a04 0 1px 0; +} + + +/* login */ + +.login * { + margin: 0; + padding: 0; +} + +.login form { + margin-left: 8px; + padding: 26px 24px 46px; + font-weight: normal; + background: #fff; + border: 1px solid #e5e5e5; + -webkit-box-shadow: rgba(200, 200, 200, 0.7) 0px 4px 10px -1px; + box-shadow: rgba(200, 200, 200, 0.7) 0px 4px 10px -1px; +} + +.login form .forgetmenot { + font-weight: normal; + float: left; + margin-bottom: 0; +} + +.login .button-primary { + float: right; +} + +#login form p { + margin-bottom: 0; +} + +#login form p.submit { + padding: 0; +} + +.login label { + color: #777; + font-size: 14px; +} + +.login form .forgetmenot label { + font-size: 12px; + line-height: 19px; +} + +.login h1 a { + background-image: url('../images/wordpress-logo.png?ver=20120216'); + background-size: 274px 63px; + background-position: top center; + background-repeat: no-repeat; + width: 326px; + height: 67px; + text-indent: -9999px; + outline: none; + overflow: hidden; + padding-bottom: 15px; + display: block; +} + +#login { + width: 320px; + padding: 114px 0 0; + margin: auto; +} + +#login_error, +.login .message { + margin: 0 0 16px 8px; + padding: 12px; +} + +.login #nav, +.login #backtoblog { + text-shadow: #fff 0 1px 0; + margin: 0 0 0 16px; + padding: 16px 16px 0; +} + +#backtoblog { + padding: 12px 16px 0; +} + +.login form .input, +.login input[type="text"] { + color: #555; + font-weight: 200; + font-size: 24px; + line-height: 1; + width: 100%; + padding: 3px; + margin-top: 2px; + margin-right: 6px; + margin-bottom: 16px; + border: 1px solid #e5e5e5; + background: #fbfbfb; + outline: none; + -webkit-box-shadow: inset 1px 1px 2px rgba(200, 200, 200, 0.2); + box-shadow: inset 1px 1px 2px rgba(200, 200, 200, 0.2); +} + +.login #pass-strength-result { + width: 250px; + font-weight: bold; + border-style: solid; + border-width: 1px; + margin: 12px 0 6px; + padding: 6px 5px; + text-align: center; +} + +.mobile #login { + padding: 20px 0; +} + +.mobile #login form, +.mobile #login .message, +.mobile #login_error { + margin-left: 0; +} + +.mobile #login #nav, +.mobile #login #backtoblog { + margin-left: 8px; +} + +.mobile #login h1 a { + width: auto; +} + +body.interim-login { + height: auto; +} + +.interim-login #login { + padding: 0; + margin: 5px auto 20px; +} + +.interim-login.login h1 a { + width: auto; +} + +.interim-login #login_error, +.interim-login.login .message { + margin: 0 0 16px; +} + +.interim-login.login form { + margin: 0; +} + +/* ms */ +/* Dashboard: MS Specific Data */ +#dashboard_right_now p.musub { + margin-top: 12px; + border-top: 1px solid #ececec; + padding-left: 16px; + position: static; +} + +.rtl #dashboard_right_now p.musub { + padding-left: 0; + padding-right: 16px; +} + +#dashboard_right_now td.b a.musublink { + font-size: 16px; +} + +#dashboard_right_now div.musubtable { + border-top: none; +} + +#dashboard_right_now div.musubtable .t { + white-space: normal; +} + +/* Background Color for Site Status */ +.wp-list-table .site-deleted { + background: #ff8573; +} +.wp-list-table .site-spammed { + background: #faafaa; +} +.wp-list-table .site-archived { + background: #ffebe8; +} +.wp-list-table .site-mature { + background: #fecac2; +} + +/* nav-menu */ + +.no-js #message { + display: block; +} + +#nav-menu-meta ul.outer-border { + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.accordion-section ul.category-tabs, +.accordion-section ul.add-menu-item-tabs, +.accordion-section ul.wp-tab-bar { + margin: 0; +} + +.accordion-section .categorychecklist { + margin: 13px 0; +} + +#nav-menu-meta .accordion-section-content { + padding: 18px 13px; +} + +#nav-menu-meta .button-controls { + margin-bottom: 0; +} + +#nav-menus-frame { + margin-left: 300px; + margin-top: 23px; +} + +#wpbody-content #menu-settings-column { + display:inline; + width:281px; + margin-left: -300px; + clear: both; + float: left; + padding-top: 0; +} + +#menu-settings-column .inside { + clear: both; + margin: 10px 0 0; +} + +.metabox-holder-disabled .postbox, +.metabox-holder-disabled .accordion-section-content { + opacity: 0.5; + filter: alpha(opacity=50); +} + +.metabox-holder-disabled .button-controls .select-all { + display: none; +} + +#wpbody { + position: relative; +} + +.blank-slate .menu-name { + height: 2em; +} + +.blank-slate .menu-settings { + border: none; + margin-top: 0; + padding-top: 0; + overflow: hidden; +} + +.is-submenu { + font-style: italic; + font-weight: normal; + margin-left: 4px; +} + +.manage-menus { + margin-top: 23px; + padding: 10px; + overflow: hidden; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.manage-menus select { + float: left; + margin-right: 6px; +} + +.manage-menus .selected-menu { + float: left; + margin: 5px 6px 0 0; +} + +.manage-menus .submit-btn { + float: left; + margin-top: 1px; +} + +.menu-edit p { + margin: .3em 0 .6em; +} + +.menu-edit #post-body-content h3 { + margin: 0 0 10px; +} + +.menu-settings { + margin-top: 2em; + overflow: hidden; +} + +.menu-settings dl { + margin: 0 0 10px; + overflow: hidden; + position: relative; +} + +.menu-settings dd { + float: left; + margin: 0; + width: 60%; +} + +.menu-edit .checkbox-input { + margin-top: 4px; +} + +.theme-location-set { + font-size: 11px; +} + +/* Menu Container */ +#menu-management-liquid { + float: left; + min-width: 100%; + margin-top: 3px; +} + +#menu-management { + position: relative; + margin-right: 20px; + margin-top: -3px; + width: 100%; +} + +#menu-management .menu-edit { + margin-bottom: 20px; +} + +.nav-menus-php #post-body { + padding: 0 10px 10px; + border-width: 1px 0; + border-style: solid; +} + +#nav-menu-header, +#nav-menu-footer { + padding: 0 10px; +} + +#nav-menu-header { + border-bottom: 1px solid; + margin-bottom: 13px; +} + +#nav-menu-header .menu-name-label { + margin-top: 2px; +} + +#nav-menu-footer { + border-top: 1px solid; +} + +.nav-menus-php #post-body div.updated, +.nav-menus-php #post-body div.error { + margin: 0; +} + +.nav-menus-php #post-body-content { + position: relative; + float: none; +} + +#menu-management .menu-add-new abbr { + font-weight:bold; +} + +#select-nav-menu-container { + text-align: right; + padding: 0 10px 3px 10px; + margin-bottom: 5px; +} + +#select-nav-menu { + width: 100px; + display: inline; +} + +#menu-name-label { + margin-top: -2px; +} + +.widefat td.menu-location-menus { + padding-bottom: 5px; +} + +.menu-location-menus select { + float: left; +} + +#locations-nav-menu-wrapper { + padding: 5px 0; +} + +.locations-nav-menu-select select { + float: left; + width: 160px; + margin-right: 5px; +} + +.locations-row-links { + float: left; + margin: 6px 0 0 6px; +} + +.locations-edit-menu-link, +.locations-add-menu-link { + margin: 0 3px; +} + +.locations-edit-menu-link { + padding-right: 3px; + border-right: 1px solid #ccc; +} + +#wpbody .open-label { + display: block; + float:left; +} + +#wpbody .open-label span { + padding-right: 10px; +} + +.js .input-with-default-title { + font-style: italic; +} + +#menu-management .inside { + padding: 0 10px; +} + +/* Add Menu Item Boxes */ +.postbox .howto input, +.accordion-container .howto input { + width: 180px; + float: right; +} + +.accordion-container .outer-border { + margin: 0; +} + +#nav-menu-meta .accordion-container .top { + border-top: 1px solid #dfdfdf; +} + +#nav-menu-meta .accordion-container .accordion-section:first-child, +#nav-menu-meta .accordion-container .accordion-section:first-child h3, +#nav-menu-meta .accordion-container .top, +#nav-menu-meta .accordion-container .top h3 { + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + +#nav-menu-meta .accordion-container .accordion-section:last-child, +#nav-menu-meta .accordion-container .accordion-section:last-child .accordion-section-content, +#nav-menu-meta .accordion-container .bottom, +#nav-menu-meta .accordion-container .bottom:not(.open) h3 { + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.customlinkdiv .howto input { + width: 180px; +} + +.customlinkdiv p { + margin-top: 0 +} + +#nav-menu-theme-locations .howto select { + width: 100%; +} + +#nav-menu-theme-locations .button-controls { + text-align: right; +} + +.add-menu-item-view-all { + height: 400px; +} + +/* Button Primary Actions */ +#menu-container .submit { + margin: 0 0 10px; + padding: 0; +} + +.nav-menus-php .add-new-menu-action { + float: left; + margin: 6px 0 0 6px; + line-height: 15px; +} + +.nav-menus-php .meta-sep, +.nav-menus-php .submitdelete, +.nav-menus-php .submitcancel { + display: block; + float: left; + margin: 4px 0; + line-height: 15px; +} + +.meta-sep { + padding: 0 2px; +} + +#cancel-save { + text-decoration: underline; + font-size: 12px; + margin-left: 20px; + margin-top: 5px; +} + +.button.right, .button-secondary.right, .button-primary.right { + float: right; +} + +/* Button Secondary Actions */ +.list-controls { + float: left; + margin-top: 5px; +} + +.add-to-menu { + float: right; +} + +.postbox .spinner { + display: none; + vertical-align: middle; +} + +.button-controls { + clear:both; + margin: 10px 0; +} + +.show-all, +.hide-all { + cursor: pointer; +} + +.hide-all { + display: none; +} + +/* Create Menu */ +#menu-name { + width: 270px; +} + +#manage-menu .inside { + padding: 0px 0px; +} + +/* Custom Links */ +#available-links dt { + display: block; +} + +#add-custom-link .howto { + font-size: 12px; +} + +#add-custom-link label span { + display: block; + float: left; + margin-top: 5px; + padding-right: 5px; +} + +.menu-item-textbox { + width: 180px; +} + +.nav-menus-php .howto span { + margin-top: 4px; + display: block; + float: left; +} + +/* Menu item types */ +.quick-search { + width: 190px; +} + +.nav-menus-php .list-wrap { + display: none; + clear: both; + margin-bottom: 10px; +} + +.nav-menus-php .list-container { + max-height: 200px; + overflow-y: auto; + padding: 10px 10px 5px; +} + +.nav-menus-php .postbox p.submit { + margin-bottom: 0; +} + +/* Listings */ +.nav-menus-php .list li { + display: none; + margin: 0; + margin-bottom: 5px; +} + +.nav-menus-php .list li .menu-item-title { + cursor: pointer; + display: block; +} + +.nav-menus-php .list li .menu-item-title input { + margin-right: 3px; + margin-top: -3px; +} + +/* Nav Menu */ +#menu-container .inside { + padding-bottom: 10px; +} + +.menu { + padding-top:1em; +} + +#menu-to-edit { + margin: 0; + padding: 0.1em 0; +} + +.menu ul { + width: 100%; +} + +.menu li { + margin-bottom: 0; + position:relative; +} + +.menu-item-bar { + clear:both; + line-height:1.5em; + position:relative; + margin: 9px 0 0; +} + +.menu-item-handle { + border: 1px solid #dfdfdf; + position: relative; + padding-left: 10px; + height: auto; + width: 400px; + line-height: 35px; + text-shadow: 0 1px 0 #FFFFFF; + overflow: hidden; + word-wrap: break-word; +} + +#menu-to-edit .menu-item-invalid .menu-item-handle { + background: #f6c9cc; + background-image: -webkit-gradient(linear, left bottom, left top, from(#f6c9cc), to(#fdf8ff)); + background-image: -webkit-linear-gradient(bottom, #f6c9cc, #fdf8ff); + background-image: -moz-linear-gradient(bottom, #f6c9cc, #fdf8ff); + background-image: -o-linear-gradient(bottom, #f6c9cc, #fdf8ff); + background-image: linear-gradient(to top, #f6c9cc, #fdf8ff); +} + +.menu-item-edit-active .menu-item-handle { + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.no-js .menu-item-edit-active .item-edit { + display: none; +} + +.js .menu-item-handle { + cursor: move; +} + +.menu li.deleting .menu-item-handle { + background-image: none; + text-shadow: 0 0 0; +} + +.menu-item-handle .item-title { + font-size: 12px; + font-weight: bold; + padding: 7px 0; + line-height: 20px; + min-height: 20px; + display: block; + margin-right: 13em; +} + +/* Sortables */ +li.menu-item.ui-sortable-helper dl { + margin-top: 0; +} + +li.menu-item.ui-sortable-helper .menu-item-transport dl { + margin-top: 13px; +} + +.menu .sortable-placeholder { + height: 35px; + width: 410px; + margin-top: 13px; +} + +/* WARNING: The factor of 30px is hardcoded into the nav-menus javascript. */ +.menu-item-depth-0 { margin-left: 0px; } +.menu-item-depth-1 { margin-left: 30px; } +.menu-item-depth-2 { margin-left: 60px; } +.menu-item-depth-3 { margin-left: 90px; } +.menu-item-depth-4 { margin-left: 120px; } +.menu-item-depth-5 { margin-left: 150px; } +.menu-item-depth-6 { margin-left: 180px; } +.menu-item-depth-7 { margin-left: 210px; } +.menu-item-depth-8 { margin-left: 240px; } +.menu-item-depth-9 { margin-left: 270px; } +.menu-item-depth-10 { margin-left: 300px; } +.menu-item-depth-11 { margin-left: 330px; } + +.menu-item-depth-0 .menu-item-transport { margin-left: 0px; } +.menu-item-depth-1 .menu-item-transport { margin-left: -30px; } +.menu-item-depth-2 .menu-item-transport { margin-left: -60px; } +.menu-item-depth-3 .menu-item-transport { margin-left: -90px; } +.menu-item-depth-4 .menu-item-transport { margin-left: -120px; } +.menu-item-depth-5 .menu-item-transport { margin-left: -150px; } +.menu-item-depth-6 .menu-item-transport { margin-left: -180px; } +.menu-item-depth-7 .menu-item-transport { margin-left: -210px; } +.menu-item-depth-8 .menu-item-transport { margin-left: -240px; } +.menu-item-depth-9 .menu-item-transport { margin-left: -270px; } +.menu-item-depth-10 .menu-item-transport { margin-left: -300px; } +.menu-item-depth-11 .menu-item-transport { margin-left: -330px; } + +body.menu-max-depth-0 { min-width: 950px !important; } +body.menu-max-depth-1 { min-width: 980px !important; } +body.menu-max-depth-2 { min-width: 1010px !important; } +body.menu-max-depth-3 { min-width: 1040px !important; } +body.menu-max-depth-4 { min-width: 1070px !important; } +body.menu-max-depth-5 { min-width: 1100px !important; } +body.menu-max-depth-6 { min-width: 1130px !important; } +body.menu-max-depth-7 { min-width: 1160px !important; } +body.menu-max-depth-8 { min-width: 1190px !important; } +body.menu-max-depth-9 { min-width: 1220px !important; } +body.menu-max-depth-10 { min-width: 1250px !important; } +body.menu-max-depth-11 { min-width: 1280px !important; } + +/* Menu item controls */ +.item-type { + font-size: 12px; + padding-right: 10px; +} + +.item-controls { + font-size: 12px; + position: absolute; + right: 20px; + top: -1px; +} + +.item-controls a { + text-decoration: none; +} + +.item-controls a:hover { + cursor: pointer; +} + +.item-controls .item-order { + padding-right: 10px; +} + +.nav-menus-php .item-edit { + position: absolute; + right: -20px; + top: 0; + display: block; + width: 30px; + height: 36px; + overflow: hidden; + text-indent:-999em; + border-bottom: 1px solid; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +/* Menu editing */ +.menu-instructions-inactive { + display: none; +} + +.menu-item-settings { + display: block; + width: 400px; + padding: 10px 0 10px 10px; + border: solid; + border-width: 0 1px 1px 1px; + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} + +.menu-item-settings .field-move a { + display: none; + margin: 0 2px; +} + +.menu-item-edit-active .menu-item-settings { + display: block; +} + +.menu-item-edit-inactive .menu-item-settings { + display: none; +} + +.add-menu-item-pagelinks { + margin: .5em auto; + text-align: center; +} + +.link-to-original { + display: block; + margin: 0 0 10px; + padding: 3px 5px 5px; + font-size: 12px; + font-style: italic; +} + +.link-to-original a { + padding-left: 4px; + font-style: normal; +} + +.hidden-field { + display: none; +} + +.menu-item-settings .description-thin, +.menu-item-settings .description-wide { + margin-right: 10px; + float: left; +} + +.description-thin { + width: 190px; + height: 40px; +} + +.description-wide { + width: 390px; +} + +.menu-item-actions { + padding-top: 15px; +} + +#cancel-save { + cursor: pointer; +} + +/* Major/minor publishing actions (classes) */ +.nav-menus-php .major-publishing-actions { + clear: both; + padding: 3px 0 5px; +} + +.nav-menus-php .major-publishing-actions .publishing-action { + text-align: right; + float: right; + line-height: 23px; + margin: 2px 0 1px; +} + +.nav-menus-php .blank-slate .menu-settings { + display: none; +} + +.nav-menus-php .delete-action { + float: left; + margin-top: 2px; +} + +.nav-menus-php .submitbox .submitcancel { + border-bottom: 1px solid; + padding: 1px 2px; + text-decoration: none; +} + +.nav-menus-php .major-publishing-actions .form-invalid { + padding-left: 4px; + margin-left: -4px; + border: 0 none; +} + +/* Clearfix */ +#menu-item-name-wrap:after, +#menu-item-url-wrap:after, +#menu-name-label:after, +#menu-settings-column .inside:after, +#nav-menus-frame:after, +.nav-menus-php #post-body-content:after, +.nav-menus-php .button-controls:after, +.nav-menus-php .major-publishing-actions:after, +.nav-menus-php .menu-item-settings:after { + clear: both; + content: "."; + display: block; + height: 0; + visibility: hidden; +} + +#nav-menus-frame, +.button-controls, +#menu-item-url-wrap, +#menu-item-name-wrap { + display: block; +} + +/* Star ratings */ +div.star-holder { + position: relative; + height: 17px; + width: 100px; + background: url('../images/stars.png?ver=20121108') repeat-x bottom left; +} + +div.star-holder .star-rating { + background: url('../images/stars.png?ver=20121108') repeat-x top left; + height: 17px; + float: left; +} + +div.action-links { + font-weight: normal; + margin: 6px 0 0; +} + +/* Header on thickbox */ +#plugin-information-header { + margin: 0; + padding: 0 5px; + font-weight: bold; + position: relative; + border-bottom-width: 1px; + border-bottom-style: solid; + height: 2.5em; +} +#plugin-information ul#sidemenu { + font-weight: normal; + margin: 0 5px; + position: absolute; + left: 0; + bottom: -1px; +} + +/* Install sidemenu */ +#plugin-information p.action-button { + width: 100%; + padding-bottom: 0; + margin-bottom: 0; + margin-top: 10px; + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +#plugin-information .action-button a { + text-align: center; + font-weight: bold; + text-decoration: none; + display: block; + line-height: 2em; +} + +#plugin-information h2 { + clear: none !important; + margin-right: 200px; +} + +#plugin-information .fyi { + margin: 0 10px 50px; + width: 210px; +} + +#plugin-information .fyi h2 { + font-size: 0.9em; + margin-bottom: 0; + margin-right: 0; +} + +#plugin-information .fyi h2.mainheader { + padding: 5px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; +} + +#plugin-information .fyi ul { + padding: 10px 5px 10px 7px; + margin: 0; + list-style: none; + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +#plugin-information .fyi li { + margin-right: 0; +} + +#plugin-information #section-holder { + padding: 10px; +} + +#plugin-information .section ul, +#plugin-information .section ol { + margin-left: 16px; + list-style-type: square; + list-style-image: none; +} + +#plugin-information #section-screenshots ol { + list-style: none; + margin: 0; +} + +#plugin-information #section-screenshots li img { + vertical-align: text-top; + max-width: 100%; + width: auto; + height: auto; +} + +#plugin-information #section-screenshots li p { + font-style: italic; + padding-left: 20px; + padding-bottom: 2em; +} + +#plugin-information #section-screenshots ol, +#plugin-information .updated, +#plugin-information pre { + margin-right: 215px; +} + +#plugin-information pre { + padding: 7px; + overflow: auto; +} + +/* press-this */ +body.press-this { + color: #333; + margin: 0; + padding: 0; + min-width: 675px; + min-height: 400px; +} + +img { + border: none; +} + +/* Header */ +.press-this #wphead { + height: 32px; + margin-left: 0; + margin-right: 0; + margin-bottom: 5px; +} + +.press-this #header-logo { + float: left; + margin: 7px 7px 0; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.press-this #wphead h1 { + font-weight: normal; + font-size: 16px; + line-height: 32px; + margin: 0; + float: left; +} + +.press-this #wphead h1 a { + text-decoration: none; +} + +.press-this #wphead h1 a:hover { + text-decoration: underline; +} + +.press-this #message { + margin: 10px 0; +} + +.press-this-sidebar { + float: right; + width: 200px; + padding-top: 10px; +} + +.press-this #title { + margin-left: 0; + margin-right: 0; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} + +.press-this .tagchecklist span a { + background: transparent url(../images/xit.gif) no-repeat 0 0; +} + +.press-this #titlediv { + margin: 0; +} + +.press-this .wp-media-buttons { + cursor: default; + padding: 8px 8px 0; +} + +.press-this .howto { + margin-top: 2px; + margin-bottom: 3px; + font-size: 12px; + font-style: italic; + display: block; +} + +/* Editor/Main Column */ +.press-this #poststuff { + margin: 0 10px 10px; + padding: 0; +} + +.press-this #photo-add-url-div input[type="text"] { + width: 220px; +} + +#poststuff #editor-toolbar { + height: 30px; +} + +div.zerosize { + border: 0 none; + height: 0; + margin: 0; + overflow: hidden; + padding: 0; + width: 0; +} + +.posting { + margin-right: 212px; + position: relative; +} + +.press-this .inner-sidebar { + width: 200px; +} + +.press-this .inner-sidebar .sleeve { + padding-top: 5px; +} + +.press-this #submitdiv p { + margin: 0; + padding: 6px; +} + +.press-this #submitdiv #publishing-actions { + border-bottom: 1px solid #dfdfdf; +} + +.press-this #publish { + float: right; +} + +.press-this #poststuff h2, +.press-this #poststuff h3 { + font-size: 14px; + line-height: 1; +} + +.press-this #tagsdiv-post_tag h3, +.press-this #categorydiv h3 { + cursor: pointer; +} + +.press-this #submitdiv h3 { + cursor: default; +} + +h3.tb { + text-shadow: 0 1px 0 #fff; + font-weight: bold; + font-size: 12px; + margin-left: 5px; +} + +#TB_window { + border: 1px solid #333; +} + +.press-this .postbox, +.press-this .stuffbox { + margin-bottom: 10px; + min-width: 0; +} + +.js .postbox:hover .handlediv, +.js .stuffbox:hover .handlediv { + background: transparent url(../images/arrows.png) no-repeat 6px 7px; +} + +.press-this #submitdiv:hover .handlediv { + background: none; +} + +.tbtitle { + font-size: 1.7em; + outline: none; + padding: 3px 4px; + border-color: #dfdfdf; +} + +.press-this .actions { + float: right; + margin: -19px 0 0; +} + +.press-this #extra-fields .actions { + margin: -32px -7px 0 0; +} + +.press-this .actions li { + float: left; + list-style: none; + margin-right: 10px; +} + +#extra-fields .button { + margin-right: 5px; +} + +/* Photo Styles */ +#photo_saving { + margin: 0 8px 8px; + vertical-align: middle; +} + +#img_container_container { + overflow: auto; +} + +#extra-fields { + margin-top: 10px; + position: relative; +} + +#extra-fields h2 { + margin: 12px; +} + +#waiting { + margin-top: 10px; + overflow: hidden; +} + +#waiting span { + float: right; + margin: 0 0 0 5px; +} + +#waiting .spinner { + display: block; +} + +#extra-fields .postbox { + margin-bottom: 5px; +} + +#extra-fields .titlewrap { + padding: 0; + overflow: auto; + height: 100px; +} + +#img_container a { + display: block; + float: left; + overflow: hidden; +} + +#img_container img, +#img_container a { + width: 68px; + height: 68px; +} + +#img_container img { + border: none; + background-color: #f4f4f4; + cursor: pointer; +} + +#img_container a, +#img_container a:link, +#img_container a:visited { + border: 1px solid #ccc; + display: block; + position: relative; +} + +#img_container a:hover, +#img_container a:active { + border-color: #000; + z-index: 1000; + border-width: 2px; + margin: -1px; +} + +/* Video */ +#embed-code { + width: 100%; + height: 98px; +} + +/* Categories */ +.press-this .categorydiv div.tabs-panel { + height: 100px; +} + +/* Tags */ +.press-this .tagsdiv .newtag { + width: 120px; +} + +.press-this #content { + margin: 5px 0; + padding: 0 5px; + border: 0 none; + height: 345px; + font-family: Consolas, Monaco, monospace; + font-size: 13px; + line-height: 19px; + background: transparent; +} + +/* Submit */ +.press-this #publishing-actions .spinner { + display: inline; + vertical-align: middle; +} + +#TB_ajaxContent #options { + position: absolute; + top: 20px; + right: 25px; + padding: 5px; +} + +#TB_ajaxContent h3 { + margin-bottom: .25em; +} + +.error a { + text-decoration: underline; +} + +.updated a { + text-decoration: none; + padding-bottom: 2px; +} + +/* tag hints */ +.taghint { + color: #aaa; + margin: -17px 0 0 7px; + visibility: hidden; +} + +input.newtag ~ div.taghint { + visibility: visible; +} + +input.newtag:focus ~ div.taghint { + visibility: hidden; +} + +#photo-add-url-div input[type="text"] { + width: 300px; +} + +/* theme-editor */ +.alignleft h3 { + margin: 0; +} + +h3 span { + font-weight: normal; +} + +#template textarea { + font-family: Consolas, Monaco, monospace; + font-size: 12px; + width: 97%; + background: #f9f9f9; + outline: none; +} + +#template p { + width: 97%; +} + +#templateside { + float: right; + width: 190px; + word-wrap: break-word; +} + +#templateside h3, +#postcustomstuff p.submit { + margin: 0; +} + +#templateside h4 { + margin: 1em 0 0; +} + +#templateside ol, +#templateside ul { + margin: .5em; + padding: 0; +} + +#templateside li { + margin: 4px 0; +} + +#templateside ul li a span.highlight { + display:block; +} + +.nonessential { + font-size: 11px; + font-style: italic; + padding-left: 12px; +} + +.highlight { + padding: 3px 3px 3px 12px; + margin-left: -12px; + font-weight: bold; + border: 0 none; +} + +#documentation { + margin-top: 10px; +} +#documentation label { + line-height: 22px; + vertical-align: top; + font-weight: bold; +} + +.fileedit-sub { + padding: 10px 0 8px; + line-height: 180%; +} + +#filter-box { + clear: both; +} + +.feature-filter { + padding: 8px 12px 0; +} + +.feature-filter .feature-group { + float: left; + margin: 5px 10px 10px; +} + +.feature-filter .feature-group li { + display: inline-block; + vertical-align: top; + list-style-type: none; + padding-right: 25px; + width: 150px; +} + +.feature-container { + width: 100%; + overflow: auto; + margin-bottom: 10px; +} + +/* widgets */ + +/* 2 column liquid layout */ +div.widget-liquid-left { + float: left; + clear: left; + width: 100%; + margin-right: -325px; +} + +div#widgets-left { + margin-left: 5px; + margin-right: 325px; +} + +div#widgets-right { + width: 285px; + margin: 0 auto; +} + +div.widget-liquid-right { + float: right; + clear: right; + width: 300px; +} + +.widget-liquid-right .widget, +.inactive-sidebar .widget, +.widget-liquid-right .sidebar-description { + width: 250px; + margin: 0 auto 20px; + overflow: hidden; +} + +.widget-liquid-right .sidebar-description { + margin-bottom: 10px; +} + +.inactive-sidebar .widget { + margin: 0 10px 20px; + display: inline-block; +} + +div.sidebar-name h3 { + font-weight: normal; + font-size: 15px; + margin: 0; + padding: 8px 10px; + overflow: hidden; + white-space: nowrap; +} + +div.sidebar-name { + font-size: 13px; + border-width: 1px; + border-style: solid; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + +.js .sidebar-name { + cursor: pointer; +} + +.js .closed .sidebar-name { + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.widget-liquid-right .widgets-sortables, +#widgets-left .widget-holder { + border-width: 0 1px 1px; + border-style: none solid solid; + -webkit-border-bottom-right-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.js .closed .widgets-sortables, +.js .closed .widget-holder { + display: none; +} + +.widget-liquid-right .widgets-sortables { + padding: 15px 0 0; +} + +#available-widgets .widget-holder { + padding: 7px 5px 0; +} + +#available-widgets .widget { + -webkit-box-shadow: none; + box-shadow: none; +} + +.inactive-sidebar { + padding: 5px 5px 0; +} + +#widget-list .widget { + width: 250px; + margin: 0 10px 15px; + border: 0 none; + background: transparent; + display: inline-block; + vertical-align: top; +} + +#widget-list .widget-description { + padding: 5px 8px; +} + +.widget-placeholder { + border-width: 1px; + border-style: dashed; + margin: 0 auto 20px; + height: 27px; + width: 250px; +} + +.inactive-sidebar .widget-placeholder { + margin: 0 10px 20px; + float: left; +} + +div.widgets-holder-wrap { + padding: 0; + margin: 10px 0 20px; +} + +#widgets-left #available-widgets { + background-color: transparent; + border: 0 none; +} + +ul#widget-list { + list-style: none; + margin: 0; + padding: 0; + min-height: 100px; +} + +.widget .widget-top { + margin-bottom: -1px; + font-size: 12px; + font-weight: bold; + height: 26px; + overflow: hidden; +} + +.widget-top .widget-title { + padding: 7px 9px; +} + +.widget-top .widget-title-action { + float: right; +} + +a.widget-action { + display: block; + width: 24px; + height: 26px; +} + +#available-widgets a.widget-action { + display: none; +} + +.widget-top a.widget-action { + background: transparent url(../images/arrows.png) no-repeat 4px 6px; +} + +.widget-top a.widget-action:hover { + background: transparent url(../images/arrows-dark.png) no-repeat 4px 6px; +} + +.widget .widget-inside, +.widget .widget-description { + padding: 12px 12px 10px; + font-size: 12px; + line-height: 16px; +} + +.widget-inside, +.widget-description { + display: none; +} + +#available-widgets .widget-description { + display: block; +} + +.widget .widget-inside p { + margin: 0 0 1em; + padding: 0; +} + +.widget-title h4 { + margin: 0; + padding-bottom: 0.2em; + line-height: 1; + overflow: hidden; + white-space: nowrap; +} + +.widgets-sortables { + min-height: 90px; +} + +.widget-control-actions { + margin-top: 8px; +} + +.widget-control-actions a { + text-decoration: none; +} + +.widget-control-actions a:hover { + text-decoration: underline; +} + +.widget-control-actions div.alignleft { + margin-top: 6px; +} + +div#sidebar-info { + padding: 0 1em; + margin-bottom: 1em; + font-size: 12px; +} + +.widget-title a, +.widget-title a:hover { + text-decoration: none; + border-bottom: none; +} + +.widget-control-edit { + display: block; + font-size: 12px; + font-weight: normal; + line-height: 26px; + padding: 0 8px 0 0; +} + +a.widget-control-edit { + text-decoration: none; +} + +.widget-control-edit .add, +.widget-control-edit .edit { + display: none; +} + +#available-widgets .widget-control-edit .add, +#widgets-right .widget-control-edit .edit, +.inactive-sidebar .widget-control-edit .edit { + display: inline; +} + +.editwidget { + margin: 0 auto 15px; +} + +.editwidget .widget-inside { + display: block; + padding: 10px; +} + +.inactive p.description { + margin: 5px 15px 10px; +} + +#available-widgets p.description { + margin: 0 12px 12px; +} + +.widget-position { + margin-top: 8px; +} + +.inactive { + padding-top: 2px; +} + +.sidebar-name .spinner { + float: none; + margin: 0 3px -3px; +} + +.sidebar-name-arrow { + float: right; + height: 29px; + width: 26px; +} + +.widget-title .in-widget-title { + font-size: 12px; + white-space: nowrap; +} + +#removing-widget { + display: none; + font-weight: normal; + padding-left: 15px; + font-size: 12px; + line-height: 1; +} + +.widget-control-noform, +#access-off, +.widgets_access .widget-action, +.widgets_access .sidebar-name-arrow, +.widgets_access #access-on, +.widgets_access .widget-holder .description { + display: none; +} + +.widgets_access .widget-holder, +.widgets_access #widget-list { + padding-top: 10px; +} + +.widgets_access #access-off { + display: inline; +} + +.widgets_access #wpbody-content .widget-title-action, +.widgets_access #wpbody-content .widget-control-edit, +.widgets_access .closed .widgets-sortables, +.widgets_access .closed .widget-holder { + display: block; +} + +.widgets_access .closed .sidebar-name { + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.widgets_access .sidebar-name, +.widgets_access .widget .widget-top { + cursor: default; +} + +/* Enable draggable on IE10 touch events until it's rolled into jQuery UI core */ +.ui-sortable, +.ui-draggable { + -ms-touch-action: none; +} + +/* Accordion */ + +.accordion-section { + border-top: 1px solid #fff; + border-bottom: 1px solid #dfdfdf; + margin: 0; +} + +.accordion-section:first-child { + border-top: 1px solid #dfdfdf; +} + +.accordion-section:last-child { + box-shadow: 0 1px 0 0px #fff; +} + +.accordion-section.open .accordion-section-content, +.no-js .accordion-section .accordion-section-content { + display: block; +} + +.accordion-section.open:hover { + border-bottom-color: #dfdfdf; +} + +.accordion-section-content { + display: none; + padding: 10px 20px 15px; + overflow: hidden; + background: #fdfdfd; + border-left: 1px solid #dfdfdf; + border-right: 1px solid #dfdfdf; +} + +.accordion-section-title { + margin: 0; + padding: 15px 20px; + position: relative; + border-left: 1px solid #dfdfdf; + border-right: 1px solid #dfdfdf; + + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.js .accordion-section-title { + cursor: pointer; +} + +.js .accordion-section-title:after { + content: ''; + width: 0; + height: 0; + border-color: #ccc transparent; + border-style: solid; + border-width: 6px 6px 0; + position: absolute; + top: 25px; + right: 20px; + z-index: 1; +} + +.accordion-section-title:focus { + outline: none; +} + +.accordion-section-title:hover:after, +.accordion-section-title:focus:after { + border-color: #aaa transparent; +} + +.cannot-expand .accordion-section-title { + cursor: auto; +} + +.cannot-expand .accordion-section-title:after { + display: none; +} + +.control-section .accordion-section-title { + padding: 10px 20px; + color: #464646; + font-size: 15px; + font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; + font-weight: normal; + text-shadow: 0 1px 0 #fff; + background: #f5f5f5; + background-image: -webkit-gradient(linear, left bottom, left top, from(#eee), to(#f5f5f5)); + background-image: -webkit-linear-gradient(bottom, #eee, #f5f5f5); + background-image: -moz-linear-gradient(bottom, #eee, #f5f5f5); + background-image: -o-linear-gradient(bottom, #eee, #f5f5f5); + background-image: linear-gradient(to top, #eee, #f5f5f5); +} + +.control-section .accordion-section-title:after { + top: 15px; +} + +.js .control-section:hover .accordion-section-title, +.js .control-section .accordion-section-title:hover, +.js .control-section.open .accordion-section-title, +.js .control-section .accordion-section-title:focus { + color: #000; + background: #f9f9f9; + background-image: -webkit-gradient(linear, left bottom, left top, from(#ececec), to(#f9f9f9)); + background-image: -webkit-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: -moz-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: -o-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: linear-gradient(to top, #ececec, #f9f9f9); +} + +.control-section.open .accordion-section-title { + border-bottom: 1px solid #dfdfdf; +} + +/* =Media Queries +-------------------------------------------------------------- */ + +@media only screen and (max-width: 768px) { + /* categories */ + #col-left { + width: 100%; + } + + #col-right { + width: 100%; + } +} + +@media only screen and (min-width: 769px) { + /* categories */ + #col-left { + width: 35%; + } + + #col-right { + width: 65%; + } +} + +@media only screen and (max-width: 860px) { + + /* categories */ + #col-left { + width: 35%; + } + + #col-right { + width: 65%; + } +} + +@media only screen and (min-width: 980px) { + + /* categories */ + #col-left { + width: 35%; + } + + #col-right { + width: 65%; + } +} + +@media only screen and (max-width: 768px) { + /* categories */ + #col-left { + width: 100%; + } + + #col-right { + width: 100%; + } + + .form-field input, + .form-field textarea { + width: 99%; + } + + .form-wrap .form-field { + padding:0; + } + + /* users */ + #profile-page .form-table textarea { + max-width: 400px; + width: auto; + } +} + +/** + * HiDPI Displays + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + + .press-this .tagchecklist span a { + background-image: url('../images/xit-2x.gif'); + background-size: 20px auto; + } + + .js .postbox:hover .handlediv, + .js .stuffbox:hover .handlediv, + .widget-top a.widget-action { + background-image: url('../images/arrows-2x.png'); + background-size: 15px 123px; + } + + .widget-top a.widget-action:hover { + background-image: url('../images/arrows-dark-2x.png'); + background-size: 15px 123px; + } + + .post-com-count { + background-image: url('../images/bubble_bg-2x.gif'); + background-size: 18px 100px; + } + + tr.wp-locked .locked-indicator { + background-image: url('../images/lock-2x.png'); + background-size: 16px 16px; + } + + th .comment-grey-bubble { + background-image: url('../images/comment-grey-bubble-2x.png'); + background-size: 12px 12px; + } + + .sorting-indicator { + background-image: url('../images/sort-2x.gif?ver=20130102'); + background-size: 14px 4px; + } + + #content-resize-handle, + #post-body .wp_themeSkin .mceStatusbar a.mceResize { + background: transparent url('../images/resize-2x.gif') no-repeat scroll right bottom; + background-size: 11px 11px; + } + + div.star-holder { + background: url('../images/stars-2x.png?ver=20121108') repeat-x bottom left; + background-size: 21px 37px; + } + + div.star-holder .star-rating { + background: url('../images/stars-2x.png?ver=20121108') repeat-x top left; + background-size: 21px 37px; + } + + .welcome-panel .welcome-panel-close:before { + background-image: url('../images/xit-2x.gif'); + background-size: 20px auto; + } + + .welcome-panel .welcome-icon { + background-image: url('../images/welcome-icons-2x.png'); + } + + .login h1 a { + background-image: url('../images/wordpress-logo-2x.png?ver=20120412'); + background-size: 274px 63px; + } + + .wp-badge { + background-image: url('../images/wp-badge-2x.png?ver=20120516'); + background-size: 173px 194px; + } + + .wp-full-overlay .collapse-sidebar-arrow { + background-image: url('../images/arrows-2x.png'); + background-size: 15px 123px; + } + + .pressthis a span { + background-image: url(../images/press-this-2x.png?v=20121105); + } + + .imgedit-crop, + .imgedit-rleft, + .imgedit-rright, + .imgedit-flipv, + .imgedit-fliph, + .imgedit-undo, + .imgedit-redo { + background-image: url('../images/imgedit-icons-2x.png'); + background-size: 260px 64px; + } + + .spinner, + .imgedit-wait, + .customize-loading #customize-container { + background-image: url(../images/wpspin_light-2x.gif); + } + + .wp-slider .ui-slider-handle:before { + background-image: url(../images/arrows-pr-2x.png); + background-size: 16px 102px; + } + +} + +/* =Localized CSS +-------------------------------------------------------------- */ + +/* zh_CN: Remove italic properties. */ +.locale-zh-cn .howto, +.locale-zh-cn .tablenav .displaying-num, +.locale-zh-cn .js .input-with-default-title, +.locale-zh-cn .link-to-original, +.locale-zh-cn .inline-edit-row fieldset span.title, +.locale-zh-cn .inline-edit-row fieldset span.checkbox-title, +.locale-zh-cn #utc-time, +.locale-zh-cn #local-time, +.locale-zh-cn p.install-help, +.locale-zh-cn p.help, +.locale-zh-cn p.description, +.locale-zh-cn span.description, +.locale-zh-cn .form-wrap p { + font-style: normal; +} + +/* zh_CN: Enlarge dashboard widget 'Configure' link */ +.locale-zh-cn .hdnle a { font-size: 12px; } + +/* zn_CH: Enlarge font size, set font-size: normal */ +.locale-zh-cn form.upgrade .hint { font-style: normal; font-size: 100%; } + +/* Zn_CH: Distraction free writing. + * More beautiful font for "Just write." + * Larger text for HTML/Visual mode. + */ +.locale-zh-cn #wp-fullscreen-tagline { font-family: KaiTi, "楷体", sans-serif; } +.locale-zh-cn #wp-fullscreen-modes a { font-size: 12px; } + +/* zh_CN: Enlarge font-size. */ +.locale-zh-cn #sort-buttons { font-size: 1em !important; } + +/* ru_RU: Text needs more room to breathe. */ +.locale-ru-ru .inline-edit-row fieldset label span.title { + width: auto; /* default 5em */ + min-width: 5em; +} +.locale-ru-ru.press-this .posting { + margin-right: 257px; /* default 212px + 45px */ +} +.locale-ru-ru.press-this #photo-add-url-div input[type="text"] { + width: 255px; /* default 300px - 45px */ +} +.locale-ru-ru.press-this #side-sortables { + width: 245px; /* default 200px + 45px */ +} +.locale-ru-ru #customize-header-actions .button { + padding: 0 8px 1px; /* default 0 10px 1px; */ +} + +/* lt_LT: QuickEdit */ +.locale-lt-lt .inline-edit-row fieldset label span.title { + width: 8em; +} +.locale-lt-lt .inline-edit-row fieldset label span.input-text-wrap { + margin-left: 8em; +} diff --git a/sources/wp-admin/css/wp-admin.min.css b/sources/wp-admin/css/wp-admin.min.css new file mode 100644 index 0000000..40ffd2e --- /dev/null +++ b/sources/wp-admin/css/wp-admin.min.css @@ -0,0 +1 @@ +#wpwrap{height:auto;min-height:100%;width:100%;position:relative}#wpcontent{height:100%}#wpcontent,#wpfooter{margin-left:165px}.folded #wpcontent,.folded #wpfooter{margin-left:52px}#wpbody-content{padding-bottom:65px;float:left;width:100%}#adminmenuback,#adminmenuwrap,#adminmenu,#adminmenu .wp-submenu{width:145px}#adminmenuback{position:absolute;top:0;bottom:0;z-index:-1}#adminmenu{clear:left;margin:0;padding:0;list-style:none}.folded #adminmenuback,.folded #adminmenuwrap,.folded #adminmenu,.folded #adminmenu li.menu-top{width:32px}.inner-sidebar{float:right;clear:right;display:none;width:281px;position:relative}.columns-2 .inner-sidebar{margin-right:auto;width:286px;display:block}.inner-sidebar #side-sortables,.columns-2 .inner-sidebar #side-sortables{min-height:300px;width:280px;padding:0}.has-right-sidebar .inner-sidebar{display:block}.has-right-sidebar #post-body{float:left;clear:left;width:100%;margin-right:-2000px}.has-right-sidebar #post-body-content{margin-right:300px;float:none;width:auto}#col-container,#col-left,#col-right{overflow:hidden;padding:0;margin:0}#col-left{width:35%}#col-right{float:right;clear:right;width:65%}.col-wrap{padding:0 7px}.alignleft{float:left}.alignright{float:right}.textleft{text-align:left}.textright{text-align:right}.clear{clear:both}.screen-reader-text,.screen-reader-text span,.ui-helper-hidden-accessible{position:absolute;left:-1000em;top:-1000em;height:1px;width:1px;overflow:hidden}.screen-reader-shortcut{position:absolute;top:-1000em}.screen-reader-shortcut:focus{left:6px;top:-21px;height:auto;width:auto;display:block;font-size:14px;font-weight:700;padding:15px 23px 14px;background:#f1f1f1;color:#21759b;border-radius:3px;z-index:100000;line-height:normal;-webkit-box-shadow:0 0 2px 2px rgba(0,0,0,.6);box-shadow:0 0 2px 2px rgba(0,0,0,.6);text-decoration:none}.hidden,.js .closed .inside,.js .hide-if-js,.no-js .hide-if-no-js,.js.wp-core-ui .hide-if-js,.js .wp-core-ui .hide-if-js,.no-js.wp-core-ui .hide-if-no-js,.no-js .wp-core-ui .hide-if-no-js{display:none}input[type=text],input[type=password],input[type=number],input[type=search],input[type=email],input[type=url],textarea{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{vertical-align:text-top;padding:0;margin:1px 0 0}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-decoration{display:none}html,body{height:100%;margin:0;padding:0}body{font-family:sans-serif;font-size:12px;line-height:1.4em;min-width:600px}body.iframe{min-width:0;padding-top:1px}body.login{background:#fbfbfb;min-width:0}iframe,img{border:0}td,textarea,input,select,button{font-family:inherit;font-size:inherit;font-weight:inherit}td,textarea{line-height:inherit}input,select{line-height:15px}a,input[type=text],input[type=password],input[type=number],input[type=search],input[type=email],input[type=url],select,textarea,div{outline:0}a:focus,a:active{outline:thin dotted}#adminmenu a:focus,#adminmenu a:active,.screen-reader-text:focus{outline:0}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}p{margin:1em 0}blockquote{margin:1em}label{cursor:pointer}li,dd{margin-bottom:6px}textarea,input,select{margin:1px;padding:3px}h1,h2,h3,h4,h5,h6{display:block;font-weight:700}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}ul,ol{padding:0}ul{list-style:none}ol{list-style-type:decimal;margin-left:2em}ul.ul-disc{list-style:disc outside}ul.ul-square{list-style:square outside}ol.ol-decimal{list-style:decimal outside}ul.ul-disc,ul.ul-square,ol.ol-decimal{margin-left:1.8em}ul.ul-disc>li,ul.ul-square>li,ol.ol-decimal>li{margin:0 0 .5em}.code,code{font-family:Consolas,Monaco,monospace}kbd,code{padding:1px 3px;margin:0 1px;font-size:11px}.subsubsub{list-style:none;margin:8px 0 5px;padding:0;font-size:12px;float:left}.subsubsub a{line-height:2;padding:.2em;text-decoration:none}.subsubsub a .count,.subsubsub a.current .count{color:#999;font-weight:400}.subsubsub a.current{font-weight:700;border:0}.subsubsub li{display:inline-block;margin:0;padding:0;white-space:nowrap}.widefat,div.updated,div.error,.wrap .add-new-h2,textarea,input[type=text],input[type=password],input[type=file],input[type=email],input[type=number],input[type=search],input[type=tel],input[type=url],select,.tablenav .tablenav-pages a,.tablenav-pages span.current,#titlediv #title,.postbox,#postcustomstuff table,#postcustomstuff input,#postcustomstuff textarea,.imgedit-menu div,.plugin-update-tr .update-message,#poststuff .inside .the-tagcloud,.login form,#login_error,.login .message,#menu-management .menu-edit,.nav-menus-php .list-container,.menu-item-handle,.link-to-original,.nav-menus-php .major-publishing-actions .form-invalid,.press-this #message,#TB_window,.tbtitle,.highlight,.feature-filter,#widget-list .widget-top,.editwidget .widget-inside{-webkit-border-radius:3px;border-radius:3px;border-width:1px;border-style:solid}.widefat{border-spacing:0;width:100%;clear:both;margin:0}.widefat *{word-wrap:break-word}.widefat a{text-decoration:none}.widefat thead th:first-of-type{-webkit-border-top-left-radius:3px;border-top-left-radius:3px}.widefat thead th:last-of-type{-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.widefat tfoot th:first-of-type{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px}.widefat tfoot th:last-of-type{-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.widefat td,.widefat th{border-width:1px 0;border-style:solid}.widefat tfoot th{border-bottom:0}.widefat .no-items td{border-bottom-width:0}.widefat td{font-size:12px;padding:4px 7px 2px;vertical-align:top}.widefat td p,.widefat td ol,.widefat td ul{font-size:12px}.widefat th{padding:7px 7px 8px;text-align:left;line-height:1.3em;font-size:14px}.widefat th input{margin:0 0 0 8px;padding:0;vertical-align:text-top}.widefat .check-column{width:2.2em;padding:6px 0 25px;vertical-align:top}.widefat tbody th.check-column{padding:9px 0 22px}.widefat.media .check-column{padding-top:8px}.widefat thead .check-column,.widefat tfoot .check-column{padding:10px 0 0}.no-js .widefat thead .check-column input,.no-js .widefat tfoot .check-column input{display:none}.widefat .num,.column-comments,.column-links,.column-posts{text-align:center}.widefat th#comments{vertical-align:middle}.wrap{margin:4px 15px 0 0}div.updated,div.error{padding:0 .6em;margin:5px 15px 2px}div.updated p,div.error p{margin:.5em 0;padding:2px}.wrap div.updated,.wrap div.error,.media-upload-form div.error{margin:5px 0 15px}.wrap h2,.subtitle{font-weight:400;margin:0;text-shadow:#fff 0 1px 0}.wrap h2{font-size:23px;padding:9px 15px 4px 0;line-height:29px}.subtitle{font-size:14px;padding-left:25px}.wrap .add-new-h2{font-family:sans-serif;margin-left:4px;padding:3px 8px;position:relative;top:-3px;text-decoration:none;font-size:12px;border:0 none}.wrap h2.long-header{padding-right:0}html,.wp-dialog{background-color:#fff}textarea,input[type=text],input[type=password],input[type=file],input[type=email],input[type=number],input[type=search],input[type=tel],input[type=url],select{background-color:#fff;color:#333}select{color:#000}select[disabled]{color:#7f7f7f}select:focus{border-color:#aaa}textarea:focus,input[type=text]:focus,input[type=password]:focus,input[type=file]:focus,input[type=email]:focus,input[type=number]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=url]:focus,select:focus{-webkit-box-shadow:1px 1px 2px rgba(0,0,0,.1);box-shadow:1px 1px 2px rgba(0,0,0,.1)}input[readonly]{background-color:#eee}:-moz-placeholder,.wp-core-ui :-moz-placeholder{color:#a9a9a9}div.sidebar-name h3,#menu-management .nav-tab,#dashboard_plugins h5,a.rsswidget,#dashboard_right_now td.b,#dashboard-widgets h4,.tool-box .title,#poststuff h3,.metabox-holder h3,.pressthis a,#your-profile legend,.inline-edit-row fieldset span.title,.inline-edit-row fieldset span.checkbox-title,.tablenav .displaying-num,.widefat th,.quicktags,.search{font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif}h2 .nav-tab,.wrap h2,.subtitle,.login form .input{font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",sans-serif}.quicktags,.search{font-size:12px}.icon32{float:left;height:34px;margin:7px 8px 0 0;width:36px}.icon16{height:18px;width:18px;padding:6px;margin:-6px 0 0 -8px;float:left}.key-labels label{line-height:24px}.pre{white-space:pre-wrap;word-wrap:break-word}.howto{font-style:italic;display:block;font-family:sans-serif}p.install-help{margin:8px 0;font-style:italic}.no-break{white-space:nowrap}.wp-admin select{padding:2px;height:2em}.wp-admin select[multiple]{height:auto}.submit{padding:1.5em 0;margin:5px 0;-webkit-border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-left-radius:3px;border-bottom-right-radius:3px}form p.submit a.cancel:hover{text-decoration:none}#minor-publishing-actions input,#major-publishing-actions input,#minor-publishing-actions .preview{text-align:center}textarea.all-options,input.all-options{width:250px}input.large-text,textarea.large-text{width:99%}input.regular-text,#adduser .form-field input{width:25em}input.small-text{width:50px}input[type=number].small-text{width:60px}#doaction,#doaction2,#post-query-submit{margin:1px 8px 0 0}.tablenav #changeit,.tablenav #delete_all,.tablenav #clear-recent-list{margin-top:1px}.tablenav .actions select{float:left;margin-right:6px;max-width:200px}.ie8 .tablenav .actions select{width:155px}.ie8 .tablenav .actions select#cat{width:200px}#timezone_string option{margin-left:1em}label,#your-profile label+a{vertical-align:middle}#misc-publishing-actions label{vertical-align:baseline}#pass-strength-result{border-style:solid;border-width:1px;float:left;margin:13px 5px 5px 1px;padding:3px 5px;text-align:center;width:200px;display:none}.indicator-hint{padding-top:8px}p.search-box{float:right;margin:0}.search-box input[name="s"],#search-plugins input[name="s"],.tagsdiv .newtag{float:left;height:2em;margin:0 4px 0 0}input[type=text].ui-autocomplete-loading{background:transparent url(../images/loading.gif) no-repeat right center;visibility:visible}ul#add-to-blog-users{margin:0 0 0 14px}.ui-autocomplete-input.open{border-bottom-right-radius:0;border-bottom-left-radius:0}.ui-autocomplete{padding:0;margin:0;list-style:none;position:absolute;z-index:10000;border-bottom-right-radius:3px;border-bottom-left-radius:3px;border-width:1px;border-style:solid}.ui-autocomplete li{margin-bottom:0;white-space:nowrap;text-align:left}.ui-autocomplete li a{display:block;height:100%;padding:4px 10px}.ui-autocomplete li a.ui-state-focus{cursor:pointer}#major-publishing-actions{padding:10px 10px 8px;clear:both;border-top:1px solid #f5f5f5;margin-top:-2px}#delete-action{line-height:25px;vertical-align:middle;text-align:left;float:left}#publishing-action{text-align:right;float:right;line-height:23px}#publishing-action .spinner{float:left}#misc-publishing-actions{padding:6px 0 0}.misc-pub-section{padding:6px 10px 8px;border-width:1px 0;border-style:solid}.misc-pub-section:first-child{border-top-width:0}.misc-pub-section-last{border-bottom-width:0}#minor-publishing-actions{padding:10px 10px 2px 8px;text-align:right}#minor-publishing{border-bottom-width:1px;border-bottom-style:solid;-webkit-box-shadow:0 1px 0 #fff;box-shadow:0 1px 0 #fff}#save-post{float:left}.preview{float:right}#sticky-span{margin-left:18px}.side-info{margin:0;padding:4px;font-size:11px}.side-info h5{padding-bottom:7px;font-size:14px;margin:12px 2px 5px;border-bottom-width:1px;border-bottom-style:solid}.side-info ul{margin:0;padding-left:18px;list-style:square}.approve,.unapproved .unapprove{display:none}.unapproved .approve,.spam .approve,.trash .approve{display:inline}td.action-links,th.action-links{text-align:right}#update-nag,.update-nag{line-height:19px;padding:5px 0;font-size:12px;text-align:center;margin:-1px 15px 0 5px;border-width:1px;border-style:solid;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.plugins .plugin-update{padding:0}.plugin-update .update-message{margin:0 10px 8px 31px;font-weight:700}ul#dismissed-updates{display:none}form.upgrade{margin-top:8px}form.upgrade .hint{font-style:italic;font-size:85%;margin:-.5em 0 2em 0}.update-php .spinner{float:none;margin:-4px 0}#ajax-loading,.ajax-loading,.ajax-feedback,.imgedit-wait-spin,.list-ajax-loading{visibility:hidden}#ajax-response.alignleft{margin-left:2em}#adminmenu a,#sidemenu a,#taglist a,#catlist a{text-decoration:none}#screen-options-wrap,#contextual-help-wrap{margin:0;padding:8px 20px 12px;position:relative}#contextual-help-wrap{overflow:auto}#screen-meta .screen-reader-text{visibility:hidden}#screen-meta-links{margin:0 24px 0 0}#screen-meta-links a:focus{-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.4);box-shadow:1px 1px 1px rgba(0,0,0,.4);outline:0}#screen-meta{display:none;position:relative;margin:0 15px 0 5px;border-width:0 1px 1px;border-style:none solid solid}#screen-options-link-wrap,#contextual-help-link-wrap{float:right;height:23px;padding:0;margin:0 0 0 6px;font-family:sans-serif}#screen-options-link-wrap,#contextual-help-link-wrap,#screen-meta{-webkit-border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-left-radius:3px;border-bottom-right-radius:3px}#screen-meta-links .screen-meta-toggle{position:relative;top:-1px}#screen-meta-links a.show-settings{text-decoration:none;z-index:1;padding:1px 16px 0 6px;height:22px;line-height:22px;font-size:12px;display:block;text-shadow:rgba(255,255,255,.7) 0 1px 0}#screen-meta-links a.show-settings:hover{text-decoration:none}.toggle-arrow{background-repeat:no-repeat;background-position:top left;background-color:transparent;height:22px;line-height:22px;display:block}.toggle-arrow-active{background-position:bottom left}#screen-options-wrap h5,#contextual-help-wrap h5{margin:8px 0;font-size:13px}.metabox-prefs label{display:inline-block;padding-right:15px;white-space:nowrap;line-height:30px}.metabox-prefs label input{margin:0 5px 0 2px}.metabox-prefs .columns-prefs label input{margin:0 2px}.metabox-prefs label a{display:none}#contextual-help-wrap{padding:0;margin-left:-4px}#contextual-help-columns{position:relative}#contextual-help-back{position:absolute;top:0;bottom:0;left:150px;right:170px;border-width:0 1px;border-style:solid}#contextual-help-wrap.no-sidebar #contextual-help-back{right:0;border-right-width:0;-webkit-border-bottom-right-radius:2px;border-bottom-right-radius:2px}.contextual-help-tabs{float:left;width:150px;margin:0}.contextual-help-tabs ul{margin:1em 0}.contextual-help-tabs li{margin-bottom:0;list-style-type:none;border-style:solid;border-width:1px 0;border-color:transparent}.contextual-help-tabs a{display:block;padding:5px 5px 5px 12px;line-height:18px;text-decoration:none}.contextual-help-tabs .active{padding:0;margin:0 -1px 0 0;border-width:1px 0 1px 1px;border-style:solid}.contextual-help-tabs-wrap{padding:0 20px;overflow:auto}.help-tab-content{display:none;margin:0 22px 12px 0;line-height:1.6em}.help-tab-content.active{display:block}.help-tab-content ul li{list-style-type:disc;margin-left:18px}.contextual-help-sidebar{width:150px;float:right;padding:0 8px 0 12px;overflow:auto}#adminmenuback,#adminmenuwrap{border-width:0 1px 0 0;border-style:solid}#adminmenuwrap{position:relative;float:left}#adminmenushadow{position:absolute;top:0;right:0;bottom:0;width:6px;z-index:20}#adminmenu *{-webkit-user-select:none;-moz-user-select:none;user-select:none}#adminmenu li{margin:0;padding:0;cursor:pointer}#adminmenu a{display:block;line-height:18px;padding:2px 5px}#adminmenu li.menu-top{min-height:28px;position:relative}#adminmenu .wp-submenu{list-style:none;padding:4px 0;margin:0;position:absolute;top:-1000em;left:146px;z-index:1000;overflow:visible;border-width:1px;border-style:solid;-webkit-border-bottom-right-radius:3px;-webkit-border-top-right-radius:3px;border-bottom-right-radius:3px;border-top-right-radius:3px}.js #adminmenu .sub-open,.js #adminmenu .opensub .wp-submenu,#adminmenu a.menu-top:focus+.wp-submenu,.no-js li.wp-has-submenu:hover .wp-submenu{top:-1px}#adminmenu .wp-has-current-submenu .wp-submenu,.no-js li.wp-has-current-submenu:hover .wp-submenu,#adminmenu a.wp-has-current-submenu:focus+.wp-submenu,#adminmenu .wp-has-current-submenu .wp-submenu.sub-open,#adminmenu .wp-has-current-submenu.opensub .wp-submenu{position:relative;z-index:3;top:auto;left:auto;right:auto;bottom:auto;border:0 none;-webkit-box-shadow:none;box-shadow:none}.folded #adminmenu .wp-submenu.sub-open,.folded #adminmenu .opensub .wp-submenu,.folded #adminmenu .wp-has-current-submenu .wp-submenu.sub-open,.folded #adminmenu .wp-has-current-submenu.opensub .wp-submenu,.folded #adminmenu a.menu-top:focus+.wp-submenu,.folded #adminmenu .wp-has-current-submenu a.menu-top:focus+.wp-submenu,.no-js.folded #adminmenu .wp-has-submenu:hover .wp-submenu{top:-1px;left:32px}.folded #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.folded #adminmenu .wp-has-current-submenu .wp-submenu{border-width:1px;border-style:solid;position:absolute;top:-1000em}#adminmenu .wp-submenu a{font-size:12px;line-height:18px;margin:0;padding-left:12px}#adminmenu .wp-not-current-submenu li>a{padding-left:16px}#adminmenu .wp-has-current-submenu ul>li>a,.folded #adminmenu li.menu-top .wp-submenu>li>a{padding-left:12px}#adminmenu a.menu-top,#adminmenu .wp-submenu-head{font-size:13px;font-weight:700;line-height:18px;padding:0}#adminmenu .wp-submenu-head,.folded #adminmenu .wp-menu-name{display:none}.folded #adminmenu .wp-submenu-head{display:block}#adminmenu .wp-submenu li{padding:0;margin:0;overflow:hidden}#adminmenu a.menu-top{border-width:1px 0;border-style:solid none}#adminmenu .wp-menu-image img{padding:7px 0 0 7px;opacity:.6;filter:alpha(opacity=60)}#adminmenu div.wp-menu-name{padding:5px}#adminmenu div.wp-menu-image{float:left;width:28px;height:28px}.folded #adminmenu div.wp-menu-image{width:32px;position:absolute;z-index:25}.folded #adminmenu a.menu-top{height:28px}.wp-menu-arrow{z-index:25;position:absolute;right:100%;margin:0;height:30px;width:6px;-moz-transform:translate(146px);-webkit-transform:translate(146px);-o-transform:translate(146px);-ms-transform:translate(146px);transform:translate(146px)}#adminmenu .wp-menu-arrow div{display:none;position:absolute;top:7px;left:-1px;width:14px;height:15px;-moz-transform:matrix(-.6,1,.6,1,0,0);-webkit-transform:matrix(-.6,1,.6,1,0,0);-o-transform:matrix(-.6,1,.6,1,0,0);-ms-transform:matrix(-.6,1,.6,1,0,0);transform:matrix(-.6,1,.6,1,0,0)}#adminmenu li.wp-not-current-submenu .wp-menu-arrow{-moz-transform:translate(145px);-webkit-transform:translate(145px);-o-transform:translate(145px);-ms-transform:translate(145px);transform:translate(145px);height:28px;border-width:1px 0;border-style:solid;top:0}.folded #adminmenu li .wp-menu-arrow{-moz-transform:translate(32px);-webkit-transform:translate(32px);-o-transform:translate(32px);-ms-transform:translate(32px);transform:translate(32px)}#adminmenu li.current .wp-menu-arrow,#adminmenu li.wp-has-current-submenu .wp-menu-arrow,#adminmenu li.wp-has-current-submenu .wp-menu-arrow div,#adminmenu li.wp-has-submenu .wp-menu-arrow div,#adminmenu li.current .wp-menu-arrow div,.no-js #adminmenu li.wp-has-submenu:hover .wp-menu-arrow,#adminmenu li.wp-has-submenu.opensub .wp-menu-arrow,#adminmenu a.wp-has-submenu:focus .wp-menu-arrow,#adminmenu a:hover .wp-menu-arrow{display:block}#adminmenu li.current .wp-menu-arrow,#adminmenu li.wp-menu-open .wp-menu-arrow{top:0}.no-js #adminmenu li.wp-has-submenu:hover .wp-menu-arrow,#adminmenu li.wp-has-submenu.opensub .wp-menu-arrow,#adminmenu a.wp-has-submenu:focus .wp-menu-arrow{z-index:1001}.ie8 #adminmenu li.menu-top:hover .wp-menu-arrow{display:none}#adminmenu .wp-not-current-submenu .wp-menu-arrow div{width:15px;top:6px;border-width:0 0 1px 1px;border-style:solid}.wp-menu-arrow,.folded #adminmenu li .wp-menu-arrow div,.no-js #adminmenu li.wp-not-current-submenu:hover .wp-menu-arrow{display:none}.folded #adminmenu li.current .wp-menu-arrow,.folded #adminmenu li.current .wp-menu-arrow div,.folded #adminmenu li.wp-has-current-submenu .wp-menu-arrow div,.folded #adminmenu li.wp-menu-open .wp-menu-arrow,.folded #adminmenu li a:focus .wp-menu-arrow{display:block}#adminmenu li.menu-top:hover .wp-menu-image img,#adminmenu li.wp-has-current-submenu .wp-menu-image img{opacity:1;filter:alpha(opacity=100)}#adminmenu li.wp-menu-separator{height:3px;padding:0;margin:0;border-width:1px 0;border-style:solid;cursor:inherit}#adminmenu div.separator{height:1px;padding:0;border-width:1px 0 0;border-style:solid}#adminmenu .wp-submenu .wp-submenu-head{padding:5px 4px 5px 10px;margin:-4px -1px 4px;border-width:1px 0;border-style:solid;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}#adminmenu li.wp-menu-open{border-width:0 0 1px;border-style:solid}#adminmenu li.current,.folded #adminmenu li.wp-menu-open{border:0 none}.folded #adminmenu li.wp-has-current-submenu{margin-bottom:1px}.folded #adminmenu .wp-has-current-submenu.menu-top-last{margin-bottom:0}#adminmenu .awaiting-mod,#adminmenu span.update-plugins,#sidemenu li a span.update-plugins{position:absolute;font-family:sans-serif;font-size:9px;line-height:17px;font-weight:700;margin-top:1px;margin-left:7px;-webkit-border-radius:10px;border-radius:10px;z-index:26}#adminmenu li .awaiting-mod span,#adminmenu li span.update-plugins span,#sidemenu li a span.update-plugins span{display:block;padding:0 6px}#adminmenu li span.count-0,#sidemenu li a .count-0{display:none}#collapse-menu{font-size:12px;line-height:34px;border-width:1px 0 0;border-style:solid}.folded #collapse-menu span{display:none}#collapse-button,#collapse-button div{width:15px;height:15px}#collapse-button{float:left;margin:8px 6px;border-width:1px;border-style:solid;-webkit-border-radius:10px;border-radius:10px}@media only screen and (max-width:900px){.auto-fold #wpcontent,.auto-fold #wpfooter{margin-left:52px}.auto-fold #adminmenuback,.auto-fold #adminmenuwrap,.auto-fold #adminmenu,.auto-fold #adminmenu li.menu-top{width:32px}.auto-fold #adminmenu .wp-submenu.sub-open,.auto-fold #adminmenu .opensub .wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu.sub-open,.auto-fold #adminmenu .wp-has-current-submenu.opensub .wp-submenu,.auto-fold #adminmenu a.menu-top:focus+.wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu a.menu-top:focus+.wp-submenu{top:-1px;left:32px}.auto-fold #adminmenu a.wp-has-current-submenu:focus+.wp-submenu,.auto-fold #adminmenu .wp-has-current-submenu .wp-submenu{border-width:1px;border-style:solid;position:absolute;top:-1000em}.auto-fold #adminmenu li.menu-top .wp-submenu>li>a{padding-left:12px}.auto-fold #adminmenu .wp-menu-name{display:none}.auto-fold #adminmenu .wp-submenu-head{display:block}.auto-fold #adminmenu div.wp-menu-image{width:32px;position:absolute;z-index:25}.auto-fold #adminmenu a.menu-top{height:28px}.auto-fold #adminmenu li .wp-menu-arrow{-moz-transform:translate(32px);-webkit-transform:translate(32px);-o-transform:translate(32px);-ms-transform:translate(32px);transform:translate(32px)}.auto-fold #adminmenu li .wp-menu-arrow div{display:none}.auto-fold #adminmenu li.current .wp-menu-arrow,.auto-fold #adminmenu li.current .wp-menu-arrow div,.auto-fold #adminmenu li.wp-has-current-submenu .wp-menu-arrow div,.auto-fold #adminmenu li.wp-menu-open .wp-menu-arrow,.auto-fold #adminmenu li a:focus .wp-menu-arrow{display:block}.auto-fold #adminmenu li.wp-menu-open{border:0 none}.auto-fold #adminmenu li.wp-has-current-submenu{margin-bottom:1px}.auto-fold #adminmenu .wp-has-current-submenu.menu-top-last{margin-bottom:0}.auto-fold #collapse-menu span{display:none}}.post-com-count-wrapper{min-width:22px;font-family:sans-serif}.post-com-count{background-image:url(../images/bubble_bg.gif);height:1.3em;line-height:1.1em;display:block;text-decoration:none;padding:0 0 6px;cursor:pointer;background-position:center -80px;background-repeat:no-repeat}.post-com-count span{font-size:11px;font-weight:700;height:1.4em;line-height:1.4em;min-width:.7em;padding:0 6px;display:inline-block;-webkit-border-radius:5px;border-radius:5px}strong .post-com-count{background-position:center -55px}.post-com-count:hover{background-position:center -3px}.column-response .post-com-count{float:left;margin-right:5px;text-align:center}.response-links{float:left}#the-comment-list .attachment-80x60{padding:4px 8px}th .comment-grey-bubble{background-image:url(../images/comment-grey-bubble.png);background-repeat:no-repeat;height:12px;width:12px}html.wp-toolbar{padding-top:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.narrow{width:70%;margin-bottom:40px}.narrow p{line-height:150%}.widefat th,.widefat td{overflow:hidden}.widefat th{font-weight:400}.widefat td p{margin:2px 0 .8em}.widefat .column-comment p{margin:.6em 0}.postbox-container{float:left}#dashboard-widgets.columns-1 .postbox-container{width:100%}#dashboard-widgets.columns-2 .postbox-container{width:49.5%}#dashboard-widgets.columns-2 #postbox-container-2,#dashboard-widgets.columns-2 #postbox-container-3,#dashboard-widgets.columns-2 #postbox-container-4{float:right;width:50.5%}#dashboard-widgets.columns-3 .postbox-container{width:33.5%}#dashboard-widgets.columns-3 #postbox-container-1{width:33%}#dashboard-widgets.columns-3 #postbox-container-3,#dashboard-widgets.columns-3 #postbox-container-4{float:right}#dashboard-widgets.columns-4 .postbox-container{width:25%}.postbox-container .meta-box-sortables{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.metabox-holder .postbox-container .empty-container{border:3px dashed #CCC;height:250px}.metabox-holder.columns-1 .postbox-container .empty-container,.columns-2 #postbox-container-3 .empty-container,.columns-2 #postbox-container-4 .empty-container,.columns-3 #postbox-container-4 .empty-container{border:0 none;height:0;min-height:0}#poststuff{padding-top:10px}#poststuff #post-body{padding:0}#post-body-content{width:100%;float:left}#poststuff .postbox-container{width:100%}#poststuff #post-body.columns-2{margin-right:300px}#post-body.columns-2 #postbox-container-1{float:right;margin-right:-300px;width:280px}#post-body.columns-2 #side-sortables{min-height:250px}@media only screen and (max-width:799px){#wpbody-content #dashboard-widgets .postbox-container{width:100%}#wpbody-content .metabox-holder .postbox-container .empty-container{border:0 none;height:0;min-height:0}}@media only screen and (min-width:800px) and (max-width:1200px){#wpbody-content #dashboard-widgets .postbox-container{width:49.5%}#wpbody-content #dashboard-widgets #postbox-container-2,#wpbody-content #dashboard-widgets #postbox-container-3,#wpbody-content #dashboard-widgets #postbox-container-4{float:right;width:50.5%}#dashboard-widgets #postbox-container-3 .empty-container,#dashboard-widgets #postbox-container-4 .empty-container{border:0 none;height:0;min-height:0}#wpbody #wpbody-content #dashboard-widgets.columns-1 .postbox-container{width:100%}#wpbody #wpbody-content .metabox-holder.columns-1 .postbox-container .empty-container{border:0 none;height:0;min-height:0}.index-php .screen-layout,.index-php .columns-prefs{display:block}.columns-prefs .columns-prefs-3,.columns-prefs .columns-prefs-4{display:none}}@media only screen and (max-width:960px){#wpbody-content #poststuff #post-body{margin:0}#wpbody-content #post-body.columns-2 #postbox-container-1{margin-right:0;width:100%}#poststuff #postbox-container-1 .empty-container,#poststuff #postbox-container-1 #side-sortables:empty{border:0 none;height:0;min-height:0}#poststuff #post-body.columns-2 #side-sortables{min-height:0}.screen-layout,.columns-prefs{display:none}}.postbox .hndle{-webkit-border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px}.js .postbox .hndle{cursor:move}.postbox.closed .hndle{-webkit-border-radius:3px;border-radius:3px}.hndle a{font-size:11px;font-weight:400}.postbox .handlediv{float:right;width:27px;height:30px}.js .postbox .handlediv{cursor:pointer}.sortable-placeholder{border-width:1px;border-style:dashed;margin-bottom:20px}.widget,.postbox,.stuffbox{margin-bottom:20px;padding:0;border-width:1px;border-style:solid;line-height:1}.widget .widget-top,.postbox h3,.stuffbox h3{margin-top:1px;border-bottom-width:1px;border-bottom-style:solid;-webkit-user-select:none;-moz-user-select:none;user-select:none}.js .widget .widget-top,.js .postbox h3{cursor:move}.postbox .inside,.stuffbox .inside{padding:0 12px 0 10px;line-height:1.4em}.postbox .inside{margin:10px 0;position:relative}.postbox.closed h3{border:0;-webkit-box-shadow:none;box-shadow:none}.postbox table.form-table{margin-bottom:0}.temp-border{border:1px dotted #ccc}.columns-prefs label{padding:0 5px}#dashboard-widgets-wrap{margin:0 -8px}#wpbody-content .metabox-holder{padding-top:10px}#dashboard-widgets .meta-box-sortables{margin:0 8px}#dashboard_recent_comments div.undo{border-top-style:solid;border-top-width:1px;margin:0 -10px;padding:3px 8px;font-size:11px}#the-comment-list td.comment p.comment-author{margin-top:0;margin-left:0}#the-comment-list p.comment-author img{float:left;margin-right:8px}#the-comment-list p.comment-author strong a{border:0}#the-comment-list td{vertical-align:top}#the-comment-list td.comment{word-wrap:break-word}.welcome-panel{position:relative;overflow:auto;margin:20px 0;padding:23px 10px 12px;border-width:1px;border-style:solid;border-radius:3px;font-size:13px;line-height:2.1em}.welcome-panel h3{margin:0;font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",sans-serif;font-size:21px;font-weight:400;line-height:1.2}.welcome-panel h4{margin:1.33em 0 0;font-size:13px}.welcome-panel .about-description{font-size:16px;margin:0}.welcome-panel .welcome-panel-close{position:absolute;top:5px;right:10px;padding:8px 3px;font-size:13px;text-decoration:none;line-height:1}.welcome-panel .welcome-panel-close:before{content:' ';position:absolute;left:-12px;width:10px;height:100%;background:url(../images/xit.gif) 0 17% no-repeat}.welcome-panel .welcome-panel-close:hover:before{background-position:100% 17%}.wp-core-ui .welcome-panel .button.button-hero{margin:15px 0 3px}.welcome-panel-content{margin-left:13px;max-width:1500px}.welcome-panel .welcome-panel-column-container{clear:both;overflow:hidden;position:relative}.welcome-panel .welcome-panel-column{width:32%;min-width:200px;float:left}.ie8 .welcome-panel .welcome-panel-column{min-width:230px}.welcome-panel .welcome-panel-column:first-child{width:36%}.welcome-panel-column p{margin-top:7px}.welcome-panel .welcome-icon{display:block;padding:2px 0 8px 32px;background-image:url(../images/welcome-icons.png);background-repeat:no-repeat;background-size:16px}.welcome-panel .welcome-add-page{background-position:0 2px}.welcome-panel .welcome-edit-page{background-position:0 -90px}.welcome-panel .welcome-learn-more{background-position:0 -136px}.welcome-panel .welcome-comments{background-position:0 -182px}.welcome-panel .welcome-view-site{background-position:0 -274px}.welcome-panel .welcome-widgets-menus{background-position:1px -229px;line-height:14px}.welcome-panel .welcome-write-blog{background-position:0 -44px}.welcome-panel .welcome-panel-column ul{margin:.8em 1em 1em 0}.welcome-panel .welcome-panel-column li{line-height:16px;list-style-type:none}@media screen and (max-width:870px){.welcome-panel .welcome-panel-column,.welcome-panel .welcome-panel-column:first-child{display:block;float:none;width:100%}.welcome-panel .welcome-panel-column li{display:inline-block;margin-right:13px}.welcome-panel .welcome-panel-column ul{margin:.4em 0 0}.welcome-panel .welcome-icon{padding-left:25px}}table.fixed{table-layout:fixed}.fixed .column-rating,.fixed .column-visible{width:8%}.fixed .column-posts,.fixed .column-date,.fixed .column-parent,.fixed .column-links,.fixed .column-author,.fixed .column-format{width:10%}.fixed .column-response,.fixed .column-categories,.fixed .column-tags,.fixed .column-rel,.fixed .column-role{width:15%}.fixed .column-slug{width:25%}.fixed .column-locations{width:35%}.fixed .column-comments{width:4em;padding:8px 0;text-align:left}.fixed .column-comments .vers{padding-left:3px}.fixed .column-comments a{float:left}.fixed .column-icon{width:80px}#comments-form .fixed .column-author{width:20%}#commentsdiv.postbox .inside{margin:0;padding:0}#commentsdiv .inside .row-actions{line-height:18px}#commentsdiv .inside .column-author{width:25%}#commentsdiv .column-comment p{margin:.6em 0;padding:0}#commentsdiv #replyrow td{padding:0}#commentsdiv p{padding:8px 10px;margin:0}#commentsdiv #add-new-comment{border-width:0 0 1px;border-style:none none solid}#commentsdiv .comments-box{border:0 none}#commentsdiv .comments-box thead th{background:transparent;padding:0 7px 4px;font-style:italic}#commentsdiv .comments-box tr:last-child td{border-bottom:0 none}#commentsdiv .spinner{padding-left:5px}.sorting-indicator{display:none;width:7px;height:4px;margin-top:8px;margin-left:7px;background-image:url(../images/sort.gif);background-repeat:no-repeat}tr.wp-locked .locked-indicator{background:url(../images/lock.png) no-repeat;margin:-2px 0 0 6px;height:20px;width:16px}tr.wp-locked .check-column label,tr.wp-locked .check-column input[type=checkbox],tr.wp-locked .row-actions .inline,tr.wp-locked .row-actions .trash{display:none}tr .locked-info{height:0;opacity:0}tr.wp-locked .locked-info{height:auto;opacity:1}tr.locked-info,tr.wp-locked .locked-info{-webkit-transition:height 1s,opacity 500ms;-moz-transition:height 1s,opacity 500ms;-ms-transition:height 1s,opacity 500ms;-o-transition:height 1s,opacity 500ms;transition:height 1s,opacity 500ms}.fixed .column-comments .sorting-indicator{margin-top:3px}#menu-locations-wrap .widefat{width:60%}.widefat th.sortable,.widefat th.sorted{padding:0}th.sortable a,th.sorted a{display:block;overflow:hidden;padding:7px 7px 8px}.fixed .column-comments.sortable a,.fixed .column-comments.sorted a{padding:8px 0}th.sortable a span,th.sorted a span{float:left;cursor:pointer}th.sorted.asc .sorting-indicator,th.desc:hover span.sorting-indicator{display:block;background-position:0 0}th.sorted.desc .sorting-indicator,th.asc:hover span.sorting-indicator{display:block;background-position:-7px 0}.tablenav-pages a{border-bottom-style:solid;border-bottom-width:2px;font-weight:700;margin-right:1px;padding:0 2px}.tablenav-pages .current-page{text-align:center}.tablenav-pages .next-page{margin-left:2px}.tablenav a.button-secondary{display:block;margin:3px 8px 0 0}.tablenav{clear:both;height:30px;margin:6px 0 4px;vertical-align:middle}.tablenav.themes{max-width:98%}.tablenav .tablenav-pages{float:right;display:block;cursor:default;height:30px;line-height:30px;font-size:12px}.tablenav .no-pages,.tablenav .one-page .pagination-links{display:none}.tablenav .tablenav-pages a,.tablenav-pages span.current{text-decoration:none;padding:3px 6px}.tablenav .tablenav-pages a.disabled:hover,.tablenav .tablenav-pages a.disabled:active{cursor:default}.tablenav .displaying-num{margin-right:10px;font-size:12px;font-style:italic}.tablenav .actions{overflow:hidden;padding:2px 8px 0 0}.tablenav .delete{margin-right:20px}.view-switch{float:right;margin:6px 8px 0}.view-switch a{text-decoration:none}.filter{float:left;margin:-5px 0 0 10px}.filter .subsubsub{margin-left:-10px;margin-top:13px}.screen-per-page{width:4em}#posts-filter fieldset{float:left;margin:0 1.5ex 1em 0;padding:0}#posts-filter fieldset legend{padding:0 0 .2em 1px}#wpbody-content .inline-edit-row fieldset{font-size:12px;float:left;margin:0;padding:0;width:100%}tr.inline-edit-row td,#wpbody-content .inline-edit-row fieldset .inline-edit-col{padding:0 .5em}#wpbody-content .quick-edit-row-page fieldset.inline-edit-col-right .inline-edit-col{border-width:0 0 0 1px;border-style:none none none solid}#wpbody-content .quick-edit-row-post .inline-edit-col-left{width:40%}#wpbody-content .quick-edit-row-post .inline-edit-col-right{width:39%}#wpbody-content .inline-edit-row-post .inline-edit-col-center{width:20%}#wpbody-content .quick-edit-row-page .inline-edit-col-left{width:50%}#wpbody-content .quick-edit-row-page .inline-edit-col-right,#wpbody-content .bulk-edit-row-post .inline-edit-col-right{width:49%}#wpbody-content .bulk-edit-row .inline-edit-col-left{width:30%}#wpbody-content .bulk-edit-row-page .inline-edit-col-right{width:69%}#wpbody-content .bulk-edit-row .inline-edit-col-bottom{float:right;width:69%}#wpbody-content .inline-edit-row-page .inline-edit-col-right{margin-top:27px}.inline-edit-row fieldset .inline-edit-group{clear:both}.inline-edit-row fieldset .inline-edit-group:after{content:".";display:block;height:0;clear:both;visibility:hidden}.inline-edit-row p.submit{clear:both;padding:.5em;margin:.5em 0 0}.inline-edit-row span.error{line-height:22px;margin:0 15px;padding:3px 5px}.inline-edit-row h4{margin:.2em 0;padding:0;line-height:23px}.inline-edit-row fieldset span.title,.inline-edit-row fieldset span.checkbox-title{margin:0;padding:0;line-height:27px}.inline-edit-row fieldset label,.inline-edit-row fieldset span.inline-edit-categories-label{display:block;margin:.2em 0}.inline-edit-row fieldset label.inline-edit-tags{margin-top:0}.inline-edit-row fieldset label.inline-edit-tags span.title{margin:.2em 0;width:auto}.inline-edit-row fieldset label span.title{display:block;float:left;width:5em}.inline-edit-row fieldset label span.input-text-wrap{display:block;margin-left:5em}.quick-edit-row-post fieldset.inline-edit-col-right label span.title{width:auto;padding-right:.5em}.inline-edit-row .input-text-wrap input[type=text]{width:100%}.inline-edit-row fieldset label input[type=checkbox]{vertical-align:text-bottom}.inline-edit-row fieldset label textarea{width:100%;height:4em}#wpbody-content .bulk-edit-row fieldset .inline-edit-group label{max-width:50%}#wpbody-content .quick-edit-row fieldset .inline-edit-group label.alignleft:first-child{margin-right:.5em}.inline-edit-col-right .input-text-wrap input.inline-edit-menu-order-input{width:6em}.inline-edit-save .spinner{padding:4px 10px 0;vertical-align:top;float:right}.inline-edit-row h4{text-transform:uppercase}.inline-edit-row fieldset span.title,.inline-edit-row fieldset span.checkbox-title{font-style:italic;line-height:1.8em}.inline-edit-row fieldset input[type=text],.inline-edit-row fieldset textarea{border-style:solid;border-width:1px}.inline-edit-row fieldset .inline-edit-date{float:left}.inline-edit-row fieldset input[name=jj],.inline-edit-row fieldset input[name=hh],.inline-edit-row fieldset input[name=mn]{font-size:12px;width:2.1em}.inline-edit-row fieldset input[name=aa]{font-size:12px;width:3.5em}.inline-edit-row fieldset label input.inline-edit-password-input{width:8em}ul.cat-checklist{height:12em;border-style:solid;border-width:1px;overflow-y:scroll;padding:0 5px;margin:0}#bulk-titles{display:block;height:12em;border-style:solid;border-width:1px;overflow-y:scroll;padding:0 5px;margin:0 0 5px}.inline-edit-row fieldset ul.cat-checklist li,.inline-edit-row fieldset ul.cat-checklist input{margin:0}.inline-edit-row fieldset ul.cat-checklist label,.inline-edit-row #bulk-titles div{font-family:sans-serif;font-style:normal;font-size:11px}.inline-edit-row fieldset label input.inline-edit-menu-order-input{width:3em}.inline-edit-row fieldset label input.inline-edit-slug-input{width:75%}.quick-edit-row-post fieldset label.inline-edit-status{float:left}#bulk-titles{line-height:140%}#bulk-titles div{margin:.2em .3em}#bulk-titles div a{cursor:pointer;display:block;float:left;height:10px;margin:3px 3px 0 -2px;overflow:hidden;position:relative;text-indent:-9999px;width:10px}#show-comments{overflow:hidden}#save-action .spinner,#show-comments a,#show-comments .spinner{float:left}#lost-connection-notice .spinner{display:block;float:left;margin:0 5px 0 0}.rtl #lost-connection-notice .spinner{float:right;margin:0 0 0 5px}#titlediv{position:relative;margin-bottom:5px}#titlediv label{cursor:text}#titlediv div.inside{margin:0}#poststuff #titlewrap{border:0;padding:0}#titlediv #title{padding:3px 8px;font-size:1.7em;line-height:100%;height:1.7em;width:100%;outline:0;margin:1px 0}#titlediv #title-prompt-text,#wp-fullscreen-title-prompt-text{color:#bbb;position:absolute;font-size:1.7em;padding:11px 10px}#wp-fullscreen-save .fs-saved{color:#999;float:right;margin-top:4px}#wp-fullscreen-title-prompt-text{padding:11px}#poststuff .inside-submitbox,#side-sortables .inside-submitbox{margin:0 3px;font-size:11px}input#link_description,input#link_url{width:98%}#pending{background:0 none;border:0 none;padding:0;font-size:11px;margin-top:-1px}#edit-slug-box{line-height:24px;min-height:25px;margin-top:5px;padding-right:6px}#edit-slug-box .cancel{margin-right:10px;font-size:11px}#editable-post-name-full{display:none}#editable-post-name input{width:16em}.postarea h3 label{float:left}.submitbox .submit{text-align:left;padding:12px 10px 10px;font-size:11px}.submitbox .submitdelete{text-decoration:none;padding:1px 2px}.submitbox .submitdelete,.submitbox .submit a:hover{border-bottom-width:1px;border-bottom-style:solid}.submitbox .submit input{margin-bottom:8px;margin-right:4px;padding:6px}.inside-submitbox #post_status{margin:2px 0 2px -2px}#post-status-select{line-height:2.5em;margin-top:3px}#post-body #normal-sortables{min-height:50px}.postbox{position:relative;min-width:255px}#trackback_url{width:99%}#normal-sortables .postbox .submit{background:transparent none;border:0 none;float:right;padding:0 12px;margin:0}.category-add input[type=text],.category-add select{width:100%;max-width:260px}.press-this #side-sortables .category-tabs li,ul.category-tabs li,#side-sortables .add-menu-item-tabs li,.wp-tab-bar li{display:inline;line-height:1.35em}.no-js .category-tabs li.hide-if-no-js{display:none}.category-tabs a,#side-sortables .add-menu-item-tabs a,.wp-tab-bar a{text-decoration:none}.category-tabs{margin:8px 0 3px}#category-adder h4{margin:10px 0}#side-sortables .add-menu-item-tabs,.wp-tab-bar{margin-bottom:3px}#normal-sortables .postbox #replyrow .submit{float:none;margin:0;padding:0 7px 5px}#side-sortables .submitbox .submit input,#side-sortables .submitbox .submit .preview,#side-sortables .submitbox .submit a.preview:hover{border:0 none}#side-sortables .inside-submitbox .insidebox,.stuffbox .insidebox{margin:11px 0}ul.category-tabs,ul.add-menu-item-tabs,ul.wp-tab-bar{margin-top:12px}ul.category-tabs li{border-style:solid;border-width:1px;position:relative}ul.add-menu-item-tabs li.tabs,.wp-tab-active{border-style:solid solid none;border-width:1px 1px 0}#post-body .add-menu-item-tabs li.tabs{border-style:solid none solid solid;border-width:1px 0 1px 1px;margin-right:-1px}ul.category-tabs li,ul.add-menu-item-tabs li,ul.wp-tab-bar li{padding:3px 5px 5px;-webkit-border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px}form#tags-filter{position:relative}td.post-title strong,td.plugin-title strong{display:block;margin-bottom:.2em}td.post-title p,td.plugin-title p{margin:6px 0}.wp-hidden-children .wp-hidden-child,.ui-tabs-hide{display:none}.commentlist .avatar{vertical-align:text-top}#post-body .tagsdiv #newtag{margin-right:5px;width:16em}#side-sortables input#post_password{width:94%}#side-sortables .tagsdiv #newtag{width:68%}#post-status-info{border-width:0 1px 1px;border-style:none solid solid;width:100%;-webkit-border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-left-radius:3px;border-bottom-right-radius:3px}#post-status-info td{font-size:12px}.autosave-info{padding:2px 15px;text-align:right}#editorcontent #post-status-info{border:0}#post-body .wp_themeSkin .mceStatusbar a.mceResize{display:block;background:transparent url(../images/resize.gif) no-repeat scroll right bottom;width:12px;cursor:se-resize;margin:0 1px;position:relative;top:-2px}#post-body .postarea .wp_themeSkin .mceStatusbar a.mceResize{top:20px}#content-resize-handle{background:transparent url(../images/resize.gif) no-repeat scroll right bottom;width:12px;cursor:se-resize;position:absolute;right:2px;height:19px}.press-this #content-resize-handle{bottom:2px}.tmce-active #content-resize-handle{display:none}#wp-word-count{display:block;padding:2px 10px}#timestampdiv select{height:20px;line-height:14px;padding:0;vertical-align:top}#aa,#jj,#hh,#mn{padding:1px;font-size:12px}#jj,#hh,#mn{width:2em}#aa{width:3.4em}.curtime #timestamp{background-repeat:no-repeat;background-position:left center;padding:2px 0 1px 20px}#timestampdiv{padding-top:5px;line-height:23px}#timestampdiv p{margin:8px 0 6px}#timestampdiv input{border-width:1px;border-style:solid}.notification-dialog{position:fixed;top:30%;left:50%;width:450px;margin-left:-225px;background:#fff;line-height:1.5;z-index:1000005}.notification-dialog-background{position:fixed;top:0;left:0;right:0;bottom:0;background:#000;opacity:.5;filter:alpha(opacity=50);z-index:1000000}#post-lock-dialog .post-locked-message,#post-lock-dialog .post-taken-over{margin:25px}#post-lock-dialog .post-locked-message a.button{margin-right:10px}#post-lock-dialog .post-locked-avatar{float:left;margin:0 20px 20px 0}#post-lock-dialog .wp-tab-first{outline:0}#post-lock-dialog .locked-saving img{float:left;margin-right:3px}#post-lock-dialog.saving .locked-saving,#post-lock-dialog.saved .locked-saved{display:inline}#postcustomstuff thead th{padding:5px 8px 8px}#postcustom #postcustomstuff .submit{border:0 none;float:none;padding:0 8px 8px}#side-sortables #postcustom #postcustomstuff .submit{margin:0;padding:0}#side-sortables #postcustom #postcustomstuff #the-list textarea{height:85px}#side-sortables #postcustom #postcustomstuff td.left input,#side-sortables #postcustom #postcustomstuff td.left select,#side-sortables #postcustomstuff #newmetaleft a{margin:3px 3px 0}#postcustomstuff table{margin:0;width:100%;border-width:1px;border-style:solid;border-spacing:0}#postcustomstuff tr{vertical-align:top}#postcustomstuff table input,#postcustomstuff table select,#postcustomstuff table textarea{width:96%;margin:8px}#side-sortables #postcustomstuff table input,#side-sortables #postcustomstuff table select,#side-sortables #postcustomstuff table textarea{margin:3px}#postcustomstuff th.left,#postcustomstuff td.left{width:38%}#postcustomstuff .submit input{margin:0;width:auto}#postcustomstuff #newmetaleft a{display:inline-block;margin:0 8px 8px;text-decoration:none}.no-js #postcustomstuff #enternew{display:none}#post-body-content .compat-attachment-fields{margin-bottom:20px}.compat-attachment-fields th{padding-top:5px;padding-right:10px}.revisions-control-frame,.revisions-diff-frame{position:relative}.revisions-controls{padding-top:40px;height:100px;z-index:1}.revisions-controls input[type=checkbox]{position:relative;top:-1px;vertical-align:text-bottom}.revisions.pinned .revisions-controls{position:fixed;top:0;padding-bottom:10px}.revisions-tickmarks{position:relative;margin:0 auto;height:.8em;top:7px;max-width:70%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.revisions-tickmarks>div{position:absolute;height:100%;border-style:solid;border-width:0 1px 0 0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.revisions-tickmarks>div:first-child{border-width:0}.comparing-two-revisions .revisions-controls{height:140px}.revisions .diff-error{position:absolute;text-align:center;margin:0 auto;width:100%;display:none}.revisions.diff-error .diff-error{display:block}.revisions .loading-indicator{position:fixed;vertical-align:middle;opacity:0;width:100%;top:50%;margin-left:-90px;-webkit-transition:opacity .5s;-moz-transition:opacity .5s;-ms-transition:opacity .5s;-o-transition:opacity .5s;transition:opacity .5s;filter:alpha(opacity=0)}body.folded .revisions .loading-indicator{margin-left:-32px}.revisions .loading-indicator span.spinner{display:block;margin:0 auto;float:none}.revisions.loading .loading-indicator{opacity:1;filter:alpha(opacity=100)}.revisions .diff{-webkit-transition:opacity .5s;-moz-transition:opacity .5s;-ms-transition:opacity .5s;-o-transition:opacity .5s;transition:opacity .5s}.revisions.loading .diff{opacity:.5;filter:alpha(opacity=50)}.revisions.diff-error .diff{visibility:hidden}.revisions-meta{margin-top:15px}.revision-toggle-compare-mode{position:absolute;top:0;right:0}.comparing-two-revisions .revisions-previous,.comparing-two-revisions .revisions-next,.revisions-meta .diff-meta-to strong{display:none}.revisions-controls .author-card .date{color:#777}.revisions-controls .author-card.autosave{color:#d54e21}.revisions-controls .author-card .author-name{font-weight:700}.comparing-two-revisions .diff-meta-to strong{display:block}.revisions-previous,.revisions-next{position:relative;z-index:1}.revisions-previous{float:left}.revisions-next{float:right}.revisions-controls .wp-slider{max-width:70%;margin:0 auto;top:-3px}.post-revisions li img,#revisions-meta-restored img{vertical-align:middle}table.diff{table-layout:fixed;width:100%;white-space:pre-wrap;word-wrap:break-word}table.diff col.content{width:auto}table.diff col.content.diffsplit{width:48%}table.diff col.diffsplit.middle{width:auto}table.diff col.ltype{width:30px}table.diff tr{background-color:transparent}table.diff td,table.diff th{padding:.5em;font-family:Consolas,Monaco,monospace}table.diff .diff-deletedline del,table.diff .diff-addedline ins{text-decoration:none}.diff-meta{-webkit-border-radius:3px;border-radius:3px;padding:5px;clear:both;min-height:32px}.diff-title strong{line-height:32px;min-width:60px;text-align:right;float:left;margin-right:5px}.revisions-controls .author-card .avatar,.revisions-controls .author-card .author-info{float:left;margin-left:6px;margin-right:6px}.revisions-controls .author-card .byline{display:block;font-size:12px}.revisions-controls .author-card .avatar{vertical-align:middle}.diff-meta input.restore-revision{float:right;margin-left:6px;margin-right:6px;margin-top:4px}.diff-meta-from{display:none}.comparing-two-revisions .diff-meta-from{display:block}.revisions-tooltip{position:absolute;bottom:105px;margin-right:0;margin-left:-69px;z-index:0;max-width:350px;min-width:130px;padding:8px 4px;display:none;opacity:0}.revisions-tooltip.flipped{margin-left:0;margin-right:-70px}.revisions.pinned .revisions-tooltip{display:none!important}.comparing-two-revisions .revisions-tooltip{bottom:145px}.revisions-tooltip-arrow{width:70px;height:15px;overflow:hidden;position:absolute;left:0;margin-left:35px;bottom:-15px}.revisions-tooltip.flipped .revisions-tooltip-arrow{margin-left:0;margin-right:35px;left:auto;right:0}.revisions-tooltip-arrow>span{content:"";position:absolute;left:20px;top:-20px;width:25px;height:25px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.revisions-tooltip.flipped .revisions-tooltip-arrow>span{left:auto;right:20px}.ie8 .revisions-tooltip-arrow>span{left:15px;top:-25px;-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"}.ie8 .revisions-tooltip.flipped .revisions-tooltip-arrow>span{right:25px}.revisions-tooltip,.revisions-tooltip-arrow>span{border-width:1px;border-style:solid}div.revisions-controls>.wp-slider>.ui-slider-handle{margin-left:-10px}.wp-slider.ui-slider{position:relative;border-width:1px;border-style:solid;border-radius:3px;text-align:left;cursor:pointer}.wp-slider .ui-slider-handle{position:absolute;z-index:2;margin-top:-3px;width:19px;height:19px;border-width:1px;border-style:solid;border-radius:50%}.wp-slider .ui-slider-handle:before{content:"";position:absolute;top:6px;left:3px;height:8px;width:13px;background:url(../images/arrows-pr.png) no-repeat -2px -47px}.wp-slider .ui-slider-handle.from-handle:before,.wp-slider .ui-slider-handle.to-handle:before{height:8px;width:7px}.wp-slider .ui-slider-handle.from-handle:before{background-position:-5px -84px;left:7px}.wp-slider .ui-slider-handle.to-handle:before{background-position:-4px -65px;left:5px}.wp-slider .ui-slider-range{position:absolute;font-size:.7em;display:block;border:0;background-color:transparent;background-image:none}.wp-slider.ui-slider-horizontal{height:.8em}.wp-slider.ui-slider-horizontal .ui-slider-handle{top:-.25em;margin-left:-.6em}.wp-slider.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.wp-slider.ui-slider-horizontal .ui-slider-range-min{left:0}.wp-slider.ui-slider-horizontal .ui-slider-range-max{right:0}#select-featured-image{padding:4px 0;overflow:hidden}#select-featured-image img{max-width:100%;height:auto;margin-bottom:10px}#select-featured-image a{float:left;clear:both}#select-featured-image .remove{display:none;margin-top:10px}.js #select-featured-image.has-featured-image .remove{display:inline-block}.no-js #select-featured-image .choose{display:none}a.post-state-format{overflow:hidden;display:inline-block;vertical-align:middle;height:16px;width:16px;margin-right:5px;background-repeat:no-repeat;text-indent:-999em}#post-formats-select{line-height:2em}label.post-format-icon{margin-left:5px;padding:2px 0 2px 21px}.post-format-icon.post-format-standard{background-position:0 0}.post-format-icon.post-format-image{background-position:0 -32px}.post-format-icon.post-format-gallery{background-position:0 -64px}.post-format-icon.post-format-audio{background-position:0 -96px}.post-format-icon.post-format-video{background-position:0 -128px}.post-format-icon.post-format-chat{background-position:0 -160px}.post-format-icon.post-format-status{background-position:0 -192px}.post-format-icon.post-format-aside{background-position:0 -224px}.post-format-icon.post-format-quote{background-position:0 -256px}.post-format-icon.post-format-link{background-position:0 -288px}.category-adder{margin-left:120px;padding:4px 0}.category-adder h4{margin:0 0 8px}#side-sortables .category-adder{margin:0}#post-body ul.add-menu-item-tabs{float:left;width:120px;text-align:right;margin:0 -120px 0 5px;padding:0}#post-body ul.add-menu-item-tabs li{padding:8px}#post-body ul.add-menu-item-tabs li.tabs{-webkit-border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-top-left-radius:3px;border-bottom-left-radius:3px}.wp-tab-panel,.categorydiv div.tabs-panel,.customlinkdiv div.tabs-panel,.posttypediv div.tabs-panel,.taxonomydiv div.tabs-panel{min-height:42px;max-height:200px;overflow:auto;padding:0 .9em;border-style:solid;border-width:1px}div.tabs-panel-active{display:block}div.tabs-panel-inactive{display:none}#front-page-warning,#front-static-pages ul,ul.export-filters,.inline-editor ul.cat-checklist ul,.categorydiv ul.categorychecklist ul,.customlinkdiv ul.categorychecklist ul,.posttypediv ul.categorychecklist ul,.taxonomydiv ul.categorychecklist ul{margin-left:18px}ul.categorychecklist li{margin:0;padding:0;line-height:19px;word-wrap:break-word}.categorydiv .tabs-panel,.customlinkdiv .tabs-panel,.posttypediv .tabs-panel,.taxonomydiv .tabs-panel{border-width:3px;border-style:solid}.form-wrap p,.form-wrap label{font-size:11px}.form-wrap label{display:block;padding:2px;font-size:12px}.form-field input,.form-field textarea{border-style:solid;border-width:1px;width:95%}p.description,.form-wrap p{margin:2px 0 5px}p.help,p.description,span.description,.form-wrap p{font-size:12px;font-style:italic;font-family:sans-serif}.form-wrap .form-field{margin:0 0 10px;padding:8px 0}.form-wrap .form-field #parent{max-width:100%}.col-wrap h3{margin:12px 0;font-size:1.1em}.col-wrap p.submit{margin-top:-10px}#poststuff .taghint{color:#aaa;margin:15px 0 -24px 12px}#poststuff .tagsdiv .howto{margin:0 0 6px 8px}.ajaxtag .newtag{position:relative}.tagsdiv .newtag{width:180px}.tagsdiv .the-tags{display:block;height:60px;margin:0 auto;overflow:auto;width:260px}#post-body-content .tagsdiv .the-tags{margin:0 5px}p.popular-tags{-webkit-border-radius:8px;border-radius:8px;border-width:1px;border-style:solid;line-height:2em;max-width:1000px;padding:8px 12px 12px;text-align:justify}p.popular-tags a{padding:0 3px}.tagcloud{width:97%;margin:0 0 40px;text-align:justify}.tagcloud h3{margin:2px 0 12px}.ac_results{padding:0;margin:0;list-style:none;position:absolute;z-index:10000;display:none;border-width:1px;border-style:solid}.ac_results li{padding:2px 5px;white-space:nowrap;text-align:left}.ac_over{cursor:pointer}.ac_match{text-decoration:underline}table.links-table{width:100%}.links-table th{font-weight:400;text-align:left;vertical-align:top;min-width:80px;width:20%;word-wrap:break-word}.links-table th,.links-table td{padding:5px 0}.links-table td label{margin-right:8px}.links-table td input[type=text],.links-table td textarea{width:100%}.links-table #link_rel{max-width:280px}.media-item .describe{border-collapse:collapse;width:100%;border-top-style:solid;border-top-width:1px;clear:both;cursor:default}.media-item.media-blank .describe{border:0}.media-item .describe th{vertical-align:top;text-align:left;padding:5px 10px 10px;width:140px}.media-item .describe .align th{padding-top:0}.media-item .media-item-info tr{background-color:transparent}.media-item .describe td{padding:0 8px 8px 0;vertical-align:top}.media-item thead.media-item-info td{padding:4px 10px 0}.media-item .media-item-info .A1B1{padding:0 0 0 10px}.media-item td.savesend{padding-bottom:15px}.media-item .thumbnail{max-height:128px;max-width:128px}#wpbody-content #async-upload-wrap a{display:none}.media-upload-form{margin-top:20px}.media-upload-form td label{margin-right:6px;margin-left:2px}.media-upload-form .align .field label{display:inline;padding:0 0 0 23px;margin:0 1em 0 3px;font-weight:700}.media-upload-form tr.image-size label{margin:0 0 0 5px;font-weight:700}.media-upload-form th.label label{font-weight:700;margin:.5em;font-size:13px}.media-upload-form th.label label span{padding:0 5px}abbr.required{border:medium none;text-decoration:none}.media-item .describe input[type=text],.media-item .describe textarea{width:460px}.media-item .describe p.help{margin:0;padding:0 0 0 5px}.media-item .edit-attachment,.describe-toggle-on,.describe-toggle-off{display:block;line-height:36px;float:right;margin-right:15px}.media-item .describe-toggle-off,.media-item.open .describe-toggle-on{display:none}.media-item.open .describe-toggle-off{display:block}#media-items .media-item{border-style:solid;border-width:1px;min-height:36px;position:relative;margin-top:-1px;width:100%}#media-items{width:623px}.media-new-php #media-items{margin:1em 0}#media-items:empty{border:0 none}.media-item .filename{line-height:36px;overflow:hidden;padding:0 10px}.media-item .error-div{padding-left:10px}.media-item .pinkynail{float:left;margin:2px 2px 0;max-width:40px;max-height:32px}.media-item .startopen,.media-item .startclosed{display:none}.media-item .original{position:relative;height:34px}.media-item .progress{float:right;height:22px;margin:6px 10px 0 0;width:200px;line-height:2em;padding:0;overflow:hidden;margin-bottom:2px;border:1px solid #d1d1d1;background:#f7f7f7;background-image:-webkit-gradient(linear,left bottom,left top,from(#fff),to(#f7f7f7));background-image:-webkit-linear-gradient(bottom,#fff,#f7f7f7);background-image:-moz-linear-gradient(bottom,#fff,#f7f7f7);background-image:-o-linear-gradient(bottom,#fff,#f7f7f7);background-image:linear-gradient(to top,#fff,#f7f7f7);-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 0 3px rgba(0,0,0,.1);box-shadow:inset 0 0 3px rgba(0,0,0,.1)}.media-item .bar{z-index:9;width:0;height:100%;margin-top:-24px;background-color:#8cc1e9;background-image:-webkit-gradient(linear,left bottom,left top,from(#72a7cf),to(#8cc1e9));background-image:-webkit-linear-gradient(bottom,#72a7cf,#8cc1e9);background-image:-moz-linear-gradient(bottom,#72a7cf,#8cc1e9);background-image:-o-linear-gradient(bottom,#72a7cf,#8cc1e9);background-image:linear-gradient(to top,#72a7cf,#8cc1e9);-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 0 3px rgba(0,0,0,.3);box-shadow:0 0 3px rgba(0,0,0,.3)}.media-item .progress .percent{z-index:10;position:relative;width:200px;padding:0 8px;text-shadow:0 1px 0 rgba(255,255,255,.4);color:rgba(0,0,0,.6)}.upload-php .fixed .column-parent{width:15%}.js .html-uploader #plupload-upload-ui{display:none}.js .html-uploader #html-upload-ui{display:block}.media-upload-form .media-item.error{margin:0;padding:0}.media-upload-form .media-item.error p,.media-item .error-div{line-height:16px;margin:5px 10px;padding:0}.media-item .error-div a.dismiss{display:block;float:right;margin:5px 4px 0 15px}.find-box{width:600px;height:300px;overflow:hidden;padding:33px 0 51px;position:absolute;z-index:1000}.find-box-head{cursor:move;font-weight:700;height:2em;line-height:2em;padding:1px 12px;position:absolute;top:5px;width:100%}.find-box-inside{overflow:auto;padding:6px;height:100%}.find-box-search{overflow:hidden;padding:9px;position:relative}.find-box-search .spinner{float:none;left:125px;position:absolute;top:9px}#find-posts-input{float:left;width:140px;height:24px}#find-posts-search{float:left;margin:1px 4px 0 3px}#find-posts-response{margin:8px 0;padding:0 1px 6px}#find-posts-response table{width:100%}#find-posts-response .found-radio{padding:3px 0 0 8px;width:15px}.find-box-buttons{padding:8px;overflow:hidden}.find-box #resize-se{position:absolute;right:1px;bottom:1px}.ui-find-overlay{position:absolute;top:0;left:0;background-color:#000;opacity:.6;filter:alpha(opacity=60)}ul#dismissed-updates{display:none}form.upgrade{margin-top:8px}form.upgrade .hint{font-style:italic;font-size:85%;margin:-.5em 0 2em 0}#poststuff .inside .the-tagcloud{margin:5px 0 10px;padding:8px;border-width:1px;border-style:solid;line-height:1.8em;word-spacing:3px;-webkit-border-radius:6px;border-radius:6px}.drag-drop #drag-drop-area{border:4px dashed #DDD;height:200px}.drag-drop .drag-drop-inside{margin:70px auto 0;width:250px}.drag-drop-inside p{color:#aaa;font-size:14px;margin:5px 0;display:none}.drag-drop .drag-drop-inside p{text-align:center}.drag-drop-inside p.drag-drop-info{font-size:20px}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}#plupload-upload-ui{position:relative}.describe .image-editor{vertical-align:top}.imgedit-wrap{position:relative}.imgedit-settings p{margin:8px 0}.post-php .imgedit-wrap table{width:100%}.describe .imgedit-wrap table td,.wp_attachment_holder .imgedit-wrap table td{vertical-align:top;padding-top:0}.describe .imgedit-wrap table td.imgedit-settings{padding:0 5px}.wp_attachment_holder .imgedit-wrap table td.imgedit-settings{width:250px}td.imgedit-settings input{margin-top:0;vertical-align:middle}.imgedit-wait{position:absolute;top:0;background:#fff url(../images/wpspin_light.gif) no-repeat scroll 22px 10px;background-size:16px 16px;opacity:.7;filter:alpha(opacity=70);width:100%;height:500px;display:none}.spinner{background:url(../images/wpspin_light.gif) no-repeat;background-size:16px 16px;display:none;float:right;opacity:.7;filter:alpha(opacity=70);width:16px;height:16px;margin:5px 5px 0}.no-float{float:none}.media-disabled,.imgedit-settings .disabled{color:grey}.wp_attachment_image,.A1B1{overflow:hidden}.wp_attachment_image .button,.A1B1 .button{float:left}.no-js .wp_attachment_image .button{display:none}.wp_attachment_image .spinner,.A1B1 .spinner{float:left;padding:0 4px 4px;vertical-align:bottom}.imgedit-menu{margin:0 0 12px;min-width:300px}.imgedit-menu div{float:left;width:32px;height:32px}.imgedit-crop-wrap{position:relative}.imgedit-crop{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -9px -31px;margin:0 8px 0 0}.imgedit-crop.disabled:hover{background-position:-9px -31px}.imgedit-crop:hover{background-position:-9px -1px}.imgedit-rleft{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -46px -31px;margin:0 3px}.imgedit-rleft.disabled:hover{background-position:-46px -31px}.imgedit-rleft:hover{background-position:-46px -1px}.imgedit-rright{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -77px -31px;margin:0 8px 0 3px}.imgedit-rright.disabled:hover{background-position:-77px -31px}.imgedit-rright:hover{background-position:-77px -1px}.imgedit-flipv{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -115px -31px;margin:0 3px}.imgedit-flipv.disabled:hover{background-position:-115px -31px}.imgedit-flipv:hover{background-position:-115px -1px}.imgedit-fliph{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -147px -31px;margin:0 8px 0 3px}.imgedit-fliph.disabled:hover{background-position:-147px -31px}.imgedit-fliph:hover{background-position:-147px -1px}.imgedit-undo{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -184px -31px;margin:0 3px}.imgedit-undo.disabled:hover{background-position:-184px -31px}.imgedit-undo:hover{background-position:-184px -1px}.imgedit-redo{background:transparent url(../images/imgedit-icons.png) no-repeat scroll -215px -31px;margin:0 8px 0 3px}.imgedit-redo.disabled:hover{background-position:-215px -31px}.imgedit-redo:hover{background-position:-215px -1px}.imgedit-applyto img{margin:0 8px 0 0}.imgedit-group-top{margin:5px 0}.imgedit-applyto .imgedit-label{padding:2px 0 0;display:block}.imgedit-help{display:none;font-style:italic;margin-bottom:8px}a.imgedit-help-toggle{text-decoration:none}.form-table td.imgedit-response{padding:0}.imgedit-submit{margin:8px 0}.imgedit-submit-btn{margin-left:20px}.imgedit-wrap .nowrap{white-space:nowrap}span.imgedit-scale-warn{color:red;font-size:20px;font-style:normal;visibility:hidden;vertical-align:middle}.imgedit-group{border-width:1px;border-style:solid;-webkit-border-radius:3px;border-radius:3px;margin-bottom:8px;padding:2px 10px}.form-table{border-collapse:collapse;margin-top:.5em;width:100%;margin-bottom:-8px;clear:both}.form-table td{margin-bottom:9px;padding:8px 10px;line-height:20px;font-size:12px}.form-table th,.form-wrap label{font-weight:400;text-shadow:#fff 0 1px 0}.form-table th{vertical-align:top;text-align:left;padding:10px;width:200px}.form-table th.th-full{width:auto}.form-table div.color-option{display:block;clear:both;margin-top:12px}.form-table input.tog{margin-top:2px;margin-right:2px;float:left}.form-table td p{margin-top:4px}.form-table table.color-palette{vertical-align:bottom;float:left;margin:-12px 3px 11px}.form-table .color-palette td{border-width:1px 1px 0;border-style:solid solid none;height:10px;line-height:20px;width:10px}.commentlist li{padding:1em 1em .2em;margin:0;border-bottom-width:1px;border-bottom-style:solid}.commentlist li li{border-bottom:0;padding:0}.commentlist p{padding:0;margin:0 0 .8em}#replyrow input{border-width:1px;border-style:solid}#replyrow td{padding:2px}#replysubmit{margin:0;padding:0 5px 3px;text-align:center}#replysubmit .spinner{padding:2px 0 0;vertical-align:top;float:right}#replysubmit .button{margin-right:5px}#replysubmit .error{color:red;line-height:21px;text-align:center}#replyrow h5{margin:.2em 0 0;padding:0 5px;line-height:1.4em;font-size:1em}#edithead .inside{float:left;padding:3px 0 2px 5px;margin:0;text-align:center}#edithead .inside input{width:180px}#edithead label{padding:2px 0}#replycontainer{padding:5px}#replycontent{height:120px;-webkit-box-shadow:none;box-shadow:none}.comment-php .wp-editor-area{height:200px}.comment-ays{margin-bottom:0;border-style:solid;border-width:1px}.comment-ays th{border-right-style:solid;border-right-width:1px}.trash-undo-inside,.spam-undo-inside{margin:1px 8px 1px 0;line-height:16px}.spam-undo-inside .avatar,.trash-undo-inside .avatar{height:20px;width:20px;margin-right:8px;vertical-align:middle}.stuffbox .editcomment{clear:none}#comment-status-radio p{margin:3px 0 5px}#comment-status-radio input{margin:2px 3px 5px 0;vertical-align:middle}#comment-status-radio label{padding:5px 0}.commentlist .avatar{vertical-align:text-top}.theme-install-php .tablenav{height:auto}.theme-install-php .spinner{margin-top:9px}h3.available-themes{margin:.3em 0 1em;float:left}.available-theme{display:inline-block;margin-right:10px;overflow:hidden;padding:20px 20px 20px 0;vertical-align:top;width:300px}.available-theme .screenshot{width:300px;height:225px;display:block;border-width:1px;border-style:solid;margin-bottom:10px;overflow:hidden}.available-theme img{width:300px}.available-theme h3{margin:15px 0 0}.available-theme .theme-author{line-height:18px}.available-theme .action-links{margin-top:10px;overflow:hidden}.available-theme a.screenshot:focus{border-color:#777}#current-theme .theme-info li,.theme-options li,.available-theme .action-links li{float:left;padding-right:10px;margin-right:10px;border-right:1px solid #dfdfdf}.available-theme .action-links li{padding-right:8px;margin-right:8px}.ie8 .available-theme .action-links li{padding-right:7px;margin-right:7px}#current-theme .theme-info li:last-child,.theme-options li:last-child,.available-theme .action-links li:last-child{padding-right:0;margin-right:0;border-right:0}.available-theme .action-links .delete-theme{float:right;margin-left:8px;margin-right:0}.available-theme .action-links .delete-theme a{color:red;padding:2px}.available-theme .action-links .delete-theme a:hover{background:red;color:#fff;text-decoration:none}.available-theme .action-links p{float:left}#current-theme{margin:20px 0 10px;padding:0 0 20px;border-bottom-width:1px;border-bottom-style:solid;overflow:hidden}#current-theme.has-screenshot{padding-left:330px}#current-theme h3{margin:0;font-size:12px;font-weight:400;color:#999}#current-theme h4{margin:3px 0 16px;font-size:20px}#current-theme h4 span{margin-left:20px;font-size:12px;font-weight:400}#current-theme a{border-bottom:0}#current-theme .theme-info{margin:1em 0;overflow:hidden}#current-theme .theme-description{margin-top:5px;max-width:600px;line-height:1.6em}#current-theme img{float:left;width:300px;margin-left:-330px;border-width:1px;border-style:solid}.theme-options{overflow:hidden;font-size:14px;padding-bottom:10px}.theme-options .load-customize{margin-right:30px;float:left}.theme-options span{float:left;margin-right:10px;text-transform:uppercase;font-size:11px;line-height:18px;color:#999}.theme-options ul{float:left;margin:0}@media only screen and (max-width:1200px){.folded .available-theme,.folded .available-theme .screenshot{width:300px}.folded .available-theme .screenshot{height:225px}.folded #current-theme img{width:300px}.folded #current-theme.has-screenshot{padding-left:330px}.folded #current-theme img{margin-left:-330px}}@media only screen and (max-width:1079px){.folded .available-theme,.folded .available-theme .screenshot{width:270px}.folded .available-theme .screenshot{height:203px}.folded #current-theme img{width:270px}.folded #current-theme.has-screenshot{padding-left:300px}.folded #current-theme img{margin-left:-300px}}@media only screen and (max-width:1200px){.available-theme,.available-theme .screenshot,#current-theme img{width:240px}.available-theme .screenshot{height:180px}.available-theme img{width:100%}#current-theme.has-screenshot{padding-left:270px}#current-theme img{margin-left:-270px}}#post-body ul.add-menu-item-tabs li.tabs a,#TB_window #TB_title a.tb-theme-preview-link,#TB_window #TB_title a.tb-theme-preview-link:visited{font-weight:700;text-decoration:none}#TB_window #TB_title{background-color:#222;color:#cfcfcf}#broken-themes{text-align:left;width:50%;border-spacing:3px;padding:3px}.theme-install-php h4{margin:2.5em 0 8px}.appearance_page_custom-header #headimg{border:1px solid #DFDFDF;overflow:hidden;width:100%}.appearance_page_custom-header #upload-form p label{font-size:12px}.appearance_page_custom-header .available-headers .default-header{float:left;margin:0 20px 20px 0}.appearance_page_custom-header .random-header{clear:both;margin:0 20px 20px 0;vertical-align:middle}.appearance_page_custom-header .available-headers label input,.appearance_page_custom-header .random-header label input{margin-right:10px}.appearance_page_custom-header .available-headers label img{vertical-align:middle}div#custom-background-image{min-height:100px;border:1px solid #dfdfdf}div#custom-background-image img{max-width:400px;max-height:300px}.nav-tab{border-style:solid;border-width:1px 1px 0;color:#aaa;text-shadow:#fff 0 1px 0;font-size:12px;line-height:16px;display:inline-block;padding:4px 14px 6px;text-decoration:none;margin:0 6px -1px 0;-webkit-border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px}.nav-tab-active{border-width:1px;color:#464646}h2.nav-tab-wrapper,h3.nav-tab-wrapper{border-bottom-width:1px;border-bottom-style:solid;padding-bottom:0}h2 .nav-tab{padding:4px 10px 6px;font-weight:200;font-size:20px;line-height:24px}#dashboard_right_now .versions .b,#post-status-display,#post-visibility-display,#adminmenu .wp-submenu li.current,#adminmenu .wp-submenu li.current a,#adminmenu .wp-submenu li.current a:hover,.media-item .percent,.plugins .name,#pass-strength-result.strong,#pass-strength-result.short,#ed_reply_toolbar #ed_reply_strong,.item-controls .item-order a,.feature-filter .feature-name{font-weight:700}.plugins p{margin:0 4px;padding:0}.plugins .desc p{margin:0 0 8px}.plugins td.desc{line-height:1.5em}.plugins .desc ul,.plugins .desc ol{margin:0 0 0 2em}.plugins .desc ul{list-style-type:disc}.plugins .row-actions{padding:0}.plugins tbody th.check-column{padding:7px 0}.plugins .inactive td,.plugins .inactive th,.plugins .active td,.plugins .active th{border-top-style:solid;border-top-width:1px;padding:5px 7px 0}.plugins .update th,.plugins .update td{border-bottom:0}.plugin-update-tr td{border-top:0}#wpbody-content .plugins .plugin-title,#wpbody-content .plugins .theme-title{padding-right:12px;white-space:nowrap}.plugins .second,.plugins .row-actions{padding:0 0 5px}.plugins .update .second,.plugins .update .row-actions{padding-bottom:0}.plugins-php .widefat tfoot th,.plugins-php .widefat tfoot td{border-top-style:solid;border-top-width:1px}.plugin-update-tr .update-message{margin:5px;padding:3px 5px}.plugin-install-php h4{margin:2.5em 0 8px}#profile-page .form-table textarea{width:500px;margin-bottom:6px}#profile-page .form-table #rich_editing{margin-right:5px}#your-profile legend{font-size:22px}#your-profile #rich_editing{border:0}#display_name{width:15em}#createuser .form-field input{width:25em}.pressthis{margin:20px 0}.pressthis a,.pressthis a:hover,.pressthis a:focus,.pressthis a:active{display:inline-block;position:relative;cursor:move;color:#333;background:#e6e6e6;background-image:-webkit-gradient(linear,left bottom,left top,color-stop(7%,#e6e6e6),color-stop(77%,#d8d8d8));background-image:-webkit-linear-gradient(bottom,#e6e6e6 7%,#d8d8d8 77%);background-image:-moz-linear-gradient(bottom,#e6e6e6 7%,#d8d8d8 77%);background-image:-o-linear-gradient(bottom,#e6e6e6 7%,#d8d8d8 77%);background-image:linear-gradient(to top,#e6e6e6 7%,#d8d8d8 77%);-webkit-border-radius:5px;border-radius:5px;border:1px solid #b4b4b4;font-style:normal;line-height:16px;font-size:14px;text-decoration:none;text-shadow:0 1px 0 #fff}.pressthis a:active{outline:0}.pressthis a:hover:after{-webkit-transform:skew(20deg) rotate(9deg);-moz-transform:skew(20deg) rotate(9deg);transform:skew(20deg) rotate(9deg);-webkit-box-shadow:0 10px 8px rgba(0,0,0,.7);box-shadow:0 10px 8px rgba(0,0,0,.7)}.pressthis a span{background:url(../images/press-this.png?v=20120502) no-repeat 0 5px;background-size:24px 20px;padding:8px 11px 8px 27px;margin:0 5px;display:inline-block}.pressthis a:after{content:'';width:70%;height:55%;z-index:-1;position:absolute;right:10px;bottom:9px;background:transparent;-webkit-transform:skew(20deg) rotate(6deg);-moz-transform:skew(20deg) rotate(6deg);transform:skew(20deg) rotate(6deg);-webkit-box-shadow:0 10px 8px rgba(0,0,0,.6);box-shadow:0 10px 8px rgba(0,0,0,.6)}#utc-time,#local-time{padding-left:25px;font-style:italic;font-family:sans-serif}.defaultavatarpicker .avatar{margin:2px 0;vertical-align:middle}.options-general-php .spinner{float:none;margin:-3px 3px}#wpfooter{position:absolute;bottom:0;left:0;right:0;padding:10px 0;margin-right:20px;border-top-width:1px;border-top-style:solid}#wpfooter p{margin:0;line-height:20px}#wpfooter a{text-decoration:none}#wpfooter a:hover{text-decoration:underline}.about-wrap{position:relative;margin:25px 40px 0 20px;max-width:1050px;font-size:15px}.about-wrap div.updated,.about-wrap div.error{display:none!important}.about-wrap p.about-notice{background-color:#ffffe0;border:1px solid #e6db55;margin:5px 0 15px;padding:.4em .8em;border-radius:3px;-webkit-border-radius:3px}.about-wrap p{line-height:1.6em}.about-wrap h1{margin:.2em 200px 0 0;line-height:1.2em;font-size:2.8em;font-weight:200}.about-text,.about-description,.about-wrap li.wp-person a.web{font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",sans-serif;font-weight:400;line-height:1.6em;font-size:20px}.about-description{margin-top:1.4em}.about-text{margin:1em 200px 1.4em 0;min-height:60px;font-size:24px}.about-wrap h3{font-size:1.5em;line-height:1.5em;padding-top:20px}.about-wrap .feature-section{padding-bottom:20px}.about-wrap .feature-section h4{margin-bottom:.6em}.about-wrap .feature-section p{margin-top:.6em}.about-wrap code{font-size:14px}.about-wrap .point-releases{margin-top:5px}.about-wrap .changelog.point-releases h3{padding-top:35px}.about-wrap .changelog.point-releases h3:first-child{padding-top:7px}.wp-badge{padding-top:142px;height:50px;width:173px;font-weight:700;font-size:14px;text-align:center;margin:0 -5px;background:url(../images/wp-badge.png?ver=20111120) no-repeat}.about-wrap .wp-badge{position:absolute;top:0;right:0}.about-wrap h2.nav-tab-wrapper{padding-left:6px}.about-wrap h2 .nav-tab{padding:4px 10px 6px;margin:0 3px -1px 0;font-size:18px;vertical-align:top}.about-wrap h2 .nav-tab-active{font-weight:700;padding-top:3px}.about-wrap .feature-section.three-col img{margin:.5em 0 .5em 5px;max-width:100%;float:none}.about-wrap .feature-section.col{margin-bottom:0}.about-wrap .feature-section.col h4{margin:0 0 .6em}.about-wrap .feature-section.two-col div{width:47%;margin-right:4.999999999%;float:left}.about-wrap .feature-section.three-col div{width:30%;margin-right:4.999999999%;float:left}.about-wrap .three-col.about-updates .col-1,.about-wrap .three-col.about-updates .col-3{width:37%;margin:0}.about-wrap .three-col.about-updates .col-2{width:16%;margin:0 5%}.about-wrap .feature-section.col .last-feature{margin-right:0}.about-wrap .three-col.about-updates img{margin:0}.about-wrap .changelog .feature-section{overflow:hidden}.about-wrap .about-passwords{margin:20px 0;padding:1px 20px 10px;background-color:#f9f9f9}.about-wrap .about-auto-update{text-align:center;background-color:#f9f9ef;clear:both;padding:10px}.about-wrap .about-auto-update.cool{background-color:#eff9ef}.about-wrap .about-password-meter input{font-size:250%;line-height:1;width:100%;display:block;padding:5px}.about-wrap .about-password-meter #pass-strength-result{display:block!important;font-size:150%;font-weight:400!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;padding:17px 0;margin-bottom:15px}.about-wrap .feature-section div p img{float:right;margin-left:10px;max-width:20%}.about-wrap .changelog li{list-style-type:disc;margin-left:3em}.about-wrap .return-to-dashboard{margin:30px 0 0 -5px;font-size:14px;font-weight:700}.about-wrap .return-to-dashboard a{text-decoration:none;padding:0 5px}.about-wrap h4.wp-people-group{margin-top:2.6em;font-size:16px}.about-wrap ul.wp-people-group{overflow:hidden;padding:0 5px;margin:0 -15px 0 -5px}.about-wrap ul.compact{margin-bottom:0}.about-wrap li.wp-person{float:left;margin-right:10px}.about-wrap li.wp-person img.gravatar{float:left;margin:0 10px 10px 0;padding:2px;width:60px;height:60px}.about-wrap ul.compact li.wp-person img.gravatar{width:30px;height:30px}.about-wrap li.wp-person{height:70px;width:280px;padding-bottom:15px}.about-wrap ul.compact li.wp-person{height:auto;width:180px;padding-bottom:0;margin-bottom:0}.about-wrap #wp-people-group-validators+p.wp-credits-list{margin-top:0}.about-wrap li.wp-person a.web{display:block;margin:6px 0 2px;font-size:16px;text-decoration:none}.about-wrap p.wp-credits-list a{white-space:nowrap}.freedoms-php .about-wrap ol{margin:40px 60px}.freedoms-php .about-wrap ol li{list-style-type:decimal;font-weight:700}.freedoms-php .about-wrap ol p{font-weight:400;margin:.6em 0}body.full-overlay-active{overflow:hidden}.wp-full-overlay{background:#fff;z-index:500000;position:fixed;overflow:visible;top:0;bottom:0;left:0;right:0;height:100%;min-width:0}.wp-full-overlay-sidebar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:fixed;width:300px;height:100%;top:0;bottom:0;left:0;padding:0;margin:0;z-index:10;overflow:auto;background:#f5f5f5;border-right:1px solid rgba(0,0,0,.2)}.wp-full-overlay.collapsed .wp-full-overlay-sidebar{overflow:visible}.wp-full-overlay.collapsed,.wp-full-overlay.expanded .wp-full-overlay-sidebar{margin-left:0!important}.wp-full-overlay.expanded{margin-left:300px}.wp-full-overlay.collapsed .wp-full-overlay-sidebar{margin-left:-300px}.wp-full-overlay-sidebar:after{content:'';display:block;position:absolute;top:0;bottom:0;right:0;width:3px;box-shadow:-5px 0 4px -4px rgba(0,0,0,.1) inset;z-index:1000}.wp-full-overlay-main{position:absolute;left:0;right:0;top:0;bottom:0;height:100%}.wp-full-overlay-sidebar .wp-full-overlay-header{position:absolute;left:0;right:0;height:45px;padding:0 20px;line-height:45px;z-index:10;margin:0}.wp-full-overlay-sidebar .wp-full-overlay-header{border-top:0;border-bottom:1px solid #fff;box-shadow:inset 0 -1px 0 0 #dfdfdf}.wp-full-overlay-sidebar .wp-full-overlay-footer{bottom:0;border-bottom:0;border-top:1px solid #dfdfdf;box-shadow:inset 0 1px 0 0 #fff}.wp-full-overlay-sidebar .wp-full-overlay-sidebar-content{position:absolute;top:45px;bottom:45px;left:0;right:0;overflow:auto}.wp-full-overlay-sidebar-content .accordion-section:first-child{border-top:1px solid #fff}.wp-full-overlay .close-full-overlay{text-decoration:none}.wp-full-overlay a.collapse-sidebar{position:absolute;bottom:12px;left:0;z-index:50;display:block;width:19px;height:19px;margin-left:15px;padding:0;border-radius:50%;text-decoration:none}.wp-full-overlay.collapsed .collapse-sidebar{position:absolute;left:100%}.wp-full-overlay .collapse-sidebar-arrow{position:absolute;margin-top:2px;margin-left:2px;display:block;width:15px;height:15px;background:transparent url(../images/arrows.png) no-repeat -1px -73px}.wp-full-overlay.collapsed .collapse-sidebar-arrow{background-position:-1px -109px}.wp-full-overlay .collapse-sidebar-label{position:absolute;left:100%;color:gray;line-height:20px;margin-left:10px}.wp-full-overlay.collapsed .collapse-sidebar-label{display:none}.wp-full-overlay .collapse-sidebar:hover .collapse-sidebar-label{color:#666}.wp-full-overlay,.wp-full-overlay-sidebar,.wp-full-overlay .collapse-sidebar,.wp-full-overlay-main{-webkit-transition-property:left,right,top,bottom,width,margin;-moz-transition-property:left,right,top,bottom,width,margin;-ms-transition-property:left,right,top,bottom,width,margin;-o-transition-property:left,right,top,bottom,width,margin;transition-property:left,right,top,bottom,width,margin;-webkit-transition-duration:.2s;-moz-transition-duration:.2s;-ms-transition-duration:.2s;-o-transition-duration:.2s;transition-duration:.2s}.no-customize-support .hide-if-no-customize,.customize-support .hide-if-customize,.no-customize-support.wp-core-ui .hide-if-no-customize,.no-customize-support .wp-core-ui .hide-if-no-customize,.customize-support.wp-core-ui .hide-if-customize,.customize-support .wp-core-ui .hide-if-customize{display:none}#customize-container{display:none;background:#fff;z-index:500000;position:fixed;overflow:visible;top:0;bottom:0;left:0;right:0;height:100%}.customize-active #customize-container{display:block}.customize-loading #customize-container iframe{opacity:0}.customize-loading #customize-container{background:#fff url(../images/wpspin_light.gif) no-repeat fixed center center;background-size:16px 16px}#customize-container iframe,#theme-installer iframe{height:100%;width:100%;z-index:20;-webkit-transition:opacity .3s;-moz-transition:opacity .3s;-ms-transition:opacity .3s;-o-transition:opacity .3s;transition:opacity .3s}#customize-container .collapse-sidebar{bottom:16px}#theme-installer{display:none}#theme-installer.single-theme{display:block}.install-theme-info{display:none;padding:10px 20px 20px}.single-theme .install-theme-info{padding-top:15px}#theme-installer .install-theme-info{display:block}.install-theme-info .theme-install{float:right;margin-top:18px}.install-theme-info .theme-name{font-size:16px;line-height:24px;margin-bottom:0}.install-theme-info .theme-screenshot{margin-top:15px;width:258px;border:1px solid #ccc}.install-theme-info .theme-details{overflow:hidden}.theme-details .theme-version{margin:15px 0;float:left}.theme-details .star-holder{margin:14px 0;float:right}.theme-details .theme-description{float:left;color:#777;line-height:20px}#excerpt,.attachmentlinks{margin:0;height:4em;width:98%}#template div{margin-right:190px}p.pagenav{margin:0;display:inline}.pagenav span{font-weight:700;margin:0 6px}.row-title{font-size:13px!important;font-weight:700}.column-author img,.column-username img{float:left;margin-right:10px;margin-top:1px}.row-actions{visibility:hidden;padding:2px 0 0}tr:hover .row-actions,.mobile .row-actions,.row-actions.visible,div.comment-item:hover .row-actions{visibility:visible}.row-actions-visible{padding:2px 0 0}.form-table .pre{padding:8px;margin:0}table.form-table td .updated{font-size:13px}.tagchecklist{margin-left:14px;font-size:12px;overflow:auto}.tagchecklist strong{margin-left:-8px;position:absolute}.tagchecklist span{margin-right:25px;display:block;float:left;font-size:11px;line-height:1.8em;white-space:nowrap;cursor:default}.tagchecklist span a{margin:4px 0 0 -10px;cursor:pointer;width:10px;height:10px;display:block;float:left;text-indent:-9999px;overflow:hidden;position:absolute}#poststuff h2{margin-top:20px;font-size:1.5em;margin-bottom:15px;padding:0 0 3px;clear:left}#poststuff h3,.metabox-holder h3{font-size:15px;font-weight:400;padding:7px 10px;margin:0;line-height:1}#poststuff .inside{margin:6px 0 8px}#poststuff .inside #parent_id,#poststuff .inside #page_template{max-width:100%}.inline-edit-row #post_parent,.inline-edit-row select[name=page_template]{max-width:80%}.ie8 #poststuff .inside #parent_id,.ie8 #poststuff .inside #page_template,.ie8 .inline-edit-row #post_parent,.ie8 .inline-edit-row select[name=page_template]{width:250px}#post-visibility-select{line-height:1.5em;margin-top:3px}#poststuff #submitdiv .inside{margin:0;padding:0}.edit-form-section{margin-bottom:20px}#templateside ul li a{text-decoration:none}.tool-box .title{margin:8px 0;font-size:18px;font-weight:400;line-height:24px}#sidemenu{margin:-30px 15px 0 315px;list-style:none;position:relative;float:right;padding-left:10px;font-size:12px}#sidemenu a{padding:0 7px;display:block;float:left;line-height:28px;border-top-width:1px;border-top-style:solid;border-bottom-width:1px;border-bottom-style:solid}#sidemenu li{display:inline;line-height:200%;list-style:none;text-align:center;white-space:nowrap;margin:0;padding:0}#sidemenu a.current{font-weight:400;padding-left:6px;padding-right:6px;-webkit-border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-left-radius:3px;border-top-right-radius:3px;border-width:1px;border-style:solid}#sidemenu li a .count-0{display:none}.plugin-install #description,.plugin-install-network #description{width:60%}table .vers,table .column-visible,table .column-rating{text-align:left}.error-message{color:red;font-weight:700}body.iframe{height:98%}.lp-show-latest p{display:none}.lp-show-latest p:last-child,.lp-show-latest .lp-error p{display:block}td.media-icon{text-align:center;width:80px;padding-top:8px;padding-bottom:8px}td.media-icon img{max-width:80px;max-height:60px}#howto{font-size:11px;margin:0 5px;display:block}.importers td{padding-right:14px}.importers{font-size:16px;width:auto}#namediv table{width:100%}#namediv td.first{width:10px;white-space:nowrap}#namediv input{width:98%}#namediv p{margin:10px 0}#submitdiv h3{margin-bottom:0!important}.zerosize{height:0;width:0;margin:0;border:0;padding:0;overflow:hidden;position:absolute}br.clear{height:2px;line-height:2px}.checkbox{border:0;margin:0;padding:0}fieldset{border:0;padding:0;margin:0}.post-categories{display:inline;margin:0;padding:0}.post-categories li{display:inline}.edit-box{display:none}h3:hover .edit-box{display:inline}#dashboard-widgets form .input-text-wrap input{width:100%}#dashboard-widgets form .textarea-wrap textarea{width:100%}#dashboard-widgets .postbox form .submit{float:none;margin:.5em 0 0;padding:0;border:0}#dashboard-widgets-wrap #dashboard-widgets .postbox form .submit #publish{min-width:0}#dashboard-widgets a{text-decoration:none}#dashboard-widgets h3 a{text-decoration:underline}#dashboard-widgets h3 .postbox-title-action{position:absolute;right:10px;padding:0;top:5px}.js #dashboard-widgets h3 .postbox-title-action{right:30px}#dashboard-widgets h4{font-weight:400;font-size:13px;margin:0 0 .2em;padding:0}#dashboard_right_now p.sub,#dashboard_right_now .table,#dashboard_right_now .versions{margin:-12px}#dashboard_right_now .inside{font-size:12px;padding-top:20px}#dashboard_right_now p.sub{padding:5px 0 15px;color:#8f8f8f;font-size:14px;position:absolute;top:-17px;left:15px}#dashboard_right_now .table{margin:0;padding:0;position:relative}#dashboard_right_now .table_content{float:left;border-top-width:1px;border-top-style:solid;width:45%}#dashboard_right_now .table_discussion{float:right;border-top-width:1px;border-top-style:solid;width:45%}#dashboard_right_now table td{padding:3px 0;white-space:nowrap}#dashboard_right_now table tr.first td{border-top:0}#dashboard_right_now td.b{padding-right:6px;text-align:right;font-size:14px;width:1%}#dashboard_right_now td.b a{font-size:18px}#dashboard_right_now td.b a:hover{color:#d54e21}#dashboard_right_now .t{font-size:12px;padding-right:12px;padding-top:6px;color:#777}#dashboard_right_now .t a{white-space:nowrap}#dashboard_right_now .spam{color:red}#dashboard_right_now .waiting{color:#e66f00}#dashboard_right_now .approved{color:green}#dashboard_right_now .versions{padding:6px 10px 12px;clear:both}#dashboard_right_now a.button{float:right;clear:right;position:relative;top:-5px}#dashboard_recent_comments h3{margin-bottom:0}#dashboard_recent_comments .inside{margin-top:0}#dashboard_recent_comments .comment-meta .approve{font-style:italic;font-family:sans-serif;font-size:10px}#dashboard_recent_comments .subsubsub{float:none;white-space:normal}#the-comment-list{position:relative}#the-comment-list .comment-item{padding:1em 10px;border-top:1px solid}#the-comment-list .pingback{padding-left:9px!important}#the-comment-list .comment-item,#the-comment-list #replyrow{margin:0 -10px}#the-comment-list .comment-item:first-child{border-top:0}#the-comment-list .comment-item .avatar{float:left;margin:0 10px 5px 0}#the-comment-list .comment-item h4{line-height:1.7em;margin-top:-.4em;color:#777}#the-comment-list .comment-item h4 cite{font-style:normal;font-weight:400}#the-comment-list .comment-item blockquote,#the-comment-list .comment-item blockquote p{margin:0;padding:0;display:inline}#dashboard_recent_comments #the-comment-list .trackback blockquote,#dashboard_recent_comments #the-comment-list .pingback blockquote{display:block}#the-comment-list .comment-item p.row-actions{margin:3px 0 0;padding:0;font-size:12px}.no-js #dashboard_quick_press{display:none}#dashboard_quick_press .easy-blogging{padding:0 8px;text-align:left}#dashboard_quick_press .input-text-wrap{position:relative}#dashboard_quick_press .prompt{color:#bbb;position:absolute}#dashboard_quick_press div.updated{padding:0 5px}#title-wrap label,#tags-input-wrap label{cursor:text}#title-wrap #title{padding:2px 6px;font-size:1.3em;line-height:100%;outline:0}#tags-input-wrap #tags-input{outline:0}#title-wrap #title-prompt-text{font-size:1.3em;padding:5px 8px}#tags-input-wrap #tags-input-prompt-text{font-size:1em;padding:4px 8px}#dashboard_quick_press .input-text-wrap,#dashboard_quick_press .textarea-wrap{margin:0 0 1em}#dashboard_quick_press .wp-media-buttons{margin:0 0 .2em 1px;padding:0}#dashboard_quick_press .wp-media-buttons a{color:#777}#dashboard-widgets #dashboard_quick_press form p.submit input{float:left}#dashboard-widgets #dashboard_quick_press form p.submit #save-post{margin:0 .7em 0 1px}#dashboard-widgets #dashboard_quick_press form p.submit #publish{float:right}#dashboard-widgets #dashboard_quick_press form p.submit .spinner{vertical-align:middle;margin:4px 6px 0 0}#dashboard_recent_drafts ul,#dashboard_recent_drafts p{margin:0;padding:0;word-wrap:break-word}#dashboard_recent_drafts ul{list-style:none}#dashboard_recent_drafts ul li{margin-bottom:1em}#dashboard_recent_drafts h4{line-height:1.7em;word-wrap:break-word}#dashboard_recent_drafts h4 abbr{font-weight:400;font-family:sans-serif;font-size:12px;color:#999;margin-left:3px}.rss-widget ul{margin:0;padding:0;list-style:none}a.rsswidget{font-size:13px;line-height:1.7em}.rss-widget ul li{line-height:1.5em;margin-bottom:12px}.rss-widget span.rss-date{color:#999;font-size:12px;margin-left:3px}.rss-widget cite{display:block;text-align:right;margin:0 0 1em;padding:0}.rss-widget cite:before{content:'\2014'}#dashboard_plugins h4{line-height:1.7em}#dashboard_plugins h5{font-weight:400;font-size:13px;margin:0;display:inline;line-height:1.4em}#dashboard_plugins h5 a{line-height:1.4em}#dashboard_plugins .inside span{font-size:12px;padding-left:5px}#dashboard_plugins p{margin:.3em 0 1.4em;line-height:1.4em}.dashboard-comment-wrap{overflow:hidden;word-wrap:break-word}#dashboard_browser_nag a.update-browser-link{font-size:1.2em;font-weight:700}#dashboard_browser_nag a{text-decoration:underline}#dashboard_browser_nag p.browser-update-nag.has-browser-icon{padding-right:125px}#dashboard_browser_nag .browser-icon{margin-top:-35px}#dashboard_browser_nag.postbox.browser-insecure{background-color:#ac1b1b;border-color:#ac1b1b}#dashboard_browser_nag.postbox{background-color:#e29808;background-image:none;border-color:#edc048;color:#fff;-webkit-box-shadow:none;box-shadow:none}#dashboard_browser_nag.postbox.browser-insecure h3{border-bottom-color:#cd5a5a;color:#fff}#dashboard_browser_nag.postbox h3{border-bottom-color:#f6e2ac;text-shadow:none;background:transparent none;color:#fff;-webkit-box-shadow:none;box-shadow:none}#dashboard_browser_nag a{color:#fff}#dashboard_browser_nag.browser-insecure a.browse-happy-link,#dashboard_browser_nag.browser-insecure a.update-browser-link{text-shadow:#871b15 0 1px 0}#dashboard_browser_nag a.browse-happy-link,#dashboard_browser_nag a.update-browser-link{text-shadow:#d29a04 0 1px 0}.login *{margin:0;padding:0}.login form{margin-left:8px;padding:26px 24px 46px;font-weight:400;background:#fff;border:1px solid #e5e5e5;-webkit-box-shadow:rgba(200,200,200,.7) 0 4px 10px -1px;box-shadow:rgba(200,200,200,.7) 0 4px 10px -1px}.login form .forgetmenot{font-weight:400;float:left;margin-bottom:0}.login .button-primary{float:right}#login form p{margin-bottom:0}#login form p.submit{padding:0}.login label{color:#777;font-size:14px}.login form .forgetmenot label{font-size:12px;line-height:19px}.login h1 a{background-image:url(../images/wordpress-logo.png?ver=20120216);background-size:274px 63px;background-position:top center;background-repeat:no-repeat;width:326px;height:67px;text-indent:-9999px;outline:0;overflow:hidden;padding-bottom:15px;display:block}#login{width:320px;padding:114px 0 0;margin:auto}#login_error,.login .message{margin:0 0 16px 8px;padding:12px}.login #nav,.login #backtoblog{text-shadow:#fff 0 1px 0;margin:0 0 0 16px;padding:16px 16px 0}#backtoblog{padding:12px 16px 0}.login form .input,.login input[type=text]{color:#555;font-weight:200;font-size:24px;line-height:1;width:100%;padding:3px;margin-top:2px;margin-right:6px;margin-bottom:16px;border:1px solid #e5e5e5;background:#fbfbfb;outline:0;-webkit-box-shadow:inset 1px 1px 2px rgba(200,200,200,.2);box-shadow:inset 1px 1px 2px rgba(200,200,200,.2)}.login #pass-strength-result{width:250px;font-weight:700;border-style:solid;border-width:1px;margin:12px 0 6px;padding:6px 5px;text-align:center}.mobile #login{padding:20px 0}.mobile #login form,.mobile #login .message,.mobile #login_error{margin-left:0}.mobile #login #nav,.mobile #login #backtoblog{margin-left:8px}.mobile #login h1 a{width:auto}body.interim-login{height:auto}.interim-login #login{padding:0;margin:5px auto 20px}.interim-login.login h1 a{width:auto}.interim-login #login_error,.interim-login.login .message{margin:0 0 16px}.interim-login.login form{margin:0}#dashboard_right_now p.musub{margin-top:12px;border-top:1px solid #ececec;padding-left:16px;position:static}.rtl #dashboard_right_now p.musub{padding-left:0;padding-right:16px}#dashboard_right_now td.b a.musublink{font-size:16px}#dashboard_right_now div.musubtable{border-top:0}#dashboard_right_now div.musubtable .t{white-space:normal}.wp-list-table .site-deleted{background:#ff8573}.wp-list-table .site-spammed{background:#faafaa}.wp-list-table .site-archived{background:#ffebe8}.wp-list-table .site-mature{background:#fecac2}.no-js #message{display:block}#nav-menu-meta ul.outer-border{-webkit-border-radius:3px;border-radius:3px}.accordion-section ul.category-tabs,.accordion-section ul.add-menu-item-tabs,.accordion-section ul.wp-tab-bar{margin:0}.accordion-section .categorychecklist{margin:13px 0}#nav-menu-meta .accordion-section-content{padding:18px 13px}#nav-menu-meta .button-controls{margin-bottom:0}#nav-menus-frame{margin-left:300px;margin-top:23px}#wpbody-content #menu-settings-column{display:inline;width:281px;margin-left:-300px;clear:both;float:left;padding-top:0}#menu-settings-column .inside{clear:both;margin:10px 0 0}.metabox-holder-disabled .postbox,.metabox-holder-disabled .accordion-section-content{opacity:.5;filter:alpha(opacity=50)}.metabox-holder-disabled .button-controls .select-all{display:none}#wpbody{position:relative}.blank-slate .menu-name{height:2em}.blank-slate .menu-settings{border:0;margin-top:0;padding-top:0;overflow:hidden}.is-submenu{font-style:italic;font-weight:400;margin-left:4px}.manage-menus{margin-top:23px;padding:10px;overflow:hidden;-webkit-border-radius:3px;border-radius:3px}.manage-menus select{float:left;margin-right:6px}.manage-menus .selected-menu{float:left;margin:5px 6px 0 0}.manage-menus .submit-btn{float:left;margin-top:1px}.menu-edit p{margin:.3em 0 .6em}.menu-edit #post-body-content h3{margin:0 0 10px}.menu-settings{margin-top:2em;overflow:hidden}.menu-settings dl{margin:0 0 10px;overflow:hidden;position:relative}.menu-settings dd{float:left;margin:0;width:60%}.menu-edit .checkbox-input{margin-top:4px}.theme-location-set{font-size:11px}#menu-management-liquid{float:left;min-width:100%;margin-top:3px}#menu-management{position:relative;margin-right:20px;margin-top:-3px;width:100%}#menu-management .menu-edit{margin-bottom:20px}.nav-menus-php #post-body{padding:0 10px 10px;border-width:1px 0;border-style:solid}#nav-menu-header,#nav-menu-footer{padding:0 10px}#nav-menu-header{border-bottom:1px solid;margin-bottom:13px}#nav-menu-header .menu-name-label{margin-top:2px}#nav-menu-footer{border-top:1px solid}.nav-menus-php #post-body div.updated,.nav-menus-php #post-body div.error{margin:0}.nav-menus-php #post-body-content{position:relative;float:none}#menu-management .menu-add-new abbr{font-weight:700}#select-nav-menu-container{text-align:right;padding:0 10px 3px;margin-bottom:5px}#select-nav-menu{width:100px;display:inline}#menu-name-label{margin-top:-2px}.widefat td.menu-location-menus{padding-bottom:5px}.menu-location-menus select{float:left}#locations-nav-menu-wrapper{padding:5px 0}.locations-nav-menu-select select{float:left;width:160px;margin-right:5px}.locations-row-links{float:left;margin:6px 0 0 6px}.locations-edit-menu-link,.locations-add-menu-link{margin:0 3px}.locations-edit-menu-link{padding-right:3px;border-right:1px solid #ccc}#wpbody .open-label{display:block;float:left}#wpbody .open-label span{padding-right:10px}.js .input-with-default-title{font-style:italic}#menu-management .inside{padding:0 10px}.postbox .howto input,.accordion-container .howto input{width:180px;float:right}.accordion-container .outer-border{margin:0}#nav-menu-meta .accordion-container .top{border-top:1px solid #dfdfdf}#nav-menu-meta .accordion-container .accordion-section:first-child,#nav-menu-meta .accordion-container .accordion-section:first-child h3,#nav-menu-meta .accordion-container .top,#nav-menu-meta .accordion-container .top h3{-webkit-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;border-top-right-radius:3px;border-top-left-radius:3px}#nav-menu-meta .accordion-container .accordion-section:last-child,#nav-menu-meta .accordion-container .accordion-section:last-child .accordion-section-content,#nav-menu-meta .accordion-container .bottom,#nav-menu-meta .accordion-container .bottom:not(.open) h3{-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.customlinkdiv .howto input{width:180px}.customlinkdiv p{margin-top:0}#nav-menu-theme-locations .howto select{width:100%}#nav-menu-theme-locations .button-controls{text-align:right}.add-menu-item-view-all{height:400px}#menu-container .submit{margin:0 0 10px;padding:0}.nav-menus-php .add-new-menu-action{float:left;margin:6px 0 0 6px;line-height:15px}.nav-menus-php .meta-sep,.nav-menus-php .submitdelete,.nav-menus-php .submitcancel{display:block;float:left;margin:4px 0;line-height:15px}.meta-sep{padding:0 2px}#cancel-save{text-decoration:underline;font-size:12px;margin-left:20px;margin-top:5px}.button.right,.button-secondary.right,.button-primary.right{float:right}.list-controls{float:left;margin-top:5px}.add-to-menu{float:right}.postbox .spinner{display:none;vertical-align:middle}.button-controls{clear:both;margin:10px 0}.show-all,.hide-all{cursor:pointer}.hide-all{display:none}#menu-name{width:270px}#manage-menu .inside{padding:0}#available-links dt{display:block}#add-custom-link .howto{font-size:12px}#add-custom-link label span{display:block;float:left;margin-top:5px;padding-right:5px}.menu-item-textbox{width:180px}.nav-menus-php .howto span{margin-top:4px;display:block;float:left}.quick-search{width:190px}.nav-menus-php .list-wrap{display:none;clear:both;margin-bottom:10px}.nav-menus-php .list-container{max-height:200px;overflow-y:auto;padding:10px 10px 5px}.nav-menus-php .postbox p.submit{margin-bottom:0}.nav-menus-php .list li{display:none;margin:0;margin-bottom:5px}.nav-menus-php .list li .menu-item-title{cursor:pointer;display:block}.nav-menus-php .list li .menu-item-title input{margin-right:3px;margin-top:-3px}#menu-container .inside{padding-bottom:10px}.menu{padding-top:1em}#menu-to-edit{margin:0;padding:.1em 0}.menu ul{width:100%}.menu li{margin-bottom:0;position:relative}.menu-item-bar{clear:both;line-height:1.5em;position:relative;margin:9px 0 0}.menu-item-handle{border:1px solid #dfdfdf;position:relative;padding-left:10px;height:auto;width:400px;line-height:35px;text-shadow:0 1px 0 #FFF;overflow:hidden;word-wrap:break-word}#menu-to-edit .menu-item-invalid .menu-item-handle{background:#f6c9cc;background-image:-webkit-gradient(linear,left bottom,left top,from(#f6c9cc),to(#fdf8ff));background-image:-webkit-linear-gradient(bottom,#f6c9cc,#fdf8ff);background-image:-moz-linear-gradient(bottom,#f6c9cc,#fdf8ff);background-image:-o-linear-gradient(bottom,#f6c9cc,#fdf8ff);background-image:linear-gradient(to top,#f6c9cc,#fdf8ff)}.menu-item-edit-active .menu-item-handle{-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.no-js .menu-item-edit-active .item-edit{display:none}.js .menu-item-handle{cursor:move}.menu li.deleting .menu-item-handle{background-image:none;text-shadow:0 0 0}.menu-item-handle .item-title{font-size:12px;font-weight:700;padding:7px 0;line-height:20px;min-height:20px;display:block;margin-right:13em}li.menu-item.ui-sortable-helper dl{margin-top:0}li.menu-item.ui-sortable-helper .menu-item-transport dl{margin-top:13px}.menu .sortable-placeholder{height:35px;width:410px;margin-top:13px}.menu-item-depth-0{margin-left:0}.menu-item-depth-1{margin-left:30px}.menu-item-depth-2{margin-left:60px}.menu-item-depth-3{margin-left:90px}.menu-item-depth-4{margin-left:120px}.menu-item-depth-5{margin-left:150px}.menu-item-depth-6{margin-left:180px}.menu-item-depth-7{margin-left:210px}.menu-item-depth-8{margin-left:240px}.menu-item-depth-9{margin-left:270px}.menu-item-depth-10{margin-left:300px}.menu-item-depth-11{margin-left:330px}.menu-item-depth-0 .menu-item-transport{margin-left:0}.menu-item-depth-1 .menu-item-transport{margin-left:-30px}.menu-item-depth-2 .menu-item-transport{margin-left:-60px}.menu-item-depth-3 .menu-item-transport{margin-left:-90px}.menu-item-depth-4 .menu-item-transport{margin-left:-120px}.menu-item-depth-5 .menu-item-transport{margin-left:-150px}.menu-item-depth-6 .menu-item-transport{margin-left:-180px}.menu-item-depth-7 .menu-item-transport{margin-left:-210px}.menu-item-depth-8 .menu-item-transport{margin-left:-240px}.menu-item-depth-9 .menu-item-transport{margin-left:-270px}.menu-item-depth-10 .menu-item-transport{margin-left:-300px}.menu-item-depth-11 .menu-item-transport{margin-left:-330px}body.menu-max-depth-0{min-width:950px!important}body.menu-max-depth-1{min-width:980px!important}body.menu-max-depth-2{min-width:1010px!important}body.menu-max-depth-3{min-width:1040px!important}body.menu-max-depth-4{min-width:1070px!important}body.menu-max-depth-5{min-width:1100px!important}body.menu-max-depth-6{min-width:1130px!important}body.menu-max-depth-7{min-width:1160px!important}body.menu-max-depth-8{min-width:1190px!important}body.menu-max-depth-9{min-width:1220px!important}body.menu-max-depth-10{min-width:1250px!important}body.menu-max-depth-11{min-width:1280px!important}.item-type{font-size:12px;padding-right:10px}.item-controls{font-size:12px;position:absolute;right:20px;top:-1px}.item-controls a{text-decoration:none}.item-controls a:hover{cursor:pointer}.item-controls .item-order{padding-right:10px}.nav-menus-php .item-edit{position:absolute;right:-20px;top:0;display:block;width:30px;height:36px;overflow:hidden;text-indent:-999em;border-bottom:1px solid;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px}.menu-instructions-inactive{display:none}.menu-item-settings{display:block;width:400px;padding:10px 0 10px 10px;border:solid;border-width:0 1px 1px;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.menu-item-settings .field-move a{display:none;margin:0 2px}.menu-item-edit-active .menu-item-settings{display:block}.menu-item-edit-inactive .menu-item-settings{display:none}.add-menu-item-pagelinks{margin:.5em auto;text-align:center}.link-to-original{display:block;margin:0 0 10px;padding:3px 5px 5px;font-size:12px;font-style:italic}.link-to-original a{padding-left:4px;font-style:normal}.hidden-field{display:none}.menu-item-settings .description-thin,.menu-item-settings .description-wide{margin-right:10px;float:left}.description-thin{width:190px;height:40px}.description-wide{width:390px}.menu-item-actions{padding-top:15px}#cancel-save{cursor:pointer}.nav-menus-php .major-publishing-actions{clear:both;padding:3px 0 5px}.nav-menus-php .major-publishing-actions .publishing-action{text-align:right;float:right;line-height:23px;margin:2px 0 1px}.nav-menus-php .blank-slate .menu-settings{display:none}.nav-menus-php .delete-action{float:left;margin-top:2px}.nav-menus-php .submitbox .submitcancel{border-bottom:1px solid;padding:1px 2px;text-decoration:none}.nav-menus-php .major-publishing-actions .form-invalid{padding-left:4px;margin-left:-4px;border:0 none}#menu-item-name-wrap:after,#menu-item-url-wrap:after,#menu-name-label:after,#menu-settings-column .inside:after,#nav-menus-frame:after,.nav-menus-php #post-body-content:after,.nav-menus-php .button-controls:after,.nav-menus-php .major-publishing-actions:after,.nav-menus-php .menu-item-settings:after{clear:both;content:".";display:block;height:0;visibility:hidden}#nav-menus-frame,.button-controls,#menu-item-url-wrap,#menu-item-name-wrap{display:block}div.star-holder{position:relative;height:17px;width:100px;background:url(../images/stars.png?ver=20121108) repeat-x bottom left}div.star-holder .star-rating{background:url(../images/stars.png?ver=20121108) repeat-x top left;height:17px;float:left}div.action-links{font-weight:400;margin:6px 0 0}#plugin-information-header{margin:0;padding:0 5px;font-weight:700;position:relative;border-bottom-width:1px;border-bottom-style:solid;height:2.5em}#plugin-information ul#sidemenu{font-weight:400;margin:0 5px;position:absolute;left:0;bottom:-1px}#plugin-information p.action-button{width:100%;padding-bottom:0;margin-bottom:0;margin-top:10px;-webkit-border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-top-left-radius:3px;border-bottom-left-radius:3px}#plugin-information .action-button a{text-align:center;font-weight:700;text-decoration:none;display:block;line-height:2em}#plugin-information h2{clear:none!important;margin-right:200px}#plugin-information .fyi{margin:0 10px 50px;width:210px}#plugin-information .fyi h2{font-size:.9em;margin-bottom:0;margin-right:0}#plugin-information .fyi h2.mainheader{padding:5px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px}#plugin-information .fyi ul{padding:10px 5px 10px 7px;margin:0;list-style:none;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px}#plugin-information .fyi li{margin-right:0}#plugin-information #section-holder{padding:10px}#plugin-information .section ul,#plugin-information .section ol{margin-left:16px;list-style-type:square;list-style-image:none}#plugin-information #section-screenshots ol{list-style:none;margin:0}#plugin-information #section-screenshots li img{vertical-align:text-top;max-width:100%;width:auto;height:auto}#plugin-information #section-screenshots li p{font-style:italic;padding-left:20px;padding-bottom:2em}#plugin-information #section-screenshots ol,#plugin-information .updated,#plugin-information pre{margin-right:215px}#plugin-information pre{padding:7px;overflow:auto}body.press-this{color:#333;margin:0;padding:0;min-width:675px;min-height:400px}img{border:0}.press-this #wphead{height:32px;margin-left:0;margin-right:0;margin-bottom:5px}.press-this #header-logo{float:left;margin:7px 7px 0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.press-this #wphead h1{font-weight:400;font-size:16px;line-height:32px;margin:0;float:left}.press-this #wphead h1 a{text-decoration:none}.press-this #wphead h1 a:hover{text-decoration:underline}.press-this #message{margin:10px 0}.press-this-sidebar{float:right;width:200px;padding-top:10px}.press-this #title{margin-left:0;margin-right:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.press-this .tagchecklist span a{background:transparent url(../images/xit.gif) no-repeat 0 0}.press-this #titlediv{margin:0}.press-this .wp-media-buttons{cursor:default;padding:8px 8px 0}.press-this .howto{margin-top:2px;margin-bottom:3px;font-size:12px;font-style:italic;display:block}.press-this #poststuff{margin:0 10px 10px;padding:0}.press-this #photo-add-url-div input[type=text]{width:220px}#poststuff #editor-toolbar{height:30px}div.zerosize{border:0 none;height:0;margin:0;overflow:hidden;padding:0;width:0}.posting{margin-right:212px;position:relative}.press-this .inner-sidebar{width:200px}.press-this .inner-sidebar .sleeve{padding-top:5px}.press-this #submitdiv p{margin:0;padding:6px}.press-this #submitdiv #publishing-actions{border-bottom:1px solid #dfdfdf}.press-this #publish{float:right}.press-this #poststuff h2,.press-this #poststuff h3{font-size:14px;line-height:1}.press-this #tagsdiv-post_tag h3,.press-this #categorydiv h3{cursor:pointer}.press-this #submitdiv h3{cursor:default}h3.tb{text-shadow:0 1px 0 #fff;font-weight:700;font-size:12px;margin-left:5px}#TB_window{border:1px solid #333}.press-this .postbox,.press-this .stuffbox{margin-bottom:10px;min-width:0}.js .postbox:hover .handlediv,.js .stuffbox:hover .handlediv{background:transparent url(../images/arrows.png) no-repeat 6px 7px}.press-this #submitdiv:hover .handlediv{background:0 0}.tbtitle{font-size:1.7em;outline:0;padding:3px 4px;border-color:#dfdfdf}.press-this .actions{float:right;margin:-19px 0 0}.press-this #extra-fields .actions{margin:-32px -7px 0 0}.press-this .actions li{float:left;list-style:none;margin-right:10px}#extra-fields .button{margin-right:5px}#photo_saving{margin:0 8px 8px;vertical-align:middle}#img_container_container{overflow:auto}#extra-fields{margin-top:10px;position:relative}#extra-fields h2{margin:12px}#waiting{margin-top:10px;overflow:hidden}#waiting span{float:right;margin:0 0 0 5px}#waiting .spinner{display:block}#extra-fields .postbox{margin-bottom:5px}#extra-fields .titlewrap{padding:0;overflow:auto;height:100px}#img_container a{display:block;float:left;overflow:hidden}#img_container img,#img_container a{width:68px;height:68px}#img_container img{border:0;background-color:#f4f4f4;cursor:pointer}#img_container a,#img_container a:link,#img_container a:visited{border:1px solid #ccc;display:block;position:relative}#img_container a:hover,#img_container a:active{border-color:#000;z-index:1000;border-width:2px;margin:-1px}#embed-code{width:100%;height:98px}.press-this .categorydiv div.tabs-panel{height:100px}.press-this .tagsdiv .newtag{width:120px}.press-this #content{margin:5px 0;padding:0 5px;border:0 none;height:345px;font-family:Consolas,Monaco,monospace;font-size:13px;line-height:19px;background:transparent}.press-this #publishing-actions .spinner{display:inline;vertical-align:middle}#TB_ajaxContent #options{position:absolute;top:20px;right:25px;padding:5px}#TB_ajaxContent h3{margin-bottom:.25em}.error a{text-decoration:underline}.updated a{text-decoration:none;padding-bottom:2px}.taghint{color:#aaa;margin:-17px 0 0 7px;visibility:hidden}input.newtag~div.taghint{visibility:visible}input.newtag:focus~div.taghint{visibility:hidden}#photo-add-url-div input[type=text]{width:300px}.alignleft h3{margin:0}h3 span{font-weight:400}#template textarea{font-family:Consolas,Monaco,monospace;font-size:12px;width:97%;background:#f9f9f9;outline:0}#template p{width:97%}#templateside{float:right;width:190px;word-wrap:break-word}#templateside h3,#postcustomstuff p.submit{margin:0}#templateside h4{margin:1em 0 0}#templateside ol,#templateside ul{margin:.5em;padding:0}#templateside li{margin:4px 0}#templateside ul li a span.highlight{display:block}.nonessential{font-size:11px;font-style:italic;padding-left:12px}.highlight{padding:3px 3px 3px 12px;margin-left:-12px;font-weight:700;border:0 none}#documentation{margin-top:10px}#documentation label{line-height:22px;vertical-align:top;font-weight:700}.fileedit-sub{padding:10px 0 8px;line-height:180%}#filter-box{clear:both}.feature-filter{padding:8px 12px 0}.feature-filter .feature-group{float:left;margin:5px 10px 10px}.feature-filter .feature-group li{display:inline-block;vertical-align:top;list-style-type:none;padding-right:25px;width:150px}.feature-container{width:100%;overflow:auto;margin-bottom:10px}div.widget-liquid-left{float:left;clear:left;width:100%;margin-right:-325px}div#widgets-left{margin-left:5px;margin-right:325px}div#widgets-right{width:285px;margin:0 auto}div.widget-liquid-right{float:right;clear:right;width:300px}.widget-liquid-right .widget,.inactive-sidebar .widget,.widget-liquid-right .sidebar-description{width:250px;margin:0 auto 20px;overflow:hidden}.widget-liquid-right .sidebar-description{margin-bottom:10px}.inactive-sidebar .widget{margin:0 10px 20px;display:inline-block}div.sidebar-name h3{font-weight:400;font-size:15px;margin:0;padding:8px 10px;overflow:hidden;white-space:nowrap}div.sidebar-name{font-size:13px;border-width:1px;border-style:solid;-webkit-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;border-top-right-radius:3px;border-top-left-radius:3px}.js .sidebar-name{cursor:pointer}.js .closed .sidebar-name{-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.widget-liquid-right .widgets-sortables,#widgets-left .widget-holder{border-width:0 1px 1px;border-style:none solid solid;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.js .closed .widgets-sortables,.js .closed .widget-holder{display:none}.widget-liquid-right .widgets-sortables{padding:15px 0 0}#available-widgets .widget-holder{padding:7px 5px 0}#available-widgets .widget{-webkit-box-shadow:none;box-shadow:none}.inactive-sidebar{padding:5px 5px 0}#widget-list .widget{width:250px;margin:0 10px 15px;border:0 none;background:transparent;display:inline-block;vertical-align:top}#widget-list .widget-description{padding:5px 8px}.widget-placeholder{border-width:1px;border-style:dashed;margin:0 auto 20px;height:27px;width:250px}.inactive-sidebar .widget-placeholder{margin:0 10px 20px;float:left}div.widgets-holder-wrap{padding:0;margin:10px 0 20px}#widgets-left #available-widgets{background-color:transparent;border:0 none}ul#widget-list{list-style:none;margin:0;padding:0;min-height:100px}.widget .widget-top{margin-bottom:-1px;font-size:12px;font-weight:700;height:26px;overflow:hidden}.widget-top .widget-title{padding:7px 9px}.widget-top .widget-title-action{float:right}a.widget-action{display:block;width:24px;height:26px}#available-widgets a.widget-action{display:none}.widget-top a.widget-action{background:transparent url(../images/arrows.png) no-repeat 4px 6px}.widget-top a.widget-action:hover{background:transparent url(../images/arrows-dark.png) no-repeat 4px 6px}.widget .widget-inside,.widget .widget-description{padding:12px 12px 10px;font-size:12px;line-height:16px}.widget-inside,.widget-description{display:none}#available-widgets .widget-description{display:block}.widget .widget-inside p{margin:0 0 1em;padding:0}.widget-title h4{margin:0;padding-bottom:.2em;line-height:1;overflow:hidden;white-space:nowrap}.widgets-sortables{min-height:90px}.widget-control-actions{margin-top:8px}.widget-control-actions a{text-decoration:none}.widget-control-actions a:hover{text-decoration:underline}.widget-control-actions div.alignleft{margin-top:6px}div#sidebar-info{padding:0 1em;margin-bottom:1em;font-size:12px}.widget-title a,.widget-title a:hover{text-decoration:none;border-bottom:0}.widget-control-edit{display:block;font-size:12px;font-weight:400;line-height:26px;padding:0 8px 0 0}a.widget-control-edit{text-decoration:none}.widget-control-edit .add,.widget-control-edit .edit{display:none}#available-widgets .widget-control-edit .add,#widgets-right .widget-control-edit .edit,.inactive-sidebar .widget-control-edit .edit{display:inline}.editwidget{margin:0 auto 15px}.editwidget .widget-inside{display:block;padding:10px}.inactive p.description{margin:5px 15px 10px}#available-widgets p.description{margin:0 12px 12px}.widget-position{margin-top:8px}.inactive{padding-top:2px}.sidebar-name .spinner{float:none;margin:0 3px -3px}.sidebar-name-arrow{float:right;height:29px;width:26px}.widget-title .in-widget-title{font-size:12px;white-space:nowrap}#removing-widget{display:none;font-weight:400;padding-left:15px;font-size:12px;line-height:1}.widget-control-noform,#access-off,.widgets_access .widget-action,.widgets_access .sidebar-name-arrow,.widgets_access #access-on,.widgets_access .widget-holder .description{display:none}.widgets_access .widget-holder,.widgets_access #widget-list{padding-top:10px}.widgets_access #access-off{display:inline}.widgets_access #wpbody-content .widget-title-action,.widgets_access #wpbody-content .widget-control-edit,.widgets_access .closed .widgets-sortables,.widgets_access .closed .widget-holder{display:block}.widgets_access .closed .sidebar-name{-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.widgets_access .sidebar-name,.widgets_access .widget .widget-top{cursor:default}.ui-sortable,.ui-draggable{-ms-touch-action:none}.accordion-section{border-top:1px solid #fff;border-bottom:1px solid #dfdfdf;margin:0}.accordion-section:first-child{border-top:1px solid #dfdfdf}.accordion-section:last-child{box-shadow:0 1px 0 0 #fff}.accordion-section.open .accordion-section-content,.no-js .accordion-section .accordion-section-content{display:block}.accordion-section.open:hover{border-bottom-color:#dfdfdf}.accordion-section-content{display:none;padding:10px 20px 15px;overflow:hidden;background:#fdfdfd;border-left:1px solid #dfdfdf;border-right:1px solid #dfdfdf}.accordion-section-title{margin:0;padding:15px 20px;position:relative;border-left:1px solid #dfdfdf;border-right:1px solid #dfdfdf;-webkit-user-select:none;-moz-user-select:none;user-select:none}.js .accordion-section-title{cursor:pointer}.js .accordion-section-title:after{content:'';width:0;height:0;border-color:#ccc transparent;border-style:solid;border-width:6px 6px 0;position:absolute;top:25px;right:20px;z-index:1}.accordion-section-title:focus{outline:0}.accordion-section-title:hover:after,.accordion-section-title:focus:after{border-color:#aaa transparent}.cannot-expand .accordion-section-title{cursor:auto}.cannot-expand .accordion-section-title:after{display:none}.control-section .accordion-section-title{padding:10px 20px;color:#464646;font-size:15px;font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;font-weight:400;text-shadow:0 1px 0 #fff;background:#f5f5f5;background-image:-webkit-gradient(linear,left bottom,left top,from(#eee),to(#f5f5f5));background-image:-webkit-linear-gradient(bottom,#eee,#f5f5f5);background-image:-moz-linear-gradient(bottom,#eee,#f5f5f5);background-image:-o-linear-gradient(bottom,#eee,#f5f5f5);background-image:linear-gradient(to top,#eee,#f5f5f5)}.control-section .accordion-section-title:after{top:15px}.js .control-section:hover .accordion-section-title,.js .control-section .accordion-section-title:hover,.js .control-section.open .accordion-section-title,.js .control-section .accordion-section-title:focus{color:#000;background:#f9f9f9;background-image:-webkit-gradient(linear,left bottom,left top,from(#ececec),to(#f9f9f9));background-image:-webkit-linear-gradient(bottom,#ececec,#f9f9f9);background-image:-moz-linear-gradient(bottom,#ececec,#f9f9f9);background-image:-o-linear-gradient(bottom,#ececec,#f9f9f9);background-image:linear-gradient(to top,#ececec,#f9f9f9)}.control-section.open .accordion-section-title{border-bottom:1px solid #dfdfdf}@media only screen and (max-width:768px){#col-left{width:100%}#col-right{width:100%}}@media only screen and (min-width:769px){#col-left{width:35%}#col-right{width:65%}}@media only screen and (max-width:860px){#col-left{width:35%}#col-right{width:65%}}@media only screen and (min-width:980px){#col-left{width:35%}#col-right{width:65%}}@media only screen and (max-width:768px){#col-left{width:100%}#col-right{width:100%}.form-field input,.form-field textarea{width:99%}.form-wrap .form-field{padding:0}#profile-page .form-table textarea{max-width:400px;width:auto}}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.press-this .tagchecklist span a{background-image:url(../images/xit-2x.gif);background-size:20px auto}.js .postbox:hover .handlediv,.js .stuffbox:hover .handlediv,.widget-top a.widget-action{background-image:url(../images/arrows-2x.png);background-size:15px 123px}.widget-top a.widget-action:hover{background-image:url(../images/arrows-dark-2x.png);background-size:15px 123px}.post-com-count{background-image:url(../images/bubble_bg-2x.gif);background-size:18px 100px}tr.wp-locked .locked-indicator{background-image:url(../images/lock-2x.png);background-size:16px 16px}th .comment-grey-bubble{background-image:url(../images/comment-grey-bubble-2x.png);background-size:12px 12px}.sorting-indicator{background-image:url(../images/sort-2x.gif?ver=20130102);background-size:14px 4px}#content-resize-handle,#post-body .wp_themeSkin .mceStatusbar a.mceResize{background:transparent url(../images/resize-2x.gif) no-repeat scroll right bottom;background-size:11px 11px}div.star-holder{background:url(../images/stars-2x.png?ver=20121108) repeat-x bottom left;background-size:21px 37px}div.star-holder .star-rating{background:url(../images/stars-2x.png?ver=20121108) repeat-x top left;background-size:21px 37px}.welcome-panel .welcome-panel-close:before{background-image:url(../images/xit-2x.gif);background-size:20px auto}.welcome-panel .welcome-icon{background-image:url(../images/welcome-icons-2x.png)}.login h1 a{background-image:url(../images/wordpress-logo-2x.png?ver=20120412);background-size:274px 63px}.wp-badge{background-image:url(../images/wp-badge-2x.png?ver=20120516);background-size:173px 194px}.wp-full-overlay .collapse-sidebar-arrow{background-image:url(../images/arrows-2x.png);background-size:15px 123px}.pressthis a span{background-image:url(../images/press-this-2x.png?v=20121105)}.imgedit-crop,.imgedit-rleft,.imgedit-rright,.imgedit-flipv,.imgedit-fliph,.imgedit-undo,.imgedit-redo{background-image:url(../images/imgedit-icons-2x.png);background-size:260px 64px}.spinner,.imgedit-wait,.customize-loading #customize-container{background-image:url(../images/wpspin_light-2x.gif)}.wp-slider .ui-slider-handle:before{background-image:url(../images/arrows-pr-2x.png);background-size:16px 102px}}.locale-zh-cn .howto,.locale-zh-cn .tablenav .displaying-num,.locale-zh-cn .js .input-with-default-title,.locale-zh-cn .link-to-original,.locale-zh-cn .inline-edit-row fieldset span.title,.locale-zh-cn .inline-edit-row fieldset span.checkbox-title,.locale-zh-cn #utc-time,.locale-zh-cn #local-time,.locale-zh-cn p.install-help,.locale-zh-cn p.help,.locale-zh-cn p.description,.locale-zh-cn span.description,.locale-zh-cn .form-wrap p{font-style:normal}.locale-zh-cn .hdnle a{font-size:12px}.locale-zh-cn form.upgrade .hint{font-style:normal;font-size:100%}.locale-zh-cn #wp-fullscreen-tagline{font-family:KaiTi,"楷体",sans-serif}.locale-zh-cn #wp-fullscreen-modes a{font-size:12px}.locale-zh-cn #sort-buttons{font-size:1em!important}.locale-ru-ru .inline-edit-row fieldset label span.title{width:auto;min-width:5em}.locale-ru-ru.press-this .posting{margin-right:257px}.locale-ru-ru.press-this #photo-add-url-div input[type=text]{width:255px}.locale-ru-ru.press-this #side-sortables{width:245px}.locale-ru-ru #customize-header-actions .button{padding:0 8px 1px}.locale-lt-lt .inline-edit-row fieldset label span.title{width:8em}.locale-lt-lt .inline-edit-row fieldset label span.input-text-wrap{margin-left:8em} \ No newline at end of file diff --git a/sources/wp-admin/custom-background.php b/sources/wp-admin/custom-background.php new file mode 100644 index 0000000..9765608 --- /dev/null +++ b/sources/wp-admin/custom-background.php @@ -0,0 +1,428 @@ +admin_header_callback = $admin_header_callback; + $this->admin_image_div_callback = $admin_image_div_callback; + + add_action( 'admin_menu', array( $this, 'init' ) ); + add_action( 'wp_ajax_set-background-image', array( $this, 'wp_set_background_image' ) ); + } + + /** + * Set up the hooks for the Custom Background admin page. + * + * @since 3.0.0 + */ + function init() { + if ( ! current_user_can('edit_theme_options') ) + return; + + $this->page = $page = add_theme_page(__('Background'), __('Background'), 'edit_theme_options', 'custom-background', array($this, 'admin_page')); + + add_action("load-$page", array($this, 'admin_load')); + add_action("load-$page", array($this, 'take_action'), 49); + add_action("load-$page", array($this, 'handle_upload'), 49); + + if ( $this->admin_header_callback ) + add_action("admin_head-$page", $this->admin_header_callback, 51); + } + + /** + * Set up the enqueue for the CSS & JavaScript files. + * + * @since 3.0.0 + */ + function admin_load() { + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

' . __( 'You can customize the look of your site without touching any of your theme’s code by using a custom background. Your background can be an image or a color.' ) . '

' . + '

' . __( 'To use a background image, simply upload it or choose an image that has already been uploaded to your Media Library by clicking the “Choose Image” button. You can display a single instance of your image, or tile it to fill the screen. You can have your background fixed in place, so your site content moves on top of it, or you can have it scroll with your site.' ) . '

' . + '

' . __( 'You can also choose a background color by clicking the Select Color button and either typing in a legitimate HTML hex value, e.g. “#ff0000” for red, or by choosing a color using the color picker.' ) . '

' . + '

' . __( 'Don’t forget to click on the Save Changes button when you are finished.' ) . '

' + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __( 'For more information:' ) . '

' . + '

' . __( 'Documentation on Custom Background' ) . '

' . + '

' . __( 'Support Forums' ) . '

' + ); + + wp_enqueue_media(); + wp_enqueue_script('custom-background'); + wp_enqueue_style('wp-color-picker'); + } + + /** + * Execute custom background modification. + * + * @since 3.0.0 + */ + function take_action() { + + if ( empty($_POST) ) + return; + + if ( isset($_POST['reset-background']) ) { + check_admin_referer('custom-background-reset', '_wpnonce-custom-background-reset'); + remove_theme_mod('background_image'); + remove_theme_mod('background_image_thumb'); + $this->updated = true; + return; + } + + if ( isset($_POST['remove-background']) ) { + // @TODO: Uploaded files are not removed here. + check_admin_referer('custom-background-remove', '_wpnonce-custom-background-remove'); + set_theme_mod('background_image', ''); + set_theme_mod('background_image_thumb', ''); + $this->updated = true; + wp_safe_redirect( $_POST['_wp_http_referer'] ); + return; + } + + if ( isset($_POST['background-repeat']) ) { + check_admin_referer('custom-background'); + if ( in_array($_POST['background-repeat'], array('repeat', 'no-repeat', 'repeat-x', 'repeat-y')) ) + $repeat = $_POST['background-repeat']; + else + $repeat = 'repeat'; + set_theme_mod('background_repeat', $repeat); + } + + if ( isset($_POST['background-position-x']) ) { + check_admin_referer('custom-background'); + if ( in_array($_POST['background-position-x'], array('center', 'right', 'left')) ) + $position = $_POST['background-position-x']; + else + $position = 'left'; + set_theme_mod('background_position_x', $position); + } + + if ( isset($_POST['background-attachment']) ) { + check_admin_referer('custom-background'); + if ( in_array($_POST['background-attachment'], array('fixed', 'scroll')) ) + $attachment = $_POST['background-attachment']; + else + $attachment = 'fixed'; + set_theme_mod('background_attachment', $attachment); + } + + if ( isset($_POST['background-color']) ) { + check_admin_referer('custom-background'); + $color = preg_replace('/[^0-9a-fA-F]/', '', $_POST['background-color']); + if ( strlen($color) == 6 || strlen($color) == 3 ) + set_theme_mod('background_color', $color); + else + set_theme_mod('background_color', ''); + } + + $this->updated = true; + } + + /** + * Display the custom background page. + * + * @since 3.0.0 + */ + function admin_page() { +?> +
+ +

+updated) ) { ?> +
+

Visit your site to see how it looks.' ), home_url( '/' ) ); ?>

+
+admin_image_div_callback ) { + call_user_func($this->admin_image_div_callback); + } else { +?> +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+

+
+ + + + +

+

+
+ +

+
+
+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + +
+ + +
+ + /> +
+ + + +
+ +
+ false); + + $uploaded_file = $_FILES['import']; + $wp_filetype = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'], false ); + if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) + wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) ); + + $file = wp_handle_upload($uploaded_file, $overrides); + + if ( isset($file['error']) ) + wp_die( $file['error'] ); + + $url = $file['url']; + $type = $file['type']; + $file = $file['file']; + $filename = basename($file); + + // Construct the object array + $object = array( + 'post_title' => $filename, + 'post_content' => $url, + 'post_mime_type' => $type, + 'guid' => $url, + 'context' => 'custom-background' + ); + + // Save the data + $id = wp_insert_attachment($object, $file); + + // Add the meta-data + wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) ); + update_post_meta( $id, '_wp_attachment_is_custom_background', get_option('stylesheet' ) ); + + set_theme_mod('background_image', esc_url_raw($url)); + + $thumbnail = wp_get_attachment_image_src( $id, 'thumbnail' ); + set_theme_mod('background_image_thumb', esc_url_raw( $thumbnail[0] ) ); + + /** This action is documented in wp-admin/custom-header.php */ + do_action( 'wp_create_file_in_uploads', $file, $id ); // For replication + $this->updated = true; + } + + /** + * Unused since 3.5.0. + * + * @since 3.4.0 + */ + function attachment_fields_to_edit( $form_fields ) { + return $form_fields; + } + + /** + * Unused since 3.5.0. + * + * @since 3.4.0 + */ + function filter_upload_tabs( $tabs ) { + return $tabs; + } + + public function wp_set_background_image() { + if ( ! current_user_can('edit_theme_options') || ! isset( $_POST['attachment_id'] ) ) exit; + $attachment_id = absint($_POST['attachment_id']); + /** This filter is documented in wp-admin/includes/media.php */ + $sizes = array_keys(apply_filters( 'image_size_names_choose', array('thumbnail' => __('Thumbnail'), 'medium' => __('Medium'), 'large' => __('Large'), 'full' => __('Full Size')) )); + $size = 'thumbnail'; + if ( in_array( $_POST['size'], $sizes ) ) + $size = esc_attr( $_POST['size'] ); + + update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', get_option('stylesheet' ) ); + $url = wp_get_attachment_image_src( $attachment_id, $size ); + $thumbnail = wp_get_attachment_image_src( $attachment_id, 'thumbnail' ); + set_theme_mod( 'background_image', esc_url_raw( $url[0] ) ); + set_theme_mod( 'background_image_thumb', esc_url_raw( $thumbnail[0] ) ); + exit; + } +} diff --git a/sources/wp-admin/custom-header.php b/sources/wp-admin/custom-header.php new file mode 100644 index 0000000..7b1a4b3 --- /dev/null +++ b/sources/wp-admin/custom-header.php @@ -0,0 +1,1045 @@ +admin_header_callback = $admin_header_callback; + $this->admin_image_div_callback = $admin_image_div_callback; + + add_action( 'admin_menu', array( $this, 'init' ) ); + } + + /** + * Set up the hooks for the Custom Header admin page. + * + * @since 2.1.0 + */ + function init() { + if ( ! current_user_can('edit_theme_options') ) + return; + + $this->page = $page = add_theme_page(__('Header'), __('Header'), 'edit_theme_options', 'custom-header', array($this, 'admin_page')); + + add_action("admin_print_scripts-$page", array($this, 'js_includes')); + add_action("admin_print_styles-$page", array($this, 'css_includes')); + add_action("admin_head-$page", array($this, 'help') ); + add_action("admin_head-$page", array($this, 'take_action'), 50); + add_action("admin_head-$page", array($this, 'js'), 50); + if ( $this->admin_header_callback ) + add_action("admin_head-$page", $this->admin_header_callback, 51); + } + + /** + * Adds contextual help. + * + * @since 3.0.0 + */ + function help() { + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

' . __( 'This screen is used to customize the header section of your theme.') . '

' . + '

' . __( 'You can choose from the theme’s default header images, or use one of your own. You can also customize how your Site Title and Tagline are displayed.') . '

' + ) ); + + get_current_screen()->add_help_tab( array( + 'id' => 'set-header-image', + 'title' => __('Header Image'), + 'content' => + '

' . __( 'You can set a custom image header for your site. Simply upload the image and crop it, and the new header will go live immediately. Alternatively, you can use an image that has already been uploaded to your Media Library by clicking the “Choose Image” button.' ) . '

' . + '

' . __( 'Some themes come with additional header images bundled. If you see multiple images displayed, select the one you’d like and click the “Save Changes” button.' ) . '

' . + '

' . __( 'If your theme has more than one default header image, or you have uploaded more than one custom header image, you have the option of having WordPress display a randomly different image on each page of your site. Click the “Random” radio button next to the Uploaded Images or Default Images section to enable this feature.') . '

' . + '

' . __( 'If you don’t want a header image to be displayed on your site at all, click the “Remove Header Image” button at the bottom of the Header Image section of this page. If you want to re-enable the header image later, you just have to select one of the other image options and click “Save Changes”.') . '

' + ) ); + + get_current_screen()->add_help_tab( array( + 'id' => 'set-header-text', + 'title' => __('Header Text'), + 'content' => + '

' . sprintf( __( 'For most themes, the header text is your Site Title and Tagline, as defined in the General Settings section.' ), admin_url( 'options-general.php' ) ) . '

' . + '

' . __( 'In the Header Text section of this page, you can choose whether to display this text or hide it. You can also choose a color for the text by clicking the Select Color button and either typing in a legitimate HTML hex value, e.g. “#ff0000” for red, or by choosing a color using the color picker.' ) . '

' . + '

' . __( 'Don’t forget to click “Save Changes” when you’re done!') . '

' + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __( 'For more information:' ) . '

' . + '

' . __( 'Documentation on Custom Header' ) . '

' . + '

' . __( 'Support Forums' ) . '

' + ); + } + + /** + * Get the current step. + * + * @since 2.6.0 + * + * @return int Current step + */ + function step() { + if ( ! isset( $_GET['step'] ) ) + return 1; + + $step = (int) $_GET['step']; + if ( $step < 1 || 3 < $step || + ( 2 == $step && ! wp_verify_nonce( $_REQUEST['_wpnonce-custom-header-upload'], 'custom-header-upload' ) ) || + ( 3 == $step && ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'custom-header-crop-image' ) ) + ) + return 1; + + return $step; + } + + /** + * Set up the enqueue for the JavaScript files. + * + * @since 2.1.0 + */ + function js_includes() { + $step = $this->step(); + + if ( ( 1 == $step || 3 == $step ) ) { + wp_enqueue_media(); + wp_enqueue_script( 'custom-header' ); + if ( current_theme_supports( 'custom-header', 'header-text' ) ) + wp_enqueue_script( 'wp-color-picker' ); + } elseif ( 2 == $step ) { + wp_enqueue_script('imgareaselect'); + } + } + + /** + * Set up the enqueue for the CSS files + * + * @since 2.7 + */ + function css_includes() { + $step = $this->step(); + + if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) ) + wp_enqueue_style( 'wp-color-picker' ); + elseif ( 2 == $step ) + wp_enqueue_style('imgareaselect'); + } + + /** + * Execute custom header modification. + * + * @since 2.6.0 + */ + function take_action() { + if ( ! current_user_can('edit_theme_options') ) + return; + + if ( empty( $_POST ) ) + return; + + $this->updated = true; + + if ( isset( $_POST['resetheader'] ) ) { + check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' ); + $this->reset_header_image(); + return; + } + + if ( isset( $_POST['removeheader'] ) ) { + check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' ); + $this->remove_header_image(); + return; + } + + if ( isset( $_POST['text-color'] ) && ! isset( $_POST['display-header-text'] ) ) { + check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' ); + set_theme_mod( 'header_textcolor', 'blank' ); + } elseif ( isset( $_POST['text-color'] ) ) { + check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' ); + $_POST['text-color'] = str_replace( '#', '', $_POST['text-color'] ); + $color = preg_replace('/[^0-9a-fA-F]/', '', $_POST['text-color']); + if ( strlen($color) == 6 || strlen($color) == 3 ) + set_theme_mod('header_textcolor', $color); + elseif ( ! $color ) + set_theme_mod( 'header_textcolor', 'blank' ); + } + + if ( isset( $_POST['default-header'] ) ) { + check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' ); + $this->set_header_image( $_POST['default-header'] ); + return; + } + } + + /** + * Process the default headers + * + * @since 3.0.0 + */ + function process_default_headers() { + global $_wp_default_headers; + + if ( !empty($this->headers) ) + return; + + if ( !isset($_wp_default_headers) ) + return; + + $this->default_headers = $_wp_default_headers; + $template_directory_uri = get_template_directory_uri(); + $stylesheet_directory_uri = get_stylesheet_directory_uri(); + foreach ( array_keys($this->default_headers) as $header ) { + $this->default_headers[$header]['url'] = sprintf( $this->default_headers[$header]['url'], $template_directory_uri, $stylesheet_directory_uri ); + $this->default_headers[$header]['thumbnail_url'] = sprintf( $this->default_headers[$header]['thumbnail_url'], $template_directory_uri, $stylesheet_directory_uri ); + } + + } + + /** + * Display UI for selecting one of several default headers. + * + * Show the random image option if this theme has multiple header images. + * Random image option is on by default if no header has been set. + * + * @since 3.0.0 + */ + function show_header_selector( $type = 'default' ) { + if ( 'default' == $type ) { + $headers = $this->default_headers; + } else { + $headers = get_uploaded_header_images(); + $type = 'uploaded'; + } + + if ( 1 < count( $headers ) ) { + echo '
'; + echo ''; + echo '
'; + } + + echo '
'; + foreach ( $headers as $header_key => $header ) { + $header_thumbnail = $header['thumbnail_url']; + $header_url = $header['url']; + $header_desc = empty( $header['description'] ) ? '' : $header['description']; + echo '
'; + echo ''; + echo '
'; + } + echo '
'; + } + + /** + * Execute Javascript depending on step. + * + * @since 2.1.0 + */ + function js() { + $step = $this->step(); + if ( ( 1 == $step || 3 == $step ) && current_theme_supports( 'custom-header', 'header-text' ) ) + $this->js_1(); + elseif ( 2 == $step ) + $this->js_2(); + } + + /** + * Display Javascript based on Step 1 and 3. + * + * @since 2.6.0 + */ + function js_1() { ?> + + + +process_default_headers(); +?> + +
+ +

+ +updated ) ) { ?> +
+

Visit your site to see how it looks.' ), home_url( '/' ) ); ?>

+
+ + +

+ + + + + + + + + + + + + + + + + + +
+ admin_image_div_callback ) { + call_user_func( $this->admin_image_div_callback ); + } else { + $custom_header = get_custom_header(); + $header_image_style = 'background-image:url(' . esc_url( get_header_image() ) . ');'; + if ( $custom_header->width ) + $header_image_style .= 'max-width:' . $custom_header->width . 'px;'; + if ( $custom_header->height ) + $header_image_style .= 'height:' . $custom_header->height . 'px;'; + ?> + + +
+


+ %1$d × %2$d pixels will be used as-is.' ) . '
', get_theme_support( 'custom-header', 'width' ), get_theme_support( 'custom-header', 'height' ) ); + } elseif ( current_theme_supports( 'custom-header', 'flex-height' ) ) { + if ( ! current_theme_supports( 'custom-header', 'flex-width' ) ) + printf( __( 'Images should be at least %1$d pixels wide.' ) . ' ', get_theme_support( 'custom-header', 'width' ) ); + } elseif ( current_theme_supports( 'custom-header', 'flex-width' ) ) { + if ( ! current_theme_supports( 'custom-header', 'flex-height' ) ) + printf( __( 'Images should be at least %1$d pixels tall.' ) . ' ', get_theme_support( 'custom-header', 'height' ) ); + } + if ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) { + if ( current_theme_supports( 'custom-header', 'width' ) ) + printf( __( 'Suggested width is %1$d pixels.' ) . ' ', get_theme_support( 'custom-header', 'width' ) ); + if ( current_theme_supports( 'custom-header', 'height' ) ) + printf( __( 'Suggested height is %1$d pixels.' ) . ' ', get_theme_support( 'custom-header', 'height' ) ); + } + ?>

+
+

+
+ + + + +

+ 'custom-header', + 'step' => 2, + '_wpnonce-custom-header-upload' => wp_create_nonce('custom-header-upload'), + ), admin_url('themes.php') ) ); + ?> +

+
+ +

+
+
+ +
+ + + + + + + + default_headers ) ) : ?> + + + + + + + + + + + + + + + + +
+

+ show_header_selector( 'uploaded' ); + ?> +
+ +

+ +

+ + show_header_selector( 'default' ); + ?> +
+

+ +
+

+ +
+ + + +

+ + + + + + + + + + + + + +
+

+ +

+
+

+'; + if ( $default_color ) + echo ' ' . sprintf( _x( 'Default: %s', 'color' ), $default_color ) . ''; +} +?> +

+
+ + + +
+
+ +step_2_manage_upload()); + } + + if ( file_exists( $file ) ) { + list( $width, $height, $type, $attr ) = getimagesize( $file ); + } else { + $data = wp_get_attachment_metadata( $attachment_id ); + $height = isset( $data[ 'height' ] ) ? $data[ 'height' ] : 0; + $width = isset( $data[ 'width' ] ) ? $data[ 'width' ] : 0; + unset( $data ); + } + + $max_width = 0; + // For flex, limit size of image displayed to 1500px unless theme says otherwise + if ( current_theme_supports( 'custom-header', 'flex-width' ) ) + $max_width = 1500; + + if ( current_theme_supports( 'custom-header', 'max-width' ) ) + $max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) ); + $max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) ); + + // If flexible height isn't supported and the image is the exact right size + if ( ! current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) + && $width == get_theme_support( 'custom-header', 'width' ) && $height == get_theme_support( 'custom-header', 'height' ) ) + { + // Add the meta-data + if ( file_exists( $file ) ) + wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) ); + + $this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) ); + + /** + * Fires after the header image is set or an error is returned. + * + * @since 2.1.0 + * + * @param string $file Path to the file. + * @param int $attachment_id Attachment ID. + */ + do_action( 'wp_create_file_in_uploads', $file, $attachment_id ); // For replication + + return $this->finished(); + } elseif ( $width > $max_width ) { + $oitar = $width / $max_width; + $image = wp_crop_image($attachment_id, 0, 0, $width, $height, $max_width, $height / $oitar, false, str_replace(basename($file), 'midsize-'.basename($file), $file)); + if ( ! $image || is_wp_error( $image ) ) + wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) ); + + /** This filter is documented in wp-admin/custom-header.php */ + $image = apply_filters( 'wp_create_file_in_uploads', $image, $attachment_id ); // For replication + + $url = str_replace(basename($url), basename($image), $url); + $width = $width / $oitar; + $height = $height / $oitar; + } else { + $oitar = 1; + } + ?> + +
+ +

+ +
+

+

+ +
+ +
+ + + + + + + + + + + + +

+ + +

+
+
+ false); + + $uploaded_file = $_FILES['import']; + $wp_filetype = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'], false ); + if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) + wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) ); + + $file = wp_handle_upload($uploaded_file, $overrides); + + if ( isset($file['error']) ) + wp_die( $file['error'], __( 'Image Upload Error' ) ); + + $url = $file['url']; + $type = $file['type']; + $file = $file['file']; + $filename = basename($file); + + // Construct the object array + $object = array( + 'post_title' => $filename, + 'post_content' => $url, + 'post_mime_type' => $type, + 'guid' => $url, + 'context' => 'custom-header' + ); + + // Save the data + $attachment_id = wp_insert_attachment( $object, $file ); + return compact( 'attachment_id', 'file', 'filename', 'url', 'type' ); + } + + /** + * Display third step of custom header image page. + * + * @since 2.1.0 + */ + function step_3() { + check_admin_referer( 'custom-header-crop-image' ); + + if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + + if ( ! empty( $_POST['skip-cropping'] ) && ! ( current_theme_supports( 'custom-header', 'flex-height' ) || current_theme_supports( 'custom-header', 'flex-width' ) ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + + if ( $_POST['oitar'] > 1 ) { + $_POST['x1'] = $_POST['x1'] * $_POST['oitar']; + $_POST['y1'] = $_POST['y1'] * $_POST['oitar']; + $_POST['width'] = $_POST['width'] * $_POST['oitar']; + $_POST['height'] = $_POST['height'] * $_POST['oitar']; + } + + $attachment_id = absint( $_POST['attachment_id'] ); + $original = get_attached_file($attachment_id); + + + $max_width = 0; + // For flex, limit size of image displayed to 1500px unless theme says otherwise + if ( current_theme_supports( 'custom-header', 'flex-width' ) ) + $max_width = 1500; + + if ( current_theme_supports( 'custom-header', 'max-width' ) ) + $max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) ); + $max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) ); + + if ( ( current_theme_supports( 'custom-header', 'flex-height' ) && ! current_theme_supports( 'custom-header', 'flex-width' ) ) || $_POST['width'] > $max_width ) + $dst_height = absint( $_POST['height'] * ( $max_width / $_POST['width'] ) ); + elseif ( current_theme_supports( 'custom-header', 'flex-height' ) && current_theme_supports( 'custom-header', 'flex-width' ) ) + $dst_height = absint( $_POST['height'] ); + else + $dst_height = get_theme_support( 'custom-header', 'height' ); + + if ( ( current_theme_supports( 'custom-header', 'flex-width' ) && ! current_theme_supports( 'custom-header', 'flex-height' ) ) || $_POST['width'] > $max_width ) + $dst_width = absint( $_POST['width'] * ( $max_width / $_POST['width'] ) ); + elseif ( current_theme_supports( 'custom-header', 'flex-width' ) && current_theme_supports( 'custom-header', 'flex-height' ) ) + $dst_width = absint( $_POST['width'] ); + else + $dst_width = get_theme_support( 'custom-header', 'width' ); + + if ( empty( $_POST['skip-cropping'] ) ) + $cropped = wp_crop_image( $attachment_id, (int) $_POST['x1'], (int) $_POST['y1'], (int) $_POST['width'], (int) $_POST['height'], $dst_width, $dst_height ); + elseif ( ! empty( $_POST['create-new-attachment'] ) ) + $cropped = _copy_image_file( $attachment_id ); + else + $cropped = get_attached_file( $attachment_id ); + + if ( ! $cropped || is_wp_error( $cropped ) ) + wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) ); + + /** This filter is documented in wp-admin/custom-header.php */ + $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication + + $parent = get_post($attachment_id); + $parent_url = $parent->guid; + $url = str_replace( basename( $parent_url ), basename( $cropped ), $parent_url ); + + $size = @getimagesize( $cropped ); + $image_type = ( $size ) ? $size['mime'] : 'image/jpeg'; + + // Construct the object array + $object = array( + 'ID' => $attachment_id, + 'post_title' => basename($cropped), + 'post_content' => $url, + 'post_mime_type' => $image_type, + 'guid' => $url, + 'context' => 'custom-header' + ); + if ( ! empty( $_POST['create-new-attachment'] ) ) + unset( $object['ID'] ); + + // Update the attachment + $attachment_id = wp_insert_attachment( $object, $cropped ); + wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $cropped ) ); + + $width = $dst_width; + $height = $dst_height; + $this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) ); + + // cleanup + $medium = str_replace( basename( $original ), 'midsize-' . basename( $original ), $original ); + if ( file_exists( $medium ) ) { + /** + * Filter the path of the file to delete. + * + * @since 2.1.0 + * + * @param string $medium Path to the file to delete. + */ + @unlink( apply_filters( 'wp_delete_file', $medium ) ); + } + + if ( empty( $_POST['create-new-attachment'] ) && empty( $_POST['skip-cropping'] ) ) { + /** This filter is documented in wp-admin/custom-header.php */ + @unlink( apply_filters( 'wp_delete_file', $original ) ); + } + + return $this->finished(); + } + + /** + * Display last step of custom header image page. + * + * @since 2.1.0 + */ + function finished() { + $this->updated = true; + $this->step_1(); + } + + /** + * Display the page based on the current step. + * + * @since 2.1.0 + */ + function admin_page() { + if ( ! current_user_can('edit_theme_options') ) + wp_die(__('You do not have permission to customize headers.')); + $step = $this->step(); + if ( 2 == $step ) + $this->step_2(); + elseif ( 3 == $step ) + $this->step_3(); + else + $this->step_1(); + } + + /** + * Unused since 3.5.0. + * + * @since 3.4.0 + */ + function attachment_fields_to_edit( $form_fields ) { + return $form_fields; + } + + /** + * Unused since 3.5.0. + * + * @since 3.4.0 + */ + function filter_upload_tabs( $tabs ) { + return $tabs; + } + + /** + * Choose a header image, selected from existing uploaded and default headers, + * or provide an array of uploaded header data (either new, or from media library). + * + * @param mixed $choice Which header image to select. Allows for values of 'random-default-image', + * for randomly cycling among the default images; 'random-uploaded-image', for randomly cycling + * among the uploaded images; the key of a default image registered for that theme; and + * the key of an image uploaded for that theme (the basename of the URL). + * Or an array of arguments: attachment_id, url, width, height. All are required. + * + * @since 3.4.0 + */ + final public function set_header_image( $choice ) { + if ( is_array( $choice ) || is_object( $choice ) ) { + $choice = (array) $choice; + if ( ! isset( $choice['attachment_id'] ) || ! isset( $choice['url'] ) ) + return; + + $choice['url'] = esc_url_raw( $choice['url'] ); + + $header_image_data = (object) array( + 'attachment_id' => $choice['attachment_id'], + 'url' => $choice['url'], + 'thumbnail_url' => $choice['url'], + 'height' => $choice['height'], + 'width' => $choice['width'], + ); + + update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() ); + set_theme_mod( 'header_image', $choice['url'] ); + set_theme_mod( 'header_image_data', $header_image_data ); + return; + } + + if ( in_array( $choice, array( 'remove-header', 'random-default-image', 'random-uploaded-image' ) ) ) { + set_theme_mod( 'header_image', $choice ); + remove_theme_mod( 'header_image_data' ); + return; + } + + $uploaded = get_uploaded_header_images(); + if ( $uploaded && isset( $uploaded[ $choice ] ) ) { + $header_image_data = $uploaded[ $choice ]; + + } else { + $this->process_default_headers(); + if ( isset( $this->default_headers[ $choice ] ) ) + $header_image_data = $this->default_headers[ $choice ]; + else + return; + } + + set_theme_mod( 'header_image', esc_url_raw( $header_image_data['url'] ) ); + set_theme_mod( 'header_image_data', $header_image_data ); + } + + /** + * Remove a header image. + * + * @since 3.4.0 + */ + final public function remove_header_image() { + return $this->set_header_image( 'remove-header' ); + } + + /** + * Reset a header image to the default image for the theme. + * + * This method does not do anything if the theme does not have a default header image. + * + * @since 3.4.0 + */ + final public function reset_header_image() { + $this->process_default_headers(); + $default = get_theme_support( 'custom-header', 'default-image' ); + + if ( ! $default ) + return $this->remove_header_image(); + + $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() ); + + $default_data = array(); + foreach ( $this->default_headers as $header => $details ) { + if ( $details['url'] == $default ) { + $default_data = $details; + break; + } + } + + set_theme_mod( 'header_image', $default ); + set_theme_mod( 'header_image_data', (object) $default_data ); + } +} diff --git a/sources/wp-admin/customize.php b/sources/wp-admin/customize.php new file mode 100644 index 0000000..7f26586 --- /dev/null +++ b/sources/wp-admin/customize.php @@ -0,0 +1,243 @@ +registered; +$wp_scripts = new WP_Scripts; +$wp_scripts->registered = $registered; + +add_action( 'customize_controls_print_scripts', 'print_head_scripts', 20 ); +add_action( 'customize_controls_print_footer_scripts', '_wp_footer_scripts' ); +add_action( 'customize_controls_print_styles', 'print_admin_styles', 20 ); + +/** + * Fires when Customizer controls are initialized, before scripts are enqueued. + * + * @since 3.4.0 + */ +do_action( 'customize_controls_init' ); + +wp_enqueue_script( 'customize-controls' ); +wp_enqueue_style( 'customize-controls' ); + +wp_enqueue_script( 'accordion' ); + +/** + * Enqueue Customizer control scripts. + * + * @since 3.4.0 + */ +do_action( 'customize_controls_enqueue_scripts' ); + +// Let's roll. +@header('Content-Type: ' . get_option('html_type') . '; charset=' . get_option('blog_charset')); + +wp_user_settings(); +_wp_admin_html_begin(); + +$body_class = 'wp-core-ui js'; + +if ( wp_is_mobile() ) : + $body_class .= ' mobile'; + + ?>theme()->display('Name') ) ) ); +?><?php echo $admin_title; ?> + + +
+
+ +
+ is_theme_active() ? __( 'Save & Publish' ) : __( 'Save & Activate' ); + submit_button( $save_text, 'primary save', 'save', false ); + ?> + + + + +
+ + theme()->get_screenshot(); + $cannot_expand = ! ( $screenshot || $wp_customize->theme()->get('Description') ); + ?> + +
+
+
+ ' . $wp_customize->theme()->display('Name') . '' ); + ?> +
+ +
+ + + + + theme()->get('Description') ): ?> +
theme()->display('Description'); ?>
+ +
+ +
+ +
    + sections() as $section ) + $section->maybe_render(); + ?> +
+
+ + +
+
+ 1, + 'template' => $wp_customize->get_template(), + 'stylesheet' => $wp_customize->get_stylesheet(), + 'preview_iframe' => true, + 'TB_iframe' => 'true' + ), home_url( '/' ) ); + + $login_url = add_query_arg( array( + 'interim-login' => 1, + 'customize-login' => 1 + ), wp_login_url() ); + + $settings = array( + 'theme' => array( + 'stylesheet' => $wp_customize->get_stylesheet(), + 'active' => $wp_customize->is_theme_active(), + ), + 'url' => array( + 'preview' => esc_url( $url ? $url : home_url( '/' ) ), + 'parent' => esc_url( admin_url() ), + 'activated' => admin_url( 'themes.php?activated=true&previewed' ), + 'ajax' => esc_url( admin_url( 'admin-ajax.php', 'relative' ) ), + 'allowed' => array_map( 'esc_url', $allowed_urls ), + 'isCrossDomain' => $cross_domain, + 'fallback' => $fallback_url, + 'home' => esc_url( home_url( '/' ) ), + 'login' => $login_url, + ), + 'browser' => array( + 'mobile' => wp_is_mobile(), + 'ios' => $is_ios, + ), + 'settings' => array(), + 'controls' => array(), + 'nonce' => array( + 'save' => wp_create_nonce( 'save-customize_' . $wp_customize->get_stylesheet() ), + 'preview' => wp_create_nonce( 'preview-customize_' . $wp_customize->get_stylesheet() ) + ), + ); + + foreach ( $wp_customize->settings() as $id => $setting ) { + $settings['settings'][ $id ] = array( + 'value' => $setting->js_value(), + 'transport' => $setting->transport, + ); + } + + foreach ( $wp_customize->controls() as $id => $control ) { + $control->to_json(); + $settings['controls'][ $id ] = $control->json; + } + + ?> + +
+ + diff --git a/sources/wp-admin/edit-comments.php b/sources/wp-admin/edit-comments.php new file mode 100644 index 0000000..f084ab5 --- /dev/null +++ b/sources/wp-admin/edit-comments.php @@ -0,0 +1,255 @@ +get_pagenum(); + +$doaction = $wp_list_table->current_action(); + +if ( $doaction ) { + check_admin_referer( 'bulk-comments' ); + + if ( 'delete_all' == $doaction && !empty( $_REQUEST['pagegen_timestamp'] ) ) { + $comment_status = wp_unslash( $_REQUEST['comment_status'] ); + $delete_time = wp_unslash( $_REQUEST['pagegen_timestamp'] ); + $comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_approved = %s AND %s > comment_date_gmt", $comment_status, $delete_time ) ); + $doaction = 'delete'; + } elseif ( isset( $_REQUEST['delete_comments'] ) ) { + $comment_ids = $_REQUEST['delete_comments']; + $doaction = ( $_REQUEST['action'] != -1 ) ? $_REQUEST['action'] : $_REQUEST['action2']; + } elseif ( isset( $_REQUEST['ids'] ) ) { + $comment_ids = array_map( 'absint', explode( ',', $_REQUEST['ids'] ) ); + } elseif ( wp_get_referer() ) { + wp_safe_redirect( wp_get_referer() ); + exit; + } + + $approved = $unapproved = $spammed = $unspammed = $trashed = $untrashed = $deleted = 0; + + $redirect_to = remove_query_arg( array( 'trashed', 'untrashed', 'deleted', 'spammed', 'unspammed', 'approved', 'unapproved', 'ids' ), wp_get_referer() ); + $redirect_to = add_query_arg( 'paged', $pagenum, $redirect_to ); + + foreach ( $comment_ids as $comment_id ) { // Check the permissions on each + if ( !current_user_can( 'edit_comment', $comment_id ) ) + continue; + + switch ( $doaction ) { + case 'approve' : + wp_set_comment_status( $comment_id, 'approve' ); + $approved++; + break; + case 'unapprove' : + wp_set_comment_status( $comment_id, 'hold' ); + $unapproved++; + break; + case 'spam' : + wp_spam_comment( $comment_id ); + $spammed++; + break; + case 'unspam' : + wp_unspam_comment( $comment_id ); + $unspammed++; + break; + case 'trash' : + wp_trash_comment( $comment_id ); + $trashed++; + break; + case 'untrash' : + wp_untrash_comment( $comment_id ); + $untrashed++; + break; + case 'delete' : + wp_delete_comment( $comment_id ); + $deleted++; + break; + } + } + + if ( $approved ) + $redirect_to = add_query_arg( 'approved', $approved, $redirect_to ); + if ( $unapproved ) + $redirect_to = add_query_arg( 'unapproved', $unapproved, $redirect_to ); + if ( $spammed ) + $redirect_to = add_query_arg( 'spammed', $spammed, $redirect_to ); + if ( $unspammed ) + $redirect_to = add_query_arg( 'unspammed', $unspammed, $redirect_to ); + if ( $trashed ) + $redirect_to = add_query_arg( 'trashed', $trashed, $redirect_to ); + if ( $untrashed ) + $redirect_to = add_query_arg( 'untrashed', $untrashed, $redirect_to ); + if ( $deleted ) + $redirect_to = add_query_arg( 'deleted', $deleted, $redirect_to ); + if ( $trashed || $spammed ) + $redirect_to = add_query_arg( 'ids', join( ',', $comment_ids ), $redirect_to ); + + wp_safe_redirect( $redirect_to ); + exit; +} elseif ( ! empty( $_GET['_wp_http_referer'] ) ) { + wp_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); + exit; +} + +$wp_list_table->prepare_items(); + +wp_enqueue_script('admin-comments'); +enqueue_comment_hotkeys_js(); + +if ( $post_id ) + $title = sprintf( __( 'Comments on “%s”' ), wp_html_excerpt( _draft_or_post_title( $post_id ), 50, '…' ) ); +else + $title = __('Comments'); + +add_screen_option( 'per_page', array('label' => _x( 'Comments', 'comments per page (screen options)' )) ); + +get_current_screen()->add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

' . __( 'You can manage comments made on your site similar to the way you manage posts and other content. This screen is customizable in the same ways as other management screens, and you can act on comments using the on-hover action links or the Bulk Actions.' ) . '

' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'moderating-comments', +'title' => __('Moderating Comments'), +'content' => + '

' . __( 'A yellow row means the comment is waiting for you to moderate it.' ) . '

' . + '

' . __( 'In the Author column, in addition to the author’s name, email address, and blog URL, the commenter’s IP address is shown. Clicking on this link will show you all the comments made from this IP address.' ) . '

' . + '

' . __( 'In the Comment column, above each comment it says “Submitted on,” followed by the date and time the comment was left on your site. Clicking on the date/time link will take you to that comment on your live site. Hovering over any comment gives you options to approve, reply (and approve), quick edit, edit, spam mark, or trash that comment.' ) . '

' . + '

' . __( 'In the In Response To column, there are three elements. The text is the name of the post that inspired the comment, and links to the post editor for that entry. The View Post link leads to that post on your live site. The small bubble with the number in it shows the number of approved comments that post has received. If the bubble is gray, you have moderated all comments for that post. If it is blue, there are pending comments. Clicking the bubble will filter the comments screen to show only comments on that post.' ) . '

' . + '

' . __( 'Many people take advantage of keyboard shortcuts to moderate their comments more quickly. Use the link to the side to learn more.' ) . '

' +) ); + +get_current_screen()->set_help_sidebar( + '

' . __( 'For more information:' ) . '

' . + '

' . __( 'Documentation on Comments' ) . '

' . + '

' . __( 'Documentation on Comment Spam' ) . '

' . + '

' . __( 'Documentation on Keyboard Shortcuts' ) . '

' . + '

' . __( 'Support Forums' ) . '

' +); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
+ +

%s', + get_edit_post_link( $post_id ), + wp_html_excerpt( _draft_or_post_title( $post_id ), 50, '…' ) + ) + ); +else + echo __('Comments'); + +if ( isset($_REQUEST['s']) && $_REQUEST['s'] ) + echo '' . sprintf( __( 'Search results for “%s”' ), wp_html_excerpt( esc_html( wp_unslash( $_REQUEST['s'] ) ), 50, '…' ) ) . ''; ?> +

+ +

' . $error_msg . '

'; +} + +if ( isset($_REQUEST['approved']) || isset($_REQUEST['deleted']) || isset($_REQUEST['trashed']) || isset($_REQUEST['untrashed']) || isset($_REQUEST['spammed']) || isset($_REQUEST['unspammed']) || isset($_REQUEST['same']) ) { + $approved = isset( $_REQUEST['approved'] ) ? (int) $_REQUEST['approved'] : 0; + $deleted = isset( $_REQUEST['deleted'] ) ? (int) $_REQUEST['deleted'] : 0; + $trashed = isset( $_REQUEST['trashed'] ) ? (int) $_REQUEST['trashed'] : 0; + $untrashed = isset( $_REQUEST['untrashed'] ) ? (int) $_REQUEST['untrashed'] : 0; + $spammed = isset( $_REQUEST['spammed'] ) ? (int) $_REQUEST['spammed'] : 0; + $unspammed = isset( $_REQUEST['unspammed'] ) ? (int) $_REQUEST['unspammed'] : 0; + $same = isset( $_REQUEST['same'] ) ? (int) $_REQUEST['same'] : 0; + + if ( $approved > 0 || $deleted > 0 || $trashed > 0 || $untrashed > 0 || $spammed > 0 || $unspammed > 0 || $same > 0 ) { + if ( $approved > 0 ) + $messages[] = sprintf( _n( '%s comment approved', '%s comments approved', $approved ), $approved ); + + if ( $spammed > 0 ) { + $ids = isset($_REQUEST['ids']) ? $_REQUEST['ids'] : 0; + $messages[] = sprintf( _n( '%s comment marked as spam.', '%s comments marked as spam.', $spammed ), $spammed ) . ' ' . __('Undo') . '
'; + } + + if ( $unspammed > 0 ) + $messages[] = sprintf( _n( '%s comment restored from the spam', '%s comments restored from the spam', $unspammed ), $unspammed ); + + if ( $trashed > 0 ) { + $ids = isset($_REQUEST['ids']) ? $_REQUEST['ids'] : 0; + $messages[] = sprintf( _n( '%s comment moved to the Trash.', '%s comments moved to the Trash.', $trashed ), $trashed ) . ' ' . __('Undo') . '
'; + } + + if ( $untrashed > 0 ) + $messages[] = sprintf( _n( '%s comment restored from the Trash', '%s comments restored from the Trash', $untrashed ), $untrashed ); + + if ( $deleted > 0 ) + $messages[] = sprintf( _n( '%s comment permanently deleted', '%s comments permanently deleted', $deleted ), $deleted ); + + if ( $same > 0 && $comment = get_comment( $same ) ) { + switch ( $comment->comment_approved ) { + case '1' : + $messages[] = __('This comment is already approved.') . ' ' . __( 'Edit comment' ) . ''; + break; + case 'trash' : + $messages[] = __( 'This comment is already in the Trash.' ) . ' ' . __( 'View Trash' ) . ''; + break; + case 'spam' : + $messages[] = __( 'This comment is already marked as spam.' ) . ' ' . __( 'Edit comment' ) . ''; + break; + } + } + + echo '

' . implode( "
\n", $messages ) . '

'; + } +} +?> + +views(); ?> + +
+ +search_box( __( 'Search Comments' ), 'comment' ); ?> + + + + + + + + + + + + + + + +display(); ?> +
+
+ +
+ + diff --git a/sources/wp-admin/edit-form-advanced.php b/sources/wp-admin/edit-form-advanced.php new file mode 100644 index 0000000..dab3f84 --- /dev/null +++ b/sources/wp-admin/edit-form-advanced.php @@ -0,0 +1,608 @@ + $post_ID ) ); +} + +// Add the local autosave notice HTML +add_action( 'admin_footer', '_local_storage_notice' ); + +/* + * @todo Document the $messages array(s). + */ +$messages = array(); +$messages['post'] = array( + 0 => '', // Unused. Messages start at index 1. + 1 => sprintf( __('Post updated. View post'), esc_url( get_permalink($post_ID) ) ), + 2 => __('Custom field updated.'), + 3 => __('Custom field deleted.'), + 4 => __('Post updated.'), + /* translators: %s: date and time of the revision */ + 5 => isset($_GET['revision']) ? sprintf( __('Post restored to revision from %s'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, + 6 => sprintf( __('Post published. View post'), esc_url( get_permalink($post_ID) ) ), + 7 => __('Post saved.'), + 8 => sprintf( __('Post submitted. Preview post'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ), + 9 => sprintf( __('Post scheduled for: %1$s. Preview post'), + // translators: Publish box date format, see http://php.net/date + date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ), + 10 => sprintf( __('Post draft updated. Preview post'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ), +); +$messages['page'] = array( + 0 => '', // Unused. Messages start at index 1. + 1 => sprintf( __('Page updated. View page'), esc_url( get_permalink($post_ID) ) ), + 2 => __('Custom field updated.'), + 3 => __('Custom field deleted.'), + 4 => __('Page updated.'), + 5 => isset($_GET['revision']) ? sprintf( __('Page restored to revision from %s'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, + 6 => sprintf( __('Page published. View page'), esc_url( get_permalink($post_ID) ) ), + 7 => __('Page saved.'), + 8 => sprintf( __('Page submitted. Preview page'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ), + 9 => sprintf( __('Page scheduled for: %1$s. Preview page'), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ), + 10 => sprintf( __('Page draft updated. Preview page'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ), +); +$messages['attachment'] = array_fill( 1, 10, __( 'Media attachment updated.' ) ); // Hack, for now. + +/** + * Filter the post updated messages. + * + * @since 3.0.0 + * + * @param array $messages Post updated messages. For defaults @see $messages declarations above. + */ +$messages = apply_filters( 'post_updated_messages', $messages ); + +$message = false; +if ( isset($_GET['message']) ) { + $_GET['message'] = absint( $_GET['message'] ); + if ( isset($messages[$post_type][$_GET['message']]) ) + $message = $messages[$post_type][$_GET['message']]; + elseif ( !isset($messages[$post_type]) && isset($messages['post'][$_GET['message']]) ) + $message = $messages['post'][$_GET['message']]; +} + +$notice = false; +$form_extra = ''; +if ( 'auto-draft' == $post->post_status ) { + if ( 'edit' == $action ) + $post->post_title = ''; + $autosave = false; + $form_extra .= ""; +} else { + $autosave = wp_get_post_autosave( $post_ID ); +} + +$form_action = 'editpost'; +$nonce_action = 'update-post_' . $post_ID; +$form_extra .= ""; + +// Detect if there exists an autosave newer than the post and if that autosave is different than the post +if ( $autosave && mysql2date( 'U', $autosave->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) { + foreach ( _wp_post_revision_fields() as $autosave_field => $_autosave_field ) { + if ( normalize_whitespace( $autosave->$autosave_field ) != normalize_whitespace( $post->$autosave_field ) ) { + $notice = sprintf( __( 'There is an autosave of this post that is more recent than the version below. View the autosave' ), get_edit_post_link( $autosave->ID ) ); + break; + } + } + // If this autosave isn't different from the current post, begone. + if ( ! $notice ) + wp_delete_post_revision( $autosave->ID ); + unset($autosave_field, $_autosave_field); +} + +$post_type_object = get_post_type_object($post_type); + +// All meta boxes should be defined and added before the first do_meta_boxes() call (or potentially during the do_meta_boxes action). +require_once( ABSPATH . 'wp-admin/includes/meta-boxes.php' ); + + +$publish_callback_args = null; +if ( post_type_supports($post_type, 'revisions') && 'auto-draft' != $post->post_status ) { + $revisions = wp_get_post_revisions( $post_ID ); + + // We should aim to show the revisions metabox only when there are revisions. + if ( count( $revisions ) > 1 ) { + reset( $revisions ); // Reset pointer for key() + $publish_callback_args = array( 'revisions_count' => count( $revisions ), 'revision_id' => key( $revisions ) ); + add_meta_box('revisionsdiv', __('Revisions'), 'post_revisions_meta_box', null, 'normal', 'core'); + } +} + +if ( 'attachment' == $post_type ) { + wp_enqueue_script( 'image-edit' ); + wp_enqueue_style( 'imgareaselect' ); + add_meta_box( 'submitdiv', __('Save'), 'attachment_submit_meta_box', null, 'side', 'core' ); + add_action( 'edit_form_after_title', 'edit_form_image_editor' ); +} else { + add_meta_box( 'submitdiv', __( 'Publish' ), 'post_submit_meta_box', null, 'side', 'core', $publish_callback_args ); +} + +if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post_type, 'post-formats' ) ) + add_meta_box( 'formatdiv', _x( 'Format', 'post format' ), 'post_format_meta_box', null, 'side', 'core' ); + +// all taxonomies +foreach ( get_object_taxonomies( $post ) as $tax_name ) { + $taxonomy = get_taxonomy( $tax_name ); + if ( ! $taxonomy->show_ui ) + continue; + + $label = $taxonomy->labels->name; + + if ( ! is_taxonomy_hierarchical( $tax_name ) ) + $tax_meta_box_id = 'tagsdiv-' . $tax_name; + else + $tax_meta_box_id = $tax_name . 'div'; + + add_meta_box( $tax_meta_box_id, $label, $taxonomy->meta_box_cb, null, 'side', 'core', array( 'taxonomy' => $tax_name ) ); +} + +if ( post_type_supports($post_type, 'page-attributes') ) + add_meta_box('pageparentdiv', 'page' == $post_type ? __('Page Attributes') : __('Attributes'), 'page_attributes_meta_box', null, 'side', 'core'); + +$audio_post_support = $video_post_support = false; +$theme_support = current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' ); +if ( 'attachment' === $post_type && ! empty( $post->post_mime_type ) ) { + $audio_post_support = 0 === strpos( $post->post_mime_type, 'audio/' ) && current_theme_supports( 'post-thumbnails', 'attachment:audio' ) && post_type_supports( 'attachment:audio', 'thumbnail' ); + $video_post_support = 0 === strpos( $post->post_mime_type, 'video/' ) && current_theme_supports( 'post-thumbnails', 'attachment:video' ) && post_type_supports( 'attachment:video', 'thumbnail' ); +} + +if ( $theme_support || $audio_post_support || $video_post_support ) + add_meta_box('postimagediv', __('Featured Image'), 'post_thumbnail_meta_box', null, 'side', 'low'); + +if ( post_type_supports($post_type, 'excerpt') ) + add_meta_box('postexcerpt', __('Excerpt'), 'post_excerpt_meta_box', null, 'normal', 'core'); + +if ( post_type_supports($post_type, 'trackbacks') ) + add_meta_box('trackbacksdiv', __('Send Trackbacks'), 'post_trackback_meta_box', null, 'normal', 'core'); + +if ( post_type_supports($post_type, 'custom-fields') ) + add_meta_box('postcustom', __('Custom Fields'), 'post_custom_meta_box', null, 'normal', 'core'); + +/** + * Fires in the middle of built-in meta box registration. + * + * @since 2.1.0 + * @deprecated 3.7.0 Use 'add_meta_boxes' instead. + * + * @param WP_Post $post Post object. + */ +do_action( 'dbx_post_advanced', $post ); + +if ( post_type_supports($post_type, 'comments') ) + add_meta_box('commentstatusdiv', __('Discussion'), 'post_comment_status_meta_box', null, 'normal', 'core'); + +if ( ( 'publish' == get_post_status( $post ) || 'private' == get_post_status( $post ) ) && post_type_supports($post_type, 'comments') ) + add_meta_box('commentsdiv', __('Comments'), 'post_comment_meta_box', null, 'normal', 'core'); + +if ( ! ( 'pending' == get_post_status( $post ) && ! current_user_can( $post_type_object->cap->publish_posts ) ) ) + add_meta_box('slugdiv', __('Slug'), 'post_slug_meta_box', null, 'normal', 'core'); + +if ( post_type_supports($post_type, 'author') ) { + if ( is_super_admin() || current_user_can( $post_type_object->cap->edit_others_posts ) ) + add_meta_box('authordiv', __('Author'), 'post_author_meta_box', null, 'normal', 'core'); +} + +/** + * Fires after all built-in meta boxes have been added. + * + * @since 3.0.0 + * + * @param string $post_type Post type. + * @param WP_Post $post Post object. + */ +do_action( 'add_meta_boxes', $post_type, $post ); + +/** + * Fires after all built-in meta boxes have been added, contextually for the given post type. + * + * The dynamic portion of the hook, $post_type, refers to the post type of the post. + * + * @since 3.0.0 + * + * @param WP_Post $post Post object. + */ +do_action( 'add_meta_boxes_' . $post_type, $post ); + +/** + * Fires after meta boxes have been added. + * + * Fires once for each of the default meta box contexts: normal, advanced, and side. + * + * @since 3.0.0 + * + * @param string $post_type Post type of the post. + * @param string $context string Meta box context. + * @param WP_Post $post Post object. + */ +do_action( 'do_meta_boxes', $post_type, 'normal', $post ); +/** This action is documented in wp-admin/edit-form-advanced.php */ +do_action( 'do_meta_boxes', $post_type, 'advanced', $post ); +/** This action is documented in wp-admin/edit-form-advanced.php */ +do_action( 'do_meta_boxes', $post_type, 'side', $post ); + +add_screen_option('layout_columns', array('max' => 2, 'default' => 2) ); + +if ( 'post' == $post_type ) { + $customize_display = '

' . __('The title field and the big Post Editing Area are fixed in place, but you can reposition all the other boxes using drag and drop. You can also minimize or expand them by clicking the title bar of each box. Use the Screen Options tab to unhide more boxes (Excerpt, Send Trackbacks, Custom Fields, Discussion, Slug, Author) or to choose a 1- or 2-column layout for this screen.') . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'customize-display', + 'title' => __('Customizing This Display'), + 'content' => $customize_display, + ) ); + + $title_and_editor = '

' . __('Title - Enter a title for your post. After you enter a title, you’ll see the permalink below, which you can edit.') . '

'; + $title_and_editor .= '

' . __('Post editor - Enter the text for your post. There are two modes of editing: Visual and Text. Choose the mode by clicking on the appropriate tab. Visual mode gives you a WYSIWYG editor. Click the last icon in the row to get a second row of controls. The Text mode allows you to enter HTML along with your post text. Line breaks will be converted to paragraphs automatically. You can insert media files by clicking the icons above the post editor and following the directions. You can go to the distraction-free writing screen via the Fullscreen icon in Visual mode (second to last in the top row) or the Fullscreen button in Text mode (last in the row). Once there, you can make buttons visible by hovering over the top area. Exit Fullscreen back to the regular post editor.') . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'title-post-editor', + 'title' => __('Title and Post Editor'), + 'content' => $title_and_editor, + ) ); + + get_current_screen()->set_help_sidebar( + '

' . sprintf(__('You can also create posts with the Press This bookmarklet.'), 'options-writing.php') . '

' . + '

' . __('For more information:') . '

' . + '

' . __('Documentation on Writing and Editing Posts') . '

' . + '

' . __('Support Forums') . '

' + ); +} elseif ( 'page' == $post_type ) { + $about_pages = '

' . __('Pages are similar to Posts in that they have a title, body text, and associated metadata, but they are different in that they are not part of the chronological blog stream, kind of like permanent posts. Pages are not categorized or tagged, but can have a hierarchy. You can nest Pages under other Pages by making one the “Parent” of the other, creating a group of Pages.') . '

' . + '

' . __('Creating a Page is very similar to creating a Post, and the screens can be customized in the same way using drag and drop, the Screen Options tab, and expanding/collapsing boxes as you choose. This screen also has the distraction-free writing space, available in both the Visual and Text modes via the Fullscreen buttons. The Page editor mostly works the same as the Post editor, but there are some Page-specific features in the Page Attributes box:') . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'about-pages', + 'title' => __('About Pages'), + 'content' => $about_pages, + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __('For more information:') . '

' . + '

' . __('Documentation on Adding New Pages') . '

' . + '

' . __('Documentation on Editing Pages') . '

' . + '

' . __('Support Forums') . '

' + ); +} elseif ( 'attachment' == $post_type ) { + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

' . __('This screen allows you to edit four fields for metadata in a file within the media library.') . '

' . + '

' . __('For images only, you can click on Edit Image under the thumbnail to expand out an inline image editor with icons for cropping, rotating, or flipping the image as well as for undoing and redoing. The boxes on the right give you more options for scaling the image, for cropping it, and for cropping the thumbnail in a different way than you crop the original image. You can click on Help in those boxes to get more information.') . '

' . + '

' . __('Note that you crop the image by clicking on it (the Crop icon is already selected) and dragging the cropping frame to select the desired part. Then click Save to retain the cropping.') . '

' . + '

' . __('Remember to click Update Media to save metadata entered or changed.') . '

' + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __('For more information:') . '

' . + '

' . __('Documentation on Edit Media') . '

' . + '

' . __('Support Forums') . '

' + ); +} + +if ( 'post' == $post_type || 'page' == $post_type ) { + $inserting_media = '

' . __( 'You can upload and insert media (images, audio, documents, etc.) by clicking the Add Media button. You can select from the images and files already uploaded to the Media Library, or upload new media to add to your page or post. To create an image gallery, select the images to add and click the “Create a new gallery” button.' ) . '

'; + $inserting_media .= '

' . __( 'You can also embed media from many popular websites including Twitter, YouTube, Flickr and others by pasting the media URL on its own line into the content of your post/page. Please refer to the Codex to learn more about embeds.' ) . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'inserting-media', + 'title' => __( 'Inserting Media' ), + 'content' => $inserting_media, + ) ); +} + +if ( 'post' == $post_type ) { + $publish_box = '

' . __('Several boxes on this screen contain settings for how your content will be published, including:') . '

'; + $publish_box .= '
  • ' . __('Publish - You can set the terms of publishing your post in the Publish box. For Status, Visibility, and Publish (immediately), click on the Edit link to reveal more options. Visibility includes options for password-protecting a post or making it stay at the top of your blog indefinitely (sticky). Publish (immediately) allows you to set a future or past date and time, so you can schedule a post to be published in the future or backdate a post.') . '
  • '; + + if ( current_theme_supports( 'post-formats' ) && post_type_supports( 'post', 'post-formats' ) ) { + $publish_box .= '
  • ' . __( 'Format - Post Formats designate how your theme will display a specific post. For example, you could have a standard blog post with a title and paragraphs, or a short aside that omits the title and contains a short text blurb. Please refer to the Codex for descriptions of each post format. Your theme could enable all or some of 10 possible formats.' ) . '
  • '; + } + + if ( current_theme_supports( 'post-thumbnails' ) && post_type_supports( 'post', 'thumbnail' ) ) { + $publish_box .= '
  • ' . __('Featured Image - This allows you to associate an image with your post without inserting it. This is usually useful only if your theme makes use of the featured image as a post thumbnail on the home page, a custom header, etc.') . '
  • '; + } + + $publish_box .= '
'; + + get_current_screen()->add_help_tab( array( + 'id' => 'publish-box', + 'title' => __('Publish Settings'), + 'content' => $publish_box, + ) ); + + $discussion_settings = '

' . __('Send Trackbacks - Trackbacks are a way to notify legacy blog systems that you’ve linked to them. Enter the URL(s) you want to send trackbacks. If you link to other WordPress sites they’ll be notified automatically using pingbacks, and this field is unnecessary.') . '

'; + $discussion_settings .= '

' . __('Discussion - You can turn comments and pings on or off, and if there are comments on the post, you can see them here and moderate them.') . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'discussion-settings', + 'title' => __('Discussion Settings'), + 'content' => $discussion_settings, + ) ); +} elseif ( 'page' == $post_type ) { + $page_attributes = '

' . __('Parent - You can arrange your pages in hierarchies. For example, you could have an “About” page that has “Life Story” and “My Dog” pages under it. There are no limits to how many levels you can nest pages.') . '

' . + '

' . __('Template - Some themes have custom templates you can use for certain pages that might have additional features or custom layouts. If so, you’ll see them in this dropdown menu.') . '

' . + '

' . __('Order - Pages are usually ordered alphabetically, but you can choose your own order by entering a number (1 for first, etc.) in this field.') . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'page-attributes', + 'title' => __('Page Attributes'), + 'content' => $page_attributes, + ) ); +} + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
+ +

cap->create_posts ) ) + echo ' ' . esc_html( $post_type_object->labels->add_new ) . ''; +?>

+ +

+ + +

+ + + tag. + * + * @since 3.0.0 + * + * @param WP_Post $post Post object. + */ +?> +
> + + + + + + + + + + + + + + +
+
+
+ + +
+
+ + + +
+
+public ? get_sample_permalink_html($post->ID) : ''; +$shortlink = wp_get_shortlink($post->ID, 'post'); +$permalink = get_permalink( $post->ID ); +if ( !empty( $shortlink ) && $shortlink !== $permalink && $permalink !== home_url('?page_id=' . $post->ID) ) + $sample_permalink_html .= '' . __('Get Shortlink') . ''; + +if ( $post_type_object->public && ! ( 'pending' == get_post_status( $post ) && !current_user_can( $post_type_object->cap->publish_posts ) ) ) { + $has_sample_permalink = $sample_permalink_html && 'auto-draft' != $post->post_status; +?> +
+ +
+ +
+ +
+ +
+ +post_content, 'content', array( + 'dfw' => true, + 'tabfocus_elements' => 'insert-media-button,save-post', + 'editor_height' => 360, +) ); ?> + + + +
0' ); ?> +   +post_status ) { + echo ''; + if ( $last_user = get_userdata( get_post_meta( $post_ID, '_edit_last', true ) ) ) { + printf(__('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), mysql2date(get_option('date_format'), $post->post_modified), mysql2date(get_option('time_format'), $post->post_modified)); + } else { + printf(__('Last edited on %1$s at %2$s'), mysql2date(get_option('date_format'), $post->post_modified), mysql2date(get_option('time_format'), $post->post_modified)); + } + echo ''; + } ?> +
+ +
+ +
+ +
+ +
+
+ +
+ +
+
+
+
+
+ + + +post_title ) : ?> + + diff --git a/sources/wp-admin/edit-form-comment.php b/sources/wp-admin/edit-form-comment.php new file mode 100644 index 0000000..07c1946 --- /dev/null +++ b/sources/wp-admin/edit-form-comment.php @@ -0,0 +1,152 @@ + +
+comment_ID) ?> +
+ +

+ +
+ + + + + +
+
+
+

+
+ + + + + + + + + + + + + + + +
+ comment_author_email ) { + printf( __( 'E-mail (%s):' ), get_comment_author_email_link( __( 'send e-mail' ), '', '' ) ); + } else { + _e( 'E-mail:' ); + } +?>
+ comment_author_url ) && 'http://' != $comment->comment_author_url ) { + $link = '' . __('visit site') . ''; + printf( __( 'URL (%s):' ), apply_filters('get_comment_author_link', $link ) ); + } else { + _e( 'URL:' ); + } ?>
+
+
+
+ +
+ 'strong,em,link,block,del,ins,img,ul,ol,li,code,close' ); + wp_editor( $comment->comment_content, 'content', array( 'media_buttons' => false, 'tinymce' => false, 'quicktags' => $quicktags_settings ) ); + wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?> +
+
+ +
+
+

+
+
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+ +
+ + +
+%1$s'); +$date = date_i18n( $datef, strtotime( $comment->comment_date ) ); +?> +  +
+
+
+
+
+ +
+
+comment_ID&_wp_original_http_referer=" . urlencode(wp_get_referer()), 'delete-comment_' . $comment->comment_ID) . "'>" . ( !EMPTY_TRASH_DAYS ? __('Delete Permanently') : __('Move to Trash') ) . "\n"; ?> +
+
+ +
+
+
+
+
+
+
+ +
+ +
+ + + + + + + +
+
+
+
+ + diff --git a/sources/wp-admin/edit-link-form.php b/sources/wp-admin/edit-link-form.php new file mode 100644 index 0000000..ad2c6e5 --- /dev/null +++ b/sources/wp-admin/edit-link-form.php @@ -0,0 +1,141 @@ +Links / Edit Link' ), 'link-manager.php' ); + $submit_text = __('Update Link'); + $form = ' diff --git a/sources/wp-admin/edit-tag-form.php b/sources/wp-admin/edit-tag-form.php new file mode 100644 index 0000000..b8f4125 --- /dev/null +++ b/sources/wp-admin/edit-tag-form.php @@ -0,0 +1,96 @@ + +

+ + +
+ +

labels->edit_item; ?>

+
+
> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+

+ 0, 'hide_if_empty' => false, 'name' => 'parent', 'orderby' => 'name', 'taxonomy' => $taxonomy, 'selected' => $tag->parent, 'exclude_tree' => $tag->term_id, 'hierarchical' => true, 'show_option_none' => __('None'))); ?> + +

+ +

+
+ +
+
+ diff --git a/sources/wp-admin/edit-tags.php b/sources/wp-admin/edit-tags.php new file mode 100644 index 0000000..0a04637 --- /dev/null +++ b/sources/wp-admin/edit-tags.php @@ -0,0 +1,465 @@ +cap->manage_terms ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + +$wp_list_table = _get_list_table('WP_Terms_List_Table'); +$pagenum = $wp_list_table->get_pagenum(); + +$title = $tax->labels->name; + +if ( 'post' != $post_type ) { + $parent_file = ( 'attachment' == $post_type ) ? 'upload.php' : "edit.php?post_type=$post_type"; + $submenu_file = "edit-tags.php?taxonomy=$taxonomy&post_type=$post_type"; +} else if ( 'link_category' == $tax->name ) { + $parent_file = 'link-manager.php'; + $submenu_file = 'edit-tags.php?taxonomy=link_category'; +} else { + $parent_file = 'edit.php'; + $submenu_file = "edit-tags.php?taxonomy=$taxonomy"; +} + +add_screen_option( 'per_page', array( 'label' => $title, 'default' => 20, 'option' => 'edit_' . $tax->name . '_per_page' ) ); + +switch ( $wp_list_table->current_action() ) { + +case 'add-tag': + + check_admin_referer( 'add-tag', '_wpnonce_add-tag' ); + + if ( !current_user_can( $tax->cap->edit_terms ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + + $ret = wp_insert_term( $_POST['tag-name'], $taxonomy, $_POST ); + $location = 'edit-tags.php?taxonomy=' . $taxonomy; + if ( 'post' != $post_type ) + $location .= '&post_type=' . $post_type; + + if ( $referer = wp_get_original_referer() ) { + if ( false !== strpos( $referer, 'edit-tags.php' ) ) + $location = $referer; + } + + if ( $ret && !is_wp_error( $ret ) ) + $location = add_query_arg( 'message', 1, $location ); + else + $location = add_query_arg( 'message', 4, $location ); + wp_redirect( $location ); + exit; +break; + +case 'delete': + $location = 'edit-tags.php?taxonomy=' . $taxonomy; + if ( 'post' != $post_type ) + $location .= '&post_type=' . $post_type; + if ( $referer = wp_get_referer() ) { + if ( false !== strpos( $referer, 'edit-tags.php' ) ) + $location = $referer; + } + + if ( !isset( $_REQUEST['tag_ID'] ) ) { + wp_redirect( $location ); + exit; + } + + $tag_ID = (int) $_REQUEST['tag_ID']; + check_admin_referer( 'delete-tag_' . $tag_ID ); + + if ( !current_user_can( $tax->cap->delete_terms ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + + wp_delete_term( $tag_ID, $taxonomy ); + + $location = add_query_arg( 'message', 2, $location ); + wp_redirect( $location ); + exit; + +break; + +case 'bulk-delete': + check_admin_referer( 'bulk-tags' ); + + if ( !current_user_can( $tax->cap->delete_terms ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + + $tags = (array) $_REQUEST['delete_tags']; + foreach ( $tags as $tag_ID ) { + wp_delete_term( $tag_ID, $taxonomy ); + } + + $location = 'edit-tags.php?taxonomy=' . $taxonomy; + if ( 'post' != $post_type ) + $location .= '&post_type=' . $post_type; + if ( $referer = wp_get_referer() ) { + if ( false !== strpos( $referer, 'edit-tags.php' ) ) + $location = $referer; + } + + $location = add_query_arg( 'message', 6, $location ); + wp_redirect( $location ); + exit; + +break; + +case 'edit': + $title = $tax->labels->edit_item; + + $tag_ID = (int) $_REQUEST['tag_ID']; + + $tag = get_term( $tag_ID, $taxonomy, OBJECT, 'edit' ); + if ( ! $tag ) + wp_die( __( 'You attempted to edit an item that doesn’t exist. Perhaps it was deleted?' ) ); + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + include( ABSPATH . 'wp-admin/edit-tag-form.php' ); + +break; + +case 'editedtag': + $tag_ID = (int) $_POST['tag_ID']; + check_admin_referer( 'update-tag_' . $tag_ID ); + + if ( !current_user_can( $tax->cap->edit_terms ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + + $tag = get_term( $tag_ID, $taxonomy ); + if ( ! $tag ) + wp_die( __( 'You attempted to edit an item that doesn’t exist. Perhaps it was deleted?' ) ); + + $ret = wp_update_term( $tag_ID, $taxonomy, $_POST ); + + $location = 'edit-tags.php?taxonomy=' . $taxonomy; + if ( 'post' != $post_type ) + $location .= '&post_type=' . $post_type; + + if ( $referer = wp_get_original_referer() ) { + if ( false !== strpos( $referer, 'edit-tags.php' ) ) + $location = $referer; + } + + if ( $ret && !is_wp_error( $ret ) ) + $location = add_query_arg( 'message', 3, $location ); + else + $location = add_query_arg( 'message', 5, $location ); + + wp_redirect( $location ); + exit; +break; + +default: +if ( ! empty($_REQUEST['_wp_http_referer']) ) { + $location = remove_query_arg( array('_wp_http_referer', '_wpnonce'), wp_unslash($_SERVER['REQUEST_URI']) ); + + if ( ! empty( $_REQUEST['paged'] ) ) + $location = add_query_arg( 'paged', (int) $_REQUEST['paged'] ); + + wp_redirect( $location ); + exit; +} + +$wp_list_table->prepare_items(); +$total_pages = $wp_list_table->get_pagination_arg( 'total_pages' ); + +if ( $pagenum > $total_pages && $total_pages > 0 ) { + wp_redirect( add_query_arg( 'paged', $total_pages ) ); + exit; +} + +wp_enqueue_script('admin-tags'); +if ( current_user_can($tax->cap->edit_terms) ) + wp_enqueue_script('inline-edit-tax'); + +if ( 'category' == $taxonomy || 'link_category' == $taxonomy || 'post_tag' == $taxonomy ) { + $help =''; + if ( 'category' == $taxonomy ) + $help = '

' . sprintf(__( 'You can use categories to define sections of your site and group related posts. The default category is “Uncategorized” until you change it in your writing settings.' ) , 'options-writing.php' ) . '

'; + elseif ( 'link_category' == $taxonomy ) + $help = '

' . __( 'You can create groups of links by using Link Categories. Link Category names must be unique and Link Categories are separate from the categories you use for posts.' ) . '

'; + else + $help = '

' . __( 'You can assign keywords to your posts using tags. Unlike categories, tags have no hierarchy, meaning there’s no relationship from one tag to another.' ) . '

'; + + if ( 'link_category' == $taxonomy ) + $help .= '

' . __( 'You can delete Link Categories in the Bulk Action pull-down, but that action does not delete the links within the category. Instead, it moves them to the default Link Category.' ) . '

'; + else + $help .='

' . __( 'What’s the difference between categories and tags? Normally, tags are ad-hoc keywords that identify important information in your post (names, subjects, etc) that may or may not recur in other posts, while categories are pre-determined sections. If you think of your site like a book, the categories are like the Table of Contents and the tags are like the terms in the index.' ) . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $help, + ) ); + + if ( 'category' == $taxonomy || 'post_tag' == $taxonomy ) { + if ( 'category' == $taxonomy ) + $help = '

' . __( 'When adding a new category on this screen, you’ll fill in the following fields:' ) . '

'; + else + $help = '

' . __( 'When adding a new tag on this screen, you’ll fill in the following fields:' ) . '

'; + + $help .= '
    ' . + '
  • ' . __( 'Name - The name is how it appears on your site.' ) . '
  • '; + + if ( ! global_terms_enabled() ) + $help .= '
  • ' . __( 'Slug - The “slug” is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.' ) . '
  • '; + + if ( 'category' == $taxonomy ) + $help .= '
  • ' . __( 'Parent - Categories, unlike tags, can have a hierarchy. You might have a Jazz category, and under that have child categories for Bebop and Big Band. Totally optional. To create a subcategory, just choose another category from the Parent dropdown.' ) . '
  • '; + + $help .= '
  • ' . __( 'Description - The description is not prominent by default; however, some themes may display it.' ) . '
  • ' . + '
' . + '

' . __( 'You can change the display of this screen using the Screen Options tab to set how many items are displayed per screen and to display/hide columns in the table.' ) . '

'; + + get_current_screen()->add_help_tab( array( + 'id' => 'adding-terms', + 'title' => 'category' == $taxonomy ? __( 'Adding Categories' ) : __( 'Adding Tags' ), + 'content' => $help, + ) ); + } + + $help = '

' . __( 'For more information:' ) . '

'; + + if ( 'category' == $taxonomy ) + $help .= '

' . __( 'Documentation on Categories' ) . '

'; + elseif ( 'link_category' == $taxonomy ) + $help .= '

' . __( 'Documentation on Link Categories' ) . '

'; + else + $help .= '

' . __( 'Documentation on Tags' ) . '

'; + + $help .= '

' . __('Support Forums') . '

'; + + get_current_screen()->set_help_sidebar( $help ); + + unset( $help ); +} + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +if ( !current_user_can($tax->cap->edit_terms) ) + wp_die( __('You are not allowed to edit this item.') ); + +$messages = array(); +$messages['_item'] = array( + 0 => '', // Unused. Messages start at index 1. + 1 => __( 'Item added.' ), + 2 => __( 'Item deleted.' ), + 3 => __( 'Item updated.' ), + 4 => __( 'Item not added.' ), + 5 => __( 'Item not updated.' ), + 6 => __( 'Items deleted.' ) +); +$messages['category'] = array( + 0 => '', // Unused. Messages start at index 1. + 1 => __( 'Category added.' ), + 2 => __( 'Category deleted.' ), + 3 => __( 'Category updated.' ), + 4 => __( 'Category not added.' ), + 5 => __( 'Category not updated.' ), + 6 => __( 'Categories deleted.' ) +); +$messages['post_tag'] = array( + 0 => '', // Unused. Messages start at index 1. + 1 => __( 'Tag added.' ), + 2 => __( 'Tag deleted.' ), + 3 => __( 'Tag updated.' ), + 4 => __( 'Tag not added.' ), + 5 => __( 'Tag not updated.' ), + 6 => __( 'Tags deleted.' ) +); + +$messages = apply_filters( 'term_updated_messages', $messages ); + +$message = false; +if ( isset( $_REQUEST['message'] ) && ( $msg = (int) $_REQUEST['message'] ) ) { + if ( isset( $messages[ $taxonomy ][ $msg ] ) ) + $message = $messages[ $taxonomy ][ $msg ]; + elseif ( ! isset( $messages[ $taxonomy ] ) && isset( $messages['_item'][ $msg ] ) ) + $message = $messages['_item'][ $msg ]; +} + +?> + +
+ +

' . __('Search results for “%s”') . '', esc_html( wp_unslash($_REQUEST['s']) ) ); ?> +

+ + +

+ +
+ +
+ + + +search_box( $tax->labels->search_items, 'tag' ); ?> + +
+
+ +
+ +
+
+
+ + + +display(); ?> + +
+
+ + +
+

Note:
Deleting a category does not delete the posts in that category. Instead, posts that were only assigned to the deleted category are set to the category %s.'), apply_filters('the_category', get_cat_name(get_option('default_category')))) ?>

+ +

category to tag converter.'), 'import.php') ?>

+ +
+ +
+

tag to category converter.'), 'import.php') ;?>

+
+ + +
+
+ +
+
+ +labels->popular_items ) ) { + if ( current_user_can( $tax->cap->edit_terms ) ) + $tag_cloud = wp_tag_cloud( array( 'taxonomy' => $taxonomy, 'echo' => false, 'link' => 'edit' ) ); + else + $tag_cloud = wp_tag_cloud( array( 'taxonomy' => $taxonomy, 'echo' => false ) ); + + if ( $tag_cloud ) : + ?> +
+

labels->popular_items; ?>

+ +
+cap->edit_terms) ) { + // Back compat hooks. Deprecated in preference to {$taxonomy}_pre_add_form + if ( 'category' == $taxonomy ) + do_action('add_category_form_pre', (object)array('parent' => 0) ); + elseif ( 'link_category' == $taxonomy ) + do_action('add_link_category_form_pre', (object)array('parent' => 0) ); + else + do_action('add_tag_form_pre', $taxonomy); + + do_action($taxonomy . '_pre_add_form', $taxonomy); +?> + +
+

labels->add_new_item; ?>

+
> + + + + + + +
+ + +

+
+ +
+ + +

+
+ + +
+ + 0, + 'hide_if_empty' => false, + 'taxonomy' => $taxonomy, + 'name' => 'parent', + 'orderby' => 'name', + 'hierarchical' => true, + 'show_option_none' => __( 'None' ), + ); + + $dropdown_args = apply_filters( 'taxonomy_parent_dropdown_args', $dropdown_args, $taxonomy ); + wp_dropdown_categories( $dropdown_args ); + ?> + +

+ +
+ +
+ + +

+
+ +labels->add_new_item ); + +// Back compat hooks. Deprecated in preference to {$taxonomy}_add_form +if ( 'category' == $taxonomy ) + do_action('edit_category_form', (object)array('parent' => 0) ); +elseif ( 'link_category' == $taxonomy ) + do_action('edit_link_category_form', (object)array('parent' => 0) ); +else + do_action('add_tag_form', $taxonomy); + +do_action($taxonomy . '_add_form', $taxonomy); +?> +
+ + +
+
+ +
+
+ +inline_edit(); ?> + +cap->edit_posts ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + +$wp_list_table = _get_list_table('WP_Posts_List_Table'); +$pagenum = $wp_list_table->get_pagenum(); + +// Back-compat for viewing comments of an entry +foreach ( array( 'p', 'attachment_id', 'page_id' ) as $_redirect ) { + if ( ! empty( $_REQUEST[ $_redirect ] ) ) { + wp_redirect( admin_url( 'edit-comments.php?p=' . absint( $_REQUEST[ $_redirect ] ) ) ); + exit; + } +} +unset( $_redirect ); + +if ( 'post' != $post_type ) { + $parent_file = "edit.php?post_type=$post_type"; + $submenu_file = "edit.php?post_type=$post_type"; + $post_new_file = "post-new.php?post_type=$post_type"; +} else { + $parent_file = 'edit.php'; + $submenu_file = 'edit.php'; + $post_new_file = 'post-new.php'; +} + +$doaction = $wp_list_table->current_action(); + +if ( $doaction ) { + check_admin_referer('bulk-posts'); + + $sendback = remove_query_arg( array('trashed', 'untrashed', 'deleted', 'locked', 'ids'), wp_get_referer() ); + if ( ! $sendback ) + $sendback = admin_url( $parent_file ); + $sendback = add_query_arg( 'paged', $pagenum, $sendback ); + if ( strpos($sendback, 'post.php') !== false ) + $sendback = admin_url($post_new_file); + + if ( 'delete_all' == $doaction ) { + $post_status = preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['post_status']); + if ( get_post_status_object($post_status) ) // Check the post status exists first + $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type=%s AND post_status = %s", $post_type, $post_status ) ); + $doaction = 'delete'; + } elseif ( isset( $_REQUEST['media'] ) ) { + $post_ids = $_REQUEST['media']; + } elseif ( isset( $_REQUEST['ids'] ) ) { + $post_ids = explode( ',', $_REQUEST['ids'] ); + } elseif ( !empty( $_REQUEST['post'] ) ) { + $post_ids = array_map('intval', $_REQUEST['post']); + } + + if ( !isset( $post_ids ) ) { + wp_redirect( $sendback ); + exit; + } + + switch ( $doaction ) { + case 'trash': + $trashed = $locked = 0; + + foreach( (array) $post_ids as $post_id ) { + if ( !current_user_can( 'delete_post', $post_id) ) + wp_die( __('You are not allowed to move this item to the Trash.') ); + + if ( wp_check_post_lock( $post_id ) ) { + $locked++; + continue; + } + + if ( !wp_trash_post($post_id) ) + wp_die( __('Error in moving to Trash.') ); + + $trashed++; + } + + $sendback = add_query_arg( array('trashed' => $trashed, 'ids' => join(',', $post_ids), 'locked' => $locked ), $sendback ); + break; + case 'untrash': + $untrashed = 0; + foreach( (array) $post_ids as $post_id ) { + if ( !current_user_can( 'delete_post', $post_id) ) + wp_die( __('You are not allowed to restore this item from the Trash.') ); + + if ( !wp_untrash_post($post_id) ) + wp_die( __('Error in restoring from Trash.') ); + + $untrashed++; + } + $sendback = add_query_arg('untrashed', $untrashed, $sendback); + break; + case 'delete': + $deleted = 0; + foreach( (array) $post_ids as $post_id ) { + $post_del = get_post($post_id); + + if ( !current_user_can( 'delete_post', $post_id ) ) + wp_die( __('You are not allowed to delete this item.') ); + + if ( $post_del->post_type == 'attachment' ) { + if ( ! wp_delete_attachment($post_id) ) + wp_die( __('Error in deleting.') ); + } else { + if ( !wp_delete_post($post_id) ) + wp_die( __('Error in deleting.') ); + } + $deleted++; + } + $sendback = add_query_arg('deleted', $deleted, $sendback); + break; + case 'edit': + if ( isset($_REQUEST['bulk_edit']) ) { + $done = bulk_edit_posts($_REQUEST); + + if ( is_array($done) ) { + $done['updated'] = count( $done['updated'] ); + $done['skipped'] = count( $done['skipped'] ); + $done['locked'] = count( $done['locked'] ); + $sendback = add_query_arg( $done, $sendback ); + } + } + break; + } + + $sendback = remove_query_arg( array('action', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view'), $sendback ); + + wp_redirect($sendback); + exit(); +} elseif ( ! empty($_REQUEST['_wp_http_referer']) ) { + wp_redirect( remove_query_arg( array('_wp_http_referer', '_wpnonce'), wp_unslash($_SERVER['REQUEST_URI']) ) ); + exit; +} + +$wp_list_table->prepare_items(); + +wp_enqueue_script('inline-edit-post'); + +$title = $post_type_object->labels->name; + +if ( 'post' == $post_type ) { + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

' . __('This screen provides access to all of your posts. You can customize the display of this screen to suit your workflow.') . '

' + ) ); + get_current_screen()->add_help_tab( array( + 'id' => 'screen-content', + 'title' => __('Screen Content'), + 'content' => + '

' . __('You can customize the display of this screen’s contents in a number of ways:') . '

' . + '
    ' . + '
  • ' . __('You can hide/display columns based on your needs and decide how many posts to list per screen using the Screen Options tab.') . '
  • ' . + '
  • ' . __('You can filter the list of posts by post status using the text links in the upper left to show All, Published, Draft, or Trashed posts. The default view is to show all posts.') . '
  • ' . + '
  • ' . __('You can view posts in a simple title list or with an excerpt. Choose the view you prefer by clicking on the icons at the top of the list on the right.') . '
  • ' . + '
  • ' . __('You can refine the list to show only posts in a specific category or from a specific month by using the dropdown menus above the posts list. Click the Filter button after making your selection. You also can refine the list by clicking on the post author, category or tag in the posts list.') . '
  • ' . + '
' + ) ); + get_current_screen()->add_help_tab( array( + 'id' => 'action-links', + 'title' => __('Available Actions'), + 'content' => + '

' . __('Hovering over a row in the posts list will display action links that allow you to manage your post. You can perform the following actions:') . '

' . + '
    ' . + '
  • ' . __('Edit takes you to the editing screen for that post. You can also reach that screen by clicking on the post title.') . '
  • ' . + '
  • ' . __('Quick Edit provides inline access to the metadata of your post, allowing you to update post details without leaving this screen.') . '
  • ' . + '
  • ' . __('Trash removes your post from this list and places it in the trash, from which you can permanently delete it.') . '
  • ' . + '
  • ' . __('Preview will show you what your draft post will look like if you publish it. View will take you to your live site to view the post. Which link is available depends on your post’s status.') . '
  • ' . + '
' + ) ); + get_current_screen()->add_help_tab( array( + 'id' => 'bulk-actions', + 'title' => __('Bulk Actions'), + 'content' => + '

' . __('You can also edit or move multiple posts to the trash at once. Select the posts you want to act on using the checkboxes, then select the action you want to take from the Bulk Actions menu and click Apply.') . '

' . + '

' . __('When using Bulk Edit, you can change the metadata (categories, author, etc.) for all selected posts at once. To remove a post from the grouping, just click the x next to its name in the Bulk Edit area that appears.') . '

' + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __('For more information:') . '

' . + '

' . __('Documentation on Managing Posts') . '

' . + '

' . __('Support Forums') . '

' + ); + +} elseif ( 'page' == $post_type ) { + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

' . __('Pages are similar to posts in that they have a title, body text, and associated metadata, but they are different in that they are not part of the chronological blog stream, kind of like permanent posts. Pages are not categorized or tagged, but can have a hierarchy. You can nest pages under other pages by making one the “Parent” of the other, creating a group of pages.') . '

' + ) ); + get_current_screen()->add_help_tab( array( + 'id' => 'managing-pages', + 'title' => __('Managing Pages'), + 'content' => + '

' . __('Managing pages is very similar to managing posts, and the screens can be customized in the same way.') . '

' . + '

' . __('You can also perform the same types of actions, including narrowing the list by using the filters, acting on a page using the action links that appear when you hover over a row, or using the Bulk Actions menu to edit the metadata for multiple pages at once.') . '

' + ) ); + + get_current_screen()->set_help_sidebar( + '

' . __('For more information:') . '

' . + '

' . __('Documentation on Managing Pages') . '

' . + '

' . __('Support Forums') . '

' + ); +} + +add_screen_option( 'per_page', array( 'label' => $title, 'default' => 20, 'option' => 'edit_' . $post_type . '_per_page' ) ); + +$bulk_counts = array( + 'updated' => isset( $_REQUEST['updated'] ) ? absint( $_REQUEST['updated'] ) : 0, + 'locked' => isset( $_REQUEST['locked'] ) ? absint( $_REQUEST['locked'] ) : 0, + 'deleted' => isset( $_REQUEST['deleted'] ) ? absint( $_REQUEST['deleted'] ) : 0, + 'trashed' => isset( $_REQUEST['trashed'] ) ? absint( $_REQUEST['trashed'] ) : 0, + 'untrashed' => isset( $_REQUEST['untrashed'] ) ? absint( $_REQUEST['untrashed'] ) : 0, +); + +$bulk_messages = array(); +$bulk_messages['post'] = array( + 'updated' => _n( '%s post updated.', '%s posts updated.', $bulk_counts['updated'] ), + 'locked' => _n( '%s post not updated, somebody is editing it.', '%s posts not updated, somebody is editing them.', $bulk_counts['locked'] ), + 'deleted' => _n( '%s post permanently deleted.', '%s posts permanently deleted.', $bulk_counts['deleted'] ), + 'trashed' => _n( '%s post moved to the Trash.', '%s posts moved to the Trash.', $bulk_counts['trashed'] ), + 'untrashed' => _n( '%s post restored from the Trash.', '%s posts restored from the Trash.', $bulk_counts['untrashed'] ), +); +$bulk_messages['page'] = array( + 'updated' => _n( '%s page updated.', '%s pages updated.', $bulk_counts['updated'] ), + 'locked' => _n( '%s page not updated, somebody is editing it.', '%s pages not updated, somebody is editing them.', $bulk_counts['locked'] ), + 'deleted' => _n( '%s page permanently deleted.', '%s pages permanently deleted.', $bulk_counts['deleted'] ), + 'trashed' => _n( '%s page moved to the Trash.', '%s pages moved to the Trash.', $bulk_counts['trashed'] ), + 'untrashed' => _n( '%s page restored from the Trash.', '%s pages restored from the Trash.', $bulk_counts['untrashed'] ), +); + +/** + * Filter the bulk action updated messages. + * + * By default, custom post types use the messages for the 'post' post type. + * + * @since 3.7.0 + * + * @param array $bulk_messages Arrays of messages, each keyed by the corresponding post type. Messages are + * keyed with 'updated', 'locked', 'deleted', 'trashed', and 'untrashed'. + * @param array $bulk_counts Array of item counts for each message, used to build internationalized strings. + */ +$bulk_messages = apply_filters( 'bulk_post_updated_messages', $bulk_messages, $bulk_counts ); +$bulk_counts = array_filter( $bulk_counts ); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); +?> +
+ +

labels->name ); +if ( current_user_can( $post_type_object->cap->create_posts ) ) + echo ' ' . esc_html( $post_type_object->labels->add_new ) . ''; +if ( ! empty( $_REQUEST['s'] ) ) + printf( ' ' . __('Search results for “%s”') . '', get_search_query() ); +?>

+ + $count ) { + if ( isset( $bulk_messages[ $post_type ][ $message ] ) ) + $messages[] = sprintf( $bulk_messages[ $post_type ][ $message ], number_format_i18n( $count ) ); + elseif ( isset( $bulk_messages['post'][ $message ] ) ) + $messages[] = sprintf( $bulk_messages['post'][ $message ], number_format_i18n( $count ) ); + + if ( $message == 'trashed' && isset( $_REQUEST['ids'] ) ) { + $ids = preg_replace( '/[^0-9,]/', '', $_REQUEST['ids'] ); + $messages[] = '' . __('Undo') . ''; + } +} + +if ( $messages ) + echo '

' . join( ' ', $messages ) . '

'; +unset( $messages ); + +$_SERVER['REQUEST_URI'] = remove_query_arg( array( 'locked', 'skipped', 'updated', 'deleted', 'trashed', 'untrashed' ), $_SERVER['REQUEST_URI'] ); +?> + +views(); ?> + +
+ +search_box( $post_type_object->labels->search_items, 'post' ); ?> + + + + + + + +display(); ?> + +
+ +has_items() ) + $wp_list_table->inline_edit(); +?> + +
+
+
+ + + +add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

' . __('You can export a file of your site’s content in order to import it into another installation or platform. The export file will be an XML file format called WXR. Posts, pages, comments, custom fields, categories, and tags can be included. You can choose for the WXR file to include only certain posts or pages by setting the dropdown filters to limit the export by category, author, date range by month, or publishing status.') . '

' . + '

' . __('Once generated, your WXR file can be imported by another WordPress site or by another blogging platform able to access this format.') . '

', +) ); + +get_current_screen()->set_help_sidebar( + '

' . __('For more information:') . '

' . + '

' . __('Documentation on Export') . '

' . + '

' . __('Support Forums') . '

' +); + +if ( isset( $_GET['download'] ) ) { + $args = array(); + + if ( ! isset( $_GET['content'] ) || 'all' == $_GET['content'] ) { + $args['content'] = 'all'; + } else if ( 'posts' == $_GET['content'] ) { + $args['content'] = 'post'; + + if ( $_GET['cat'] ) + $args['category'] = (int) $_GET['cat']; + + if ( $_GET['post_author'] ) + $args['author'] = (int) $_GET['post_author']; + + if ( $_GET['post_start_date'] || $_GET['post_end_date'] ) { + $args['start_date'] = $_GET['post_start_date']; + $args['end_date'] = $_GET['post_end_date']; + } + + if ( $_GET['post_status'] ) + $args['status'] = $_GET['post_status']; + } else if ( 'pages' == $_GET['content'] ) { + $args['content'] = 'page'; + + if ( $_GET['page_author'] ) + $args['author'] = (int) $_GET['page_author']; + + if ( $_GET['page_start_date'] || $_GET['page_end_date'] ) { + $args['start_date'] = $_GET['page_start_date']; + $args['end_date'] = $_GET['page_end_date']; + } + + if ( $_GET['page_status'] ) + $args['status'] = $_GET['page_status']; + } else { + $args['content'] = $_GET['content']; + } + + /** + * Filter the export args. + * + * @since 3.5.0 + * + * @param array $args The arguments to send to the exporter. + */ + $args = apply_filters( 'export_args', $args ); + + export_wp( $args ); + die(); +} + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +/** + * Create the date options fields for exporting a given post type. + * + * @global wpdb $wpdb WordPress database object. + * @global WP_Locale $wp_locale Date and Time Locale object. + * + * @since 3.1.0 + * + * @param string $post_type The post type. Default 'post'. + */ +function export_date_options( $post_type = 'post' ) { + global $wpdb, $wp_locale; + + $months = $wpdb->get_results( $wpdb->prepare( " + SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month + FROM $wpdb->posts + WHERE post_type = %s AND post_status != 'auto-draft' + ORDER BY post_date DESC + ", $post_type ) ); + + $month_count = count( $months ); + if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) + return; + + foreach ( $months as $date ) { + if ( 0 == $date->year ) + continue; + + $month = zeroise( $date->month, 2 ); + echo ''; + } +} +?> + +
+ +

+ +

+

+

+ +

+
+ +

+

+ +

+
    +
  • + + __('All') ) ); ?> +
  • +
  • + +get_col( "SELECT DISTINCT post_author FROM {$wpdb->posts} WHERE post_type = 'post'" ); + wp_dropdown_users( array( 'include' => $authors, 'name' => 'post_author', 'multi' => true, 'show_option_all' => __('All') ) ); +?> +
  • +
  • + + + +
  • +
  • + + +
  • +
+ +

+
    +
  • + +get_col( "SELECT DISTINCT post_author FROM {$wpdb->posts} WHERE post_type = 'page'" ); + wp_dropdown_users( array( 'include' => $authors, 'name' => 'page_author', 'multi' => true, 'show_option_all' => __('All') ) ); +?> +
  • +
  • + + + +
  • +
  • + + +
  • +
+ + false, 'can_export' => true ), 'objects' ) as $post_type ) : ?> +

+ + + + + +
+
+ + diff --git a/sources/wp-admin/freedoms.php b/sources/wp-admin/freedoms.php new file mode 100644 index 0000000..672323c --- /dev/null +++ b/sources/wp-admin/freedoms.php @@ -0,0 +1,57 @@ + +
+ +

+ +
+ +
+ + + +

license, the GPL.' ), 'http://wordpress.org/about/license/' ); ?>

+ +
    +
  1. +
  2. +
  3. +
  4. +
+ +

check out our trademark guidelines first.' ), 'http://wordpressfoundation.org/trademark-policy/' ); ?>

+ +

plugins and themes there. If you get a plugin or theme from another source, make sure to ask them if it’s GPL first. If they don’t respect the WordPress license, we don’t recommend them.' ), $plugins_url, $themes_url, 'http://wordpress.org/about/license/' ); ?>

+ +

Free Software Foundation.' ); ?>

+ +
+ diff --git a/sources/wp-admin/images/about-globe-2x.png b/sources/wp-admin/images/about-globe-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..648c5dafd3c1091e54979110545a4ec073a66b8e GIT binary patch literal 10570 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 D9xW96OxqF$rT45+aoh+NA?^@O4M|HU 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 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/align-center-2x.png b/sources/wp-admin/images/align-center-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b6273445a830ebbb45b3715a3e078c062858deb GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^T0ktv#0(_W-BOBy6i@6G)=pOmiPwxqnfsMLB2}5Uv-TJ0u-6unai1( zy4H^x&L+EeX6KxH?!A*C;uk~|Ge)t%SH?F8I3>jJ#2kw|N(7GlxFHe(>j@BNh>v3u zc)(Pz>vxvX*~uN4Mt5uOla=e1jI&p{ULoJMR*5d9ejKOo3`k$y3qK4z|4ZPzgD4nm z8ApZ1ektFv7W#$x&t;=$KI*@Q%A$Yv-S_=441*x>JWuf%Q_*dLRU$p~it`_~vrcKP zQ(0>l^G)cltrqw&BKc!tQ4li0Ni~i5w{GeAX<_czLd{vneA3-qKipY? zg|@jtbfwz{O!#Qoz&j@z*BWo^dh*GFrRl+> zN&X3az;#`fUqw(sRrPvZ%cID~4D2cV;xopgD4Na>t^edt4gRd3XgC~_Dy&+qHk(bz z+qS(s1Nzr*{xv@ZW{tz6qeg`5#^U8)zopr0G znB+j+s;;hc>fC#aY7aEp8cZcdWi(>vJvOS!+J5%h>mgcv4{*+nk$qGCc>jiN%~ZK0 zm)cb>N`3x^x@0nW{o%WJf<+{V*kcd?CJ*TO%(B73R+OA1ai%NZ$~xtU#jlvmRayQl z?w-}jX<~d=D`kz5;6zabJ6IsjW;2<3I*EIkB<=5ekzFgxI#$zD$LSLtcdu@)n34$# zLzGiZl!cpN1a^+cBcdcOU8JnDa+)zQw|?5TZGLUFc0Ob0DWWeQKg&GVTq%l;F^~Xr zu~#|Dt8yxlAkajQog+kuli5qG0FP7;_KpT{ZaNIYvtD#xviDIcdh@*w09@oJ?#m2&A8LZ V(nc#<;|$O&22WQ%mvv4FO#t<{EOP(= literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/align-none.png b/sources/wp-admin/images/align-none.png new file mode 100644 index 0000000000000000000000000000000000000000..b72df647167196e48c02f9990c9443373639b01b GIT binary patch literal 417 zcmV;S0bc%zP)7?rZd=6fc?m_9K4Qk0WdRFb$0+zq)P?m$O*$hWiYc+O3pc@6l07rmXNz_$6q;&WBEDlHq$h2W5yX& zHRmiMoaO&ue%xJ9g>6hGKDc{I>Et{|=*vq58VCZrvIQG}7~^B}x5ZVLPaofKuMSQ- zLfVWKdGOCNv#;;3x?I0|hBay6_X4{V_tcZ$-7oc5%NJd~ES^JC(1t*~{Xx~i%pTWQ z)z#uvm+R$g+HXZL5Z2>&oB^2or>b)oR?C-NK7V-2p~A7Yy~9-E0Uq+te*QPVn+mie zG?d%0QEYJc5W?mEA_CT>VkY1sv;&l!Ds^!8ob#nPfNPhAC4r4sXBx07W!I6-tyxKACGf=g>wDkHa1qQA~8xsAT(wna| nFj&owdR4g5Igw#%FVOULmxHx0skwgv8pPn~>gTe~DWM4fggY*F literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/align-right.png b/sources/wp-admin/images/align-right.png new file mode 100644 index 0000000000000000000000000000000000000000..86a1b2e8764dea8899e847ebdcbd6cdf7570a909 GIT binary patch literal 509 zcmVC-K#*?T{5;D(ppyi8V`KD;~^W=&B>g zRRJoL9(%~;a;a1*lgVVWS;S~f_S^OThGnc+2^9~i?k(P!;d6bu7!6kvTVVKU!Epci zJ|WP%dnp(jkWf1amv+`IW4Rm)UGHlReYR|Dl6-LOgb}C)GYf$VNI-xao(R!E&`>xp z?j&3Wy!5?(-@=SOc_PhbGdPz&U@feR!8fp+Q-u>$9FGUPlT0Sl=``Df`fj(&y%bI+ zs0b{`=;UF6nA4FLI5T4aPVndRc}QT70RJIq=k7(T)uQq6`K1Tn4%Yrl#bo$D`@Vvh zn~wIvUF0#qns+^L4fy!7-|zpZ_!oSGSq{=KU=>uh9B;4*00000NkvXXu0mjfV=U$^ literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/arrows-2x.png b/sources/wp-admin/images/arrows-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b0c53d1a6b1988f8a8a079cf58c3fdb4fc3596f GIT binary patch literal 863 zcmeAS@N?(olHy`uVBq!ia0vp^azOlzgBe8rJYLVhz^E4B6XN>+|9_we%i;9YXjJb2?0?Fyqr_Y%)r@kI&Cqr>@@ywYsv$C>)?5R_y=I7@(H#Y;> z@$vCMa?P4GH8nN9zP^Ehfk19$WhIbYv}jRbVPQ*4OGHG(+O=yZPo7*?S65L{v2x`~ zpyKH0=+4egpfaEp>(;GHN=gE<;Q*)+&IZ~A)CF`>RaMozdGnSnTefM_CZHipmMmGn zem&6SjT<+vUcDM<$nxdOmo8npb?erJ3m0zQym|5B#nqpqZvYJnE(!7rW{7c=W{%|H z4Rg?Ti_m4!Hw^HX5o2SD`mpb4(D~(pACxcN*}}c_%}np3i?{gnalKjH)MU9@;Oo*o zJ)h1mU;1fj&o=&xU;6^h87=0jMyt$TcyIB8N$HlhzzCV@>Eakt5%>1m(W1u=B5fD* zG`FQr69$IY;WGvtlg@ai-TSY)EY;HQ=)2XCDPb$Cx5Z!myES-nxdT(JbHqtj|Cg03 zpJ+}HU3Y8#(plYWxJ;A!xi`9XtO?xp$|+n?=5KCo-fsVjrc3>tpS`(+)~&zqc4ql` zmIr-&?SbZvOAcMX9v{S_A}@cMzZ`Jvsr zAIci+{vKL-pZBUyWcn$|I$p1xoRgX7iIva281uX_eCoY|h0E7m|Ls+}Ctz*MwN0;o zzh63k-PK#4w#=V)Yu>f}^NRmVI&mnryzyhY{o$5I%+a%ZO;UtY=ht7!k*q%#aRBX;b(WMa(Bo!*|t zCVqxTe?mVS(6vRkbd9%Gny)FU$`9UhqS^5gL)-$b$?W1U&Io8Safg`8&Mg*y@x(QD z*OMm`HE)Z^?0LKL;TM$+NAJrSi<{Yhc{;1C^zb{T7Y`+Ob1ym;d*gNN7x5Qyu?5!y R>pVaS$EaktaqI0}-?rpHnYNG1 zI29Mq5_3JVLL-aursIyE|7MB$u2)<nGhaYdxA+xy5AI{3fZW?%wbvX~)f+dl#p@IkT;#T=LC_ zldK<}y!yW5YSz>jQ`aP{5Bc<|VC(I-R*?r^#m#@^xBRouH^1}u?EUWMeQz^Maldt; z*Zs!T*I)Ndlzmx!fqBXO_xdOKqS)+rvNa!6etY86zYEC@H%w*to~KlP&Pe~7VY2GN z`#oMPH%#UFrGJ0fsu8gv;ULI0I+%0_phq{DmI^VY_ zYR_Q5p&OSqWs>L#?wTESo*BMnO6NC3ADoiuCV4Zub>FnbZkjh86%)k+oL=wPF#9P; z+_jPaxuvPsS7!&@VHELUdCT`;?p1E>pRYQ*1#2B|jn&R_Y3%=Fc(Q4g<3nNZj-F*9 zecZdlu6*DVpPPK4X_cM6(njN37xu32_E?jkd9~)8;hVYFrc~7T`^VT!y4Z8b=Bm4% zjOWR{YXl#dss{S4`;#`gCr#w#nzHQ+uY3VJ<^M14i>tV##kcKP08FS1p00i_>zopr E02c8?jQ{`u literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/arrows-dark-vs-2x.png b/sources/wp-admin/images/arrows-dark-vs-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c509a4ea8a63fc710f98285df915643466bf73d0 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0vp^azOlzgAGU?R5$l!U|>4n>EaktaqI1!vsuD{GHoB3 zofIcbeZVfl)wqVMHO}E$n5^txhOJkxg}ql;?GUz;&GCgP%QL zy)t~ZLFn_Fp62);H)ns|QykIhy`v}n$6MEloI2@~tRGA7(<$n)j(Eo3SDbEh_+#iy zK^jr1u-WZF=3?>b~KOM#YSYjuVyd95gDoI5q#Xth&g|14U{(jUOK4oM{}E3Z3}F0`;$0JQU1J5WSnAf5c)T|LT?Rt^IBsX9~N_^xIClk!9P`B^L{u z!UU_H1w|ybiiY7PPEVh;k?+_;c8#Y|5(=#c7k(^g(ah1j!0+AAN zIMme|zt3gHp=+EwYhEVstX8`6>8U_*M5y9){aBR^T{1O?#aAbtNszYqp%=gJ*;WG= zF71a8B>VJFmrOjsWl?d?@X=~tpuD!sp8fnwy2RQ%5({p;WLVmrQrfWSWbeG4B6wVw z*!q8Vf!Wp2rq3jj zOPX4<{fwSj@CdClJnnIU_gk0t8H2Qr=KaUBpNVU>Wjx!yE2V1Ug4-|d7v>ciI`5fm v9d5SO!|=$vcUNy-S+ts+5g1|>FZDaV1)b4c+y4%jq!~P2{an^LB{Ts5&1_yt literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/arrows-dark-vs.png b/sources/wp-admin/images/arrows-dark-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..3c48995f352db9444a55febf5166238e68f12b9f GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^{6JjI!VDxMy^pU0QYryHA+A7LA|Mk#O5#vI1XRae z666=mAf)9SIBnON4}bpEn&+7Ug^N91978PplM@tpLrO|T8YJ)SF1K!w%-Ox&amkD{ z|0b<2z6PTuEDLzj+9q;8sB3R$)2Vr&$j0wnvEtC-N|6Ojd%NS38EO7a zT3vh%MoU;0@T9d(OR+IFeCi^y;iNJ zfaVLPToMvDWEb%C<#Giad$)4Jl9OAjzbAzV?vUD{*TleJ`&u^FWNBGB(0T?>S3j3^ HP6W3 zLAhzIa>FX12oNwdG{`lqN={BrOiWA#1Er?bDh+FaQYyKVfLf#)mI2v14I6+ebs9J7 zHf+#t*r3z6L7`#2PQyms#tq7iYjqno0u^Z20m(HA4fBC&fKos;I*sc!YB%UqZ%9Z; z&~8|z-LM{L15mMc!#bduKmgRP-MAj;Dv(hXOXVt-$~3G}YFqhG&8+da1bX3_G{nwph0RfPSu$m_pMKi)?@66m?~ zes77Rp1{(J`-*jC1>}0)FLQb~dDx{a{h|n!R7zjS!X5vfA{*p!wwbQ zCXQ$E8x>qMr#CdIh_Es_1~(`y-{aW0Ordev58*0*PMb|RmCNQke|@lWrA+ z|Hkuv-gUwii&wTRbF7%av~kX>mY1J0o;;{|;?Nt?vun9ic}dxds~;DJxxSzC_TiPa zYnMMwbw0H0ZLBn(yAjjl+20p16e@)aF>zd+a3fJqyk(({ya-qE&O;%2;sr<9MO0D^ zglvMXS?B)}<~BL{@9y=+!-C$?EMn(t5*s&qneniCDzLINEn{%>``O0i>&WE$QGLz- u_Kzo;p3bb}+uF8#S<#=n;thvCGH;jbkzBX!%za>NGI+ZBxvXDQWFAvLR|m<|DTwcDA%w`xoNF~ zgM&`vhP1S_!9c2EnRdfEpaSiN z^*}Yc6-yNw)`Pfp8+95ss^m`6ZP=*LFh3z70VpU}u@q2R&eQR~z0^O!t666=mpry5)<-q(Tx zuN`~XmvIQZ6U?6SUSP^Q!S~rJn;$3wHSYIxaSW-5yW8vDci4c(^{)4wYW`4j%B?JLB(p6@=sBO^sNdCmsej!g&D#Z?-NzRvjbP2j~Wg%$H- zHZIuG$E?!uVT-QZc82NC9^Kx1$<1I<+1b6G2?CqrA6e{p;xAAxVXvf=BIxi%uy|`; z$mgPvKjk9X*~SNFNIliau>gTe~DWM4fBfrBN literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/arrows-vs-2x.png b/sources/wp-admin/images/arrows-vs-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be558778d9a71520482e7ae3b77d5aea67ca89f3 GIT binary patch literal 723 zcmeAS@N?(olHy`uVBq!ia0vp^azOlzgBe8rJYEl^9tQY?xc>kDf9<}L1A?|3ySQ%u zshy{4f=B=_(@onSh3ZdIP?Kbxg`_-}iluMAlqRcv+u4gyN2ZEnSqZK{@zOaeB-%8>%|oZ4t~0Ry|PbH?6IDx z6NloFx@Vv6=FJlnH(ATD{Ozrz!0hJ2P7AMqTOZ1}S04PEwsl9SYk!rqclWoP^LlNU zclZ6+re3ycp~dH~k`k?9tCktm^82(t+gbWt>ob9|9-QVlQNBV1vmwYM-sV`*McspTj>dpQ} zw!c^V53<>}N$>D(7I5NFopfe~i?(2x&GjNfx13qRta%Du+&LC&R2`TrzvZfCF-OYr z1lxM){NkD2e|cB9Lgq(SoD?sDq}$(-HW9hb~V z^Ka7X;%hKk!m@xTt!*OrgSz&1Hl3OWifsJO6)O%Mt`u3oRIagh8?#gQxi*6t;qULY zYBdEkUohp8khmecfTu5)E8y6>l@pen+*`=7Ay`zjMWkLx(Fx7BH1-tlh@!)P1haU`F`+d#zec z0nHaoxg;cR$S&aN%jF6<_HN~bB`3F5e@_Y#+#$6?uZe-d_O)!T$Nk%w1VI%;^0P_z3`QqF7`1mJCV!yw?(b3T*gRNbSr|-S2tk2-y<>+v( z$>oxE^US~4S}>@!!2kdMA^!_lO;8|2VRT_wO;AHWcyM83Yh`pGVlqK6K_Vb{ZE#IZ zI!SJGbYX5|Wl2OmB6w|ZE@^3GIyOT_F)~FrIWjOdMlmr(GG%ULJtA@OwY&r+fsB}PxO{>nV7G~;}7F;iD));TkXwYqKGr-sa zo0tsfUfV9_>YkPD>jyqv^YIP!KqUA)`{V)&97wPr!Bsb0ts0;Zj=vBK=QyOb#(|GD z4`0}@2&6{F7#vj%iX2I@q{)*gJNz;t>=%NTdJKH@;Btl^naJ|I>|q3_k0LvN6z~Zo xXv(8VlPX=xZCauiP6q%=F^#~?4$r2#Kx8$W6s?M)bZsg%2$ZWXz;cKH06Q@x>Q(>% literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/bubble_bg-rtl-2x.gif b/sources/wp-admin/images/bubble_bg-rtl-2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..38747a08973d810f6939ae056755125cdec1d8e7 GIT binary patch literal 499 zcmVV}~@4coxE_} pg-)2Se!gTObg3+-ERMERqm-u_oG)xzb#au=PZ>gIBmfZs06X{L>3skI literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/bubble_bg-rtl.gif b/sources/wp-admin/images/bubble_bg-rtl.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cfbefeeb0f88607586150397772a5a5612bd07f GIT binary patch literal 400 zcmZ?wbhEHb6kiAVZMb+lDua-}^{^G;_{rhjF*cx|lI&f``~Uxc28w~= zPZmZ722BPXkVzmvF|e&YFr~mlN2>qClA@D2R`V~cDDhe=$KRAQjq_68bcyv1k((-J zPbr?fpw?`kpN>g#XV;n^d+N@=|NXySkfFKRhr6ZKo2!GtN4=@Vm%qc0Z=zp&ufOap zKOw?6mq*;jgxujqPz#w~v0JN#KW0u@)E vJAdKgr5YZ#Yu9{KuHW$1xXtDxbKh6}w%@%wzML<8uLcM|2$1q{WUvMR|7)rM literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/bubble_bg.gif b/sources/wp-admin/images/bubble_bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..315ab527fa270f2b4ffdc10f7fc80d692a763d03 GIT binary patch literal 395 zcmZ?wbhEHb6kiAVZMb+lDua-}^{^G;_{rhjF*cx|lI&f``~Uxc28w~= zPZm}Y22BPXkVzmvF|e&TFr~mlN2>qClA@D2R`V~cDDhgW#~Sgbapuvc9kDzT*_yqq zQ_`kAIAS)h>Fwo7ja_Sg?5R8d{`da|7l!6$L7$dp?)DC@?pF0a27ccbKEF}ETQ{Zl3n!GaT>cXK z(_Pu2$?knn`zrP=Gdq5-vA;Jtt@hI@ZND`clQ&)c$h1sg#++@zlb1XVTOyR9#4vrv zy%>Sudyn_sQ4~2daYpr;Pdb~9=Ui8Cd=|H&_+6Hd^3|CFij7?wi_i5ee`m1m literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/date-button-2x.gif b/sources/wp-admin/images/date-button-2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..95839c9aff34de60f5f5021a21b6a2b2dd5cf73a GIT binary patch literal 992 zcmcK1drw*i7=ZEjAgrKhkGz$|) zPqU0+x3HGhjp^37i%DrStEr2}F~vDuW@4l&Dk|a~5%GRo`XTmwf!`lb(v?Ks1vCWM z;6UN<@UXG5v81GAWMm{gJ^kR|U|?Wietv#$Z?Cela({onuC7j@Q0(mN^!NAg?(VLw zt(BIR&d$zmZ*OmIZmz7X%*@QJuC8WeWT@5Z{QP{mTy8R%91e$8t6f@JT3%jWUtizY z*zkBfZEbB*snlk(>2x}cMq@A->~?!gON&yeOiN2cQPk~ri^XESUOzfIIypJ%bUKTQ ziiASp;Nala)>dn4>(tbg#bPNhFL$|Ixw*MHIXMLd1r-$))6>&NqY=X}nM@{;NX%yQ z*w|QRW@dYPyVYvV&dx3@EL>PvC@wC}%ggKN=olIr%F4vbAPfScyRaMQ+&B6a!$TkrHKq2xK^6Cj3IaH!GDiu{-i=k@j-7i%B zq2y41jrQKxn!6{+*St??9@c;N0As>AU}_#W{rrIPghCDTecv~XYBWCk?RlFKqxhME zqG*?BQ9-6Yzb^A%f14XWYO16WuSxAXGTP+r(|T0#%{ zH0<}F`z(aZfA+ZlA+LylMa)rv$oJ=R!N3KQ;0`mM`8s|~7z;5n7hjOdArPr4E`xmF zjO6*X5-_~h;0s(^HQel~`8EA8AX)l?1J-69HwDhhQ;tE1kj;Sekpyp*Pf-G!BP7GS zv;f3K_=6bWGtTr=Tv!Vl0Nxg&t#m zL_F1l|M1ljWyqg&5on1V21xO5r0NLAeJMeSaES1eLmyAa!;tdsh}lOU{`2vvh-%02 IL^j0z2jsw+;{X5v literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/date-button.gif b/sources/wp-admin/images/date-button.gif new file mode 100644 index 0000000000000000000000000000000000000000..33ecd66e115a3aedb064ef102d4b23fba2f2cafb GIT binary patch literal 400 zcmV;B0dM|CNk%w1VGsZi0M$DH|NsANY;0RwTYi3ifPjFIkdSk8bGW#;aBy(-_4R*$ ze~gTbZEbC!prF^+*Yfi6;Nal&^z?aodF}1(V`F1{e0-FYlxb;c=;-KPUS4)~cKG=C zC@BG_xJbP+uP62&-V8Ahlht?U|`zX+Un}+*4Ea` z%ggTW?#|B6@$vE4*x1I##?8&m=jZ3#+}w3_b;82J-rnBX+1ZYcjsO4v0000000000 z00000A^8LW0027xEC2ui01yBW000K9z@2bsC<=>)p>l^vAcW1Ql0anu7}YD4ARHVH zi_PL29v=q63aFvzC>m^c15^=8EQ7p$Z;=Q!01pu-2@isV4*(iR03tF01uz&dHU%L7 zNlXAH0gxe_kS+jH0RS8%kSnK4kOwSIRGg_9suU&=;j_m83OL_@a`EqK>$0JnX%UZ literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/generic.png b/sources/wp-admin/images/generic.png new file mode 100644 index 0000000000000000000000000000000000000000..00575a078f994dea08c3c3cd0a46d1c22366fca0 GIT binary patch literal 719 zcmV;=0xzRYaiqX+wRkQt|-+_=!L_5Irp6BJm)#*T`DWda%r62Pqi&SR z0M2FA8!54)pGQ%3zXYN+dUQ&TZOpf!lK6a!JjAKy48#(xrPy@So3a5Y|Sf#B%G8UdeaN_+Vg_wH0+`+_5j-8O5v3Fb9=y=vIG#@4i3 zzE#rhQI>YlG^jn6IE!m4t%GtX_xH`K_5~pI&t^?yBoU$Oo{}owtL#A=yBjSo1V?97 z$fj^A?Kuwsf(!UK_ziWxu8wA$vWU#dzA zMU_SN4NN!|us@-sQwBi&gr8JuxNV28bK8&QG8PL&mlW?YI=#$)lle2lVsbPT`xk)R zQu3O{Xgb4V9_%_@(D}cw@pnd>nbPmc*gbT$xL#j{@7KZS7HI$=22Md*;)|Ej z$r`6Eu`^-c_T87s9h;J^)L}nBfe9vAvZR=JMEnCF40TLfp2IiXKO}y=13wx`W3&c7 zhm-}k!vl%u;8CnT6`i#y5%ci6Z-P14a}W(t>}>K%IH42%eINiJ73O~%ObGD5Ry-f^ ze;?s|{%3{c;noXnp4cqg-*?Avddc9FzBfC4&exF#I&-C^F;-c=~@lD~^ z>XGlwU&U0MTwQT=bad3q7mtq_`iSFX-2`)V+0vUYy`KH}Ny$rgyVgP<9i4^VKSud9 zb@w3l3_I5C6-^!_8grUF+6~-!etmtVOs}Ms~^dirX!N2LF2^75`_YZupJT|TzNkUFQE>HMS&C@h=D7kPH?yF-}~#i zQZ;9iHbnu3TOmNp5ImXbI-Pwey8d!r+xyl_)8cxNY27gxfgwj&6i+I^b(~=yKjsH1 zh`8mFwG@839Hn3oi-2q+KaQm^Gg`@aw9Q?i7Hvg*pgwV1@?_2u3Y{~xP`g)B~U&=K+JiLdE z)p!!L2lcv1?{BB)`GJVe)io)Ji zCvn$fa6aJ6X5{5{|9Zbj8xx{Hh9OEpk&Ka>J?hVVx>RqjB$;%&*}G}K)>bb)IvP_P zF!0yu`IGs`_1TqfSL^-sk1U&BQH{Sda)sF;u7| z+l39bPh=Kdw5W-z`8Z6cYt^0gYf~gD2``KO?v&(mxzug}t zqh6eKo^FTRp;4HX3Qr+9Nf(#4k(t_w0${(eb5`qi>oxlL)^0u$ z`w$cP*c)(CKguh);ChZQ35?h3P<>cd%wrF6O1NH`#ty3bi=X9EFkeXQnv^ZiC?6=zLdm$humUr%=U2A0cYqR6`Xz|@e`468VyQVEL zjmos<`LQT@nNBYOx0OtQ#@TS2!eOr0z#jwmzgqCbeDOznHV3x zNbFjrWA-zS-EmE;M6xTF*Mbw_eSTlm5ET`WC8wvIy?lHZg6eDtwu*sep4U#4!|}iB zNF;3g6irFiD3{a*9pA)mm;G^UGU5~At_Wurl?=nm1=eDxvK$|A?`sL3bDeUP3Sm!f z2XZnYe}KL8z~-K~6tSmDk$?I4_4@Nq=J32Z{cJ zAWX@c%M%!-x$!Br#r<%8pIz()`iILK_)1B=es+1B%A^^OgDj^1w7YkiGrh#aNK3;~ z*_`Kh0222b7s|iR;V)C#@P9hJDUwU@*N}cm?L6x^*0kLrK|)+Y)-dwsHtt3Y$Vf3N*Y)3=a;<)#!f|B{s!Zkeq=s$8$13OH9YcDP7-uR53XcCr!1 zM~(zRkI=afzKvhcjYCUYb6o<6#%8+jQcu zd?Lr^fyf}kyR-E_n*nbxbB;X^2auf|Gx}A0#@ckMwi`ImUrw;PxI`s|!x27khq3Nl?*)=dVeEiPw0z*Ai)6M0^K=Gor{&qN7tt1D_jwiJTLD zR>~!itHQm|zMQ?_87PAEo{47)U0e?)quLOF2^<0x=sfPUn4}AY_XbZFd(UGGdBQmE z1V>`bzF4Blw%iYSvMX9`68sjBhA2HJ z2;P+XWF2}zJ|ZU|Hs4GYEJd}=PGw$^P+kF~Wepagrj8sntw!Sd1~6((TWb{4W0die zR0mK(A5^en?v9K)q55yz-${&k5?FDPFkJ&zHlBthcqHmsJBK6Pb}6V%NWEk89gfChmWw6iY$-0b z$gF@KFFz)0rZE)F2%UG?UFG^9yv39Oz2*GpbZiD_ROVRxYp-J}kvK(-20GocNU4m+ zG$l)8nnqJIOHg#uuqTfTtLT3~2%{mI@Rt|Je6AbErv*<{ zt8DG5zWOMMJf$g$brwf3fJ>xJ zLd*om;?!&Zg=CMu=oO25^)J@VS?mdoBb1GC-}NI>@K?VDji*G3dR`6_6iL_H9_kO! zc6TFY&WOD|e_FpnAP7a=^G$;Tg@i=>r9w5rwZd#cHCXdK@0NRUW1PK5cS-jr(~ob< zAsp|QK)&CJVgIZl#FT=B7O8^*OO?8^q`F|*YP-mGx0@hlrh^qeZO38@Yq0(f$)>XS zBC@UfEKV6L5q?Cm-wr##@mx~(wGz#`c=MdJpGv7J?iPW#0wy++=)$1u|UH`*7uBisks zb(Dh~=U?cZ2k#!cTRVGId8odAsHfxX>-0W3ElHVEzzN0(9#X0A-C0hv-ExCM9_W?` zi}QV(z+x37e3ZZ6XIP&2sR7p=rjNud{E+ax*vFz9GO{xq6Hqx`Z!jV$COK9NVAT1@ zxBB|-SoLcVOh3CYA9l}GjNvB#Rg+(Bi=Fd5YcKoi4lT`cxMESC(qbubVV_dh8=(ac zhNm1AXm*XfVIRckdc9VZ<@)G{YjCsPX0yXUJebVBezrapl}MN3hI0yex7o$kZF=Y8 zCi7Dv&o>v5vc&auL^lazpH4`R@a#Xj#~^dd3!{7kaLx#vNc}@*S(q#gVzi*NB}0iE zrw?2L8z2Zln=$WDLt`0>r(JSzf@0?kM=jDAz)bAJ`aHq8E_J%|=*h1$!Aa0X16LKb z-`-@k(b)_`!xHP2wKYOp*g@yqS>`Q~c7%##Ln0d^sm8=GUjsO~PQ^t5+0pHnpZtQtlX7?H=jc&F8M5raaefIeT&3Z8EGY)kB6elQM1DEW#|*7E zNauME2^Ad}-|%YF2~eqBP2IA_pdnK=*Zx-Z()%}7U@;>(w|X5X7*mR0>a6&aY>*Qg zxfes|wic9p>C@0bF*_>pf>-A9fVGv0YphSK&#=LW%JKl`EtPM5S{s9fuzd?%s)bz~ zp%q2e+(KLN%Dd@e(vS2`_HOmYDQ|*)|Gi`Q|tuNp}mV16p zvq8bFL zVeqR-QpZF(nWrlJq4q+19A5$4VM`+R@__OQmu0LozV3?|ZWvgW{ z%Y(lvJQ=zdCan}>`7Kpf^kZ|6K8 zZWMiDO>w316{F!OS1ZhwFT^{}mm3keHX=o)rBpB;R2fOk)Tr$!rPIPDoUekn+mdA0 zQZD$K7SE1rdp#0=8)zQC2Q4oJ6+=~Vs6Tu!2x&!LzIDK%G)hl*dj0lBp-R}7zEuw}w;|HCSYsFk$#)X!jQw5se zHuo5!1<=c^*4{Yrbtx(5a`aH4a}|t!gjJNrZ!_%ls7_&Z@bL0-*@mP*$$L3#{iU*L zMfUkL;Q}nq*4nuZU!?3tA`6%^IY6vF=M~%oV)P>AGcn~w9 z4@`K|esHnZ^~I7qN=Q}A=4_Q$munRtZbfCqe4H#eKFoBN8tnf1Iq90cO?vAzH_PH~ zQnp?$;M{2`f^B-YhZZ` zPdVM7uu{F&@%`Esi9|H6ibR6PZ^->DYuy9PrwJ7l(*+j|z#+hIq`0FNaVV#Q>oK_Tu z-@tloaVew(U5yZy$O9-)IPoaF`&{c1E}19>ct0DGYFQDfxUakp=N0I$ux~PZ!06-S zb@g{U9R*V6a>-R?m!EYdP0n>KuT{pCp*d`|TXwNP@-hCAxq`d>ozO-u#M$Z4ja6cL z7rtI|e+hIrU-IM0;z}*nQ7ZV0qK-qwuaOfp#9HiX4Z{MBJROl9~NYeSF1#cANqJ#3L}27jC9!# zUV@kB@901NelQlf`$;C`5o-Z(pbe`Ff8Q`#aJ=s9UCm#PoevLZgxnw|p;~MCc6eVC z*Z1fkFG9EZUD*!l#6mSZv{hu^7Ru{!>J>VjM~9+t0=NTSpUrdv5**SjWS&v=x(y4%~D$4X$lV1j7$Zv7BgPv}` zS!E^mj{L_=8aD z2Z`M%djKI2jR#H-IQ{^~P#EvkYbDE!V@nM|F=*aaH!wKqdu#Nhchc6<>0lS1qfI+d z(BNF(S>QCctsBOSpj2P*Ak8S0=x2BZCx;<3>Xp4I7`4Um8VE zj1%WgOZ@dK&eu3^!niqYug$lfM}J4(aNo+a&+f0NqSR^lK;SU6x29N|@?E0dG&6yLNy*p>5`oPYNdO@lSZD zc64!Eb?5p-(9w#1z5TCuZ(50j|3upHsrI;hz?k&khL0rzoy z8*RVHW=8f-k??HVXMU}fCI+*+Yj#FZcu`GygVmiGnU=C4iIQV=W?^-ot0W~7=9Y2A z)ttiwXZepO1T}xgVf}mmzWd)xZmj%T^v~z! zhGD=Yj7hoM=Wj=}nf22uK40>Z-(vj;dQz+aYJcL1a;{9UvKdMVhqr{`J*-VJn*r3q zZ_n3(DhP+|;U1RSyzuj|vpA(eaJoDxj3M8O;P}-@ILl$qfTDfb3~R&2@M|}JGcHcv zDUs)<$5e(dY~6>YS+A8#XmH=5=6x7X`%cIPeCeWuk^liqLEaor(bfC!Y~E(6X3E|K zLZ@~q0P^7{jY@vF^Sv+W{peRh{izG(3E2Tm)>Y1MCYJxLyL*^6G2gi2Z5Sh+CU{+BVv zgxM4=Hgkm$E0=bYKiP4Z1FQuGyX2~}AAj5?;K*;1rNm6@m<@V5@nVkpGd=faiMosfWh-sve3(3|`|GDU)>ly<9RP zsQ0!*G9|jt=n$%Xs^U&ew^Hx2QT@!iF%=%fx^>b-KVmz9mu_j)eWEa-0R=#~Mb)7u z1lyGk0Ha0EG1U1a@#b-w4us}jzpFgtz{km+nx8jeaD^L|hNNMf@vmSD?MJx!4V4wH z^7!iUf3$3??Hrr+VrS|ijc!w_g6F=9g>T!R#aIv?4TBQ}NROFNgX6m{mhaHz8OJP| zx394`;OSpq=Qs7x!ZBXOTPA~+5}Txu^O8NjrJsGSv-E%7r64%ddQBO@ z1klmMlO=p=WITuWrr{1V1*{J`=&>#N0s%vIJ%KzJP5{`Hw2uHZ{TQ;gW>k7f=98l3 z3(z~|F5*9#!C6)rpqEH6psu`8%LUx!9G2DlOuAxeuB^PshTM3f10P#nFRj2(=Cb{U z8$u339W)FL<_;MQlsJ6@&Y1S_lcL#eaCnOXfReH1jULFhgZ?$U?MU?|Wtp~|HDvUN zeMzo>2gpQw4|UX*u(QZuwt|eg8A*2UZoCjA1qht_O+UtK?ywEw;1765j{`fot}i!> ztwh;*@1Sg>11$12dV?W@-#W^Zg7bplcsUPKzPE;CSv2CflcEm}zY-r4cvH3Z&aF_? zI&s=F> zMB62gfTIea$E7(^|>#n%~Uh^MAh2MZss`Zv_$up6evsXtAkN2AS~rOP{~=FA24{Hxiyx zm9t%b=ivwzn_wraxx5YdRB_{KD#~pkc1p~#!DQOy8sI@ChUg8~!w?Ih)r#{=0Ey;y zO&2r_`idJQo%|B*MNH5cE%;;#-(>UjrNVVa^y#Dk^Yp7!dboGOuc#>>Jj~r4nGSG( zp~tdiYxA}*X6q%7{i3H_pg(t~*X#z-JQ5d^^MpvN*Vr+0sYVzzCtP zcN(p(hy1*)Q_hJTGtevqCqL~rP%o1v@RW9tYXT=RLXZ#>7{Mjslkt5)&poOE<#JQX ziQI%-me4+U&h1^TOGHg}H2{PI5XWHa(*`ysb%F;x;WrHOs-BsRAI3$A^`|kjI1J`9 z6iH!mRIUu{;<<7j=3gxS{WA-RwI7Yez{;1Sm`t`Nfq|ydimNGvnVaM>2+q-+@ZS!) zMNrMOL%8}xCcPiOOk3N|GR0cXw1?s~s%o&)`N;wDAly#HA7KKh-{a-qEWCOee41Or z0#blosZz=UB_xsvvKft?G-e&%C`*KEyN-d6FJ`wV%gl-*tH=!5PKit3Cc@FlRv57U zRyQWyrz&-5iU2K`-&yD_1Y#RmpdyNA6fgL{cS%iB_>&n9G?z>NO-4p3NvCE zg6qU-F%z+>n#M@WaWnp@rIPBoO#0W(B2RzkGXn^I z=QL=RDh~Z*s70qG!|C~sPmH(v4GNi~&?uj#fc*QzmSz!n)%{m>v_eI7&htK5`vRxd z-;4$ps!pBA4Hv;t@F~vh3oIozx}|&s5Q>!@A!1>&zKv({1K8L4O`B|lA~2BwxgutU zC1e8TP=JD=`4@HxhIrO0#(^+^)IJC})Q2{>QLla~oRL)4p95-|G6?I|qbof?snLby zRKju;*omZRfx|`8#X$g1P4aMGRxFWfc^=GFSX{m)kDdSesO}RA5CNc{i!et=>Y+i< zE+V9g2-8Dh%>%X#+@LzWk6Na-oYzQ{Ic*pGPkRrPw0Q3M`hm?5au)Br32)L6%Ndb5 z1$uFy$s8#DQu*ca1{Ml`!cZzAsMb5hDOm}?AKYT+R=0x#V+ftpIfZ>^<39%>fE5Ul zW>X5DPPn}$_ZTZtGNn&hG4Hj5pvGgs!*yed@>>I5zk8>UYbH~_^pn}Rle`&))>~P= zSuCgmx@hmYOAsVwb>%MHJg3#D1cpBXIV)xFhDl^_$hNlIgGlJ3#q201-^1y`nfV5W z$rso_@}~|~P6#r_^1)@#AKFKCT6VI&jPK%!ml+n_o=fGlm!u~FjKdOR< z#kn7hd7CR;5G~D5%qSYFskrMj+gi?upz1!q@lUA^XTGaG5wP`V$SWK$H0Jj8Z9bNX zy&O(aqbvUqg=#)9z8K3c?N<5EE?EHCCr^G>9Fm@m%M0^%Mk$uAIY z5W~&R=XYxg0B6cL0toYS9)TyzTw~)rOM!r{g<+8;IYzFdtv4325RkZKd%J_S*n!yCrDM`8OLq!VSAE52U*u8^`@TO3VYh@Fo=k0w6p)y-3}Fg|Bs z2p{L`*ODj)t|Z}7vTaR91MA=gg2N&I8#%(REop=Y#63ZRcaA zyci%fFfv<*SG>0juvER@dbL5N7Ztv#^$_DGd`~{sQ!EO2WHhG9bPUw=dWL@FOL!~k z^A50L35TDgonD67^jn2Kt2O zL_2FJG`L4ra2+^Rl804JTjzf-&p};wP|;`J2EH-J(0~n{0?TP^-GCq11ES?%V+CE3 z0n7T1AFsu~@5L!XP9rvvWCO*vka?cr?FjwQ{V-0ZCOIc={y3~@-qHJ=rG2PqON%Ef z2SwD+lLyngcQ`KeSXHAAZ*-Ij0ikHAy7U3`lk>O|LF=DMi?OgF;oLv%4hiq$n|od1 zz){r-&SsLji*D0(H!DnTBMX)X^km#`e@Yk9k>|zk)?DE!f0;!!l*HyP4kx}a!n&dJ zt06z33K9Mj8D*gNo-P1DIl%C6qAVQWe1BlBWH!SREl3pj2ky3hP`Lg0E+5h3T+qyc z8!RVG`mklAU$H%c`^8Y%cZBhifeEAn*!e9Zlps64$EJ70G%bzvL0ljnDV#@^Gf)tn zXb1FwM@kaOuLbb(ux0RFcguaLHo9JY>O~P*j z@mO%QJ=b*=I4kF5bgE-A{Z21!xAzHS?*$arjR#BDhBgDUTT^WF|H9a)%j^0qsLOF4 z%942$Mh8R9OwiRM`_9v0z+*Dh_^Zs1ZA~OR>p*33Zr;KyvtK=n#ICQ^xA$~Z;*Kv( z@{9Mq#&I}FI>}o?s>$HmPq6vy9xBV`k68_sOn+}P1q}+>hZ{Dz_th*_SK0$iP_2d8 z0-;&aA=j^ygzPY=yhD7rxm94+)-|q@7@of1{}ip@rTXqVDW$_01!Nr~Z@QNYclVk6 z1hb2D&fh&IOebv1o`T`RaMX5Y+UZx*45RbUX?+j6R#yh;!jg=0gI({4?uAZED+W7rI)fPuHya=V1AX8;Ia-rYYlPRtw$!((ZV)VFV;uAR zLwVKG+-(a7Ms5`6bR{oJZZmUxw)_xC)yF~Bl?h!7X$iB;L!Rdr=LUSCRd3NC>B*n{ zOaVW{&Hpyc?w^Fmq-sD2163&fv8xM<1QdOKdCywwZ9MYRjg9ap1Z1aMyr*vfC<5X0 zIYwF}5~69t+Z5QNblQrz4%ujNL29XZv^9ACpq7sYZyhiUntF@)gN14&^i%CB6 zp!~qv@|!qShm&fpW6ouV9Nr2&fsK+?C_X*Vb7e0;VxYc&ljn z*(oiHa&M66B0<$c`)%ed(vG^Blty7$>j z;d?OY8URo`>Z9UwA??L#duS&_=>|bJIcI^Sm%fN>fY&Uxv=^c4Bm8s(rHCkQ;2M$f z%aM-n>uT@I>Y-r?P`;*m(`MtBRwcb@S)vd;*~A|@`nGyoS{-M5BV}Li=1MA~G5K|M zpde|8a(uxpSw9M8$$hrdzNW6CX|VSqodPa>bG~aYf$2^)b4^I)x$a-Hg* zaBkaqANmlx$=b(}?9nn48G5iOiH7x$EwRsaLRi0z?wJ!rZVA1Um-0r7%kl;n_dMMp zD$zQRM86rN!C>e*LS@yNDgY#UEqp5NW{3d#q--;2g>WUSP`q<*iQl8Iq9^grDUhN$ z>rQ1yBq8&MI_p+&4gmlcgZalCC~GL)@EO114v}9zCrK|Wa&OKkA_Bobr0P^S5wJ zO8yR*--_gT+UWg-AyETwO?dH0y%p&}`fp2eA`rG-p-O5S$CV7Yf|DY9Cp**WKmXQZ zc;VYTMV=F0&5)kfsi?|N;m#(WBzy-f%qV8imWn{vNnK<6y(vC^m{-f>+Lw$gvu=gYUVI?gmnL(5=M_9#NyR|y zT^9pRqgs}My$JgvXJJtnsI%#`=?nY_ppz7(l%6FIT=5x24F*&-mES~t`Hrn;R>H>M zr+%z#WBRNk${nLJzjLV2fr874nO~)!lPKCech5zQvgqxSxi6bxhnt4ZW5p-`)53F4 zB-6kX{c*nfnFx`g&S_ev2eGriXWsOzzbC{s*`oi* z;1T#f_5mZp5akd~Lvfyhhf(FS+t9jVO}}S45abfvNA;RJ->F+W`44&NX8TTjO%1R@ z!p=OBji?W_u)d-6@E3w3Nr7n()yjcd>S1B5sS2a$-FpYNePNi8K1v%Rl9Y@sA2x7et?qy zt$(?IHHn&1q@Kp5wWJT-b($sj;}n z%B{yNJ3b~tl-?PoH zLVYuBz9ot>`y~y!S&4ANZ$^ToZpg%H8VZCW+MLa`MC;0Gci-auZkwbPK33iR-TfZ5 zW^H~9YEDC%hTYPb%tnk2+eha&wlw_=Ch1tN~s0BSz`>%4%)xrLuGOm>=xzuX}E;fBL?_ zxDw3&kI<-zRWNO01WdYu;^cMSedo||^G_eRXuGgD(lU5C7}?CfAsi2QL`qa$o!g|_ zoe`=L#$j)|WDvbXUWwAehDI5vy|7sGT%f}u<%H&dId}s5p{;-}!rM9{j#6*@S404B zW3Daa$s7M}3|?gB2jPlr2Y2vL4TSo1=v)`I*jh=bj>~dqC~CORn|=lf13&nB*p4Co z8oe*J@SKj*F00QwM@(|-IV5UOeLP0ueCL)EX|?LYiNdhU>$0-hWLBqZ$4E)*_7@lt%9Rut9a`9quPCUx3KoltRRNjJOXdy-CMi3FdNA;C26+D|QS%qo(nRm`K6}>qcoLpvqg(LZ6T#BY zD1Ro@VL4cZq-RCH{HxOY*veg!i)Q1=^?LHs?0t(gz02}> zGCRT&MI2VM12Rq=%Pg+Hgb^r)wAddVh?X#ywm8k=`lZGBOoqh`l{PoXyiQq@vb#5A znMHl2RKtZWUb8drD_nNj-Uw{drS!Z}U?G)MI0vP44%?$-oDu{V>V)9Lg@hG;A@))#g;^j~ zr`Of=Fqzpp8s4u2Ba&!xiTRKxJ`e^j( zIsY}|j=zV0@_DBD0b6PnfJ+&Q(sA(9_I_PB-14Y;Q~`T{&A4anTvl<`(d=>{&{J~B z%q$B7e0;m==!l)MK<{J(#^`-G$kNeT0H`mfY;`fTP7zA$CrX z9)$D7dqY6*LLh`BPoD18^DS!wth!KQN#fw9ul0kmRny6Hs5I2Lc}FH1yz2r)Dc`nt zt7xGgY2+E_yEo<=$vodroh7Jg-0u14Z>3yCE;HaH_*qMdhs|FpWv9EY=u5ybh>thn z$gj3)526kk^or1_%-i8Rv7BAyRf5THO~@b>(|ot%1HKqZk)Z8j0{xS3LvIX(H>OBw znE9S${^*-C-j`=z;v>@E4O~J)?5L6QedzW%On>-!BHxchj2KQN;{rlk@_?aA#XcKI z-qnckQK9NlIAJPZ>80J0xc^4on+3(~NAq1T(BgTY<53Nj!pGoY(HXxKY}t40e(xW6Fg;f!gM0Z>2<5E)QOKe}UDkP(q9y(7Phf%zRNFDq>-) zUp^s@Tg6jTA{y%$50uW7!EidipnC)ystAwBBKH$n6y^qU<{h12WTQ{cAG}=4{t|U`neN>43 zqnw!Rw<$RF!>ki^eHs>QIIx>(%CLaJear2@_l`N@Ji=VG(BRzk*+MO?H{=Q2cARL~{Sj?YdoMy+sH*?okz7PkEJ*ce_gSxOX7QWlnHPOqB-l7AU;kH3 z!lJt8lWn9VVUL)i1%?PU$=(DcZjco*_Ra!A@^(H$pOwLhu^j3LxAc2S$J8*>+v^JW z*mNF4oACr80vlF21^8M zO3f1~)h`R=9bhoBI;um;HsWW7VwyAHB{N2TnHY-BO6Sx=ENG}%sJvE4x@>cO3h?Mx z1eYo3{=M_4eJ@!ln*3cu`Kp!oG_S~U?<-Y8U3GZ5^mf!uPq4$r5 zKcQc4d!2({je2YieaXJgWnYmr45n|EpJ{+Ye*lg`UfIn~)6$vPRZe3Uu zPxMD3oN!MzOK3N3t{PUy_z)t(Zu5ukCn)4?*Nv?!`1T6&*t1lE;9(7wVD4Bxm(-q&@`b0SZF8f zE@79@Mei1WHAeNneloTBlUuj^pkg``F)cL0GEKuA-$u@mE65QnkRXavgx_84#Lf*l z{4;gs`WC~js!xtGBNmC)(Qa@)(m=3 zg}@DGi07{$LjZps@`;P`xt5@)iN&n-Fw=CjigC1r@efCt-tCK|JxIaK6gJ^N1i6n5 z7pl}KC!{DZbi;>K?PfD*FX;MJ3?o|(b>0=@>djD)l7Y%ACyd78#HP*&@LU+m1DR z+x1yyHxBp14lP2yET`Qi6Ord!k>c&vgCdf9nJh7A>gakBik9g<`x-lbChz>o$~-jJ z|Dg1PrDBx!fdfMEnTWdAw88Jf957*;&CUDZyL=|T$n`AJLs85|p|*0floNQJP);G} zJ)JFZJm4yQzp7WMT$A2|>hdMTLZnH^g57UCmXrG%fiwE4{F95Z_Sr_oZKv$!wUMOw z2qCn;Wk7J?CFgoFN#d8jGxYgC@vJM8 zUmkvDz)jW3POhW|MXS#!Mh4&>hgz_{3{MKeBUol`b;V>}14QC=BI@D#BCqq(AQ5%E z2;hh>6xj)=j~92P-BR79o9t2mQ=qM@yZ<|?sE8toCaoI~`oXTA?UjZs|HwPSp_^g` zA&hlgvC6VvDy(cOBQiC@>K{jdqIpE)1ezgfvcD7$&U0Ad2l~T)KsZHhS;g8GFqw18 z9lQWwM&%4%!+e-Mzgku8a$X zUlA6HxdKH$JZic+Ro2ixD%isx4sulKZFSk7V{#~ugqFUAi+m8537Go8IC4`np53dY ze019KPw1tkM~YwIU&u_X`4VnmHPvUwD+Sy7bqO+xBuB*@PX)IGk$wHH;?v8o6`e4f z*oirtZDc!j=2kNlYB`q7;;B;&-;gyszjSa&Rl115BM%i2;KbhHW+)@SXqao^u0%Qo z_|d-+Eq;w9pc@41a=A^LyS~FTaIl0h&8p|m(Mi@-307EviFLdXix@EeVGAdFKrBiDS#lI_4i*w48raBU$G>+h9HOT1!; zcF)HItkgX`^mycuEobrB1vIF{#rfW#P#{rihI#4nR4u ztzh?+^yeh~GX*){?>o=-K_0=Mq6D==qfDX8hN#)2#(D*p zmYoiGt1VcqiN7~}|urnTc(Gjv0)w%5nk69e|YO{-(#Nrp>9J6wbEy`{V=pPvloQgyLj10jShFk6)d;Wut z8UwDB88n6oGT8_id6xVqyu%yy&6hLJw`@4@F>X17^Oc*u_0dBD-l26ez058BR|!lm z#!PNZ!1~iVZwnQb!fV-c(x1bB(GninG*8Zn&lx$W1BmV}7-z#rGm~jsTZl^qK4(1N z6TBY-DthF!En*!e@*QJo>(!G#T-X9_^MH0}bSIc-M`7aKLe=QW7W45O3YK%a*MZ@F zqgUsoanl4wUP14aOaUf`Ho#p9k&byAQZ7Qn0`vGH1j4u+8e2xfC8~(8OQUEfnRkFk$o`!v4F%ec4 zcx20Pw!$w^vRZUu3+Gx*q#A-ldz$;ULduIJNr>ZyD=U06$B;M(%fSy=YR3>fC0q*Z zZ4&T7vx!kPR~{UR_

=;E@>JJ6IpbjvaHZ>hHQz1e2KS3S9nHWDz?noS%CajQmNv zF)@SpkA!8O*?q&$INv(z5KOslyf^<$@y8@B;9(K%?jikMQGi`*WkXKiRg7g-;7?JI z&p#%1NOlr&N_uPiJYk6Fnss1LBO&zAx(bB)h%}v!a46-JYtO%&0t4<&+uEHa_#Xgu zL5jY=sqy+It#G;OjyvvnHgTJk$~SPU#@@e*Fb+81Rb-~v>;nmJx>5E;ll9HuyA#5; zGU+L)q`CMcK3ChYyrkqDuzU(H-n*>?HfHCU#oy z*yiPk3FFP1IZtSt4SJTN6teq2yI2DN)YGXfp-2yYEMne1tb|Se2KMtjX_Cl|#N-Ft zSvTBp!^RR56q`9mEc#grNweti!w=6&7>h5FH_;4Hja9_|A-&r-JRSl1dNB@01%FF67zK!T)JE?i&jxbiNZNzH28WbDUOA|1YC$s0!Lm8FO4 z*RQ7-oaZy355RcxH}~fhxPOq?ckLCJpQ|2vh(R^45AkP=FTezz4K^r_3!ga#sE~DC zuLg7+$kut6SeZLG)>|9Ed5lnl^I@iXwq=9!Fc-qO^P!_^CJ^BKBab|?rWKsuklO&U zf367F5BqTnARd!hOvqx$wv)-{wxkZ~a=ledDjvZg#yeQ@tY*P^0klPDI1bC?mRoMY zXeMMBU@LvBuSEdNappO0Ml3o>y)f_q&>2s0NCAjxQ|je9Gc)NUIFCMp5KiRY_#fGv+0axrBONtlnAz^rhJI)nw2|KdH2s%)mGvwnfrr z3&D8`W2{4I+^IhJ8v-()z9puf_^d=@4i&%l3Mr#=Ue-El$+A!}^M@>zPt@r)2R z?khPS{}Tkn^9V}=z>d!(zqv&5<2-LU z7uG!b_*2=t$A16&-}igal?~i&@Y8d~0s1SG1d^;&xohuZl4H>*7!3VaoBO`x=o zlgXgx8F|)pwGp6q<1_+5pT2)&X#NNmoZBFwh3guh7Or<2LR%3o02*VOKYj(*Onm$5Zj{PFzqqG zct#vgoEM&*V}Sh_S{SeZSF`P0&>%x*#KAUMzom?CC1B?ZBVCYM@zgNqooU17B)1wi9^89vH z0O{S%4o}AC+~kofR;*yjKdT+`z~13#9)Cf%LVD z{}~zEjHA^A=#lvv^INcqa)fu0ccevOA?9nx$k-mKefgy{gWh%2Jj4y9_6+*yC$&Yq zdXc`=KvdXHp{-_{iu^HJX+>Xru@Ws#*Z*|bjU?ZM!M;I0M3zp3<6)7ct|88li8;I> zp9ip=dkKvHXZcG%)MX=74$?T-42cWBNd29YVp1&x6m*y|k867fTs&B@ubPad#eVE^YzLB=XHg>KCwcn5A_kLDk zdAEghg3THb(n7LlRswgJ_)L^tBL8{z+_`iA(g5H*@;Cer8Tx0851T%VK@X-vfB0fk zX))RJ75c!8dvOo$l{=2{j67=u=u3n1T{TH;1nJWP%k@8Al&I6`=LB#?GFlf+O4z{? zE)h&EOETM#@5Xm*U(M0@ge3{f+RS+-I&jtj!rj&$)QZX3XP?~>?*WA+`vAZ^D{*z{ z)G@X&h>024(BS;=;lulqd^0p|4Ah#f2`d(z!05+-3BY;lP-y&Emr8;2FyUci0^;zl zV9-)O4hHoV@&c?~yO!jG0P{Bk%-5DR9~t!4(Xd?&(39B5pdjtoUg28U6F8{6TNw;` zz`e~GNn%OZ#CuTUzA;Ix!`HBNl6EFL8KYqYp=T6y8`c*NX!y=>45tKuJzU*p_B?$7 z#xjf+uBTYE5(Y*#2DL%>FkB9OD*L&Q!`tv|97E@w4XL~SH9%y~heQ~3E!=Mq zwz*oNZ4}aI1mHvo0g$5q7{N8EP&bi5pClUDPV)ct!l2K}anP|0`Uuj8{xkkI_BMS! z?UH=I!u}RJ9oza6`7|>C=Nrs#;YS+_q39vmqaW0}{NYyop?C-|N-7*lCeDNWS$2+q zMC=m-jblYl83&mNw)T42P1rkI2#D_^8;I-ri@Xx*H_UvF?;~Q`amO9kEPrOGV*U>m z*t=2R<2#Uz^iI50Rs%$Eo=)s8`31WW3OCU=;=4n%V=N-PA~uj2_Q_C3smUC#7?qv! zKeBnxQF~oEWXO;Yi+nIeHtPjo8KLiDI|=d{HSRHB0FyL+CiYY3Jiz%n2j;7W%Z3Sg zEdlEtJ?^J>zbzyUq8YT{yJXeJKHsaf{~H1NtQSAC(^P_lt`LL1=y&PPLOiOeQ>QLb zY^Z4foC)@Ol0{!H3gc%Bm%*f-UEhggB$H^LaTASC!Wqm2S3b+#KXX6$uEE{*YO_E zr{GY*w&z}ncR0$KXP)_wifQ{9+QuMxEkJtOiF>e*&svTR=t_8^-1gv|VyqXqzB;K3G>#5qL&||Lz&;CNk(Nmk82Zr$gYKaS>tz zWR|3UTko;cVe39DnWeE7W3JKUDES~Cz@|YH_$`Pt523fMpbfFX?a_&@T4htNL$-WQqrU~5r9|i+K9FQQ#e4oZfwJE(nJ2=VElrNF^7A26>gGr8z$L)J+JZ@ z;wH^dE;mtZhcf6x#pQD}NYYKA&hBb0@0ucZWABhH>(5C;1L;IiHf&e315?k;bLu<2 zqwST+Y4_3+jZYaIe4MEQ_yVXG#@%!~grDmLq-S|Hv*v|x5J-c9^ScG$yhDswM+}}~ z_&V-9#tJ|XEM_z3L*`B@YrTcf8Q?rj%SpH0cH3fzxhl6{XR83fQ*oV0j6v`JokIjb z6$4hu#L(*kOS=t%F@|1YtWgI>6Ln@z+_GxIpuFQ8dz+Fdso2F#E&`n6T=ILPgMe#x z@G*|jR~SY}GFLYY zB#HoNj^{AwV|W|dBlvx40n#&OlT@ql4k;WB;5-vOxoyE@kiei2oKLo&-U?uK+o8kBT2$iM>6OmNS_bR zyM#>obIDhfQhw;XQrtH|4AFyReT^Ae96w<@0pOy2rJJ z(z{t14NlC-}NZMF=q9PkVLRsZHNA)l_bLdp}x@Gtb*WO zV#_K(>CXR_p8c!pxN+smm9Uiztkafz$i`utX?ypQtxMl3-SatqHtyeOIMScM2e9ii z#sK;>FoY1GH}1;{eDrII@&qnX(%hoNJDszobm%PScSzied$|A1JkB%ntP!9u%|d4j z1CvIoX8j%W?EY+tvRMPle`#j<1{vbx0XLm6%79!VYjzU+@#k8%x3397VkfH&3;O`) zIp+qxTiM`z1nFtlnJ1ojqT4sgsN-{IGw3rDV38>Go8SB<`x+6P2ccPY%rVFGCBZ8O zeFix1q_D8(VZFl00qDtM&L?AxCnsVJ&KR60T+r9GdTL&m(5=XzPbJbOX%@>rFS_WW zCM9TU8Z>B7(fSB`L2^kZcQDL&w=kZ~sI8tvfZj=00lHxeq063NACI`#ld~Py+Pqy*wTqAkAq6UaMpO=)K zZM8xA5xfJ)2c@5{N|#xs!%7IkSs?&ZFRCy2qxP#Wz)oOd2U~hXdAE$A%4#X}&2=Xc zq%Q@|dn{)KgmZg@eFAK60IUB{AN%75Zh+kwYp_!oQ{K0tNWafJ`dzSVw!nUAB?EYD z%Zl0m9);gpzc0rDcS&%6=%I%;?I70fW=IRNrQT@;@2RIysDnDq!VV=Qq;f8PkgwC{ z0_j8rQ2z@92V(yWxbx0Ce=h&*c#_Z-ZGgz0|E7G`35OkaSnk;PvV2Xq2|BV}zkb-n zw1-#5b?xn|R;_wMVK_Itx`aKmhwNCk`F*yw4lUV;a_+h34we2) z6e(vP?Dib24e}O#2Be%6gPz||;qv>xy;6B9 zEj*(L2K$_I&N-{qMswx2E{_0xHn?3WgWl3vG3e7keH5JX8Je{psTh^ppm?6C3_=*> zEx}C#^_90V=jMX3h=F;}wDYWH__Bmw-{ntw_8FBmKr}wJB!6atMMS9w{RwqCGsF?n zfZ#mV>@qP|TZlOyGMK|`_keL`&$Bd>2`kQLfaExm(A{L{qU7%hV8_y1lJTB-`Q?{) zA#gs%pbz_Oe}>Hf@F%AN#ydc8evk$jt<*XPC3Pl3Xcm_3d0baIn+Ub^JUAH zk?56i%`7uQkT6aIs<9N8V}LX`C?TlIIe_kf?9@kJz&W%bTlT@sH{gn4%=z>cgfA+* z1H10JEAJ3a5d8)~0?sr{8;8^Z;KO0!GxY(?QyYoGrEfIfx z{-+&bF2SJ3xyig2VU1W7qsiV(aNc$C{=uRGRC?fn2MX<7aEi;7DDFGavt$hVnue6z zR_`Bx7CKEB06;8cOZ5l;OMSsxVwyS+LE9xV=vh?)c>&!(zV)qd<<_fYl@KKubIS$V z>1&HUcjqwZBS=p_Sqhw|u#f)Kwz}UV7{L7hpcuT39M^mo-hT)`UR9Yz`lA54zpdY^ zn3!o#A+HXrg-;kgx@jBTgWvdFfO*$}zv%1yIf!%bus1!~7o5X38CHkmfb?6a&3D## zJbKKS=9_Q2=?C)DChEOdkom9?oIgso%(uU!nErY4iuzC{T)=efYkW?`2Co9ejuj~U zhW3B%zWeTbN&Ol2>}KpHOA-HcAQ)GM?GzFxxL2cvvu;uUGfriKY|HHh&SUdAgiY2M zKnP4$TjyeP>hEZei8E%**j4t#*h??H^mpN@3ZMP=YM1Lo>e`QUbH*CllU1L2d3tz8 zLM#)eb3fUv`{{oFtv0_(Wxl@GE0IB;2qO`&nCl&&PdjJq&t3^4M(Fh-}};RyB(W4V3s+tduCH-SOP!#%MJkkk|k%l`q}6()^#&T1#y zTf76bH();RBxAsZV&_*j`5h--LlBQP%M5YDwu%BHm3F01VWKaUs15Lf@PMTy#-R8A z*ja>(14I}zW=yHDan1(>ae_%S`sZqgxG6=jt1>_zL3-)w7Aohl3Y~Gf6gcnCj`Peo zuIsV2>HmMy;0@4+@9oLo5~P%nbz5{lPYId-UX> zlfwT0^Bsde43nIw3*kN=()ftYHtv*DdOh*8pUu~p`-a|&C8-98G8S@BULT1rKq_OnZd?5Iz+pd*0ln}81#8M5-t(;dju#$Vo!s* zKG%*U?-E-|TP9=ycgsu?8{3)R2?jdt0sw1AAN^$?Itb$qhn_8~V$2+JUFbjKAxgpzepWV$f4+Y13pc;qL)RVf`&7kwI_0 z#2;qG(_VY+<^H#1g4g}_+m9_kJt61H0qE<8K_6McTggt|m-hf2Cbth`ZwYYTpJ_|m z?2NCQWG6k-;0~D5#fahQ)Cffj1T&f z+Tijsh+?}72iH{gHdVYZBW z6tIFlMDW@JUBIV=_)|itn|pAtVu`kGuQ-PX;Z|YQ_fr0(W7Y2-tM7WWPQRl&Gw8!o zX?-0H(3gJpxXiwXm@^Zl4BHC?|0ju+*uXf{rG^3{@EQsU)$C zhd8W&uK@WlWeHJ59khcOL@=V6l%XE(hi*Hx9dW5Smjv4|=>gw)Hkh@9Kmyz+#0_je z#$hH63eUUGKKpPklLijm5CM9LmgIh3;emDy!0=81>BTkzl*d*wIPY9C$?Kgc7!VPr zZZ?<@h%Qw-AMSJRjGRCuz9^XAQ)-oOnoQDe|R{XW}i zTm&$zh^T_?LO8ymLx(nfM79e8IPc=*uhhcUh5nXffWY*;NlV4aVSTQz3+vkCynL=x zMbE(a`T>QPBizjw1=7FNWQo!Ty~q-iPGGXr=5NaeW#woH-ZG&nnYLiTf^tGYIlN6t zfSw7029VWaz^_xdx}5_sK1syjch6nLg??i9<4>qxDyE+R@|3nlNWq8TnVh6HPq#Bk zKgKe4(&~y8D^_e^(y#k4==0;Yhlx7sFez+l=63qKMX{cVf&T7<2@{5kd3(DC%>$1- z@<=;*2FP*T*#ZKF47wypZ?&qpwS{=P9m(eP+%BVmzp48_sv=FmOJC z_1<;{gE;Jm8l64gtj$jY5CiBgX*VOw#EXLLq+%HNkh zeAaksdyBTNF*qM%&?5%ttv7WaLM$@qou|iP8Qd?!oaKMpXerR1ewDtI{?ecc+x80e z;?@9v_aqRPyuT{5_s5`v5g!!<@TfGbig;-UW9`!SuJRypo&A$@Y!+Y3wCp6!q0_V#O9W(&DCr7w%qcP~;Q(2%f>Dx>gI;@jz4dZtF*4X`d z;|#xLN?+a#U|gfNWI=Vn#(-C>jf8F(8U1y$e?fEvq#yinft#8 z95_sEa-Ei+jV3NFj=I@(2I%=en5;?0&!mKk+4GcIhM37)jZuot--tSXlw!wy06oA7@Y2~3VD;zKt5-KY_Sj=COW|=`9O4GnURW1>1Yr4}|NLj19Gri~Z1fwz06k{EL(}j-;cYmM zqs+Zn(u&?2fahME!*Kw9o(-nG-!q=c<9rNplOD5%Gr3`4tRq2sJ7u&B=i;a_`I=yo zxgEn5lQ2QCv1$j-N4@uih(WtBPe^_B&5=QG+cH(cN%8(7GtkFwnP#|$U@XZm%lCgv z14wOQ&sPZ0M{r*4c#rJzFJo6TF550=OlH;Es#UAV>%#j`3Y>Sr&ZaKx?^(Ld>;{h8 z|1`k$9e3Pu&p`(rv;$$Dutl&v+9OPeG46de@JU)mS^Fau)+2gd2p(BeuDGz8|u^6UK>xh4gHEY%o=IPhcw=WB{ zc{yMP%+|3{8eF%M^Wc3cM~ylF=Lwqu$Op>{pbn=2z|R9^%_Yi4Ica?ybFU15zQe&$ zPaa9$C~{6|W=hQM0SFFj8RmN`?l5hNjslVc0yw@r;`fE+s2IMmUI=4@q02GicM?mS zdYO15>}L#SyRaK1 z*L_wX{hk_Y<}2LAQ2kD@b@}f6rfp*3!m3v8yry>n;iY%Bp@L490+3$V_B2Rfonu1O zvFDQvdSe(A?AO*Ug}OM#Hf6_|sV^Oc;3$A}y1wTPtQ<%;KxELPJ8uY}cc`Iv1mJF? zd`2N)%<56e0?AVq-23Tu>(+gmTuC_z)RS!bMqtsuqOw#t-e{9V{QW`_5IV>2ohJ@M zgI{7`y&S>cz(=4Bus@3l&lKW~lyF7ZuYdh(wzui~ZRoB5y`>u9wy(_sWb5$RV@!I0 z@6%5|{SL)P zQ}tg(9#TEypF0$sk6===bS8tiyDSCYO@^!W%*JDh3RZB9iq}lQq(daUO zI`0tmu3K^qWwr>Ct@ZJ3dpfP<3&x>=-^(1}c+1~fv zqFf=}*qb&*IuoS#`vp+X{~?%XdyN?Na%5`?&PO|Hll92Dga?D+`LTc_M+l@Q5l z>F-j16#@DP&TDheo_p>&81NOFI3UijC4?U#CjTnGcZ?>kzo30nv8VNaDR3S}IDPzl zg{Cz7vC%>LSF{->0DF|a`%Hxk`m}5b#yHsY{JxHz?cdoGR3r-}AuqAY0asyOr$acJ zIUfM<0KtIwT*JOX@p&PGo)2N)%sy>7gX6BZa9@g7ZwGa}t#?BC{F*hU!lFN`o9j-q zbf8zVzXP0il3geE{ae{5?w1ty5vDYL=Zp#;VfNj3-#t|1l*~l2+~3k*M51}>k4BTj z%3<3~#^5u$gkHgH$1ljjR5%~p4?ls#uB>>#zW^U-gK$0=1v-uGiO)fuS@)q}>)N-> z3vXk8a~^-XBS4=wsJoHNsjn_V+_>aR6pv|FUU?+|__>oNO}awtyE6p>9xdhiB(rf0 zq&VXtKu>+^dXpn@rr&kmXb)&fGn&sR?@&evE#~b&-Eemhw+x{(Os_dveM9?wsFk8Fq#1m z9J(e9W5;>E9+thYGb5bqcrN+~`X%}du6rLqA7%M7&pfkUV8RZxK?j5MNYc(qCJXlp z#f|~zqj)T5n+wphuWLwT&>Nr^38GCg=*7OSmH!)#B~@n7M{r(!gor%!KsO{4%dK&C%fuvf4_44^xI1k8E1UV&_|Fd6nU z*m7u-~00DtK4XCsyA#4H+^7-#>R; z0W-i)0Bk2r4QzP)415mb1PFa0?aC?_Y*zY5uI<;apZ$Y8EZAg2Y*_R^3!o<)7G$Nh zvQZxjE{`$jgF(OU0eUN3<>752P%l9I586zloOh4l+Kl{MMjE& zd4uyP6&csr(iWxK?^$hrr}CsamBo67-_{K%AHy+pIzS(WW@&KggHy+#XVzVE7X0zY zAAe8!a-A>80qL(EGiJ=)0#j$G9HQ&DqYnH_0Y|;iWd=|{HU{AkoJU~bN}f`QQv0R9 zpBLbLxyqNc>*IC)$Qx81Rhgn^f2sUxVxP+R$wU~2w4E085C*{|-}wkBaMtgK5NN=VR+oB;L)z@?^I3EcQ26j_mZ`Y6r z(1(*M$esdzwpQPV?~@dVKY3T>FY1eH;{T?T#72O=dMgEQ7RY`GtH|X0hQK@p5*aH{ zU(;CnPe1s<4}RwB7A{~eMcOieZnk?eyp44r0NnHR+~-q#mbb*cH;5ks_!gc~&)Tf~ zU|-XYIo-Hi^V9V#=Dzp*)2{u0jA?#875c~q_bYF=t zfgeD=Ebs*GTXMXmo;h>oFqqENvmLDG7!1)&xjv}V`e;I8$exce=v^$e0O;#K$!!dM zGk^a4wM@)SoH%jD@ZrO4q!g6V@iY+>Gz8~y;Fl~}@>dxuBd@*o+Ldhq+v^UHk4|NM zFzD0I(_PrM$&eNfJ@dNs^3_t;6YfTvaeO}d=%crn-aaCyVMlUIm^E*m1+)t@tjkzt zb9e0(AWAFHJ+ho@<=nWAaxUk+*nHuI7d9#Jb`t`V>HPE0ZxSOc4xBa8=}?yeUon0S zpaZT0+5@Dcj~sV+1+T0z2+MJj$-<1s@n_t{FlKD#dUV_g+7YhjTmXIRJI5%5#_?F* zzkh$8!=dUhm@&K=_W|fxh79uwFrWLS^MpjXN{;4a>C#T0`qZa71*EsQT|)M}oYn$3 zuUNnx2+l_ay;sk$eQ(oySi0^HI-fxw0s7o!_+hfWaQmhJ3rZ)4xJiQalnPdoM^Qeu zd1B6wR6^5`Iqyjq03!hU7d5sHQFxlvDpsv*J@dp9PlQQ-hQX$y;C!@yL2mD+4U@{Vd+`IKIst@gYKb(iD3=gn>il}&&aA|0raB)n!D-hlcCyN z6Rzqtq0>Z^O)4LeO&Rou4r4M!?D==9#3p}MWx0UpV`0(fGUyvGSJn~%^p~jr>VqAx z&-}Iy5@%N3eYD9?`np);rh-Bag#b$oG%`DDO(uJ7{Tdj#tJe@6oJ=xuic<~J(DL<@SA1?-`B zk`Kvf?IpvuP4v5A!-n;farCg3U+yS&M+nTLx9D^T&f|mt(7#1|^u|_zD7L zaw|$01}ZGp8~2wLuX>=4DoPjC!Ekr*G$@Nx82b52+o&BK$?#!-=fXj&wlo^$7+JBV5?aEDjPN!^USyo zL)*ZhzgysZwMk*KW%G<`Za7@sk2XGYsa9EAU*AtN(75C^I6JIhYR3<5kpuTwo?SoFYS`xd~_&tx0G_^l~-SFdgke; zn~+^)u(k+5O5HPGw=+v7Bw+efQmo z<+_d`M?r_tTXfn+XOKnzIvJOM^z|!IFtRFP(9`yQCps9Qj{rTN0pA%z(MNRKlV%vP zW~&f}2Cy8EHoTsE62y|+Yp=b~V;K01#Uz$RmjU9r7C@Z>$j_GJ1*X?$KJ%F{bQb3_ zxelA2x}97U=gE@?>?0l}jCwQlBS0UB!rSbizWPx)JRc>rAK`)a+i$ zd}Pp5EFoB7{i{2PA#RW)NzLsDP;21U?VB1~>6c+qmkS0l9uw=FiQGWg$1#KRE)_87 zqfD7HG!{4?L3)>RL<3|26!Pc8 z4?8UDer*Qn8(5y+uwldAfNSo9F>dTAuulvhLXylGJ9g|BuDkBKxAQ6*J$m%t>AD}u z>G*q?^EitXbTv%g90(vE#u5YMzo<06LGU4^K6^UhOJK{OgHxMt9x@bedTz~~L-dR@4XT;2ULg8=?|2t$3 zD{P$LRM*3@XHt;o<+)&mr*jmA{c;57w`X}S@%fi7U0RsffJNB}Aia;*7dRgi#q!zv z>#UEA06m{=cZGeM`%Uav`pSJZ@kSrazNEYhsM`wO|4|d4CRem~Y=u-oAA((G@#?FC z4?fubZYEHVuq{ori=tS}N2`smfcZa=h+&z8D4HM|1)caaib2>IMF9bo5fNphtB1sh>rZw# z;~yH036g}sVY3<)Q3xnP5`RF!5d=k12nIuz$SRUGhzN*cFenBb7143>K7IOn%FphZ z>6vc3r~AI=-1AjccUKox^IiJB-+S+cpf7P^zMF<=C!ToXNajwD9zDKuKfl!d`6iZ4 z`L4JhM9?YRC*pQflpjnGFGZOfRP^OQ&_i->(SS7zh;otiU01AFF^w|TJfA#(d4c$k zIdm)E*}{Lv8pg6C=(AU#7k`NxkiW(_4hzZ&4b)?-f)lo~6XZ^j9^df>Hd_E)re>>~f zucvQ7VaR!hWx&M=ddyxcQi9$U^i~$k;vRsXrI{f<^g}IfwiHq*G9R-g=$YeKre>Cz z)bsXQ%i>@!qtc72G^!h)ATtahk&*LcDlA#DL}Kd3iBCN71aWQFm^*iFP1IUAj!Ms4%lyu{mZgf}#TMTCQp2LVtH zK$bA)W!?~b;8XudhwqPC1y|6U3LPhCD$aJHpf?Lu^tp$ZxnbLgdX6nxw1`yrg(_=P z8h)M}g&X3hFQA(~(ka!RU0;Nv+ z;>!t0P2rNa^EyI8j&1G{WIW_4%5~4R{A%qQyk=bfalsi~p#5q(5Z_i{aCSWFN(55e?3!x3LxGlJeMe!TeLC2r!G z3l2MDp)eEktHzZLH68L+9uK9YZh2j3$1K3 zW+L?=?#W6NDx=aymC8Xu&NsO*ZTFBn+ezx|G>u`$Nj<+S${+p~(L@~lZCI*BqRiuy zapT4vspm8lA&!;OMbH7MPW)kg>aqd;6JJVvV>~ka1DTzg&x3Be?Y3hkPoBKd3Ht1b zd5nD!XEaJhSLF7EEpf7CLu;It0Mb3M`5|+HeS^{rroLm_RI=xtcOGRF2B^#V0Mc;Bj2QzVlq79X;6v;g zEDah9f=-O)SE%Q=>#Y~)8umq{04L^=W-pY&rJ7FtC?W_Rs3FcXr(_C517x}>Jacef zh-HWg&I>u1L0RnzdhQLRd-v|$qfMJOMO9T*5U*xZP}QHsyCR`+J{bV-&|Fm|w;d zSUd>HPE5ixw9I>YuTb`q_gYM&diRvuBo4%Xns7I1COEQvp2dqVzDQQljZV;KPjDNN z!%c1rF;@r$eNdAx*W|n-T)3gO>GI{vU(t%&k5pgk%l7Z{9N}CF14zakgYU@XJIXOL zW|9Jg(Q0Z_0TEBoU}bJF_6?}GAojQ)@qp5d{V-s&W44dFbHRcIC>Vx|oZlIh3LHOI zrbRVm9cl<8%~3^IV1hCNQqf4H9G^Em@#KV^`7`brzK`-UDCVi}j_L%}B|Ri~4FwCw zxu;~QMN<1kj-nvv4{45^H_``Uk7v1X;lgCYJ1NgvP0~}6N@56iIF?>8&&i)&qHKxXQ6b?-#z2+@+!{c#w_!%M=DRJkrXnhBtQJAP zOC;_=VL22^|5&!D;eb?pU?A=ku9bSeA<7@dLkKswAX}zj0i&Zhg)6M2uJH!O``ErU z&3^XTXQOrN*3HvBJ5H8J%@3a6uhcth)LCbpW!!5<(|5rcUZL;)OWEg6&^L{Jy7?XL zftc~I1Zo}UQ~}5N@&qIBtc-&h$E<#HeVfQ*SJ2ytu?j|0*o_KItCa#+0{7MtEY!to zapqGciBi0&z@)4e-l+dBbxb^(FZnpF!ct=fRzK-ib1_ zWlq(>oSAp}>8CeK&YRgn3*~314Nu@m_C!nO9q)hRjW;M;1Bvvuo?V>|KO(Zf+v3HG zC#oS`Uy=TNFQplF68MUkpBEJz4o$OALC<#4_HJ$hU!J{vKf z7wY-diW4r4(%{xxZ$0#c6HXY^vuDpZ#}JOhij;lqqTj54tdBkD1bx%kCPhyrr4fwW zj-~VwgoH|gVlKsDiwkBJq?&Wz7CCZpze$}Y#q%9a;GqvZ@W4k=DZ$fyP1$A6I`8uz zk}p8UR9>?Z#{>~AgLPj{qr`>zWC$309<~iRWcMUpNh;e0vBeka{~0+yq~yqX$CaZ- zjY>eo+M+cidO)NzpY3l5%hh?~q<;pYzzKTpJ!OF)UHO4*N*~o*g@mOcA!GrKm24hc z!&vG#LbS6;LMbasIX~3nOrCd@zF;gK^kE^=S`Yd^JS0Sd+)uk z2X9@fg`0CFlK49***?&7A6;~+c~{V5X=4|QvGM?m=lHISwbdOV!Ob)K=6D$Y+I=fz zOdOWzNGHI^oVD)ce3jI8lBSgKUnS_KK*;7}=G1ie`?tA353 zPumcY&ilf$sLgPoGEhhRU7EDR)D(7WR0?o}tIEySp3gr)4>G0mmb!|5p8|;slnVB$ zl&^>N?%kVbK|lckWPaI3Ui;2MhJo#H@lxbaG=Kj5(pAnos(bb7g?hTF#Vwmlc{#70 zo4Nh|`|or3jmXKmZ)FWhaYBC%h<6n3+^=Na`OTX*L!>iTQC>6e*{7i_N@`SE9EaHD zJP_^7@8tVf(BppF?;zA?l+YnCLWlwJ3z?779_0+rC+jqBSI-ac(W6H;0cIjv9k>`5JW1cZ$}mvB2ia@@A_PyA&5p0F=iGvvJ2 zo!4BPr~XZySg0nW?D^-PC#z|TUcN}={4XO%(ZxY8yzs({+U-Rg1i@R(aRMx_WxPXbWV5+Pul@$ES| zZ(LbuX3bC`p@qX_uAq|)KgDAQ6&}-sU*c_A{c2>IrgE49{MzL6l)wbM8x;MYPSl(0Sha|1cVL< z7j=zrB16ihmzPNPH&y0ln<`WsfoKHa6*Dx{C2k;FWjlS=3ZkBm!?9bG{F=7OV!sd|ehM*5gdfQ&KXi+5G$GFm`R+1#Xh?J&M@ zBPw|~EYl(^v%q%zIP(iKQK)a@dE*w(@JK`k@8v=n8%j(io4!K!?vbLEd5S`w*N-~t zsAR)W0w2oNpkhHmPmn{&KGZ>RL4tm4Q!)qAo<^dO^eD1PC+7U9RyZf+aA;b}xgh>I zNA@Ldoap&XXcIYaP&pbJWz9)isldT}+b?Vq8xr(kAk1gv7uabn2%tN%@rnG&US&Gr z1LBLRjre7$9FvQAn*Sj1`{jh)Qsj1NqQqjTTrW0)KAYp9Y@hdyH{N)%=Hbo#`}dE; zckny-UF}~zYu2piqV@nM>HCWSpDTs#+2@>d4!@W1tA#EHOXeejCy3|eI&`tFH6R_! zqRh=T)OyG7BouSfB-Tn`rfCd&i-`UDd|#8YNJmJe?O9@(33W0U#%R1vixK(SrH#pyt8t;wd`D1wWMW)cIKqeN*S0E}Nt8-5miZ=$pk& zB5f)aY*+K2SJ$px(<$K?i=Ir38>!r+)2v>-dMQpJY7-py-+zCDg3X^OoqBQ9-r(pV z+aDh)OQZ~0)d8t7y7}gtqqbni%$ZSZamy`jo}TB*AUgJ@>?_%qa4D&AYddcmd#02J z<7L;MefHTEGz1jcV?loyM8?b7Kos#GEUI||vMI6&C7*uj*e10?CC?vX2!kk$FNRrX zep~3_y_7%Uv-v--*Pth`Lumqe4(U!X1F234A&7G+Q6flS%F>|Ff`CVD&-?f+^MC8s ztUiq3LcG&_l=;tdpe7{8A?m0@f66JRSk_YOGm=~ty-JHGS5fP~4dlGT z74*3#nYO9FM5Q%T3R_jOpiGiNyB;*c2?#6S`W@MMD^|^Sn`HzMYC_l zsvFM`gt*Y8?ZhP>i`2uNK{dA_x}MFB^M}()bgy>%l(1*1Z(|_~rsGD5#}k)kkB840 z?&MbIcdF<{e?{qjY{;)|altA39MRpi?UR`p8jgn`oPs)B3_`NQc;WcAgmgz{uZT#Z zPoJ@3PlvN0zbwB(iOu5`<2e*%{eBV-A=&@ht(ekk$975?JeM!&A~eabuTUVQr5WR~ zjxI~5RjF$XIK*vwMG(2+Db=o;3Lw`4q_RRpeBJV-pz)DY?QEr{D)UH_xbbmuG}9{f zsd-*M9Sl|C+VA1Gy7H607}pc}ZY8kE#Xe)58l#rFbi87bHAH?;GQB|-iv2c-PdiYux1%;p^BV>MYIe35BCCWW z4V&s8g#{W%%$dBhlK4C*PjyNiUiT;z*)hgkU%c-)!NV`tBq2w-CvDwO%o^iX1XAo8xP@XQOGr|bo+g=DTbTgH*c1u z9Qa#Vd41Ka2b#F-Zdi_zP~u9L7Ch1!<8)?cDFdaQ^5f1}h`~5Sfe?LBoh=^VWsQA* z%SIeZ_Myz`n@6vpD>VX(>?ZcQ(=6YXfCvgJ7k>4OaZ?ntsQg9f8UD8{#;7f@LCx`1;SP_+|U@ktq{e8x3m71^{Xeco00b*mnso ze;7a^fRssl!5#fmk>7p6jlU03N~jYj-*Hl;ga8p&KOs&;q>f3nU8>7YR^ms#V|wAw z+LonlW!G&*WEL5>I>tnqmT1)Eyz)$QYs^}7L5EH%Wt5#uwx^F4G=~A0PeWu~GjAZWi!^kxc%g_nD}rvH z^te6S07J+zfSPNUyV3PQ$2X%wZ=j?SgfAJGnua@5Wjie1p=pZgDUcIYA1k9>Jv!br z$u8zN#;=N7z#oInzL7TqKYX%Z=vjM7m&&8%w6`>v_HmNz$oaFG%Nz_QuQHw&5g%<1 z({(1ow_)nBz;m_!;Lov@=5k8z$+BGXg?kwZKscPc0^ZOKUq8cP=<9rDVFlI#8}0l9 zM%90>cJON#DTq-`uUytqZjHc?5;A^~2rFex8!Gg^pssXC20C`hlCQ-NCyRwK4`As^mf$iYEB7zrhY($@+%I5Z1Y=BC0@1l&J z+5-vzTqeHlzT(TupbW~2=6H+{-cLqBi}&<=KRL6{q;oo;=%MxtUaP7|^{GqLgthZC zI)Wjvz;fZ;bFJQBSC#L6Q>$}dIC$THWOnYeJBOfCrx|M)?17J0hZn!R#&~R!^e^(X z9e_ff4f4QN#4&LV#`j&lF5Hgcz%_%~s!DusjeC8LX45E>TZ91I8*buU_ACO`6{oh?(KT-J*uLxnxqBG&Bi%N z>mGe6>j5RrLn()?J*rlcudovik8UtaoNAqF(bx}VR@#N9eafG>R2c3LR=oBsmEY1+ z+BNN>=v%{fsZed7(XBXw?3)W}wKa%J9kaoQF^d+cOgKR{yf1RU45~Y`Ds~?LS$;Rt zl}R7o!hDu-obil&y0aTJ`ve3Mi{`Vvx|@?BC<7Hg7)9m-{cb%De+Vc_<_{(Q+cSdv nq5m5^!u!*coBEgK|4l}O4Ft&=JPM)q{$?@9TAP*{Uyu4PlQKXj literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/icons32-vs-2x.png b/sources/wp-admin/images/icons32-vs-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..512aea86ed88d21fe0eb88ac3b31a93298ab15df GIT binary patch literal 37994 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�S%$7zQ*0=S%;XtDgE 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 be|@?Y*Jq`A-|Gc_I;vWjTA9=syT|_rK-htE literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/icons32-vs.png b/sources/wp-admin/images/icons32-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..c96784465075038f059f0c6d83294147e5cef8b0 GIT binary patch literal 12920 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 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/icons32.png b/sources/wp-admin/images/icons32.png new file mode 100644 index 0000000000000000000000000000000000000000..af061c1abb78a28558d0c8ab5bffe75c758ff18b GIT binary patch literal 12989 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

>$_Kxvc_zADITm|^u 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 P&IbxIs?x=hMgjj1X8h)N literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/imgedit-icons.png b/sources/wp-admin/images/imgedit-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..ca0b88d339b33dc2e889f75adb707e4dfb771a75 GIT binary patch literal 6989 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 Z-hU36-n|G37`gxe002ovPDHLkV1ka^55oWe literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/list.png b/sources/wp-admin/images/list.png new file mode 100644 index 0000000000000000000000000000000000000000..85d1295e8131f8f0f3a4c9bc53fa2b3f3d770abc GIT binary patch literal 1003 zcmVjg5`Awzjvox2~?PudlC^l$5Zrur@X}j*gBqGc!Oy zKte)7U|?WjVPRxsWMyS#Yinz4Y;0|9ZEkLEadB~Sa&mQbb#``kczAeud3k(%e0_a= zetv#{fPjRAgocKOhlhuVh=_}ei;azqj*gCykdTp)k&=>kjqokyyrKP2(r>Ci@sj8}~tE;Q5tgNlAt*)-FudlDMv9YqUva_?ZxVX5vxw*Q! zy1To(yu7@>zrVo1z{0}9!^6YG#KgtL#m2_Q%F4>i%gfHr&d<-!(9qD)(b3b>)6~?| z)z#J3*4Ee8*Vx$D+1c6J+S=RO+uhyW-rnBd-{0Wi;Njun;^N}tFMg~>g((4?Ck9A?d|UF?(p#N^Yioc^z`=j_V@Sq`T6<#`}_U<{r~^}ug4=r0000H zbW%=J06#xXPE%FM$?56q>+J09?PoCh2><{BAxT6*R5;6Zl+SAuK@`W|yqO(}iYM_B z5Va+^iC#pcwMSdf98@ZJ_D}O45X6HB^&lwPgOoxkTl+%~dQuPZU`=*5JImn!^eQy*_PuEM7=^M{{*?r1wU|C3K_PFi} zI74;Sxq!>#a!u0#NWq1Y3~zH?=~%^Ow0DMId}Xff#bY0CqXI)k;!n2Gt$d_dJIxT6 z+I`o@DHWPK&^W>>1)0@>VeKn~cqxo4tTB2RY``o@aNo@1|Yeinxp zNN1{FbKN~k5*TLQuoqXDG<+DpHVK_;x$t9hm%PZEp$LpymM>?zM=vNI5W_^vqBl1b z3VP~RV#*us?FI$8gPpHez-R&!SEpGtZ;u{pJS%JhQDw}QmlOcE;t60Wa{K# zxvVDDWMYMs87jSH;LqW5Y3iyXrW9s+YYgN1hB4!M%4DXqT>~TAH)UB>wH2t8*4f?| Z{sDKP&y0=cFCPE^002ovPDHLkV1i3i7!m*g literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/loading.gif b/sources/wp-admin/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..85b99d46b9911ba53a792d716d9f688f3bb3c784 GIT binary patch literal 2530 zcmb8xdrVVT90%}oAH9#>bK6p?cF>G=h0@JhTLdf!(gIdN1QeV+L;)2XD9^zNN@xod zwcvQjRvj8}y3J)yFv=3A2@i*l5Fc|hs2f3R;^QAN{$aL%*eO}IEP(~izxV$0$@lmB zp0hT=YKq8{00}@xHO(cjNl%Njq^=3k8whNA8mRstISPn@&imc_Tf_3@%d4xaj~qF2 z`t<3uXU|@|c=5`WE2E>Mw{G3KfB*i(#Kf~_&tAQH_4e)C>6t?woVxLBCtLOMhuB(t zGPLP@xf$T%5Zyz3iOuKI^?SO*zNFJ?wrL@=YKNznIpw!L(PPjKYQ7%}eBCama_c91pIJ1~(b1Kal`fZSz8V+OJY|r^QHxE6+WMoDB(^~{XdW=!#+uo_ zaF>U{k0Hho~yN%NrSyV`soxiBvd>cj#}5&$KDA)3{S^?ffCPkeDi5Vo>T8sy}Wj_Hf}N$J0Hz& zv|)_<-f+~-Hi-jgzIkG5vY*T|>7-8J0U*@$d8~ScFqA)f4R7yaDBs3j(<2>@V?*ZD zy6{Vy+~KLc_m5He=9(fsy~0c&4a-*{&i)i(02j`@8?In8dBM!Y(Znu4jtn@VMj|y5 zrTNa5ki}vtEiGN(#07>Rk#HaVI5ZB4@@yk%765mBN(yieTXgm{oK}vXn!h0oZG3gj;>>W?MbZnG6Q_cX~h&<^+R)8g9 zSd!4lZEm4K#ma0{aTpMHv%wr`1VF@rrKl5H7Hyn$;=;nh3JVMEcKbqhXnqO(3z}-# zu=v1OV7q%OY`*dVI>Y}97i4s2yl$S zmSto?fO|=u8h;vSPKY2zqaEs;LlhJgv~%aqwzjtUie_4FUNiT>r-& zOO#{4cBb6f^ zov;AUp?UAne>@_GHz5+(221Xlve$OHK)tvvi!~l<%)zr4PhU@ z(CY^us$O5!${6Pje5gy?*WtA2j>{<;$_PvVQNKa&69IX)a|Fw5>C&=WQ6s37gabVh SjHs`-`=fdj^ILtus=om5Wbpz3 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/lock-2x.png b/sources/wp-admin/images/lock-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..46c5a482b7b27d718ef1810a8eb861dbb781cc12 GIT binary patch literal 716 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0V3Z2*332`Z|9??YQDI?WLqkJf zUtcj8l$4Z|fdNpwySp2x00@9GJv}{settk%pdmm26e%q&1(HBnAOolv$N-W+k&226 zAPEF+|Q&@87=%O1*pc?$f7F-@bhV8oPGw+KU%2o3wt4gBl`B`KrKJJgcHqE)qeqW+bab3Od-lwkGxO)qpE+~p z{rmT?T)A@f>eVk_zWn&{>1GgH*VZ`{ra`vnZVFc@(X5oCdBr)PwVH8UhSWGQ#}8~Ul-w;dTn?4b*HI$|K;8pv|xYtW1GXwfQWcGv#7QjrK-{UWs#z_6yoG$FMJUxKJm} zGvoBph8s0@_wUbsU6X%Cg4rf1_E1^z&5a@Awmbn#&x%D0=bKMD#So+QUGv3s?-{JS zOWK-zs*W?>beh*xqj;L}^mA3V$*ixho3;syZCg1f=b`cjO)K@IWh|?d-p@#J{mZ^n zXt@l_{UvUjZ!VB-TA6ay%`Lachw*~z>OM}ZCl?f7M27kVD6+GB>Yf_mxe&Z6?@V!OIu|HTR?fjY*m+nQy(>hFWnD}$%2pUXO@geCwUwQLLk literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/lock.png b/sources/wp-admin/images/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..e17cc7dcb68a74bf580f5b0f68ca41edd77fde61 GIT binary patch literal 338 zcmV-Y0j>UtP)A&TOMuIrDP24F^Z)ZGP=Bz;{6g8$~OwHfbLF! zMbk7i48tYppnE82+m`Y?U&ykIY}*Ey*BqT|K~WS7NsFVv|omXa}Cd-7m&;}9i~R+D^|CPVjmaF~~mMcxZcnCb(~ zs7C`zhVD1PkjIvf8n$tsNHa=15n|-QaL1s&(8vl!3}p^y4CyC^$#6x9Cyt0yufO{Q Xv-#UbM*zvJ00000NkvXXu0mjfT}h$X literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/mask.png b/sources/wp-admin/images/mask.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc9cbe63094888432dba8f6cf7bac85b40c0eb9 GIT binary patch literal 2001 zcmV;?2QK)DP)rIT>_nGyL#U7biEZvI|%Tu{Yuh0$6T>SyOO&;c5wX+h-1=j zhh&lFwFY3T!m)E!*6!+a$+gFUM4tiRBxoneJ)+lL0@`8apTiTQ=ga7GC-|=dLeyqY z6<1^cv$2v)ss&}0wPb$;b12}BjZA}_*NVnRjaNvyLZGYHsEoJ3fL2Cf3$L?XqE|LW zcG2%9cuf}ptQ;))&dTsOuurg}w=sP?LSx1g>;So@kb;f{3QBgaSpnG&7+;wbBZOtZ zRDo9s%Cya79GgBWQI_eG**uyMx>|%x%$u3t7Qdr$%@iq>qx_S=y~5ll<^1-qHCcR@ zqLv6fzxm&3+gDFn?O4&Z*o%zK7|KbRx1=yf4Gd9NgBbNSqS&xRq&P;_ij?PLhY=`P zB}+-VM$Ykd!xmkO+Oqnj=6D2zsJmJw1hAG{QE(=Y2iHz`L+YBcc^n0Rx~)kiCh|&! zNF$08s~A~y_QjUVswY4MdQ~NQl7y`B?E0(5Ns$ue304>-q_G=0g{%l5pO8AsCmxVr z0p2p<%Yvin0qq8vD!e5_fhR1vA|ndFFXv&yml0=KR%pw#vt;fnEZ>ki^PUV@>i@$; zpM3~H0XVBj1{j6}BZ;Vb{&J4Y<}oUX?c!^;$OU)F1ktdJB_#`fR2ZBfgeeL8_==Lj{dwdrH79h;x ze$^v7z09MMm??oRQB_qEI1{>7L6oZ_x#>GqJ-JYhdNMRI#5$3*)j8$O z;|NZUm784b{rjEp5Gu3^L9>wOqV>B%^dnIjG56lp;^5?Qh$q96C$D)SCsCv@UkEkA zQl6FUoXa0|cS9yilNFgUiT z6JZumPnOdx*%T=#TE?!#%#@ay61M9Y#S3x+!ZFL62(Gf22i1~8KcDI*5{;1n!kWG# z<(;S$&}BCbhr<&cz-7AA|p?~)&uQ%(r%V*Q@g(grtkGnHR z??@2V33gWA5qS!uXmnJP1p&nRD3Es7ZDlZb9^Wo_;^UOk8B%Z&DOUBA?0sqb`)Rum z^!aWWhLorZQ!Nw3F?%NvcM!ll7qETq>ur(7IN-l=Y(J(LIPTh9);g!TlisUh)2pHg>&f_(IZ}R3)(~6Fb%fQCO(+Di0_6<{7wM z+Ye7c!IC@2R)Oz)(-4aKsj^K=;_N~I|4yxrm!v7bQ?o{@K9u=9{ zYh#w^)fhgA9FtKBFER%kQrl!+c}hj7-#q3O*lc{d{o-9 z^Y6mmXdwCSeoWsHkrL$(X2C(0p&-^^<){L8=Qt{ST`ADX`K)2=xIo{r+NZqY$8Io& jJ3hkz{D;5KOMU(U$~kl8WzRKR00000NkvXXu0mjfeC@PD literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/media-button-2x.png b/sources/wp-admin/images/media-button-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b8f8ed4df8c50d7e5085d3b7532958c1602a62a3 GIT binary patch literal 850 zcmV-Y1FigtP)UcXxMqczAnzdwhI+eSLj^fPjL6f`^BPh=_=ZiHVDgi;Rqnjg5_ylara5nV+AZ zp`oFpqob>U3S z$H&OX$jQmc%F4>j%*@Tr&Cbrw&(F`$(9qG*(bCe=)6>(`)YR40)z;S5*VotB*x1_I z+S}XP+}zyV-QC~c-{9cj;o;%p;^O1ugww2>+9_7?CtIC z?(XjI@9*&N@bU5S^78WZ^z`-h_4fAm_xJbs`1twx`TF|$`}_O+{QUj>{r>*`|Ns9e zjNhFA000qmQchC<8z(A1NT{o>2q322n7Ds5&&T7Hvq_E z0sM5a6Sl4M6AW6;tJ7#UTgVeGz^~h5=ecTE4ASt_#2$cZPnLOm)2ex@BQHSrhJJm~ zvTa*gn3`Hp=&1TYMb|Ei`KD>6qL>gIO_`>J+^@RMLHV+Do>Lmy?yR0kr!#tNU%NxF za8-V2Kn||+S>@=!DaLRvK0hDN;klxQph|lO%658dbK^xGBgcv5<-`#glT`#I+KUMC zdpkROXJnKCdP%DJ!L({z&k3|mLDS}g6ujA8U2HYuto_L9t=wZN}0tiJ`v)R>1h)uvI2#K#5?&}K&-N}B> cVBqiG0De`Lwb`RaBme*a07*qoM6N<$f{hp1UjP6A literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/media-button-image.gif b/sources/wp-admin/images/media-button-image.gif new file mode 100644 index 0000000000000000000000000000000000000000..5e7e4265f8f40117642214da16e3cc88feb553a2 GIT binary patch literal 206 zcmZ?wbhEHb({UH^75LRnn#Zw-Mo3Tu(0s!*RLNxe*E#{$G30aK7amv z{`~n>t5)sXx9`}oW81cE+puB7zkmPUy?giP&!6n<>^E=TG&D3Y;0B66S-_GyAQEIJ z1FQD})xMO-xfxYmL9h3%t&s7_y}o&cM!@^;)`3bNHKe+o1(_~pSk3nCW?(3YSRb}Z j!Qf@p{<{u}PI|LXvUXLSO_SDQK9uCA&ZE^Pz+epkWp`Pm literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/media-button-music.gif b/sources/wp-admin/images/media-button-music.gif new file mode 100644 index 0000000000000000000000000000000000000000..0254a0881101b767577c82b30a7f6a7f522e6dad GIT binary patch literal 205 zcmV;;05bnaNk%w1VGIBa0K^{vm6et1>gt!5m#?p{v9YoH`}_3t^w-zdd3kxXw6ueR zgUZUvfq{Xir>C>Cv(nPiSy@@XzrU)gs)>n-`T6V!YA^8LW0018VEC2ui01N;O000F_;3s|sc6f=@ZR5AS@Y`-q`?j{W z@$vEO?Cj^~=l}ozA^8LW0018VEC2ui01W^Q000GY;3tY2F`lPjLFh+q0b~IVv~83q zT*w1(fXC&M5Cs^TLIqGMWFi=mN3!r(tpmqE^e`+sU~oqDQCt=Wj#@pKToeKaK{F`W vHJ*f{$Wcu)fEo@41t$^>8xb2A5iJM^3;>T8BL@ut1O^zJ1_S^d1t9=C?A334 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/media-button-video.gif b/sources/wp-admin/images/media-button-video.gif new file mode 100644 index 0000000000000000000000000000000000000000..50ac6e0283a959c8afe2d49dcc04ce12f5be6015 GIT binary patch literal 139 zcmZ?wbhEHblp9uU@UGsd@0=!TIy&>+0&V zv$K~kU*6Er@c;jR1_lPjpDaLkRD1&!vGO@CAXsUWLQ5?~Y?LdkEK*PQAL5XO^|*zP ze;nr99nc~oCI|vL!1pUyzVBE6B;+ZW)#O9k_noS$LYk0^jql$s&IF1il z(B!V`AagcNLrId5=XprEhy}}fSG-|$k#QiO9OK&f&tE8B0kfKn75-MaD6WbR#V0_G zp5r*Ot|k+iQNqo2-EV+FL+@Nx1CMbW37|Ihp2^EF3e*kJz?-zeu VdC9Lf9jyQW002ovPDHLkV1n4Ni%tLl literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/menu-2x.png b/sources/wp-admin/images/menu-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0038190a546788ecdca7b909a42d0766e5dd6243 GIT binary patch literal 30324 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 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/menu-shadow-rtl.png b/sources/wp-admin/images/menu-shadow-rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..fa9830cfceecea43b069bdfeaf176e50e6bde5a4 GIT binary patch literal 92 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Q+p0V3GAr}70DG3P)ZAoDYX^of8 h^eh&FK<8K{hJx=b8x8l(dkIv_;OXk;vd$@?2>^xR7=Qo( literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/menu-vs-2x.png b/sources/wp-admin/images/menu-vs-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..17309fccd03d3f87c8d2a65668422b19d070aca6 GIT binary patch literal 29592 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 Q|DLTRr!HG5Z65sp0Pifuy#N3J literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/menu-vs.png b/sources/wp-admin/images/menu-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..afdb3d3f012e2eaddf2f9040d5e3955e0c322e29 GIT binary patch literal 9320 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 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/menu.png b/sources/wp-admin/images/menu.png new file mode 100644 index 0000000000000000000000000000000000000000..52189c2aff6e227264bb6eb4b51fa4651ff01d8f GIT binary patch literal 9165 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 literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/no.png b/sources/wp-admin/images/no.png new file mode 100644 index 0000000000000000000000000000000000000000..59c35bdccc6d423e369eb9c947ae0f5ad04a5237 GIT binary patch literal 755 zcmWlXeN4=89LL}H^y|9o?tXf>r}ZQ=cWt2uk|Cw1TkRx0(6Gi9`9njqh8a<6D?&wS zwpz|pCDNm(x>{W9I_;!KU5#*zJd7m1zHP71<39WB^ZD#k5U-Dxh}0qg5?xG00=4YC z2zgX%{A8N}PFs9jVk8ZZ0|p=)Xwmwg6H93ZJe~vKIPc-LkV|zp7uQ(l8i}llb!?Y9 z9$u`?Qn|YUHo<&DIq+7%dE>yR{(BDitdb*e$^-I&BA^&31Ij6Z!4(@~E(4Xo6`%^J z2Cm8#29`BA%M5ZigF7i_ODpDmm3IVC)Ve zyAx|);Pz3a`jn9JIrHE&Fuhp&9ry|STC;Kn_)XF8_+8sId$xEEn2X*1ud$toq(mYk z3N`UsM7$Rfjh3vBCHhpdFN0*AB!`R0@pGiGl2q4_)>dK~B<3+@e(At1IMXlgp3ft|=)kDH+Y3klty& zkP=@K*mB}4Z=1E~;oqWrb4NS2Mg2(=k9S+9T{kwyEJMQe2ov*~Zej~cev^R%3o!TME=DTV&l29NNI<@7Oo_V|uSP2a}oUeHDABkIG` Ga{dF?bQEj= literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/post-formats-vs.png b/sources/wp-admin/images/post-formats-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e7e8d3fd2d27c2869153338c21ab5376ddbf83 GIT binary patch literal 2794 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 Npr>W5S)-1L_&-vr6_Nk| literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/press-this-2x.png b/sources/wp-admin/images/press-this-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c6b948c877244d4f84b420f64b9c9f13716d70a9 GIT binary patch literal 755 zcmV>5FVNoJo>*I3)9tLUuOspC$qR(T;cq6& z=kvh6quC6MXObVD67Z?3oLMG*gx1Ip6k_{^> zD~iYC8Xg`N5~HJ|;-|R}lt?7By}d19HoK5_6ZujFi%cSDi({Wx3^dQ z{rwsk7|_trkSFrRoO^F1l7`F;32z(yCjwhrTMs6cN{Nf^?CexmR~JhL5hOmDi+@MI zCH4Y4J39}Bwa!|W*=^L*)1!rj1<~VmKdJz4J=xpa)AaPT2akdI7r0S*^;z#MDMF7E zfxf;zk^TLBYY06~1X#P|;NZX-LXQ&xZa{K)c*u5mADo9fj}v;F2t=b%k)xv{YY06~ z1Ufo8MAGTBHH01~0&ImOlgVgiX6BFK_Xs^s1k9(SNH&|bhS1|gzb;wh(%p2-Mfti=3UESwrY?B2ZUXCvtv% zuDQ9n+i)D1?>$fGaUxJ#TPt#LabXRi$B95N7!vuiIL?qX){ch8++a{tlkbY68`|EyN4i*C33l4)^8QJyqSOYsx!c00W3py=dX z2$y78)`tKrgfN**q>9Dj*VW>K!9W%Wf&i=43cl}SKA&SYn_)a2V>B9}-|s_JRj_!W zPzXz<(zh5B7|Xx&1NIrc%BE>b(!x6*tUHJv|26H>vcLI zfODr4j_Yy2g&-`O5%qdK>~=fpq}gn8T+9Sy<6ytv<8U}2O;aREg6(!IA#ogM<3Ri~ z6hZt3_@d|_8vtJlyQhxFBlB5YdlWDf!W9j<|85Ay`(XY}xjz#p*v$j^*w6wI@+1da9{{R30A^!_lO;8|2 zVRT_wO;AHWcyM83Yh`pGVlqK6K_Vb{ZE#IZI!SJGbYX5|Wl2OmB6w|ZE@^3GIxsLX zLOC@zLozTnFflPjGG%ULJtA@KKQu*ag>%7N6B`GaEjae;4umypaF^I}5~I#sB~S literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/resize-rtl-2x.gif b/sources/wp-admin/images/resize-rtl-2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ca2a631b7c1a120bc86ec5348d6a67b9a10d7cf GIT binary patch literal 232 zcmVw6wI@+1da9{{R30A^!_lO;8|2 zVRT_wO;AHWcyM83Yh`pGVlqK6K_Vb{ZE#IZI!SJGbYX5|Wl2OmB6w|ZE@^3GIxsLX zLOC@!FfuSUFflPjGG%ULJtA@^QR< zO$bF|OTXGCrT8nge&nOzU&x1oU)q8aLDNzQ{#&t#0YMrW&zsroP9*4qd3)yG^X@(O z&EA_z4|H|sYe+5cl5mDSTPNlu*)v( z+E*t|YTN%IwV6>`5YHQ))0@o>$}o}}gxj<|{|kyV+;897zlr?%OT6G26M*tA5PMb- zo&juIC#f_>A%H6L?L1d@%ET8Wc0>Cw5|4&>A+QhSlH^<`e$Q}R$-hI~WsK(wtWza! z8}lQi(FmTfDoh-#_qjI+d-xcCKcc8_gx6oi%4{Luca-)H3jVhs`ud66h!=|HK$^If z&uY;f7!I-Wu~|+Jg*Y~1TbaQs-ffR&z9eRRMRm%FTouoHlgDJtzW}AIDy?_%J@=K7~i1UUV1Hz(K^8=D2iG)`0Y`3MSHHL z=Fwyh;eVfb9w}2qQnh200cF{;{7GVqZz4#zkxojfr>b8cxwmJo@2>f@6?N&<{f65! zQ8^U9adxAu@Tz55(W^Hiyy#^Mb&uMqrqwRB8=87V?NJY_eSABp4%SW#Q=y4-)a_Dz zo;BE*qPMEm-*meO`;C7Z_EJjN!Zi&|&Va02Dw>uE9O3pBcZB&SC}&IPKUo2O_kgBP z>$bIAFh`We<+`o>1#sv;&V+k)TPs^)*JWU7zfo}~tN9e=E>ITd+4n%Qx_t)5i+kXaL&inrV xSA75FZxpc#+_YrJgR?Qt=4$%($L32nez29uw#Izd`QmhQt09M@?LjV8( literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/se.png b/sources/wp-admin/images/se.png new file mode 100644 index 0000000000000000000000000000000000000000..eb487b4636adc76182cf5354745c275ccb8f4515 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2VGmzZ%#=aj&u?6^qxc>kDzqz?>(UI9!KoQ20 zAirP+hi5m^fE)!+7srr_Tdl_ofjW5(Ieh-_Z++v@3KxsND=P)7t~6(Y2Y=kfwmVZ$Q7I`Q?|9n*`!t0J*88 zenlnkG2|`)p~KjCUGv%WCz|)~M0SECKLUalApRwg{VS+HQOWxivgd)D2f)yKF{)O5 ziDv&SAoK~ay8kwbZ$P7bMIWMt@OI>;9mtFWEBh)D*Ck&!wcD(%XyKNXKuz)ik~vFK zZv%nONO+$9{~iq0RJ265&Rg`ui%h+|N8XU5dv6#T^&{rg8CC! z)t{s3Uxx_bhPgQc`#}8&dbL|j=`$VzSb9Y{lurz3zv@$`y@(6~*IsNG$`v?UQ=XDP zTL=k(4}q(u`boG!d7jqR(S*l==y$;Ub9F;Gf;}x3{mG8lDBydhZYW34)mqW`NiUYW zflE8;Cp-kobG1%1J!wGf1Tbf8jQQQ5ym0G8<7eJM^haR!sm2j`$v;f35skWC2o3@> zPu|HwC+M@=%%Sc&j3=)K_c${RXvCfo$Da+GsQ?Nbv5ZABw)JHjJ?|5MPbz)hI%)fs*M z9x+J(iyxHoq8^L3qTyjLf%0p;U&gsT#7a5;q;{f-^9I}+&Ja!QdMLl2$Y>`TIaM)& z%4Lrk5&Pw}_K#$3(f_?@WNh<;q%GPO)mn7h!ysxRK$!I|>LO64Q?H^%0y2KntEiJe zcIgNbQ!lXWF1?8wcqEJK8Az+&vgoMZMC}B!iv!q*VnIkU&+0{V3riLAF>vIToh&+} z7tuZfnFSl}h;>Oms@os5Xa~!zXP0nyWUqh5q7JP@jl}zP&_f`7`7o+Qv5;g@a84a` zG$M*dD5PdkD>94y+^!Ki8WE+DI(T0S$$xOakXFC1r!SVYG%}(Vmd*JGp>@#IVM(Ww z#bjeyDLA5?KUrTlnh9y;Yq_LN^(T{jznPiufs&w|m0Yr4%SWhLww-HcG>0^O z*7K;wFFXw;L5q<^uWK#Z%R42dK{v^=MlD6paZOdBcJ^u|x|M)H?BJCK-6V^i(@M09 z3;(@hJ?E!C5~@b!F=eY3qAo)0gsKZ>=E2WxK8@B2x>;`5rMBoM7AUTTD@G`DwXf>F zGBNeMC`nbfeY_D-Thv4#aq*>Ek3z;ybd=k>_u9oPd z1ft{HxMSuJ(dda)NZ~HLYKiV8AY*{%l|r82J+2Ic8lo&~=MGh37ct5UN{Q&d=ZrL2 TL7I?T00000NkvXXu0mjfn-y0e literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/stars-rtl-2x.png b/sources/wp-admin/images/stars-rtl-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9790115e833c2e2459b6be745ce4d7ff2a53df13 GIT binary patch literal 3212 zcmb_fdpwg1AD`rIQOWJl=1yg^F_+mU*)T;;XUfE3n2fQRVJ_hy<$jOcP8{pFCCQzT z6GFM9TuLrcF3GLlD4lx8>6BOR<)3$-&$H)wzQ6DH_xpXnpXb@n+F#lGg}e>*sV$-STn87PavIW9uSf< z&5;aYdC)m*006~8axOi{OcI#oLG|=Tve5Ed3?%1z6Nbuzw%dU{X|I1~<7=P=a0 z{XLl^mb$06!e34P?t>+JJ25D9CWYn+-t0?qr1>z>^75O5zJ9*!=|TTG$kY3aD~>-X zi$sUQAR5rGojF1j$0O35=1g(%$C8+23|s>SSBJsWHFODZ4I~VPM8Hwd9h`47x70=q zGKooJ5NI?i#*)G!Q$03s!EjCzu)nn18DGRG=%$NpuC^lETxbXWzuYn@F5hzf7rUF4 z@BMC~$de2TnUnKoni$TG-(lMvZqY6UcYqPJt24gU%p(dv6XveBp1$ zcJjaVxALSgzwWdH-l?+wR>yo@YdiQw@P7-N%%c2Oe*s}E z$AC7-su) zQMR}bt#s>7aCH)CHY?hI*vM3Zrb zW~yUC`CdR8H1Y8n!?{?$Q)UmslOyST7UIVwY5OPg<2C zScBk784DllrPnQVKC)vCuSpwvUZ^0(R2)9brxce58VXgs9+6u$@*%FnL`P0>A*|wq zf8C)GZnI1y1J668KK^G*FWpo^o)oHhIX(*z?mBmJ;IQjB(gt%*K(!09JSq8;^Au?9 z8NZ%d{7Y(ocmZ?cDDE(xDxCfUkA1qafzld@$mZ#qndb3%xp9DJ#_M#vP_7`Q60U9% zYf?rS{W*rg=GymJx<;9ZuH@@}6FJGllOc5HM)~Bfc2|3S_-c_TijX5Rh>3Z(lojuO zRU|*>0x`AJ?3~aM4Fyo)c_)H^;~FVk=K2-2_#}W%({=XlJ{4Kr(l)i!TEK*ifrOF0 za8IA(J0bzE-J--i25-1Mj}Bd-$u(90LyiJ5XImPMMi#I2hp}x&0QJEw0)#UQ#O3e} zdeHmcmMiIxBioz#C+c|q`1pesLumaV&K_zMrmsEORZFn`yinrS{s1&_tAe*tbIm37 z1fR$JhbG=i@#^r~2E}{cPb8M-F5Nsipibs(Oiy${?n;|me1#qoWJNgW?yvQ_AI4EHzI4*gL`hJQgJMrmtiTd2! zr;4bQ+?KI<+kjFd-e9*0iRSFg<8?)qEj4j<^CJWQ@ZT8BJ+X0FC6L9evgLb>i0h1f zC61uzK64vVFLswsk@~}>KiBs(Ir&Gz58{0-y=8UD(~E-Db=R^ks3Tn+YGwppCN@cg z?ipRnO3e>{u5T0Wv{2-b#do`)m0fss_{FXM3t5vgKA_am$T3Wm0=KO>?5!Qal5X0X znOod8QB+U0M!gfLhK=qOQ^s+>rudC_1Mc!<1di@PEg$|R8BZ%=TGVLE2(O9*Q}JL2 zGnJ_a^4|P1y;#(S6)#H7qu}9;5M4X3uB|tC=Tid@vuxrvFZ^?m_ z?iYEqD91s+hY;nla)JdZ8Oi(c91d7Zv)0g3P{8exH7p6vPD<97Y*>!Ery*>{4wv=x z`e;5?`Ziv~+r3&XEs__wS5DCW)Ub2%es`~s+vciz=vm)3Wt5fqXtM&aD0KB&4P@+8 zA`Tz79Gd;`hS)W>@qKFauwv)f`M!`^2;1YjpUVO;TFm9g(uwOQ7hY7Lem!K;TNXYm zC3Hr+K+!05w(f213&HV>Ffkk>$4nA$bn!P>-{i};QNA8`4h<>=IbP|LaP>=SHT+$d z=d2bPAg!Yntcsz}D_yexh)N^R9RW(xfSgK3N-t2UMNP zTU7ssUB70!NcI7dL}cL_a!KNsSm?l2HF80=bRL9V_S#@oG%+i3X`VZ}Rl?tW>ST(7 zrWYoGUxj-dm7&HzS0#n~prKg5k}0T!mdkmVI70hyKzj6b-fs!Yj5oD1($hGvveM

KT58(gy(l_99#ePYmZ>^7nS)?Pm+!Zf&>ncr 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 ZCMTt#E3cbbe|7_0GrfMf&e$vA{{f>^-#7pO literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/wp-badge.png b/sources/wp-admin/images/wp-badge.png new file mode 100644 index 0000000000000000000000000000000000000000..ce675451ea48f763ebd2e55ec3ea8f435622b460 GIT binary patch literal 12099 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 P@qi~f2HMq{c2WNiin!l^ literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/wp-logo-2x.png b/sources/wp-admin/images/wp-logo-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a8dad4f3e40a3d2cac540ecf8b5e53679846f1c3 GIT binary patch literal 1806 zcmV+p2l4ocP)UYpee6S}y!0pZxvKimf6z8NVY9*5#$Xm3Y_r-dA%uMiB@iHi zEM#lQNOL~t@RMK{&k?%d8GvDmz+z*IoPi#&~{E+#3W+!tW z^IhgmFrKwFCuAVISG{`y{+!usNj5AxGwuEhT^+r%GcymCmzHK}dpiuqGuH4QWFU(@ z*!yn{0PrWwHmk`PY^bfdz7Y-6&F3!0pq5T1GcTGn<5ve<*Y&;eb0GeGsa zFW;ThzrMaU0;LNJ^K`N20@+h7WJrjm#JCuRv4;O3v$(K8Anb(>=z3Q)b_4&`Vlqy4 zb+liFk`Q~=)KEuB8mN(f!AXg63Tx|-fvoIVUt1#(bg|AC&>e{vQ^L<0#pXKqh0Na7vP4SJwV#gW}nc6J$;{NUA{43Eh#A(1U-3P_eaFuwmd~zknL! z)H|YtwfdQ=D46qgEx$f7W3xfT=eiuc5ByTBPvY>?~cr*iEh+hbS)axcI$?rl+SAIT(G3*IQf8klADu*<@n^ z&9Ond5wL&>Y=H0MVp&G-Zf$KTg2CV%*Fij`noX3>EtY0Alf{%o73F0VN!6!ManTte z16hecU3FEI+!}Yr#>U1Nh83`3z|Ss6)_r1n{ODnnXBjpt*;r|&Jq--yV#LbIiXuDs zc!12jZcj@UIXmyOun`mExF5PCKvQnQSSLQ1wU;z`@FyLlzZgyamJxa5t z(2(D+Y#4j~oKuiY4p!)LW>Kyqld|kKDlhR;B$bzXDU%JzVM8I8%?{ZtCKT!45#ifUv-FaH+Q_Dh-GXB7j+dUlb>3 zd~8gS#oTakx?ljJaI&m~!r>4*;YT#MKr@sSC`AZsJ(6PxO)843Dl0gz*&Kmf@^Bgg zfdJ=pf+|mzD{?QUrzOlDmy;vlpsvmi0yQ@^LNB5aRfOJay;r)?8cwzj9>R#ub8Qj* zdk-msXFP~XF{W9j9bU;8)(D{n5b_V^IvJsGD1@kirJH~SOknE<5qkbC=g=d0EXw!b zFwxI&3?xx@CcPuuL~Sp*9fKz|*Jn=kO3B1-YnUga55OJDM9C2vlENEpmK2LZ_&sSUZdgo9b(O zcdYjn6;N?O9xJF<6r(#}9IC&q^>=wLVJ{I0^tkR$D8p)SU_kPn=gx(U=mr4`hf&mV zjH8l6h5~|e-sGk=e%A=O#)*g2u#ts4`FyAcgjzzYr&~9#%V~I%jn+CsbO8gGRbamJ zLIQ740|j|*QJ^Du#Ho1%&!sbJt54G@Hlobug<<;E1>=-dA{2cgQLo{H=R42!YF9ET z#>xt{&30OI| zPyEVxj&Rp;=rselsOso+#Yq?@*LaO^t&6;tA9$}16HdV$`7qH@J6AsrBpk;$Icu3q zeMLx@wCJl>FZHuyglnnqeLhSgYr>B1z#R^~OB&&W1IIURJ7C=Xv4#l;f-Lr6FLXfH z|N3z{H#>8mM=@@kVKAPt_MbmanLcLzjQI=Zub97KJ^=o7|NifO`tgS&M-Ki{Z-|TW wGY>NWf$@wr{0AAx?(BmO=z>n@28JHNklY^0t}32h5=>(33ge;q^lk6s0K$y4}ZQ1O@zE2zXX^6i?W_~Wg>N$|^ z8q93$Y#W_j>T!E~b6Z>Rv++H*@jLcmU+%+w|62h}{B^R7y@|Gk*B#B**ZqM>5Vpux z*8I5rU>>*b&I%iuS>!f;C&0ekhx>92j`g$xq@(Wq@tLY#&)UWq2-8ce$hmS8u|@~N z6U+#YFN7?iKv+b40k`ox_90&{7~Gd*aI7cI#%|=wy@}ST^!iWQ!J}RGVnYOpVcWh>688wx7H#{m0N1rHNWrn0gSmDSknz*(>d%5Bm%aHe z)Nh=I;&=|^w8kghNfo4 zv)i+Z`wJeZk}bmbU`io&196Np7jsGl;@)*^gW3Hj828M}eGn3K7ge9sROEUR3*p;I=!u#DLFTtp?) zI;WIEmQsx9Bs2bIsY57qj!RG_7C?T|PQE2jkdSys6GE}3+C{9vovH)W_B6TIuB%0t}UIBv>JTAos=3-9fW&yJsn*n$K)EtzwzQ^qi zkis7b;IM&~fr5pnRw6953UZo-m}E0%7avcu`WpjO1?M3%xP-5qu4;&l=-g@PYLG($tF>LQe;*&Lzz;9h}3d~rBy?2EJJLH6(e`2AjN}4 z57mD@BJ~auP$B%(RF?hY!Vj5LCH(%Q;rn1t=H3?2ac2rjnm!GUz|qzXDcT3dS)2$M zo>nEUN8hW2&+A1f{&emFqIJcPky!RSm}K;Oj)+~Y^&8>#l z>lJJIqBa)~Da(U+L{t6CtYXB_NcU5o+?lus--aKD3`NlBiXfvwG8c0)_hTE8q3&a- zj7~BKesao*Kwx`k6yNqACgmYkXTy8{XaVC$MlmIAAqqa|gcMmdEr`>a@Q1Sw_bL2n2-vF|P(udI!gR;(r&@6=3uTT9ZL67a?Aw}rK~!d>UMl)0YT6P zfjPgXPyeFo7Vd zKc$kQ(MD(0l7P#QpKU_a+YL~ks>H$cQd;8;1mWHAhaSr{U+Tx?NOnz^_%V?niK--u zc1uNCIf=L^ghZv5izJInFT>FEg7o}1_Vb*Y&M)(05}FfPTpfIdx)^T&o@o) z3>*KZaU1V&0_@9uxG%@xSpV0b(=qpQw|m7m55UjH_uTeB|C|!OM)oY(x5=I(izL&q zJ+tQ<2fq2M*N%Pnm8^>I9m^Xe8zKU*@jbWkJN9AUU_Xw*u{b8jW)3OmzW^b~mFN^A RrQiSn002ovPDHLkV1nUL@5KNB literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/wp-logo-vs.png b/sources/wp-admin/images/wp-logo-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..a6197620504050e8f8b8f3d8e48f401194085cee GIT binary patch literal 751 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 SZEl;GO#+TWWmJj~^ZyTE{8Q5a literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/wpspin_light.gif b/sources/wp-admin/images/wpspin_light.gif new file mode 100644 index 0000000000000000000000000000000000000000..e10b97ff9d84d7ff8d7efe5c4c09783dd390e338 GIT binary patch literal 2193 zcmai#eNYtl8ON7(yJ6M6J=n0lMb_k8_Sd=PxP4*6q$V@fTkd$f1L8|!_`^Xw3?Nkk zC~rnNUV;$tr4l4p@CCR74h~C3V$$*262*vAVuOO9F=^{`jLEdlbka`yN0YrH{R4+i zKYO$L&)&@Qd4Au0p44>vi$C3^hxE`L2>MRrpJD#C#9u-@(0)tI%{|brFf(B$XJ#ff z!neubWH8KlFgU(MU_3BB9$3Qb4TP?MS0jA$c6+;*=;+X%9bwwSG`6)hhN%rx9zrV( z`hOU|Ta#tmwpHDnW0Ni7stE0U8AyT5q5p<7A@qYyo)eU5%q72Sl1mQe^)ydB z`SS9{o7alJO>^Lgb;EdZWTwCI-|IkR2DcbLR~R4Xo1bpfM@9-Z_5djw3Bo8~hYg%S z9p#NqBNqW-7U?J<>6|(Vf?!D^_2uVOT@nGE5ey`m(4iVdp5iSW7^kII2u23Llu=I2 z(B=VwodQXuV*iw881{Dcn@X+_N8f*NTPnzsc=mIUkhH^TwOP`B>rgj`RDSf7%7tYr z`F-gdqQ3f_rqcRCk=ci;YFH(8H?AWcno4r@%NtC0r&Cz{TEX@TL5aqLMgc!ea{^70 zAr%0_nhJF?tkQ)@-4u29d>`x;)(x693l4%j9H8lJ<{*O+&r&I$o#^b`3DC}rZepD^l?;g@|32TV~aZNyQ4R*PCVW$pR6*xek#2p z*6)7>ix2yhh<$SUE+A zJl3Gd%yTT8f;Zg12&+D=Wo@O?_OKlFLm$VxKvIE2x{Qamm{6^{srfOJ~YD>iv@x*qQU^lWMR*DmuX zE&U%?6pY@QdN{${*!bnzL~uWOy=!rh%>N9u+wUo{!TT5O`MsmlPcRHuKvR|C)_Pr~ zDJbS9z8z((6%5H$au|ZPT15qcA$SNG&e%yngMQ4kPc&dd4VlZj`rkq-wXTA`cDZw= zH2t0SjXi5WtAA5U{q)h~miHX5s^84Uyb~}#Xelj_qfSfHf0jy;n*YA~W`EfiML1qz zQp`u{+zL-tRGKiX*n&Wjf`d3=l~!qn2XOR+Xk{bdp;ZWijyeE3G!np%oW@6#IInfZ zyp=8G?KNN48~w7**>_St^~V>TIYrIIW6zG|{K zZbu^wLFIOWIHF)s#J(n?zyQN`k;HM``?RN%jhu2b@%myx*{&)`BK5&5RgB z=vj^w(2o=#ioCu#YDnP#g3fDaevjZwm0S~kcL668Tv=jpfn-~qsy2Z3|Br-)4wl;b z2M37RdtIT|5;4*A?oI@%vlYj-zkKD#5qtA$e#X#=tp53(j)lQlDS46e-5Q^&D@5Ei zD&3@@?(H=)^)_DLpgAzsY+a3HASqzQvK5m`dSe_Y=Ere@@Fvs{!vTV7uo}scOO6#o zwqL8|A2;Hm_VZi1dNC*`v%IKmHC)$x~ecdHdeT3e3rlgwcr^{9j zSJe;040k{8u4am``YjNoxURu&F$eBo@9H~6eKfbYciUHOjw{C|Zi)UJ(D_6<;`xsi zt3Ol^7sNilPG+n>l94Kf+|CaF+O#SYFRF?pxPGi!S4i=)hq2#6@klklFH%S%)2*P)EP^gW#~vR42A literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/xit-2x.gif b/sources/wp-admin/images/xit-2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..64ab2ce789b4553820bcb932f5688ea2ea0376ed GIT binary patch literal 823 zcmdVX=}VJw0KoCzGaipUu1)2crcRpI6wM=>S9UxKra?vNH0o9Qrszd1Fi9er8)Av! zNb?|*$5EosLLvi|4BW{M+B#&Ly4fZgxT)yevm@OW{uzD$gAd=@E0@bFnsWdO{$M~Z zm%ID>wOXy;@Au$%(Czk&kLz?gpU)TE-w%aCHk-{iKkrv4!l97GV$tjM3WdVybZ%{J zkyBF!gW+&x#b`ACU0x;$B7Afd+}-thz3#z5&%1XABO`~as~Z~|>+9?8p`k;Y%`cN} zZ*NlK zJ9{uZd@weq(P&7LRH;;EvpF0Nga5g-01N?ufz!u`<0l|0EWm_9gu`IQ#W5KiMARpu zXVTD;5|oxn7x%Fe0X~i=vPOj|Nf03=l2RtpiX}6kIBhg98gt;+nQRaz4g1Z zgG=Gs>t@b~BO%&-P=5mJk(H-Tfb8pyy(+9s%^zYc3163!-=4yE&R)a6mNDwt>6HA5 zbXHBvk4`f$;SIa}9Nk{cXuxh%FvO0?wkP==JkSW$#%x+r1s|)bm|ZNkgn_`I@*mW? BI+Oqa literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/xit.gif b/sources/wp-admin/images/xit.gif new file mode 100644 index 0000000000000000000000000000000000000000..80c251fdd75c5a9a960b87e4120509a1100e131b GIT binary patch literal 182 zcmZ?wbhEHb6k*_E*v!E2Y4YUH^X7fqzWv9E6F)Cs{&nNV|NsAAzI^%Y*|P@^9$dS2 z?Zk-_hYlSA3NnC!;!hSv1_oXR9S{#>1_Mj-hOLXQ1-YM6auR5rW{@(|gL%Qa!$%}I zIwj5oGO#TaVhhmdk#sr{z`ET>9X{ ht8-b~4Q^eRnCh|IEo*6(r-qn>6t9e&f{-ACH2~T}Oo9La literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/yes.png b/sources/wp-admin/images/yes.png new file mode 100644 index 0000000000000000000000000000000000000000..fbb39836bbdf6c9931e9f846776d28c6c0157a87 GIT binary patch literal 539 zcmV+$0_6RPP)rrT_844hyuh_-TydG@=!*>!j8|8=)k{x|K{|0ceg z-9~AvFq>Sf_{CL^mj2JWknrF9q{e^!4NCu6eVFgCc`$Im1Cc$5bxGQm*ngE5^Zzft zKllIq`!oJ)G%J5mtyOrm;OWf&CATyGd)~18Z+pn_KU+BSU5+$}%_yadd_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

' . __('This screen lists links to plugins to import data from blogging/content management platforms. Choose the platform you want to import from, and click Install Now when you are prompted in the popup window. If your platform is not listed, click the link to search the plugin directory for other importer plugins to see if there is one for your platform.') . '

' . + '

' . __('In previous versions of WordPress, all importers were built-in. They have been turned into plugins since most people only use them once or infrequently.') . '

', +) ); + +get_current_screen()->set_help_sidebar( + '

' . __('For more information:') . '

' . + '
' . + '

' . __('Support Forums') . '

' +); + +if ( current_user_can( 'install_plugins' ) ) + $popular_importers = wp_get_popular_importers(); +else + $popular_importers = array(); + +// Detect and redirect invalid importers like 'movabletype', which is registered as 'mt' +if ( ! empty( $_GET['invalid'] ) && isset( $popular_importers[ $_GET['invalid'] ] ) ) { + $importer_id = $popular_importers[ $_GET['invalid'] ]['importer-id']; + if ( $importer_id != $_GET['invalid'] ) { // Prevent redirect loops. + wp_redirect( admin_url( 'admin.php?import=' . $importer_id ) ); + exit; + } + unset( $importer_id ); +} + +add_thickbox(); +wp_enqueue_script( 'plugin-install' ); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); +$parent_file = 'tools.php'; +?> + +
+ +

+ +

%s importer is invalid or is not installed.'), esc_html( $_GET['invalid'] ) ); ?>

+ +

+ + $pop_data ) { + if ( isset( $importers[ $pop_importer ] ) ) + continue; + if ( isset( $importers[ $pop_data['importer-id'] ] ) ) + continue; + $importers[ $pop_data['importer-id'] ] = array( $pop_data['name'], $pop_data['description'], 'install' => $pop_data['plugin-slug'] ); +} + +if ( empty( $importers ) ) { + echo '

' . __('No importers are available.') . '

'; // TODO: make more helpful +} else { + uasort($importers, create_function('$a, $b', 'return strnatcasecmp($a[0], $b[0]);')); +?> + + + $data) { + $action = ''; + if ( isset( $data['install'] ) ) { + $plugin_slug = $data['install']; + if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_slug ) ) { + // Looks like Importer is installed, But not active + $plugins = get_plugins( '/' . $plugin_slug ); + if ( !empty($plugins) ) { + $keys = array_keys($plugins); + $plugin_file = $plugin_slug . '/' . $keys[0]; + $action = '' . $data[0] . ''; + } + } + if ( empty($action) ) { + if ( is_main_site() ) { + $action = '' . $data[0] . ''; + } else { + $action = $data[0]; + $data[1] = sprintf( __( 'This importer is not installed. Please install importers from the main site.' ), get_admin_url( $current_site->blog_id, 'import.php' ) ); + } + } + } else { + $action = "{$data[0]}"; + } + + $alt = $alt ? '' : ' class="alternate"'; + echo " + + + + "; + } +?> + +
$action{$data[1]}
+' . sprintf( __('If the importer you need is not listed, search the plugin directory to see if an importer is available.'), esc_url( network_admin_url( 'plugin-install.php?tab=search&type=tag&s=importer' ) ) ) . '

'; +?> + +
+ +id and the JS global 'pagenow' + if ( ! empty($_POST['screen_id']) ) + $screen_id = sanitize_key($_POST['screen_id']); + else + $screen_id = 'front'; + + if ( ! empty($_POST['data']) ) { + $data = wp_unslash( (array) $_POST['data'] ); + + /** + * Filter Heartbeat AJAX response in no-privilege environments. + * + * @since 3.6.0 + * + * @param array|object $response The no-priv Heartbeat response object or array. + * @param array $data An array of data passed via $_POST. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_nopriv_received', $response, $data, $screen_id ); + } + + /** + * Filter Heartbeat AJAX response when no data is passed. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_nopriv_send', $response, $screen_id ); + + /** + * Fires when Heartbeat ticks in no-privilege environments. + * + * Allows the transport to be easily replaced with long-polling. + * + * @since 3.6.0 + * + * @param array|object $response The no-priv Heartbeat response. + * @param string $screen_id The screen id. + */ + do_action( 'heartbeat_nopriv_tick', $response, $screen_id ); + + // send the current time according to the server + $response['server_time'] = time(); + + wp_send_json($response); +} + +/* + * GET-based Ajax handlers. + */ +function wp_ajax_fetch_list() { + global $wp_list_table; + + $list_class = $_GET['list_args']['class']; + check_ajax_referer( "fetch-list-$list_class", '_ajax_fetch_list_nonce' ); + + $wp_list_table = _get_list_table( $list_class, array( 'screen' => $_GET['list_args']['screen']['id'] ) ); + if ( ! $wp_list_table ) + wp_die( 0 ); + + if ( ! $wp_list_table->ajax_user_can() ) + wp_die( -1 ); + + $wp_list_table->ajax_response(); + + wp_die( 0 ); +} +function wp_ajax_ajax_tag_search() { + global $wpdb; + + if ( isset( $_GET['tax'] ) ) { + $taxonomy = sanitize_key( $_GET['tax'] ); + $tax = get_taxonomy( $taxonomy ); + if ( ! $tax ) + wp_die( 0 ); + if ( ! current_user_can( $tax->cap->assign_terms ) ) + wp_die( -1 ); + } else { + wp_die( 0 ); + } + + $s = wp_unslash( $_GET['q'] ); + + $comma = _x( ',', 'tag delimiter' ); + if ( ',' !== $comma ) + $s = str_replace( $comma, ',', $s ); + if ( false !== strpos( $s, ',' ) ) { + $s = explode( ',', $s ); + $s = $s[count( $s ) - 1]; + } + $s = trim( $s ); + if ( strlen( $s ) < 2 ) + wp_die(); // require 2 chars for matching + + $results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false ) ); + + echo join( $results, "\n" ); + wp_die(); +} + +function wp_ajax_wp_compression_test() { + if ( !current_user_can( 'manage_options' ) ) + wp_die( -1 ); + + if ( ini_get('zlib.output_compression') || 'ob_gzhandler' == ini_get('output_handler') ) { + update_site_option('can_compress_scripts', 0); + wp_die( 0 ); + } + + if ( isset($_GET['test']) ) { + header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' ); + header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); + header( 'Cache-Control: no-cache, must-revalidate, max-age=0' ); + header( 'Pragma: no-cache' ); + header('Content-Type: application/x-javascript; charset=UTF-8'); + $force_gzip = ( defined('ENFORCE_GZIP') && ENFORCE_GZIP ); + $test_str = '"wpCompressionTest Lorem ipsum dolor sit amet consectetuer mollis sapien urna ut a. Eu nonummy condimentum fringilla tempor pretium platea vel nibh netus Maecenas. Hac molestie amet justo quis pellentesque est ultrices interdum nibh Morbi. Cras mattis pretium Phasellus ante ipsum ipsum ut sociis Suspendisse Lorem. Ante et non molestie. Porta urna Vestibulum egestas id congue nibh eu risus gravida sit. Ac augue auctor Ut et non a elit massa id sodales. Elit eu Nulla at nibh adipiscing mattis lacus mauris at tempus. Netus nibh quis suscipit nec feugiat eget sed lorem et urna. Pellentesque lacus at ut massa consectetuer ligula ut auctor semper Pellentesque. Ut metus massa nibh quam Curabitur molestie nec mauris congue. Volutpat molestie elit justo facilisis neque ac risus Ut nascetur tristique. Vitae sit lorem tellus et quis Phasellus lacus tincidunt nunc Fusce. Pharetra wisi Suspendisse mus sagittis libero lacinia Integer consequat ac Phasellus. Et urna ac cursus tortor aliquam Aliquam amet tellus volutpat Vestibulum. Justo interdum condimentum In augue congue tellus sollicitudin Quisque quis nibh."'; + + if ( 1 == $_GET['test'] ) { + echo $test_str; + wp_die(); + } elseif ( 2 == $_GET['test'] ) { + if ( !isset($_SERVER['HTTP_ACCEPT_ENCODING']) ) + wp_die( -1 ); + if ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && function_exists('gzdeflate') && ! $force_gzip ) { + header('Content-Encoding: deflate'); + $out = gzdeflate( $test_str, 1 ); + } elseif ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode') ) { + header('Content-Encoding: gzip'); + $out = gzencode( $test_str, 1 ); + } else { + wp_die( -1 ); + } + echo $out; + wp_die(); + } elseif ( 'no' == $_GET['test'] ) { + update_site_option('can_compress_scripts', 0); + } elseif ( 'yes' == $_GET['test'] ) { + update_site_option('can_compress_scripts', 1); + } + } + + wp_die( 0 ); +} + +function wp_ajax_imgedit_preview() { + $post_id = intval($_GET['postid']); + if ( empty($post_id) || !current_user_can('edit_post', $post_id) ) + wp_die( -1 ); + + check_ajax_referer( "image_editor-$post_id" ); + + include_once( ABSPATH . 'wp-admin/includes/image-edit.php' ); + if ( ! stream_preview_image($post_id) ) + wp_die( -1 ); + + wp_die(); +} + +function wp_ajax_oembed_cache() { + global $wp_embed; + + $return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0'; + wp_die( $return ); +} + +function wp_ajax_autocomplete_user() { + if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) ) + wp_die( -1 ); + + /** This filter is documented in wp-admin/user-new.php */ + if ( ! is_super_admin() && ! apply_filters( 'autocomplete_users_for_site_admins', false ) ) + wp_die( -1 ); + + $return = array(); + + // Check the type of request + if ( isset( $_REQUEST['autocomplete_type'] ) ) + $type = $_REQUEST['autocomplete_type']; + else + $type = 'add'; + + // Exclude current users of this blog + if ( isset( $_REQUEST['site_id'] ) ) + $id = absint( $_REQUEST['site_id'] ); + else + $id = get_current_blog_id(); + + $include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() ); + $exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() ); + + $users = get_users( array( + 'blog_id' => false, + 'search' => '*' . $_REQUEST['term'] . '*', + 'include' => $include_blog_users, + 'exclude' => $exclude_blog_users, + 'search_columns' => array( 'user_login', 'user_nicename', 'user_email' ), + ) ); + + foreach ( $users as $user ) { + $return[] = array( + /* translators: 1: user_login, 2: user_email */ + 'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ), + 'value' => $user->user_login, + ); + } + + wp_die( json_encode( $return ) ); +} + +function wp_ajax_dashboard_widgets() { + require_once ABSPATH . 'wp-admin/includes/dashboard.php'; + + switch ( $_GET['widget'] ) { + case 'dashboard_incoming_links' : + wp_dashboard_incoming_links(); + break; + case 'dashboard_primary' : + wp_dashboard_primary(); + break; + case 'dashboard_secondary' : + wp_dashboard_secondary(); + break; + case 'dashboard_plugins' : + wp_dashboard_plugins(); + break; + } + wp_die(); +} + +function wp_ajax_logged_in() { + wp_die( 1 ); +} + +/* + * Ajax helper. + */ + +/** + * Sends back current comment total and new page links if they need to be updated. + * + * Contrary to normal success AJAX response ("1"), die with time() on success. + * + * @since 2.7 + * + * @param int $comment_id + * @return die + */ +function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) { + $total = isset( $_POST['_total'] ) ? (int) $_POST['_total'] : 0; + $per_page = isset( $_POST['_per_page'] ) ? (int) $_POST['_per_page'] : 0; + $page = isset( $_POST['_page'] ) ? (int) $_POST['_page'] : 0; + $url = isset( $_POST['_url'] ) ? esc_url_raw( $_POST['_url'] ) : ''; + + // JS didn't send us everything we need to know. Just die with success message + if ( !$total || !$per_page || !$page || !$url ) + wp_die( time() ); + + $total += $delta; + if ( $total < 0 ) + $total = 0; + + // Only do the expensive stuff on a page-break, and about 1 other time per page + if ( 0 == $total % $per_page || 1 == mt_rand( 1, $per_page ) ) { + $post_id = 0; + $status = 'total_comments'; // What type of comment count are we looking for? + $parsed = parse_url( $url ); + if ( isset( $parsed['query'] ) ) { + parse_str( $parsed['query'], $query_vars ); + if ( !empty( $query_vars['comment_status'] ) ) + $status = $query_vars['comment_status']; + if ( !empty( $query_vars['p'] ) ) + $post_id = (int) $query_vars['p']; + } + + $comment_count = wp_count_comments($post_id); + + if ( isset( $comment_count->$status ) ) // We're looking for a known type of comment count + $total = $comment_count->$status; + // else use the decremented value from above + } + + $time = time(); // The time since the last comment count + + $x = new WP_Ajax_Response( array( + 'what' => 'comment', + 'id' => $comment_id, // here for completeness - not used + 'supplemental' => array( + 'total_items_i18n' => sprintf( _n( '1 item', '%s items', $total ), number_format_i18n( $total ) ), + 'total_pages' => ceil( $total / $per_page ), + 'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ), + 'total' => $total, + 'time' => $time + ) + ) ); + $x->send(); +} + +/* + * POST-based Ajax handlers. + */ + +function _wp_ajax_add_hierarchical_term() { + $action = $_POST['action']; + $taxonomy = get_taxonomy(substr($action, 4)); + check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name ); + if ( !current_user_can( $taxonomy->cap->edit_terms ) ) + wp_die( -1 ); + $names = explode(',', $_POST['new'.$taxonomy->name]); + $parent = isset($_POST['new'.$taxonomy->name.'_parent']) ? (int) $_POST['new'.$taxonomy->name.'_parent'] : 0; + if ( 0 > $parent ) + $parent = 0; + if ( $taxonomy->name == 'category' ) + $post_category = isset($_POST['post_category']) ? (array) $_POST['post_category'] : array(); + else + $post_category = ( isset($_POST['tax_input']) && isset($_POST['tax_input'][$taxonomy->name]) ) ? (array) $_POST['tax_input'][$taxonomy->name] : array(); + $checked_categories = array_map( 'absint', (array) $post_category ); + $popular_ids = wp_popular_terms_checklist($taxonomy->name, 0, 10, false); + + foreach ( $names as $cat_name ) { + $cat_name = trim($cat_name); + $category_nicename = sanitize_title($cat_name); + if ( '' === $category_nicename ) + continue; + if ( !$cat_id = term_exists( $cat_name, $taxonomy->name, $parent ) ) + $cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) ); + if ( is_wp_error( $cat_id ) ) + continue; + else if ( is_array( $cat_id ) ) + $cat_id = $cat_id['term_id']; + $checked_categories[] = $cat_id; + if ( $parent ) // Do these all at once in a second + continue; + ob_start(); + wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name, 'descendants_and_self' => $cat_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids )); + $data = ob_get_contents(); + ob_end_clean(); + $add = array( + 'what' => $taxonomy->name, + 'id' => $cat_id, + 'data' => str_replace( array("\n", "\t"), '', $data), + 'position' => -1 + ); + } + + if ( $parent ) { // Foncy - replace the parent and all its children + $parent = get_term( $parent, $taxonomy->name ); + $term_id = $parent->term_id; + + while ( $parent->parent ) { // get the top parent + $parent = get_term( $parent->parent, $taxonomy->name ); + if ( is_wp_error( $parent ) ) + break; + $term_id = $parent->term_id; + } + + ob_start(); + wp_terms_checklist( 0, array('taxonomy' => $taxonomy->name, 'descendants_and_self' => $term_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids)); + $data = ob_get_contents(); + ob_end_clean(); + $add = array( + 'what' => $taxonomy->name, + 'id' => $term_id, + 'data' => str_replace( array("\n", "\t"), '', $data), + 'position' => -1 + ); + } + + ob_start(); + wp_dropdown_categories( array( + 'taxonomy' => $taxonomy->name, 'hide_empty' => 0, 'name' => 'new'.$taxonomy->name.'_parent', 'orderby' => 'name', + 'hierarchical' => 1, 'show_option_none' => '— '.$taxonomy->labels->parent_item.' —' + ) ); + $sup = ob_get_contents(); + ob_end_clean(); + $add['supplemental'] = array( 'newcat_parent' => $sup ); + + $x = new WP_Ajax_Response( $add ); + $x->send(); +} + +function wp_ajax_delete_comment() { + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + if ( !$comment = get_comment( $id ) ) + wp_die( time() ); + if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) ) + wp_die( -1 ); + + check_ajax_referer( "delete-comment_$id" ); + $status = wp_get_comment_status( $comment->comment_ID ); + + $delta = -1; + if ( isset($_POST['trash']) && 1 == $_POST['trash'] ) { + if ( 'trash' == $status ) + wp_die( time() ); + $r = wp_trash_comment( $comment->comment_ID ); + } elseif ( isset($_POST['untrash']) && 1 == $_POST['untrash'] ) { + if ( 'trash' != $status ) + wp_die( time() ); + $r = wp_untrash_comment( $comment->comment_ID ); + if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'trash' ) // undo trash, not in trash + $delta = 1; + } elseif ( isset($_POST['spam']) && 1 == $_POST['spam'] ) { + if ( 'spam' == $status ) + wp_die( time() ); + $r = wp_spam_comment( $comment->comment_ID ); + } elseif ( isset($_POST['unspam']) && 1 == $_POST['unspam'] ) { + if ( 'spam' != $status ) + wp_die( time() ); + $r = wp_unspam_comment( $comment->comment_ID ); + if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'spam' ) // undo spam, not in spam + $delta = 1; + } elseif ( isset($_POST['delete']) && 1 == $_POST['delete'] ) { + $r = wp_delete_comment( $comment->comment_ID ); + } else { + wp_die( -1 ); + } + + if ( $r ) // Decide if we need to send back '1' or a more complicated response including page links and comment counts + _wp_ajax_delete_comment_response( $comment->comment_ID, $delta ); + wp_die( 0 ); +} + +function wp_ajax_delete_tag() { + $tag_id = (int) $_POST['tag_ID']; + check_ajax_referer( "delete-tag_$tag_id" ); + + $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag'; + $tax = get_taxonomy($taxonomy); + + if ( !current_user_can( $tax->cap->delete_terms ) ) + wp_die( -1 ); + + $tag = get_term( $tag_id, $taxonomy ); + if ( !$tag || is_wp_error( $tag ) ) + wp_die( 1 ); + + if ( wp_delete_term($tag_id, $taxonomy)) + wp_die( 1 ); + else + wp_die( 0 ); +} + +function wp_ajax_delete_link() { + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + check_ajax_referer( "delete-bookmark_$id" ); + if ( !current_user_can( 'manage_links' ) ) + wp_die( -1 ); + + $link = get_bookmark( $id ); + if ( !$link || is_wp_error( $link ) ) + wp_die( 1 ); + + if ( wp_delete_link( $id ) ) + wp_die( 1 ); + else + wp_die( 0 ); +} + +function wp_ajax_delete_meta() { + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + check_ajax_referer( "delete-meta_$id" ); + if ( !$meta = get_metadata_by_mid( 'post', $id ) ) + wp_die( 1 ); + + if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $meta->post_id, $meta->meta_key ) ) + wp_die( -1 ); + if ( delete_meta( $meta->meta_id ) ) + wp_die( 1 ); + wp_die( 0 ); +} + +function wp_ajax_delete_post( $action ) { + if ( empty( $action ) ) + $action = 'delete-post'; + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + check_ajax_referer( "{$action}_$id" ); + if ( !current_user_can( 'delete_post', $id ) ) + wp_die( -1 ); + + if ( !get_post( $id ) ) + wp_die( 1 ); + + if ( wp_delete_post( $id ) ) + wp_die( 1 ); + else + wp_die( 0 ); +} + +function wp_ajax_trash_post( $action ) { + if ( empty( $action ) ) + $action = 'trash-post'; + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + check_ajax_referer( "{$action}_$id" ); + if ( !current_user_can( 'delete_post', $id ) ) + wp_die( -1 ); + + if ( !get_post( $id ) ) + wp_die( 1 ); + + if ( 'trash-post' == $action ) + $done = wp_trash_post( $id ); + else + $done = wp_untrash_post( $id ); + + if ( $done ) + wp_die( 1 ); + + wp_die( 0 ); +} + +function wp_ajax_untrash_post( $action ) { + if ( empty( $action ) ) + $action = 'untrash-post'; + wp_ajax_trash_post( $action ); +} + +function wp_ajax_delete_page( $action ) { + if ( empty( $action ) ) + $action = 'delete-page'; + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + check_ajax_referer( "{$action}_$id" ); + if ( !current_user_can( 'delete_page', $id ) ) + wp_die( -1 ); + + if ( ! get_post( $id ) ) + wp_die( 1 ); + + if ( wp_delete_post( $id ) ) + wp_die( 1 ); + else + wp_die( 0 ); +} + +function wp_ajax_dim_comment() { + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + + if ( !$comment = get_comment( $id ) ) { + $x = new WP_Ajax_Response( array( + 'what' => 'comment', + 'id' => new WP_Error('invalid_comment', sprintf(__('Comment %d does not exist'), $id)) + ) ); + $x->send(); + } + + if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) && ! current_user_can( 'moderate_comments' ) ) + wp_die( -1 ); + + $current = wp_get_comment_status( $comment->comment_ID ); + if ( isset( $_POST['new'] ) && $_POST['new'] == $current ) + wp_die( time() ); + + check_ajax_referer( "approve-comment_$id" ); + if ( in_array( $current, array( 'unapproved', 'spam' ) ) ) + $result = wp_set_comment_status( $comment->comment_ID, 'approve', true ); + else + $result = wp_set_comment_status( $comment->comment_ID, 'hold', true ); + + if ( is_wp_error($result) ) { + $x = new WP_Ajax_Response( array( + 'what' => 'comment', + 'id' => $result + ) ); + $x->send(); + } + + // Decide if we need to send back '1' or a more complicated response including page links and comment counts + _wp_ajax_delete_comment_response( $comment->comment_ID ); + wp_die( 0 ); +} + +function wp_ajax_add_link_category( $action ) { + if ( empty( $action ) ) + $action = 'add-link-category'; + check_ajax_referer( $action ); + if ( !current_user_can( 'manage_categories' ) ) + wp_die( -1 ); + $names = explode(',', wp_unslash( $_POST['newcat'] ) ); + $x = new WP_Ajax_Response(); + foreach ( $names as $cat_name ) { + $cat_name = trim($cat_name); + $slug = sanitize_title($cat_name); + if ( '' === $slug ) + continue; + if ( !$cat_id = term_exists( $cat_name, 'link_category' ) ) + $cat_id = wp_insert_term( $cat_name, 'link_category' ); + if ( is_wp_error( $cat_id ) ) + continue; + else if ( is_array( $cat_id ) ) + $cat_id = $cat_id['term_id']; + $cat_name = esc_html( $cat_name ); + $x->add( array( + 'what' => 'link-category', + 'id' => $cat_id, + 'data' => "", + 'position' => -1 + ) ); + } + $x->send(); +} + +function wp_ajax_add_tag() { + global $wp_list_table; + + check_ajax_referer( 'add-tag', '_wpnonce_add-tag' ); + $post_type = !empty($_POST['post_type']) ? $_POST['post_type'] : 'post'; + $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag'; + $tax = get_taxonomy($taxonomy); + + if ( !current_user_can( $tax->cap->edit_terms ) ) + wp_die( -1 ); + + $x = new WP_Ajax_Response(); + + $tag = wp_insert_term($_POST['tag-name'], $taxonomy, $_POST ); + + if ( !$tag || is_wp_error($tag) || (!$tag = get_term( $tag['term_id'], $taxonomy )) ) { + $message = __('An error has occurred. Please reload the page and try again.'); + if ( is_wp_error($tag) && $tag->get_error_message() ) + $message = $tag->get_error_message(); + + $x->add( array( + 'what' => 'taxonomy', + 'data' => new WP_Error('error', $message ) + ) ); + $x->send(); + } + + $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) ); + + $level = 0; + if ( is_taxonomy_hierarchical($taxonomy) ) { + $level = count( get_ancestors( $tag->term_id, $taxonomy ) ); + ob_start(); + $wp_list_table->single_row( $tag, $level ); + $noparents = ob_get_clean(); + } + + ob_start(); + $wp_list_table->single_row( $tag ); + $parents = ob_get_clean(); + + $x->add( array( + 'what' => 'taxonomy', + 'supplemental' => compact('parents', 'noparents') + ) ); + $x->add( array( + 'what' => 'term', + 'position' => $level, + 'supplemental' => (array) $tag + ) ); + $x->send(); +} + +function wp_ajax_get_tagcloud() { + if ( isset( $_POST['tax'] ) ) { + $taxonomy = sanitize_key( $_POST['tax'] ); + $tax = get_taxonomy( $taxonomy ); + if ( ! $tax ) + wp_die( 0 ); + if ( ! current_user_can( $tax->cap->assign_terms ) ) + wp_die( -1 ); + } else { + wp_die( 0 ); + } + + $tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) ); + + if ( empty( $tags ) ) + wp_die( $tax->labels->not_found ); + + if ( is_wp_error( $tags ) ) + wp_die( $tags->get_error_message() ); + + foreach ( $tags as $key => $tag ) { + $tags[ $key ]->link = '#'; + $tags[ $key ]->id = $tag->term_id; + } + + // We need raw tag names here, so don't filter the output + $return = wp_generate_tag_cloud( $tags, array('filter' => 0) ); + + if ( empty($return) ) + wp_die( 0 ); + + echo $return; + + wp_die(); +} + +function wp_ajax_get_comments( $action ) { + global $wp_list_table, $post_id; + if ( empty( $action ) ) + $action = 'get-comments'; + + check_ajax_referer( $action ); + + if ( empty( $post_id ) && ! empty( $_REQUEST['p'] ) ) { + $id = absint( $_REQUEST['p'] ); + if ( ! empty( $id ) ) + $post_id = $id; + } + + if ( empty( $post_id ) ) + wp_die( -1 ); + + $wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); + + if ( ! current_user_can( 'edit_post', $post_id ) ) + wp_die( -1 ); + + $wp_list_table->prepare_items(); + + if ( !$wp_list_table->has_items() ) + wp_die( 1 ); + + $x = new WP_Ajax_Response(); + ob_start(); + foreach ( $wp_list_table->items as $comment ) { + if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) ) + continue; + get_comment( $comment ); + $wp_list_table->single_row( $comment ); + } + $comment_list_item = ob_get_contents(); + ob_end_clean(); + + $x->add( array( + 'what' => 'comments', + 'data' => $comment_list_item + ) ); + $x->send(); +} + +function wp_ajax_replyto_comment( $action ) { + global $wp_list_table, $wpdb; + if ( empty( $action ) ) + $action = 'replyto-comment'; + + check_ajax_referer( $action, '_ajax_nonce-replyto-comment' ); + + $comment_post_ID = (int) $_POST['comment_post_ID']; + $post = get_post( $comment_post_ID ); + if ( ! $post ) + wp_die( -1 ); + + if ( !current_user_can( 'edit_post', $comment_post_ID ) ) + wp_die( -1 ); + + if ( empty( $post->post_status ) ) + wp_die( 1 ); + elseif ( in_array($post->post_status, array('draft', 'pending', 'trash') ) ) + wp_die( __('ERROR: you are replying to a comment on a draft post.') ); + + $user = wp_get_current_user(); + if ( $user->exists() ) { + $user_ID = $user->ID; + $comment_author = wp_slash( $user->display_name ); + $comment_author_email = wp_slash( $user->user_email ); + $comment_author_url = wp_slash( $user->user_url ); + $comment_content = trim($_POST['content']); + if ( current_user_can( 'unfiltered_html' ) ) { + if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) ) + $_POST['_wp_unfiltered_html_comment'] = ''; + + if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) { + kses_remove_filters(); // start with a clean slate + kses_init_filters(); // set up the filters + } + } + } else { + wp_die( __( 'Sorry, you must be logged in to reply to a comment.' ) ); + } + + if ( '' == $comment_content ) + wp_die( __( 'ERROR: please type a comment.' ) ); + + $comment_parent = 0; + if ( isset( $_POST['comment_ID'] ) ) + $comment_parent = absint( $_POST['comment_ID'] ); + $comment_auto_approved = false; + $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID'); + + // automatically approve parent comment + if ( !empty($_POST['approve_parent']) ) { + $parent = get_comment( $comment_parent ); + + if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) { + if ( wp_set_comment_status( $parent->comment_ID, 'approve' ) ) + $comment_auto_approved = true; + } + } + + $comment_id = wp_new_comment( $commentdata ); + $comment = get_comment($comment_id); + if ( ! $comment ) wp_die( 1 ); + + $position = ( isset($_POST['position']) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1'; + + ob_start(); + if ( isset( $_REQUEST['mode'] ) && 'dashboard' == $_REQUEST['mode'] ) { + require_once( ABSPATH . 'wp-admin/includes/dashboard.php' ); + _wp_dashboard_recent_comments_row( $comment ); + } else { + if ( isset( $_REQUEST['mode'] ) && 'single' == $_REQUEST['mode'] ) { + $wp_list_table = _get_list_table('WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); + } else { + $wp_list_table = _get_list_table('WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); + } + $wp_list_table->single_row( $comment ); + } + $comment_list_item = ob_get_clean(); + + $response = array( + 'what' => 'comment', + 'id' => $comment->comment_ID, + 'data' => $comment_list_item, + 'position' => $position + ); + + if ( $comment_auto_approved ) + $response['supplemental'] = array( 'parent_approved' => $parent->comment_ID ); + + $x = new WP_Ajax_Response(); + $x->add( $response ); + $x->send(); +} + +function wp_ajax_edit_comment() { + global $wp_list_table; + + check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' ); + + $comment_id = (int) $_POST['comment_ID']; + if ( ! current_user_can( 'edit_comment', $comment_id ) ) + wp_die( -1 ); + + if ( '' == $_POST['content'] ) + wp_die( __( 'ERROR: please type a comment.' ) ); + + if ( isset( $_POST['status'] ) ) + $_POST['comment_status'] = $_POST['status']; + edit_comment(); + + $position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1'; + $comments_status = isset($_POST['comments_listing']) ? $_POST['comments_listing'] : ''; + + $checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0; + $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); + + $comment = get_comment( $comment_id ); + if ( empty( $comment->comment_ID ) ) + wp_die( -1 ); + + ob_start(); + $wp_list_table->single_row( $comment ); + $comment_list_item = ob_get_clean(); + + $x = new WP_Ajax_Response(); + + $x->add( array( + 'what' => 'edit_comment', + 'id' => $comment->comment_ID, + 'data' => $comment_list_item, + 'position' => $position + )); + + $x->send(); +} + +function wp_ajax_add_menu_item() { + check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' ); + + if ( ! current_user_can( 'edit_theme_options' ) ) + wp_die( -1 ); + + require_once ABSPATH . 'wp-admin/includes/nav-menu.php'; + + // For performance reasons, we omit some object properties from the checklist. + // The following is a hacky way to restore them when adding non-custom items. + + $menu_items_data = array(); + foreach ( (array) $_POST['menu-item'] as $menu_item_data ) { + if ( + ! empty( $menu_item_data['menu-item-type'] ) && + 'custom' != $menu_item_data['menu-item-type'] && + ! empty( $menu_item_data['menu-item-object-id'] ) + ) { + switch( $menu_item_data['menu-item-type'] ) { + case 'post_type' : + $_object = get_post( $menu_item_data['menu-item-object-id'] ); + break; + + case 'taxonomy' : + $_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] ); + break; + } + + $_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) ); + $_menu_item = array_shift( $_menu_items ); + + // Restore the missing menu item properties + $menu_item_data['menu-item-description'] = $_menu_item->description; + } + + $menu_items_data[] = $menu_item_data; + } + + $item_ids = wp_save_nav_menu_items( 0, $menu_items_data ); + if ( is_wp_error( $item_ids ) ) + wp_die( 0 ); + + $menu_items = array(); + + foreach ( (array) $item_ids as $menu_item_id ) { + $menu_obj = get_post( $menu_item_id ); + if ( ! empty( $menu_obj->ID ) ) { + $menu_obj = wp_setup_nav_menu_item( $menu_obj ); + $menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items + $menu_items[] = $menu_obj; + } + } + + /** + * Filter the Walker class used when adding nav menu items. + * + * @since 3.4.0 + * + * @param string $class The walker class to use. Default 'Walker_Nav_Menu_Edit'. + * @param int $menu_id The menu id, derived from $_POST['menu']. + */ + $walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] ); + + if ( ! class_exists( $walker_class_name ) ) + wp_die( 0 ); + + if ( ! empty( $menu_items ) ) { + $args = array( + 'after' => '', + 'before' => '', + 'link_after' => '', + 'link_before' => '', + 'walker' => new $walker_class_name, + ); + echo walk_nav_menu_tree( $menu_items, 0, (object) $args ); + } + wp_die(); +} + +function wp_ajax_add_meta() { + check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' ); + $c = 0; + $pid = (int) $_POST['post_id']; + $post = get_post( $pid ); + + if ( isset($_POST['metakeyselect']) || isset($_POST['metakeyinput']) ) { + if ( !current_user_can( 'edit_post', $pid ) ) + wp_die( -1 ); + if ( isset($_POST['metakeyselect']) && '#NONE#' == $_POST['metakeyselect'] && empty($_POST['metakeyinput']) ) + wp_die( 1 ); + if ( $post->post_status == 'auto-draft' ) { + $save_POST = $_POST; // Backup $_POST + $_POST = array(); // Make it empty for edit_post() + $_POST['action'] = 'draft'; // Warning fix + $_POST['post_ID'] = $pid; + $_POST['post_type'] = $post->post_type; + $_POST['post_status'] = 'draft'; + $now = current_time('timestamp', 1); + $_POST['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), date( get_option( 'date_format' ), $now ), date( get_option( 'time_format' ), $now ) ); + + if ( $pid = edit_post() ) { + if ( is_wp_error( $pid ) ) { + $x = new WP_Ajax_Response( array( + 'what' => 'meta', + 'data' => $pid + ) ); + $x->send(); + } + $_POST = $save_POST; // Now we can restore original $_POST again + if ( !$mid = add_meta( $pid ) ) + wp_die( __( 'Please provide a custom field value.' ) ); + } else { + wp_die( 0 ); + } + } else if ( !$mid = add_meta( $pid ) ) { + wp_die( __( 'Please provide a custom field value.' ) ); + } + + $meta = get_metadata_by_mid( 'post', $mid ); + $pid = (int) $meta->post_id; + $meta = get_object_vars( $meta ); + $x = new WP_Ajax_Response( array( + 'what' => 'meta', + 'id' => $mid, + 'data' => _list_meta_row( $meta, $c ), + 'position' => 1, + 'supplemental' => array('postid' => $pid) + ) ); + } else { // Update? + $mid = (int) key( $_POST['meta'] ); + $key = wp_unslash( $_POST['meta'][$mid]['key'] ); + $value = wp_unslash( $_POST['meta'][$mid]['value'] ); + if ( '' == trim($key) ) + wp_die( __( 'Please provide a custom field name.' ) ); + if ( '' == trim($value) ) + wp_die( __( 'Please provide a custom field value.' ) ); + if ( ! $meta = get_metadata_by_mid( 'post', $mid ) ) + wp_die( 0 ); // if meta doesn't exist + if ( is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) || + ! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) || + ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) ) + wp_die( -1 ); + if ( $meta->meta_value != $value || $meta->meta_key != $key ) { + if ( !$u = update_metadata_by_mid( 'post', $mid, $value, $key ) ) + wp_die( 0 ); // We know meta exists; we also know it's unchanged (or DB error, in which case there are bigger problems). + } + + $x = new WP_Ajax_Response( array( + 'what' => 'meta', + 'id' => $mid, 'old_id' => $mid, + 'data' => _list_meta_row( array( + 'meta_key' => $key, + 'meta_value' => $value, + 'meta_id' => $mid + ), $c ), + 'position' => 0, + 'supplemental' => array('postid' => $meta->post_id) + ) ); + } + $x->send(); +} + +function wp_ajax_add_user( $action ) { + global $wp_list_table; + if ( empty( $action ) ) + $action = 'add-user'; + + check_ajax_referer( $action ); + if ( ! current_user_can('create_users') ) + wp_die( -1 ); + if ( ! $user_id = edit_user() ) { + wp_die( 0 ); + } elseif ( is_wp_error( $user_id ) ) { + $x = new WP_Ajax_Response( array( + 'what' => 'user', + 'id' => $user_id + ) ); + $x->send(); + } + $user_object = get_userdata( $user_id ); + + $wp_list_table = _get_list_table('WP_Users_List_Table'); + + $role = current( $user_object->roles ); + + $x = new WP_Ajax_Response( array( + 'what' => 'user', + 'id' => $user_id, + 'data' => $wp_list_table->single_row( $user_object, '', $role ), + 'supplemental' => array( + 'show-link' => sprintf(__( 'User %s added' ), "user-$user_id", $user_object->user_login), + 'role' => $role, + ) + ) ); + $x->send(); +} + +function wp_ajax_autosave() { + define( 'DOING_AUTOSAVE', true ); + + check_ajax_referer( 'autosave', 'autosavenonce' ); + + if ( ! empty( $_POST['catslist'] ) ) + $_POST['post_category'] = explode( ',', $_POST['catslist'] ); + if ( $_POST['post_type'] == 'page' || empty( $_POST['post_category'] ) ) + unset( $_POST['post_category'] ); + + $data = ''; + $supplemental = array(); + $id = $revision_id = 0; + + $post_id = (int) $_POST['post_id']; + $_POST['ID'] = $_POST['post_ID'] = $post_id; + $post = get_post( $post_id ); + if ( empty( $post->ID ) || ! current_user_can( 'edit_post', $post->ID ) ) + wp_die( __( 'You are not allowed to edit this post.' ) ); + + if ( 'page' == $post->post_type && ! current_user_can( 'edit_page', $post->ID ) ) + wp_die( __( 'You are not allowed to edit this page.' ) ); + + if ( 'auto-draft' == $post->post_status ) + $_POST['post_status'] = 'draft'; + + if ( ! empty( $_POST['autosave'] ) ) { + if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) { + // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked + $id = edit_post(); + } else { + // Non drafts or other users drafts are not overwritten. The autosave is stored in a special post revision for each user. + $revision_id = wp_create_post_autosave( $post->ID ); + if ( is_wp_error($revision_id) ) + $id = $revision_id; + else + $id = $post->ID; + } + + if ( ! is_wp_error($id) ) { + /* translators: draft saved date format, see http://php.net/date */ + $draft_saved_date_format = __('g:i:s a'); + /* translators: %s: date and time */ + $data = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) ); + } + } else { + if ( ! empty( $_POST['auto_draft'] ) ) + $id = 0; // This tells us it didn't actually save + else + $id = $post->ID; + } + + // @todo Consider exposing any errors, rather than having 'Saving draft...' + $x = new WP_Ajax_Response( array( + 'what' => 'autosave', + 'id' => $id, + 'data' => $data, + 'supplemental' => $supplemental + ) ); + $x->send(); +} + +function wp_ajax_closed_postboxes() { + check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' ); + $closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array(); + $closed = array_filter($closed); + + $hidden = isset( $_POST['hidden'] ) ? explode( ',', $_POST['hidden']) : array(); + $hidden = array_filter($hidden); + + $page = isset( $_POST['page'] ) ? $_POST['page'] : ''; + + if ( $page != sanitize_key( $page ) ) + wp_die( 0 ); + + if ( ! $user = wp_get_current_user() ) + wp_die( -1 ); + + if ( is_array($closed) ) + update_user_option($user->ID, "closedpostboxes_$page", $closed, true); + + if ( is_array($hidden) ) { + $hidden = array_diff( $hidden, array('submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu') ); // postboxes that are always shown + update_user_option($user->ID, "metaboxhidden_$page", $hidden, true); + } + + wp_die( 1 ); +} + +function wp_ajax_hidden_columns() { + check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' ); + $hidden = isset( $_POST['hidden'] ) ? $_POST['hidden'] : ''; + $hidden = explode( ',', $_POST['hidden'] ); + $page = isset( $_POST['page'] ) ? $_POST['page'] : ''; + + if ( $page != sanitize_key( $page ) ) + wp_die( 0 ); + + if ( ! $user = wp_get_current_user() ) + wp_die( -1 ); + + if ( is_array($hidden) ) + update_user_option($user->ID, "manage{$page}columnshidden", $hidden, true); + + wp_die( 1 ); +} + +function wp_ajax_update_welcome_panel() { + check_ajax_referer( 'welcome-panel-nonce', 'welcomepanelnonce' ); + + if ( ! current_user_can( 'edit_theme_options' ) ) + wp_die( -1 ); + + update_user_meta( get_current_user_id(), 'show_welcome_panel', empty( $_POST['visible'] ) ? 0 : 1 ); + + wp_die( 1 ); +} + +function wp_ajax_menu_get_metabox() { + if ( ! current_user_can( 'edit_theme_options' ) ) + wp_die( -1 ); + + require_once ABSPATH . 'wp-admin/includes/nav-menu.php'; + + if ( isset( $_POST['item-type'] ) && 'post_type' == $_POST['item-type'] ) { + $type = 'posttype'; + $callback = 'wp_nav_menu_item_post_type_meta_box'; + $items = (array) get_post_types( array( 'show_in_nav_menus' => true ), 'object' ); + } elseif ( isset( $_POST['item-type'] ) && 'taxonomy' == $_POST['item-type'] ) { + $type = 'taxonomy'; + $callback = 'wp_nav_menu_item_taxonomy_meta_box'; + $items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' ); + } + + if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) { + $menus_meta_box_object = $items[ $_POST['item-object'] ]; + /** + * Filter a nav menu meta box object. + * + * @since 3.0.0 + * + * @param object $menus_meta_box_object A nav menu meta box object, such as Page, Post, Category, Tag, etc. + */ + $item = apply_filters( 'nav_menu_meta_box_object', $menus_meta_box_object ); + ob_start(); + call_user_func_array($callback, array( + null, + array( + 'id' => 'add-' . $item->name, + 'title' => $item->labels->name, + 'callback' => $callback, + 'args' => $item, + ) + )); + + $markup = ob_get_clean(); + + echo json_encode(array( + 'replace-id' => $type . '-' . $item->name, + 'markup' => $markup, + )); + } + + wp_die(); +} + +function wp_ajax_wp_link_ajax() { + check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' ); + + $args = array(); + + if ( isset( $_POST['search'] ) ) + $args['s'] = wp_unslash( $_POST['search'] ); + $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; + + require(ABSPATH . WPINC . '/class-wp-editor.php'); + $results = _WP_Editors::wp_link_query( $args ); + + if ( ! isset( $results ) ) + wp_die( 0 ); + + echo json_encode( $results ); + echo "\n"; + + wp_die(); +} + +function wp_ajax_menu_locations_save() { + if ( ! current_user_can( 'edit_theme_options' ) ) + wp_die( -1 ); + check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' ); + if ( ! isset( $_POST['menu-locations'] ) ) + wp_die( 0 ); + set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) ); + wp_die( 1 ); +} + +function wp_ajax_meta_box_order() { + check_ajax_referer( 'meta-box-order' ); + $order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false; + $page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto'; + + if ( $page_columns != 'auto' ) + $page_columns = (int) $page_columns; + + $page = isset( $_POST['page'] ) ? $_POST['page'] : ''; + + if ( $page != sanitize_key( $page ) ) + wp_die( 0 ); + + if ( ! $user = wp_get_current_user() ) + wp_die( -1 ); + + if ( $order ) + update_user_option($user->ID, "meta-box-order_$page", $order, true); + + if ( $page_columns ) + update_user_option($user->ID, "screen_layout_$page", $page_columns, true); + + wp_die( 1 ); +} + +function wp_ajax_menu_quick_search() { + if ( ! current_user_can( 'edit_theme_options' ) ) + wp_die( -1 ); + + require_once ABSPATH . 'wp-admin/includes/nav-menu.php'; + + _wp_ajax_menu_quick_search( $_POST ); + + wp_die(); +} + +function wp_ajax_get_permalink() { + check_ajax_referer( 'getpermalink', 'getpermalinknonce' ); + $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0; + wp_die( add_query_arg( array( 'preview' => 'true' ), get_permalink( $post_id ) ) ); +} + +function wp_ajax_sample_permalink() { + check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' ); + $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0; + $title = isset($_POST['new_title'])? $_POST['new_title'] : ''; + $slug = isset($_POST['new_slug'])? $_POST['new_slug'] : null; + wp_die( get_sample_permalink_html( $post_id, $title, $slug ) ); +} + +function wp_ajax_inline_save() { + global $wp_list_table; + + check_ajax_referer( 'inlineeditnonce', '_inline_edit' ); + + if ( ! isset($_POST['post_ID']) || ! ( $post_ID = (int) $_POST['post_ID'] ) ) + wp_die(); + + if ( 'page' == $_POST['post_type'] ) { + if ( ! current_user_can( 'edit_page', $post_ID ) ) + wp_die( __( 'You are not allowed to edit this page.' ) ); + } else { + if ( ! current_user_can( 'edit_post', $post_ID ) ) + wp_die( __( 'You are not allowed to edit this post.' ) ); + } + + if ( $last = wp_check_post_lock( $post_ID ) ) { + $last_user = get_userdata( $last ); + $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' ); + printf( $_POST['post_type'] == 'page' ? __( 'Saving is disabled: %s is currently editing this page.' ) : __( 'Saving is disabled: %s is currently editing this post.' ), esc_html( $last_user_name ) ); + wp_die(); + } + + $data = &$_POST; + + $post = get_post( $post_ID, ARRAY_A ); + $post = wp_slash($post); //since it is from db + + $data['content'] = $post['post_content']; + $data['excerpt'] = $post['post_excerpt']; + + // rename + $data['user_ID'] = get_current_user_id(); + + if ( isset($data['post_parent']) ) + $data['parent_id'] = $data['post_parent']; + + // status + if ( isset($data['keep_private']) && 'private' == $data['keep_private'] ) + $data['post_status'] = 'private'; + else + $data['post_status'] = $data['_status']; + + if ( empty($data['comment_status']) ) + $data['comment_status'] = 'closed'; + if ( empty($data['ping_status']) ) + $data['ping_status'] = 'closed'; + + // Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published. + if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) { + $post['post_status'] = 'publish'; + $data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] ); + } + + // update the post + edit_post(); + + $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) ); + + $mode = $_POST['post_view']; + + $level = 0; + $request_post = array( get_post( $_POST['post_ID'] ) ); + $parent = $request_post[0]->post_parent; + + while ( $parent > 0 ) { + $parent_post = get_post( $parent ); + $parent = $parent_post->post_parent; + $level++; + } + + $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level ); + + wp_die(); +} + +function wp_ajax_inline_save_tax() { + global $wp_list_table; + + check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' ); + + $taxonomy = sanitize_key( $_POST['taxonomy'] ); + $tax = get_taxonomy( $taxonomy ); + if ( ! $tax ) + wp_die( 0 ); + + if ( ! current_user_can( $tax->cap->edit_terms ) ) + wp_die( -1 ); + + $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => 'edit-' . $taxonomy ) ); + + if ( ! isset($_POST['tax_ID']) || ! ( $id = (int) $_POST['tax_ID'] ) ) + wp_die( -1 ); + + $tag = get_term( $id, $taxonomy ); + $_POST['description'] = $tag->description; + + $updated = wp_update_term($id, $taxonomy, $_POST); + if ( $updated && !is_wp_error($updated) ) { + $tag = get_term( $updated['term_id'], $taxonomy ); + if ( !$tag || is_wp_error( $tag ) ) { + if ( is_wp_error($tag) && $tag->get_error_message() ) + wp_die( $tag->get_error_message() ); + wp_die( __( 'Item not updated.' ) ); + } + } else { + if ( is_wp_error($updated) && $updated->get_error_message() ) + wp_die( $updated->get_error_message() ); + wp_die( __( 'Item not updated.' ) ); + } + $level = 0; + $parent = $tag->parent; + while ( $parent > 0 ) { + $parent_tag = get_term( $parent, $taxonomy ); + $parent = $parent_tag->parent; + $level++; + } + $wp_list_table->single_row( $tag, $level ); + wp_die(); +} + +function wp_ajax_find_posts() { + global $wpdb; + + check_ajax_referer( 'find-posts' ); + + $post_types = get_post_types( array( 'public' => true ), 'objects' ); + unset( $post_types['attachment'] ); + + $s = wp_unslash( $_POST['ps'] ); + $searchand = $search = ''; + $args = array( + 'post_type' => array_keys( $post_types ), + 'post_status' => 'any', + 'posts_per_page' => 50, + ); + if ( '' !== $s ) + $args['s'] = $s; + + $posts = get_posts( $args ); + + if ( ! $posts ) + wp_die( __('No items found.') ); + + $html = ''; + foreach ( $posts as $post ) { + $title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' ); + + switch ( $post->post_status ) { + case 'publish' : + case 'private' : + $stat = __('Published'); + break; + case 'future' : + $stat = __('Scheduled'); + break; + case 'pending' : + $stat = __('Pending Review'); + break; + case 'draft' : + $stat = __('Draft'); + break; + } + + if ( '0000-00-00 00:00:00' == $post->post_date ) { + $time = ''; + } else { + /* translators: date format in table columns, see http://php.net/date */ + $time = mysql2date(__('Y/m/d'), $post->post_date); + } + + $html .= ''; + $html .= '' . "\n\n"; + } + + $html .= '

'.__('Title').''.__('Type').''.__('Date').''.__('Status').'
' . esc_html( $post_types[$post->post_type]->labels->singular_name ) . ''.esc_html( $time ) . '' . esc_html( $stat ). '
'; + + $x = new WP_Ajax_Response(); + $x->add( array( + 'data' => $html + )); + $x->send(); +} + +function wp_ajax_widgets_order() { + check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' ); + + if ( !current_user_can('edit_theme_options') ) + wp_die( -1 ); + + unset( $_POST['savewidgets'], $_POST['action'] ); + + // save widgets order for all sidebars + if ( is_array($_POST['sidebars']) ) { + $sidebars = array(); + foreach ( $_POST['sidebars'] as $key => $val ) { + $sb = array(); + if ( !empty($val) ) { + $val = explode(',', $val); + foreach ( $val as $k => $v ) { + if ( strpos($v, 'widget-') === false ) + continue; + + $sb[$k] = substr($v, strpos($v, '_') + 1); + } + } + $sidebars[$key] = $sb; + } + wp_set_sidebars_widgets($sidebars); + wp_die( 1 ); + } + + wp_die( -1 ); +} + +function wp_ajax_save_widget() { + global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates; + + check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' ); + + if ( !current_user_can('edit_theme_options') || !isset($_POST['id_base']) ) + wp_die( -1 ); + + unset( $_POST['savewidgets'], $_POST['action'] ); + + /** + * Fires early when editing the widgets displayed in sidebars. + * + * @since 2.8.0 + */ + do_action( 'load-widgets.php' ); + + /** + * Fires early when editing the widgets displayed in sidebars. + * + * @since 2.8.0 + */ + do_action( 'widgets.php' ); + + /** + * Fires early when editing the widgets displayed in sidebars. + * + * @since 2.2.0 + */ + do_action( 'sidebar_admin_setup' ); + + $id_base = $_POST['id_base']; + $widget_id = $_POST['widget-id']; + $sidebar_id = $_POST['sidebar']; + $multi_number = !empty($_POST['multi_number']) ? (int) $_POST['multi_number'] : 0; + $settings = isset($_POST['widget-' . $id_base]) && is_array($_POST['widget-' . $id_base]) ? $_POST['widget-' . $id_base] : false; + $error = '

' . __('An error has occurred. Please reload the page and try again.') . '

'; + + $sidebars = wp_get_sidebars_widgets(); + $sidebar = isset($sidebars[$sidebar_id]) ? $sidebars[$sidebar_id] : array(); + + // delete + if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) { + + if ( !isset($wp_registered_widgets[$widget_id]) ) + wp_die( $error ); + + $sidebar = array_diff( $sidebar, array($widget_id) ); + $_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1'); + } elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) { + if ( !$multi_number ) + wp_die( $error ); + + $_POST['widget-' . $id_base] = array( $multi_number => array_shift($settings) ); + $widget_id = $id_base . '-' . $multi_number; + $sidebar[] = $widget_id; + } + $_POST['widget-id'] = $sidebar; + + foreach ( (array) $wp_registered_widget_updates as $name => $control ) { + + if ( $name == $id_base ) { + if ( !is_callable( $control['callback'] ) ) + continue; + + ob_start(); + call_user_func_array( $control['callback'], $control['params'] ); + ob_end_clean(); + break; + } + } + + if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) { + $sidebars[$sidebar_id] = $sidebar; + wp_set_sidebars_widgets($sidebars); + echo "deleted:$widget_id"; + wp_die(); + } + + if ( !empty($_POST['add_new']) ) + wp_die(); + + if ( $form = $wp_registered_widget_controls[$widget_id] ) + call_user_func_array( $form['callback'], $form['params'] ); + + wp_die(); +} + +function wp_ajax_upload_attachment() { + check_ajax_referer( 'media-form' ); + + if ( ! current_user_can( 'upload_files' ) ) + wp_die(); + + if ( isset( $_REQUEST['post_id'] ) ) { + $post_id = $_REQUEST['post_id']; + if ( ! current_user_can( 'edit_post', $post_id ) ) + wp_die(); + } else { + $post_id = null; + } + + $post_data = isset( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array(); + + // If the context is custom header or background, make sure the uploaded file is an image. + if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) { + $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false ); + if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) { + echo json_encode( array( + 'success' => false, + 'data' => array( + 'message' => __( 'The uploaded file is not a valid image. Please try again.' ), + 'filename' => $_FILES['async-upload']['name'], + ) + ) ); + + wp_die(); + } + } + + $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data ); + + if ( is_wp_error( $attachment_id ) ) { + echo json_encode( array( + 'success' => false, + 'data' => array( + 'message' => $attachment_id->get_error_message(), + 'filename' => $_FILES['async-upload']['name'], + ) + ) ); + + wp_die(); + } + + if ( isset( $post_data['context'] ) && isset( $post_data['theme'] ) ) { + if ( 'custom-background' === $post_data['context'] ) + update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', $post_data['theme'] ); + + if ( 'custom-header' === $post_data['context'] ) + update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', $post_data['theme'] ); + } + + if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) ) + wp_die(); + + echo json_encode( array( + 'success' => true, + 'data' => $attachment, + ) ); + + wp_die(); +} + +function wp_ajax_image_editor() { + $attachment_id = intval($_POST['postid']); + if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) ) + wp_die( -1 ); + + check_ajax_referer( "image_editor-$attachment_id" ); + include_once( ABSPATH . 'wp-admin/includes/image-edit.php' ); + + $msg = false; + switch ( $_POST['do'] ) { + case 'save' : + $msg = wp_save_image($attachment_id); + $msg = json_encode($msg); + wp_die( $msg ); + break; + case 'scale' : + $msg = wp_save_image($attachment_id); + break; + case 'restore' : + $msg = wp_restore_image($attachment_id); + break; + } + + wp_image_editor($attachment_id, $msg); + wp_die(); +} + +function wp_ajax_set_post_thumbnail() { + $json = ! empty( $_REQUEST['json'] ); // New-style request + + $post_ID = intval( $_POST['post_id'] ); + if ( ! current_user_can( 'edit_post', $post_ID ) ) + wp_die( -1 ); + + $thumbnail_id = intval( $_POST['thumbnail_id'] ); + + if ( $json ) + check_ajax_referer( "update-post_$post_ID" ); + else + check_ajax_referer( "set_post_thumbnail-$post_ID" ); + + if ( $thumbnail_id == '-1' ) { + if ( delete_post_thumbnail( $post_ID ) ) { + $return = _wp_post_thumbnail_html( null, $post_ID ); + $json ? wp_send_json_success( $return ) : wp_die( $return ); + } else { + wp_die( 0 ); + } + } + + if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) { + $return = _wp_post_thumbnail_html( $thumbnail_id, $post_ID ); + $json ? wp_send_json_success( $return ) : wp_die( $return ); + } + + wp_die( 0 ); +} + +function wp_ajax_date_format() { + wp_die( date_i18n( sanitize_option( 'date_format', $_POST['date'] ) ) ); +} + +function wp_ajax_time_format() { + wp_die( date_i18n( sanitize_option( 'time_format', $_POST['date'] ) ) ); +} + +function wp_ajax_wp_fullscreen_save_post() { + $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0; + + $post = $post_type = null; + + if ( $post_id ) + $post = get_post( $post_id ); + + if ( $post ) + $post_type = $post->post_type; + elseif ( isset( $_POST['post_type'] ) && post_type_exists( $_POST['post_type'] ) ) + $post_type = $_POST['post_type']; + + check_ajax_referer('update-post_' . $post_id, '_wpnonce'); + + $post_id = edit_post(); + + if ( is_wp_error($post_id) ) { + if ( $post_id->get_error_message() ) + $message = $post_id->get_error_message(); + else + $message = __('Save failed'); + + echo json_encode( array( 'message' => $message, 'last_edited' => '' ) ); + wp_die(); + } else { + $message = __('Saved.'); + } + + if ( $post ) { + $last_date = mysql2date( get_option('date_format'), $post->post_modified ); + $last_time = mysql2date( get_option('time_format'), $post->post_modified ); + } else { + $last_date = date_i18n( get_option('date_format') ); + $last_time = date_i18n( get_option('time_format') ); + } + + if ( $last_id = get_post_meta($post_id, '_edit_last', true) ) { + $last_user = get_userdata($last_id); + $last_edited = sprintf( __('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), $last_date, $last_time ); + } else { + $last_edited = sprintf( __('Last edited on %1$s at %2$s'), $last_date, $last_time ); + } + + echo json_encode( array( 'message' => $message, 'last_edited' => $last_edited ) ); + wp_die(); +} + +function wp_ajax_wp_remove_post_lock() { + if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) ) + wp_die( 0 ); + $post_id = (int) $_POST['post_ID']; + if ( ! $post = get_post( $post_id ) ) + wp_die( 0 ); + + check_ajax_referer( 'update-post_' . $post_id ); + + if ( ! current_user_can( 'edit_post', $post_id ) ) + wp_die( -1 ); + + $active_lock = array_map( 'absint', explode( ':', $_POST['active_post_lock'] ) ); + if ( $active_lock[1] != get_current_user_id() ) + wp_die( 0 ); + + /** + * Filter the post lock window duration. + * + * @since 3.3.0 + * + * @param int $interval The interval in seconds the post lock duration should last, plus 5 seconds. Default 120. + */ + $new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', 120 ) + 5 ) . ':' . $active_lock[1]; + update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) ); + wp_die( 1 ); +} + +function wp_ajax_dismiss_wp_pointer() { + $pointer = $_POST['pointer']; + if ( $pointer != sanitize_key( $pointer ) ) + wp_die( 0 ); + +// check_ajax_referer( 'dismiss-pointer_' . $pointer ); + + $dismissed = array_filter( explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ) ); + + if ( in_array( $pointer, $dismissed ) ) + wp_die( 0 ); + + $dismissed[] = $pointer; + $dismissed = implode( ',', $dismissed ); + + update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed ); + wp_die( 1 ); +} + +/** + * Get an attachment. + * + * @since 3.5.0 + */ +function wp_ajax_get_attachment() { + if ( ! isset( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! $post = get_post( $id ) ) + wp_send_json_error(); + + if ( 'attachment' != $post->post_type ) + wp_send_json_error(); + + if ( ! current_user_can( 'upload_files' ) ) + wp_send_json_error(); + + if ( ! $attachment = wp_prepare_attachment_for_js( $id ) ) + wp_send_json_error(); + + wp_send_json_success( $attachment ); +} + +/** + * Query for attachments. + * + * @since 3.5.0 + */ +function wp_ajax_query_attachments() { + if ( ! current_user_can( 'upload_files' ) ) + wp_send_json_error(); + + $query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array(); + $query = array_intersect_key( $query, array_flip( array( + 's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type', + 'post_parent', 'post__in', 'post__not_in', + ) ) ); + + $query['post_type'] = 'attachment'; + $query['post_status'] = 'inherit'; + if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) ) + $query['post_status'] .= ',private'; + + /** + * Filter the arguments passed to WP_Query during an AJAX call for querying attachments. + * + * @since 3.7.0 + * + * @param array $query An array of query variables. @see WP_Query::parse_query() + */ + $query = apply_filters( 'ajax_query_attachments_args', $query ); + $query = new WP_Query( $query ); + + $posts = array_map( 'wp_prepare_attachment_for_js', $query->posts ); + $posts = array_filter( $posts ); + + wp_send_json_success( $posts ); +} + +/** + * Save attachment attributes. + * + * @since 3.5.0 + */ +function wp_ajax_save_attachment() { + if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + check_ajax_referer( 'update-post_' . $id, 'nonce' ); + + if ( ! current_user_can( 'edit_post', $id ) ) + wp_send_json_error(); + + $changes = $_REQUEST['changes']; + $post = get_post( $id, ARRAY_A ); + + if ( 'attachment' != $post['post_type'] ) + wp_send_json_error(); + + if ( isset( $changes['title'] ) ) + $post['post_title'] = $changes['title']; + + if ( isset( $changes['caption'] ) ) + $post['post_excerpt'] = $changes['caption']; + + if ( isset( $changes['description'] ) ) + $post['post_content'] = $changes['description']; + + if ( isset( $changes['alt'] ) ) { + $alt = wp_unslash( $changes['alt'] ); + if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) { + $alt = wp_strip_all_tags( $alt, true ); + update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) ); + } + } + + wp_update_post( $post ); + wp_send_json_success(); +} + +/** + * Save backwards compatible attachment attributes. + * + * @since 3.5.0 + */ +function wp_ajax_save_attachment_compat() { + if ( ! isset( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( empty( $_REQUEST['attachments'] ) || empty( $_REQUEST['attachments'][ $id ] ) ) + wp_send_json_error(); + $attachment_data = $_REQUEST['attachments'][ $id ]; + + check_ajax_referer( 'update-post_' . $id, 'nonce' ); + + if ( ! current_user_can( 'edit_post', $id ) ) + wp_send_json_error(); + + $post = get_post( $id, ARRAY_A ); + + if ( 'attachment' != $post['post_type'] ) + wp_send_json_error(); + + /** This filter is documented in wp-admin/includes/media.php */ + $post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data ); + + if ( isset( $post['errors'] ) ) { + $errors = $post['errors']; // @todo return me and display me! + unset( $post['errors'] ); + } + + wp_update_post( $post ); + + foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) { + if ( isset( $attachment_data[ $taxonomy ] ) ) + wp_set_object_terms( $id, array_map( 'trim', preg_split( '/,+/', $attachment_data[ $taxonomy ] ) ), $taxonomy, false ); + } + + if ( ! $attachment = wp_prepare_attachment_for_js( $id ) ) + wp_send_json_error(); + + wp_send_json_success( $attachment ); +} + +function wp_ajax_save_attachment_order() { + if ( ! isset( $_REQUEST['post_id'] ) ) + wp_send_json_error(); + + if ( ! $post_id = absint( $_REQUEST['post_id'] ) ) + wp_send_json_error(); + + if ( empty( $_REQUEST['attachments'] ) ) + wp_send_json_error(); + + check_ajax_referer( 'update-post_' . $post_id, 'nonce' ); + + $attachments = $_REQUEST['attachments']; + + if ( ! current_user_can( 'edit_post', $post_id ) ) + wp_send_json_error(); + + $post = get_post( $post_id, ARRAY_A ); + + foreach ( $attachments as $attachment_id => $menu_order ) { + if ( ! current_user_can( 'edit_post', $attachment_id ) ) + continue; + if ( ! $attachment = get_post( $attachment_id ) ) + continue; + if ( 'attachment' != $attachment->post_type ) + continue; + + wp_update_post( array( 'ID' => $attachment_id, 'menu_order' => $menu_order ) ); + } + + wp_send_json_success(); +} + +/** + * Generates the HTML to send an attachment to the editor. + * Backwards compatible with the media_send_to_editor filter and the chain + * of filters that follow. + * + * @since 3.5.0 + */ +function wp_ajax_send_attachment_to_editor() { + check_ajax_referer( 'media-send-to-editor', 'nonce' ); + + $attachment = wp_unslash( $_POST['attachment'] ); + + $id = intval( $attachment['id'] ); + + if ( ! $post = get_post( $id ) ) + wp_send_json_error(); + + if ( 'attachment' != $post->post_type ) + wp_send_json_error(); + + if ( current_user_can( 'edit_post', $id ) ) { + // If this attachment is unattached, attach it. Primarily a back compat thing. + if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) { + wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) ); + } + } + + $rel = $url = ''; + $html = $title = isset( $attachment['post_title'] ) ? $attachment['post_title'] : ''; + if ( ! empty( $attachment['url'] ) ) { + $url = $attachment['url']; + if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url ) + $rel = ' rel="attachment wp-att-' . $id . '"'; + $html = '' . $html . ''; + } + + remove_filter( 'media_send_to_editor', 'image_media_send_to_editor' ); + + if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) { + $align = isset( $attachment['align'] ) ? $attachment['align'] : 'none'; + $size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium'; + $alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : ''; + $caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : ''; + $title = ''; // We no longer insert title tags into tags, as they are redundant. + $html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt ); + } elseif ( 'video' === substr( $post->post_mime_type, 0, 5 ) || 'audio' === substr( $post->post_mime_type, 0, 5 ) ) { + $html = stripslashes_deep( $_POST['html'] ); + } + + /** This filter is documented in wp-admin/includes/media.php */ + $html = apply_filters( 'media_send_to_editor', $html, $id, $attachment ); + + wp_send_json_success( $html ); +} + +/** + * Generates the HTML to send a non-image embed link to the editor. + * + * Backwards compatible with the following filters: + * - file_send_to_editor_url + * - audio_send_to_editor_url + * - video_send_to_editor_url + * + * @since 3.5.0 + */ +function wp_ajax_send_link_to_editor() { + check_ajax_referer( 'media-send-to-editor', 'nonce' ); + + if ( ! $src = wp_unslash( $_POST['src'] ) ) + wp_send_json_error(); + + if ( ! strpos( $src, '://' ) ) + $src = 'http://' . $src; + + if ( ! $src = esc_url_raw( $src ) ) + wp_send_json_error(); + + if ( ! $title = trim( wp_unslash( $_POST['title'] ) ) ) + $title = wp_basename( $src ); + + $html = ''; + if ( $title ) + $html = '' . $title . ''; + + // Figure out what filter to run: + $type = 'file'; + if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) ) + && ( 'audio' == $ext_type || 'video' == $ext_type ) ) + $type = $ext_type; + + /** This filter is documented in wp-admin/includes/media.php */ + $html = apply_filters( $type . '_send_to_editor_url', $html, $src, $title ); + + wp_send_json_success( $html ); +} + +/** + * Heartbeat API (experimental) + * + * Runs when the user is logged in. + */ +function wp_ajax_heartbeat() { + if ( empty( $_POST['_nonce'] ) ) + wp_send_json_error(); + + $response = array(); + + if ( false === wp_verify_nonce( $_POST['_nonce'], 'heartbeat-nonce' ) ) { + // User is logged in but nonces have expired. + $response['nonces_expired'] = true; + wp_send_json($response); + } + + // screen_id is the same as $current_screen->id and the JS global 'pagenow' + if ( ! empty($_POST['screen_id']) ) + $screen_id = sanitize_key($_POST['screen_id']); + else + $screen_id = 'front'; + + if ( ! empty($_POST['data']) ) { + $data = (array) $_POST['data']; + + /** + * Filter the Heartbeat response received. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param array $data The $_POST data sent. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_received', $response, $data, $screen_id ); + } + + /** + * Filter the Heartbeat response sent. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param string $screen_id The screen id. + */ + $response = apply_filters( 'heartbeat_send', $response, $screen_id ); + + /** + * Fires when Heartbeat ticks in logged-in environments. + * + * Allows the transport to be easily replaced with long-polling. + * + * @since 3.6.0 + * + * @param array|object $response The Heartbeat response object or array. + * @param string $screen_id The screen id. + */ + do_action( 'heartbeat_tick', $response, $screen_id ); + + // Send the current time according to the server + $response['server_time'] = time(); + + wp_send_json($response); +} + +function wp_ajax_get_revision_diffs() { + require ABSPATH . 'wp-admin/includes/revision.php'; + + if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) ) + wp_send_json_error(); + + if ( ! current_user_can( 'read_post', $post->ID ) ) + wp_send_json_error(); + + // Really just pre-loading the cache here. + if ( ! $revisions = wp_get_post_revisions( $post->ID, array( 'check_enabled' => false ) ) ) + wp_send_json_error(); + + $return = array(); + @set_time_limit( 0 ); + + foreach ( $_REQUEST['compare'] as $compare_key ) { + list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to + + $return[] = array( + 'id' => $compare_key, + 'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ), + ); + } + wp_send_json_success( $return ); +} diff --git a/sources/wp-admin/includes/bookmark.php b/sources/wp-admin/includes/bookmark.php new file mode 100644 index 0000000..3378596 --- /dev/null +++ b/sources/wp-admin/includes/bookmark.php @@ -0,0 +1,316 @@ +link_url = esc_url( wp_unslash( $_GET['linkurl'] ) ); + else + $link->link_url = ''; + + if ( isset( $_GET['name'] ) ) + $link->link_name = esc_attr( wp_unslash( $_GET['name'] ) ); + else + $link->link_name = ''; + + $link->link_visible = 'Y'; + + return $link; +} + +/** + * Delete link specified from database. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link to delete + * @return bool True + */ +function wp_delete_link( $link_id ) { + global $wpdb; + /** + * Fires before a link is deleted. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link to delete. + */ + do_action( 'delete_link', $link_id ); + + wp_delete_object_term_relationships( $link_id, 'link_category' ); + + $wpdb->delete( $wpdb->links, array( 'link_id' => $link_id ) ); + /** + * Fires after a link has been deleted. + * + * @since 2.2.0 + * + * @param int $link_id ID of the deleted link. + */ + do_action( 'deleted_link', $link_id ); + + clean_bookmark_cache( $link_id ); + + return true; +} + +/** + * Retrieves the link categories associated with the link specified. + * + * @since 2.1.0 + * + * @param int $link_id Link ID to look up + * @return array The requested link's categories + */ +function wp_get_link_cats( $link_id = 0 ) { + + $cats = wp_get_object_terms( $link_id, 'link_category', array('fields' => 'ids') ); + + return array_unique( $cats ); +} + +/** + * Retrieve link data based on ID. + * + * @since 2.0.0 + * + * @param int $link_id ID of link to retrieve + * @return object Link for editing + */ +function get_link_to_edit( $link_id ) { + return get_bookmark( $link_id, OBJECT, 'edit' ); +} + +/** + * This function inserts/updates links into/in the database. + * + * @since 2.0.0 + * + * @param array $linkdata Elements that make up the link to insert. + * @param bool $wp_error Optional. If true return WP_Error object on failure. + * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success. + */ +function wp_insert_link( $linkdata, $wp_error = false ) { + global $wpdb; + + $defaults = array( 'link_id' => 0, 'link_name' => '', 'link_url' => '', 'link_rating' => 0 ); + + $linkdata = wp_parse_args( $linkdata, $defaults ); + $linkdata = sanitize_bookmark( $linkdata, 'db' ); + + extract( wp_unslash( $linkdata ), EXTR_SKIP ); + + $update = false; + + if ( !empty( $link_id ) ) + $update = true; + + if ( trim( $link_name ) == '' ) { + if ( trim( $link_url ) != '' ) { + $link_name = $link_url; + } else { + return 0; + } + } + + if ( trim( $link_url ) == '' ) + return 0; + + if ( empty( $link_rating ) ) + $link_rating = 0; + + if ( empty( $link_image ) ) + $link_image = ''; + + if ( empty( $link_target ) ) + $link_target = ''; + + if ( empty( $link_visible ) ) + $link_visible = 'Y'; + + if ( empty( $link_owner ) ) + $link_owner = get_current_user_id(); + + if ( empty( $link_notes ) ) + $link_notes = ''; + + if ( empty( $link_description ) ) + $link_description = ''; + + if ( empty( $link_rss ) ) + $link_rss = ''; + + if ( empty( $link_rel ) ) + $link_rel = ''; + + // Make sure we set a valid category + if ( ! isset( $link_category ) || 0 == count( $link_category ) || !is_array( $link_category ) ) { + $link_category = array( get_option( 'default_link_category' ) ); + } + + if ( $update ) { + if ( false === $wpdb->update( $wpdb->links, compact('link_url', 'link_name', 'link_image', 'link_target', 'link_description', 'link_visible', 'link_rating', 'link_rel', 'link_notes', 'link_rss'), compact('link_id') ) ) { + if ( $wp_error ) + return new WP_Error( 'db_update_error', __( 'Could not update link in the database' ), $wpdb->last_error ); + else + return 0; + } + } else { + if ( false === $wpdb->insert( $wpdb->links, compact('link_url', 'link_name', 'link_image', 'link_target', 'link_description', 'link_visible', 'link_owner', 'link_rating', 'link_rel', 'link_notes', 'link_rss') ) ) { + if ( $wp_error ) + return new WP_Error( 'db_insert_error', __( 'Could not insert link into the database' ), $wpdb->last_error ); + else + return 0; + } + $link_id = (int) $wpdb->insert_id; + } + + wp_set_link_cats( $link_id, $link_category ); + + if ( $update ) { + /** + * Fires after a link was updated in the database. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link that was updated. + */ + do_action( 'edit_link', $link_id ); + } else { + /** + * Fires after a link was added to the database. + * + * @since 2.0.0 + * + * @param int $link_id ID of the link that was added. + */ + do_action( 'add_link', $link_id ); + } + clean_bookmark_cache( $link_id ); + + return $link_id; +} + +/** + * Update link with the specified link categories. + * + * @since 2.1.0 + * + * @param int $link_id ID of link to update + * @param array $link_categories Array of categories to + */ +function wp_set_link_cats( $link_id = 0, $link_categories = array() ) { + // If $link_categories isn't already an array, make it one: + if ( !is_array( $link_categories ) || 0 == count( $link_categories ) ) + $link_categories = array( get_option( 'default_link_category' ) ); + + $link_categories = array_map( 'intval', $link_categories ); + $link_categories = array_unique( $link_categories ); + + wp_set_object_terms( $link_id, $link_categories, 'link_category' ); + + clean_bookmark_cache( $link_id ); +} + +/** + * Update a link in the database. + * + * @since 2.0.0 + * + * @param array $linkdata Link data to update. + * @return int|WP_Error Value 0 or WP_Error on failure. The updated link ID on success. + */ +function wp_update_link( $linkdata ) { + $link_id = (int) $linkdata['link_id']; + + $link = get_bookmark( $link_id, ARRAY_A ); + + // Escape data pulled from DB. + $link = wp_slash( $link ); + + // Passed link category list overwrites existing category list if not empty. + if ( isset( $linkdata['link_category'] ) && is_array( $linkdata['link_category'] ) + && 0 != count( $linkdata['link_category'] ) ) + $link_cats = $linkdata['link_category']; + else + $link_cats = $link['link_category']; + + // Merge old and new fields with new fields overwriting old ones. + $linkdata = array_merge( $link, $linkdata ); + $linkdata['link_category'] = $link_cats; + + return wp_insert_link( $linkdata ); +} + +/** + * @since 3.5.0 + * @access private + */ +function wp_link_manager_disabled_message() { + global $pagenow; + if ( 'link-manager.php' != $pagenow && 'link-add.php' != $pagenow && 'link.php' != $pagenow ) + return; + + add_filter( 'pre_option_link_manager_enabled', '__return_true', 100 ); + $really_can_manage_links = current_user_can( 'manage_links' ); + remove_filter( 'pre_option_link_manager_enabled', '__return_true', 100 ); + + if ( $really_can_manage_links && current_user_can( 'install_plugins' ) ) { + $link = network_admin_url( 'plugin-install.php?tab=search&s=Link+Manager' ); + wp_die( sprintf( __( 'If you are looking to use the link manager, please install the Link Manager plugin.' ), $link ) ); + } + + wp_die( __( 'You do not have sufficient permissions to edit the links for this site.' ) ); +} +add_action( 'admin_page_access_denied', 'wp_link_manager_disabled_message' ); diff --git a/sources/wp-admin/includes/class-ftp-pure.php b/sources/wp-admin/includes/class-ftp-pure.php new file mode 100644 index 0000000..c765d55 --- /dev/null +++ b/sources/wp-admin/includes/class-ftp-pure.php @@ -0,0 +1,190 @@ +__construct($verb, $le); + } + + function __construct($verb=FALSE, $le=FALSE) { + parent::__construct(false, $verb, $le); + } + +// +// +// + + function _settimeout($sock) { + if(!@stream_set_timeout($sock, $this->_timeout)) { + $this->PushError('_settimeout','socket set send timeout'); + $this->_quit(); + return FALSE; + } + return TRUE; + } + + function _connect($host, $port) { + $this->SendMSG("Creating socket"); + $sock = @fsockopen($host, $port, $errno, $errstr, $this->_timeout); + if (!$sock) { + $this->PushError('_connect','socket connect failed', $errstr." (".$errno.")"); + return FALSE; + } + $this->_connected=true; + return $sock; + } + + function _readmsg($fnction="_readmsg"){ + if(!$this->_connected) { + $this->PushError($fnction, 'Connect first'); + return FALSE; + } + $result=true; + $this->_message=""; + $this->_code=0; + $go=true; + do { + $tmp=@fgets($this->_ftp_control_sock, 512); + if($tmp===false) { + $go=$result=false; + $this->PushError($fnction,'Read failed'); + } else { + $this->_message.=$tmp; + if(preg_match("/^([0-9]{3})(-(.*[".CRLF."]{1,2})+\\1)? [^".CRLF."]+[".CRLF."]{1,2}$/", $this->_message, $regs)) $go=false; + } + } while($go); + if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF; + $this->_code=(int)$regs[1]; + return $result; + } + + function _exec($cmd, $fnction="_exec") { + if(!$this->_ready) { + $this->PushError($fnction,'Connect first'); + return FALSE; + } + if($this->LocalEcho) echo "PUT > ",$cmd,CRLF; + $status=@fputs($this->_ftp_control_sock, $cmd.CRLF); + if($status===false) { + $this->PushError($fnction,'socket write failed'); + return FALSE; + } + $this->_lastaction=time(); + if(!$this->_readmsg($fnction)) return FALSE; + return TRUE; + } + + function _data_prepare($mode=FTP_ASCII) { + if(!$this->_settype($mode)) return FALSE; + if($this->_passive) { + if(!$this->_exec("PASV", "pasv")) { + $this->_data_close(); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + return FALSE; + } + $ip_port = explode(",", ereg_replace("^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*".CRLF."$", "\\1", $this->_message)); + $this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3]; + $this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]); + $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport); + $this->_ftp_data_sock=@fsockopen($this->_datahost, $this->_dataport, $errno, $errstr, $this->_timeout); + if(!$this->_ftp_data_sock) { + $this->PushError("_data_prepare","fsockopen fails", $errstr." (".$errno.")"); + $this->_data_close(); + return FALSE; + } + else $this->_ftp_data_sock; + } else { + $this->SendMSG("Only passive connections available!"); + return FALSE; + } + return TRUE; + } + + function _data_read($mode=FTP_ASCII, $fp=NULL) { + if(is_resource($fp)) $out=0; + else $out=""; + if(!$this->_passive) { + $this->SendMSG("Only passive connections available!"); + return FALSE; + } + while (!feof($this->_ftp_data_sock)) { + $block=fread($this->_ftp_data_sock, $this->_ftp_buff_size); + if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block); + if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block)); + else $out.=$block; + } + return $out; + } + + function _data_write($mode=FTP_ASCII, $fp=NULL) { + if(is_resource($fp)) $out=0; + else $out=""; + if(!$this->_passive) { + $this->SendMSG("Only passive connections available!"); + return FALSE; + } + if(is_resource($fp)) { + while(!feof($fp)) { + $block=fread($fp, $this->_ftp_buff_size); + if(!$this->_data_write_block($mode, $block)) return false; + } + } elseif(!$this->_data_write_block($mode, $fp)) return false; + return TRUE; + } + + function _data_write_block($mode, $block) { + if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block); + do { + if(($t=@fwrite($this->_ftp_data_sock, $block))===FALSE) { + $this->PushError("_data_write","Can't write to socket"); + return FALSE; + } + $block=substr($block, $t); + } while(!empty($block)); + return true; + } + + function _data_close() { + @fclose($this->_ftp_data_sock); + $this->SendMSG("Disconnected data from remote host"); + return TRUE; + } + + function _quit($force=FALSE) { + if($this->_connected or $force) { + @fclose($this->_ftp_control_sock); + $this->_connected=false; + $this->SendMSG("Socket closed"); + } + } +} + +?> diff --git a/sources/wp-admin/includes/class-ftp-sockets.php b/sources/wp-admin/includes/class-ftp-sockets.php new file mode 100644 index 0000000..abdf0db --- /dev/null +++ b/sources/wp-admin/includes/class-ftp-sockets.php @@ -0,0 +1,250 @@ +__construct($verb, $le); + } + + function __construct($verb=FALSE, $le=FALSE) { + parent::__construct(true, $verb, $le); + } + +// +// +// + + function _settimeout($sock) { + if(!@socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) { + $this->PushError('_connect','socket set receive timeout',socket_strerror(socket_last_error($sock))); + @socket_close($sock); + return FALSE; + } + if(!@socket_set_option($sock, SOL_SOCKET , SO_SNDTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) { + $this->PushError('_connect','socket set send timeout',socket_strerror(socket_last_error($sock))); + @socket_close($sock); + return FALSE; + } + return true; + } + + function _connect($host, $port) { + $this->SendMSG("Creating socket"); + if(!($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) { + $this->PushError('_connect','socket create failed',socket_strerror(socket_last_error($sock))); + return FALSE; + } + if(!$this->_settimeout($sock)) return FALSE; + $this->SendMSG("Connecting to \"".$host.":".$port."\""); + if (!($res = @socket_connect($sock, $host, $port))) { + $this->PushError('_connect','socket connect failed',socket_strerror(socket_last_error($sock))); + @socket_close($sock); + return FALSE; + } + $this->_connected=true; + return $sock; + } + + function _readmsg($fnction="_readmsg"){ + if(!$this->_connected) { + $this->PushError($fnction,'Connect first'); + return FALSE; + } + $result=true; + $this->_message=""; + $this->_code=0; + $go=true; + do { + $tmp=@socket_read($this->_ftp_control_sock, 4096, PHP_BINARY_READ); + if($tmp===false) { + $go=$result=false; + $this->PushError($fnction,'Read failed', socket_strerror(socket_last_error($this->_ftp_control_sock))); + } else { + $this->_message.=$tmp; + $go = !preg_match("/^([0-9]{3})(-.+\\1)? [^".CRLF."]+".CRLF."$/Us", $this->_message, $regs); + } + } while($go); + if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF; + $this->_code=(int)$regs[1]; + return $result; + } + + function _exec($cmd, $fnction="_exec") { + if(!$this->_ready) { + $this->PushError($fnction,'Connect first'); + return FALSE; + } + if($this->LocalEcho) echo "PUT > ",$cmd,CRLF; + $status=@socket_write($this->_ftp_control_sock, $cmd.CRLF); + if($status===false) { + $this->PushError($fnction,'socket write failed', socket_strerror(socket_last_error($this->stream))); + return FALSE; + } + $this->_lastaction=time(); + if(!$this->_readmsg($fnction)) return FALSE; + return TRUE; + } + + function _data_prepare($mode=FTP_ASCII) { + if(!$this->_settype($mode)) return FALSE; + $this->SendMSG("Creating data socket"); + $this->_ftp_data_sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + if ($this->_ftp_data_sock < 0) { + $this->PushError('_data_prepare','socket create failed',socket_strerror(socket_last_error($this->_ftp_data_sock))); + return FALSE; + } + if(!$this->_settimeout($this->_ftp_data_sock)) { + $this->_data_close(); + return FALSE; + } + if($this->_passive) { + if(!$this->_exec("PASV", "pasv")) { + $this->_data_close(); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + return FALSE; + } + $ip_port = explode(",", ereg_replace("^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*".CRLF."$", "\\1", $this->_message)); + $this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3]; + $this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]); + $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport); + if(!@socket_connect($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) { + $this->PushError("_data_prepare","socket_connect", socket_strerror(socket_last_error($this->_ftp_data_sock))); + $this->_data_close(); + return FALSE; + } + else $this->_ftp_temp_sock=$this->_ftp_data_sock; + } else { + if(!@socket_getsockname($this->_ftp_control_sock, $addr, $port)) { + $this->PushError("_data_prepare","can't get control socket information", socket_strerror(socket_last_error($this->_ftp_control_sock))); + $this->_data_close(); + return FALSE; + } + if(!@socket_bind($this->_ftp_data_sock,$addr)){ + $this->PushError("_data_prepare","can't bind data socket", socket_strerror(socket_last_error($this->_ftp_data_sock))); + $this->_data_close(); + return FALSE; + } + if(!@socket_listen($this->_ftp_data_sock)) { + $this->PushError("_data_prepare","can't listen data socket", socket_strerror(socket_last_error($this->_ftp_data_sock))); + $this->_data_close(); + return FALSE; + } + if(!@socket_getsockname($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) { + $this->PushError("_data_prepare","can't get data socket information", socket_strerror(socket_last_error($this->_ftp_data_sock))); + $this->_data_close(); + return FALSE; + } + if(!$this->_exec('PORT '.str_replace('.',',',$this->_datahost.'.'.($this->_dataport>>8).'.'.($this->_dataport&0x00FF)), "_port")) { + $this->_data_close(); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + return FALSE; + } + } + return TRUE; + } + + function _data_read($mode=FTP_ASCII, $fp=NULL) { + $NewLine=$this->_eol_code[$this->OS_local]; + if(is_resource($fp)) $out=0; + else $out=""; + if(!$this->_passive) { + $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport); + $this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock); + if($this->_ftp_temp_sock===FALSE) { + $this->PushError("_data_read","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock))); + $this->_data_close(); + return FALSE; + } + } + + while(($block=@socket_read($this->_ftp_temp_sock, $this->_ftp_buff_size, PHP_BINARY_READ))!==false) { + if($block==="") break; + if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block); + if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block)); + else $out.=$block; + } + return $out; + } + + function _data_write($mode=FTP_ASCII, $fp=NULL) { + $NewLine=$this->_eol_code[$this->OS_local]; + if(is_resource($fp)) $out=0; + else $out=""; + if(!$this->_passive) { + $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport); + $this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock); + if($this->_ftp_temp_sock===FALSE) { + $this->PushError("_data_write","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock))); + $this->_data_close(); + return false; + } + } + if(is_resource($fp)) { + while(!feof($fp)) { + $block=fread($fp, $this->_ftp_buff_size); + if(!$this->_data_write_block($mode, $block)) return false; + } + } elseif(!$this->_data_write_block($mode, $fp)) return false; + return true; + } + + function _data_write_block($mode, $block) { + if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block); + do { + if(($t=@socket_write($this->_ftp_temp_sock, $block))===FALSE) { + $this->PushError("_data_write","socket_write", socket_strerror(socket_last_error($this->_ftp_temp_sock))); + $this->_data_close(); + return FALSE; + } + $block=substr($block, $t); + } while(!empty($block)); + return true; + } + + function _data_close() { + @socket_close($this->_ftp_temp_sock); + @socket_close($this->_ftp_data_sock); + $this->SendMSG("Disconnected data from remote host"); + return TRUE; + } + + function _quit() { + if($this->_connected) { + @socket_close($this->_ftp_control_sock); + $this->_connected=false; + $this->SendMSG("Socket closed"); + } + } +} +?> diff --git a/sources/wp-admin/includes/class-ftp.php b/sources/wp-admin/includes/class-ftp.php new file mode 100644 index 0000000..f068f15 --- /dev/null +++ b/sources/wp-admin/includes/class-ftp.php @@ -0,0 +1,907 @@ +__construct($port_mode); + } + + function __construct($port_mode=FALSE, $verb=FALSE, $le=FALSE) { + $this->LocalEcho=$le; + $this->Verbose=$verb; + $this->_lastaction=NULL; + $this->_error_array=array(); + $this->_eol_code=array(FTP_OS_Unix=>"\n", FTP_OS_Mac=>"\r", FTP_OS_Windows=>"\r\n"); + $this->AuthorizedTransferMode=array(FTP_AUTOASCII, FTP_ASCII, FTP_BINARY); + $this->OS_FullName=array(FTP_OS_Unix => 'UNIX', FTP_OS_Windows => 'WINDOWS', FTP_OS_Mac => 'MACOS'); + $this->AutoAsciiExt=array("ASP","BAT","C","CPP","CSS","CSV","JS","H","HTM","HTML","SHTML","INI","LOG","PHP3","PHTML","PL","PERL","SH","SQL","TXT"); + $this->_port_available=($port_mode==TRUE); + $this->SendMSG("Staring FTP client class".($this->_port_available?"":" without PORT mode support")); + $this->_connected=FALSE; + $this->_ready=FALSE; + $this->_can_restore=FALSE; + $this->_code=0; + $this->_message=""; + $this->_ftp_buff_size=4096; + $this->_curtype=NULL; + $this->SetUmask(0022); + $this->SetType(FTP_AUTOASCII); + $this->SetTimeout(30); + $this->Passive(!$this->_port_available); + $this->_login="anonymous"; + $this->_password="anon@ftp.com"; + $this->_features=array(); + $this->OS_local=FTP_OS_Unix; + $this->OS_remote=FTP_OS_Unix; + $this->features=array(); + if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $this->OS_local=FTP_OS_Windows; + elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'MAC') $this->OS_local=FTP_OS_Mac; + } + +// +// +// + + function parselisting($line) { + $is_windows = ($this->OS_remote == FTP_OS_Windows); + if ($is_windows && preg_match("/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|) +(.+)/",$line,$lucifer)) { + $b = array(); + if ($lucifer[3]<70) { $lucifer[3]+=2000; } else { $lucifer[3]+=1900; } // 4digit year fix + $b['isdir'] = ($lucifer[7]==""); + if ( $b['isdir'] ) + $b['type'] = 'd'; + else + $b['type'] = 'f'; + $b['size'] = $lucifer[7]; + $b['month'] = $lucifer[1]; + $b['day'] = $lucifer[2]; + $b['year'] = $lucifer[3]; + $b['hour'] = $lucifer[4]; + $b['minute'] = $lucifer[5]; + $b['time'] = @mktime($lucifer[4]+(strcasecmp($lucifer[6],"PM")==0?12:0),$lucifer[5],0,$lucifer[1],$lucifer[2],$lucifer[3]); + $b['am/pm'] = $lucifer[6]; + $b['name'] = $lucifer[8]; + } else if (!$is_windows && $lucifer=preg_split("/[ ]/",$line,9,PREG_SPLIT_NO_EMPTY)) { + //echo $line."\n"; + $lcount=count($lucifer); + if ($lcount<8) return ''; + $b = array(); + $b['isdir'] = $lucifer[0]{0} === "d"; + $b['islink'] = $lucifer[0]{0} === "l"; + if ( $b['isdir'] ) + $b['type'] = 'd'; + elseif ( $b['islink'] ) + $b['type'] = 'l'; + else + $b['type'] = 'f'; + $b['perms'] = $lucifer[0]; + $b['number'] = $lucifer[1]; + $b['owner'] = $lucifer[2]; + $b['group'] = $lucifer[3]; + $b['size'] = $lucifer[4]; + if ($lcount==8) { + sscanf($lucifer[5],"%d-%d-%d",$b['year'],$b['month'],$b['day']); + sscanf($lucifer[6],"%d:%d",$b['hour'],$b['minute']); + $b['time'] = @mktime($b['hour'],$b['minute'],0,$b['month'],$b['day'],$b['year']); + $b['name'] = $lucifer[7]; + } else { + $b['month'] = $lucifer[5]; + $b['day'] = $lucifer[6]; + if (preg_match("/([0-9]{2}):([0-9]{2})/",$lucifer[7],$l2)) { + $b['year'] = date("Y"); + $b['hour'] = $l2[1]; + $b['minute'] = $l2[2]; + } else { + $b['year'] = $lucifer[7]; + $b['hour'] = 0; + $b['minute'] = 0; + } + $b['time'] = strtotime(sprintf("%d %s %d %02d:%02d",$b['day'],$b['month'],$b['year'],$b['hour'],$b['minute'])); + $b['name'] = $lucifer[8]; + } + } + + return $b; + } + + function SendMSG($message = "", $crlf=true) { + if ($this->Verbose) { + echo $message.($crlf?CRLF:""); + flush(); + } + return TRUE; + } + + function SetType($mode=FTP_AUTOASCII) { + if(!in_array($mode, $this->AuthorizedTransferMode)) { + $this->SendMSG("Wrong type"); + return FALSE; + } + $this->_type=$mode; + $this->SendMSG("Transfer type: ".($this->_type==FTP_BINARY?"binary":($this->_type==FTP_ASCII?"ASCII":"auto ASCII") ) ); + return TRUE; + } + + function _settype($mode=FTP_ASCII) { + if($this->_ready) { + if($mode==FTP_BINARY) { + if($this->_curtype!=FTP_BINARY) { + if(!$this->_exec("TYPE I", "SetType")) return FALSE; + $this->_curtype=FTP_BINARY; + } + } elseif($this->_curtype!=FTP_ASCII) { + if(!$this->_exec("TYPE A", "SetType")) return FALSE; + $this->_curtype=FTP_ASCII; + } + } else return FALSE; + return TRUE; + } + + function Passive($pasv=NULL) { + if(is_null($pasv)) $this->_passive=!$this->_passive; + else $this->_passive=$pasv; + if(!$this->_port_available and !$this->_passive) { + $this->SendMSG("Only passive connections available!"); + $this->_passive=TRUE; + return FALSE; + } + $this->SendMSG("Passive mode ".($this->_passive?"on":"off")); + return TRUE; + } + + function SetServer($host, $port=21, $reconnect=true) { + if(!is_long($port)) { + $this->verbose=true; + $this->SendMSG("Incorrect port syntax"); + return FALSE; + } else { + $ip=@gethostbyname($host); + $dns=@gethostbyaddr($host); + if(!$ip) $ip=$host; + if(!$dns) $dns=$host; + // Validate the IPAddress PHP4 returns -1 for invalid, PHP5 false + // -1 === "255.255.255.255" which is the broadcast address which is also going to be invalid + $ipaslong = ip2long($ip); + if ( ($ipaslong == false) || ($ipaslong === -1) ) { + $this->SendMSG("Wrong host name/address \"".$host."\""); + return FALSE; + } + $this->_host=$ip; + $this->_fullhost=$dns; + $this->_port=$port; + $this->_dataport=$port-1; + } + $this->SendMSG("Host \"".$this->_fullhost."(".$this->_host."):".$this->_port."\""); + if($reconnect){ + if($this->_connected) { + $this->SendMSG("Reconnecting"); + if(!$this->quit(FTP_FORCE)) return FALSE; + if(!$this->connect()) return FALSE; + } + } + return TRUE; + } + + function SetUmask($umask=0022) { + $this->_umask=$umask; + umask($this->_umask); + $this->SendMSG("UMASK 0".decoct($this->_umask)); + return TRUE; + } + + function SetTimeout($timeout=30) { + $this->_timeout=$timeout; + $this->SendMSG("Timeout ".$this->_timeout); + if($this->_connected) + if(!$this->_settimeout($this->_ftp_control_sock)) return FALSE; + return TRUE; + } + + function connect($server=NULL) { + if(!empty($server)) { + if(!$this->SetServer($server)) return false; + } + if($this->_ready) return true; + $this->SendMsg('Local OS : '.$this->OS_FullName[$this->OS_local]); + if(!($this->_ftp_control_sock = $this->_connect($this->_host, $this->_port))) { + $this->SendMSG("Error : Cannot connect to remote host \"".$this->_fullhost." :".$this->_port."\""); + return FALSE; + } + $this->SendMSG("Connected to remote host \"".$this->_fullhost.":".$this->_port."\". Waiting for greeting."); + do { + if(!$this->_readmsg()) return FALSE; + if(!$this->_checkCode()) return FALSE; + $this->_lastaction=time(); + } while($this->_code<200); + $this->_ready=true; + $syst=$this->systype(); + if(!$syst) $this->SendMSG("Can't detect remote OS"); + else { + if(preg_match("/win|dos|novell/i", $syst[0])) $this->OS_remote=FTP_OS_Windows; + elseif(preg_match("/os/i", $syst[0])) $this->OS_remote=FTP_OS_Mac; + elseif(preg_match("/(li|u)nix/i", $syst[0])) $this->OS_remote=FTP_OS_Unix; + else $this->OS_remote=FTP_OS_Mac; + $this->SendMSG("Remote OS: ".$this->OS_FullName[$this->OS_remote]); + } + if(!$this->features()) $this->SendMSG("Can't get features list. All supported - disabled"); + else $this->SendMSG("Supported features: ".implode(", ", array_keys($this->_features))); + return TRUE; + } + + function quit($force=false) { + if($this->_ready) { + if(!$this->_exec("QUIT") and !$force) return FALSE; + if(!$this->_checkCode() and !$force) return FALSE; + $this->_ready=false; + $this->SendMSG("Session finished"); + } + $this->_quit(); + return TRUE; + } + + function login($user=NULL, $pass=NULL) { + if(!is_null($user)) $this->_login=$user; + else $this->_login="anonymous"; + if(!is_null($pass)) $this->_password=$pass; + else $this->_password="anon@anon.com"; + if(!$this->_exec("USER ".$this->_login, "login")) return FALSE; + if(!$this->_checkCode()) return FALSE; + if($this->_code!=230) { + if(!$this->_exec((($this->_code==331)?"PASS ":"ACCT ").$this->_password, "login")) return FALSE; + if(!$this->_checkCode()) return FALSE; + } + $this->SendMSG("Authentication succeeded"); + if(empty($this->_features)) { + if(!$this->features()) $this->SendMSG("Can't get features list. All supported - disabled"); + else $this->SendMSG("Supported features: ".implode(", ", array_keys($this->_features))); + } + return TRUE; + } + + function pwd() { + if(!$this->_exec("PWD", "pwd")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return ereg_replace("^[0-9]{3} \"(.+)\".+", "\\1", $this->_message); + } + + function cdup() { + if(!$this->_exec("CDUP", "cdup")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return true; + } + + function chdir($pathname) { + if(!$this->_exec("CWD ".$pathname, "chdir")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return TRUE; + } + + function rmdir($pathname) { + if(!$this->_exec("RMD ".$pathname, "rmdir")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return TRUE; + } + + function mkdir($pathname) { + if(!$this->_exec("MKD ".$pathname, "mkdir")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return TRUE; + } + + function rename($from, $to) { + if(!$this->_exec("RNFR ".$from, "rename")) return FALSE; + if(!$this->_checkCode()) return FALSE; + if($this->_code==350) { + if(!$this->_exec("RNTO ".$to, "rename")) return FALSE; + if(!$this->_checkCode()) return FALSE; + } else return FALSE; + return TRUE; + } + + function filesize($pathname) { + if(!isset($this->_features["SIZE"])) { + $this->PushError("filesize", "not supported by server"); + return FALSE; + } + if(!$this->_exec("SIZE ".$pathname, "filesize")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return ereg_replace("^[0-9]{3} ([0-9]+)".CRLF, "\\1", $this->_message); + } + + function abort() { + if(!$this->_exec("ABOR", "abort")) return FALSE; + if(!$this->_checkCode()) { + if($this->_code!=426) return FALSE; + if(!$this->_readmsg("abort")) return FALSE; + if(!$this->_checkCode()) return FALSE; + } + return true; + } + + function mdtm($pathname) { + if(!isset($this->_features["MDTM"])) { + $this->PushError("mdtm", "not supported by server"); + return FALSE; + } + if(!$this->_exec("MDTM ".$pathname, "mdtm")) return FALSE; + if(!$this->_checkCode()) return FALSE; + $mdtm = ereg_replace("^[0-9]{3} ([0-9]+)".CRLF, "\\1", $this->_message); + $date = sscanf($mdtm, "%4d%2d%2d%2d%2d%2d"); + $timestamp = mktime($date[3], $date[4], $date[5], $date[1], $date[2], $date[0]); + return $timestamp; + } + + function systype() { + if(!$this->_exec("SYST", "systype")) return FALSE; + if(!$this->_checkCode()) return FALSE; + $DATA = explode(" ", $this->_message); + return array($DATA[1], $DATA[3]); + } + + function delete($pathname) { + if(!$this->_exec("DELE ".$pathname, "delete")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return TRUE; + } + + function site($command, $fnction="site") { + if(!$this->_exec("SITE ".$command, $fnction)) return FALSE; + if(!$this->_checkCode()) return FALSE; + return TRUE; + } + + function chmod($pathname, $mode) { + if(!$this->site( sprintf('CHMOD %o %s', $mode, $pathname), "chmod")) return FALSE; + return TRUE; + } + + function restore($from) { + if(!isset($this->_features["REST"])) { + $this->PushError("restore", "not supported by server"); + return FALSE; + } + if($this->_curtype!=FTP_BINARY) { + $this->PushError("restore", "can't restore in ASCII mode"); + return FALSE; + } + if(!$this->_exec("REST ".$from, "resore")) return FALSE; + if(!$this->_checkCode()) return FALSE; + return TRUE; + } + + function features() { + if(!$this->_exec("FEAT", "features")) return FALSE; + if(!$this->_checkCode()) return FALSE; + $f=preg_split("/[".CRLF."]+/", preg_replace("/[0-9]{3}[ -].*[".CRLF."]+/", "", $this->_message), -1, PREG_SPLIT_NO_EMPTY); + $this->_features=array(); + foreach($f as $k=>$v) { + $v=explode(" ", trim($v)); + $this->_features[array_shift($v)]=$v; + } + return true; + } + + function rawlist($pathname="", $arg="") { + return $this->_list(($arg?" ".$arg:"").($pathname?" ".$pathname:""), "LIST", "rawlist"); + } + + function nlist($pathname="") { + return $this->_list(($arg?" ".$arg:"").($pathname?" ".$pathname:""), "NLST", "nlist"); + } + + function is_exists($pathname) { + return $this->file_exists($pathname); + } + + function file_exists($pathname) { + $exists=true; + if(!$this->_exec("RNFR ".$pathname, "rename")) $exists=FALSE; + else { + if(!$this->_checkCode()) $exists=FALSE; + $this->abort(); + } + if($exists) $this->SendMSG("Remote file ".$pathname." exists"); + else $this->SendMSG("Remote file ".$pathname." does not exist"); + return $exists; + } + + function fget($fp, $remotefile,$rest=0) { + if($this->_can_restore and $rest!=0) fseek($fp, $rest); + $pi=pathinfo($remotefile); + if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; + else $mode=FTP_BINARY; + if(!$this->_data_prepare($mode)) { + return FALSE; + } + if($this->_can_restore and $rest!=0) $this->restore($rest); + if(!$this->_exec("RETR ".$remotefile, "get")) { + $this->_data_close(); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + return FALSE; + } + $out=$this->_data_read($mode, $fp); + $this->_data_close(); + if(!$this->_readmsg()) return FALSE; + if(!$this->_checkCode()) return FALSE; + return $out; + } + + function get($remotefile, $localfile=NULL, $rest=0) { + if(is_null($localfile)) $localfile=$remotefile; + if (@file_exists($localfile)) $this->SendMSG("Warning : local file will be overwritten"); + $fp = @fopen($localfile, "w"); + if (!$fp) { + $this->PushError("get","can't open local file", "Cannot create \"".$localfile."\""); + return FALSE; + } + if($this->_can_restore and $rest!=0) fseek($fp, $rest); + $pi=pathinfo($remotefile); + if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; + else $mode=FTP_BINARY; + if(!$this->_data_prepare($mode)) { + fclose($fp); + return FALSE; + } + if($this->_can_restore and $rest!=0) $this->restore($rest); + if(!$this->_exec("RETR ".$remotefile, "get")) { + $this->_data_close(); + fclose($fp); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + fclose($fp); + return FALSE; + } + $out=$this->_data_read($mode, $fp); + fclose($fp); + $this->_data_close(); + if(!$this->_readmsg()) return FALSE; + if(!$this->_checkCode()) return FALSE; + return $out; + } + + function fput($remotefile, $fp) { + if($this->_can_restore and $rest!=0) fseek($fp, $rest); + $pi=pathinfo($remotefile); + if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; + else $mode=FTP_BINARY; + if(!$this->_data_prepare($mode)) { + return FALSE; + } + if($this->_can_restore and $rest!=0) $this->restore($rest); + if(!$this->_exec("STOR ".$remotefile, "put")) { + $this->_data_close(); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + return FALSE; + } + $ret=$this->_data_write($mode, $fp); + $this->_data_close(); + if(!$this->_readmsg()) return FALSE; + if(!$this->_checkCode()) return FALSE; + return $ret; + } + + function put($localfile, $remotefile=NULL, $rest=0) { + if(is_null($remotefile)) $remotefile=$localfile; + if (!file_exists($localfile)) { + $this->PushError("put","can't open local file", "No such file or directory \"".$localfile."\""); + return FALSE; + } + $fp = @fopen($localfile, "r"); + + if (!$fp) { + $this->PushError("put","can't open local file", "Cannot read file \"".$localfile."\""); + return FALSE; + } + if($this->_can_restore and $rest!=0) fseek($fp, $rest); + $pi=pathinfo($localfile); + if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII; + else $mode=FTP_BINARY; + if(!$this->_data_prepare($mode)) { + fclose($fp); + return FALSE; + } + if($this->_can_restore and $rest!=0) $this->restore($rest); + if(!$this->_exec("STOR ".$remotefile, "put")) { + $this->_data_close(); + fclose($fp); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + fclose($fp); + return FALSE; + } + $ret=$this->_data_write($mode, $fp); + fclose($fp); + $this->_data_close(); + if(!$this->_readmsg()) return FALSE; + if(!$this->_checkCode()) return FALSE; + return $ret; + } + + function mput($local=".", $remote=NULL, $continious=false) { + $local=realpath($local); + if(!@file_exists($local)) { + $this->PushError("mput","can't open local folder", "Cannot stat folder \"".$local."\""); + return FALSE; + } + if(!is_dir($local)) return $this->put($local, $remote); + if(empty($remote)) $remote="."; + elseif(!$this->file_exists($remote) and !$this->mkdir($remote)) return FALSE; + if($handle = opendir($local)) { + $list=array(); + while (false !== ($file = readdir($handle))) { + if ($file != "." && $file != "..") $list[]=$file; + } + closedir($handle); + } else { + $this->PushError("mput","can't open local folder", "Cannot read folder \"".$local."\""); + return FALSE; + } + if(empty($list)) return TRUE; + $ret=true; + foreach($list as $el) { + if(is_dir($local."/".$el)) $t=$this->mput($local."/".$el, $remote."/".$el); + else $t=$this->put($local."/".$el, $remote."/".$el); + if(!$t) { + $ret=FALSE; + if(!$continious) break; + } + } + return $ret; + + } + + function mget($remote, $local=".", $continious=false) { + $list=$this->rawlist($remote, "-lA"); + if($list===false) { + $this->PushError("mget","can't read remote folder list", "Can't read remote folder \"".$remote."\" contents"); + return FALSE; + } + if(empty($list)) return true; + if(!@file_exists($local)) { + if(!@mkdir($local)) { + $this->PushError("mget","can't create local folder", "Cannot create folder \"".$local."\""); + return FALSE; + } + } + foreach($list as $k=>$v) { + $list[$k]=$this->parselisting($v); + if($list[$k]["name"]=="." or $list[$k]["name"]=="..") unset($list[$k]); + } + $ret=true; + foreach($list as $el) { + if($el["type"]=="d") { + if(!$this->mget($remote."/".$el["name"], $local."/".$el["name"], $continious)) { + $this->PushError("mget", "can't copy folder", "Can't copy remote folder \"".$remote."/".$el["name"]."\" to local \"".$local."/".$el["name"]."\""); + $ret=false; + if(!$continious) break; + } + } else { + if(!$this->get($remote."/".$el["name"], $local."/".$el["name"])) { + $this->PushError("mget", "can't copy file", "Can't copy remote file \"".$remote."/".$el["name"]."\" to local \"".$local."/".$el["name"]."\""); + $ret=false; + if(!$continious) break; + } + } + @chmod($local."/".$el["name"], $el["perms"]); + $t=strtotime($el["date"]); + if($t!==-1 and $t!==false) @touch($local."/".$el["name"], $t); + } + return $ret; + } + + function mdel($remote, $continious=false) { + $list=$this->rawlist($remote, "-la"); + if($list===false) { + $this->PushError("mdel","can't read remote folder list", "Can't read remote folder \"".$remote."\" contents"); + return false; + } + + foreach($list as $k=>$v) { + $list[$k]=$this->parselisting($v); + if($list[$k]["name"]=="." or $list[$k]["name"]=="..") unset($list[$k]); + } + $ret=true; + + foreach($list as $el) { + if ( empty($el) ) + continue; + + if($el["type"]=="d") { + if(!$this->mdel($remote."/".$el["name"], $continious)) { + $ret=false; + if(!$continious) break; + } + } else { + if (!$this->delete($remote."/".$el["name"])) { + $this->PushError("mdel", "can't delete file", "Can't delete remote file \"".$remote."/".$el["name"]."\""); + $ret=false; + if(!$continious) break; + } + } + } + + if(!$this->rmdir($remote)) { + $this->PushError("mdel", "can't delete folder", "Can't delete remote folder \"".$remote."/".$el["name"]."\""); + $ret=false; + } + return $ret; + } + + function mmkdir($dir, $mode = 0777) { + if(empty($dir)) return FALSE; + if($this->is_exists($dir) or $dir == "/" ) return TRUE; + if(!$this->mmkdir(dirname($dir), $mode)) return false; + $r=$this->mkdir($dir, $mode); + $this->chmod($dir,$mode); + return $r; + } + + function glob($pattern, $handle=NULL) { + $path=$output=null; + if(PHP_OS=='WIN32') $slash='\\'; + else $slash='/'; + $lastpos=strrpos($pattern,$slash); + if(!($lastpos===false)) { + $path=substr($pattern,0,-$lastpos-1); + $pattern=substr($pattern,$lastpos); + } else $path=getcwd(); + if(is_array($handle) and !empty($handle)) { + while($dir=each($handle)) { + if($this->glob_pattern_match($pattern,$dir)) + $output[]=$dir; + } + } else { + $handle=@opendir($path); + if($handle===false) return false; + while($dir=readdir($handle)) { + if($this->glob_pattern_match($pattern,$dir)) + $output[]=$dir; + } + closedir($handle); + } + if(is_array($output)) return $output; + return false; + } + + function glob_pattern_match($pattern,$string) { + $out=null; + $chunks=explode(';',$pattern); + foreach($chunks as $pattern) { + $escape=array('$','^','.','{','}','(',')','[',']','|'); + while(strpos($pattern,'**')!==false) + $pattern=str_replace('**','*',$pattern); + foreach($escape as $probe) + $pattern=str_replace($probe,"\\$probe",$pattern); + $pattern=str_replace('?*','*', + str_replace('*?','*', + str_replace('*',".*", + str_replace('?','.{1,1}',$pattern)))); + $out[]=$pattern; + } + if(count($out)==1) return($this->glob_regexp("^$out[0]$",$string)); + else { + foreach($out as $tester) + if($this->my_regexp("^$tester$",$string)) return true; + } + return false; + } + + function glob_regexp($pattern,$probe) { + $sensitive=(PHP_OS!='WIN32'); + return ($sensitive? + ereg($pattern,$probe): + eregi($pattern,$probe) + ); + } + + function dirlist($remote) { + $list=$this->rawlist($remote, "-la"); + if($list===false) { + $this->PushError("dirlist","can't read remote folder list", "Can't read remote folder \"".$remote."\" contents"); + return false; + } + + $dirlist = array(); + foreach($list as $k=>$v) { + $entry=$this->parselisting($v); + if ( empty($entry) ) + continue; + + if($entry["name"]=="." or $entry["name"]=="..") + continue; + + $dirlist[$entry['name']] = $entry; + } + + return $dirlist; + } +// +// +// + function _checkCode() { + return ($this->_code<400 and $this->_code>0); + } + + function _list($arg="", $cmd="LIST", $fnction="_list") { + if(!$this->_data_prepare()) return false; + if(!$this->_exec($cmd.$arg, $fnction)) { + $this->_data_close(); + return FALSE; + } + if(!$this->_checkCode()) { + $this->_data_close(); + return FALSE; + } + $out=""; + if($this->_code<200) { + $out=$this->_data_read(); + $this->_data_close(); + if(!$this->_readmsg()) return FALSE; + if(!$this->_checkCode()) return FALSE; + if($out === FALSE ) return FALSE; + $out=preg_split("/[".CRLF."]+/", $out, -1, PREG_SPLIT_NO_EMPTY); +// $this->SendMSG(implode($this->_eol_code[$this->OS_local], $out)); + } + return $out; + } + +// +// +// +// Gnre une erreur pour traitement externe la classe + function PushError($fctname,$msg,$desc=false){ + $error=array(); + $error['time']=time(); + $error['fctname']=$fctname; + $error['msg']=$msg; + $error['desc']=$desc; + if($desc) $tmp=' ('.$desc.')'; else $tmp=''; + $this->SendMSG($fctname.': '.$msg.$tmp); + return(array_push($this->_error_array,$error)); + } + +// Rcupre une erreur externe + function PopError(){ + if(count($this->_error_array)) return(array_pop($this->_error_array)); + else return(false); + } +} + +$mod_sockets = extension_loaded( 'sockets' ); +if ( ! $mod_sockets && function_exists( 'dl' ) && is_callable( 'dl' ) ) { + $prefix = ( PHP_SHLIB_SUFFIX == 'dll' ) ? 'php_' : ''; + @dl( $prefix . 'sockets.' . PHP_SHLIB_SUFFIX ); + $mod_sockets = extension_loaded( 'sockets' ); +} + +require_once "class-ftp-" . ( $mod_sockets ? "sockets" : "pure" ) . ".php"; +?> diff --git a/sources/wp-admin/includes/class-pclzip.php b/sources/wp-admin/includes/class-pclzip.php new file mode 100644 index 0000000..5e6a619 --- /dev/null +++ b/sources/wp-admin/includes/class-pclzip.php @@ -0,0 +1,5687 @@ +zipname = $p_zipname; + $this->zip_fd = 0; + $this->magic_quotes_status = -1; + + // ----- Return + return; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // create($p_filelist, $p_add_dir="", $p_remove_dir="") + // create($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two different synopsis. The first one is historical. + // This method creates a Zip Archive. The Zip file is created in the + // filesystem. The files and directories indicated in $p_filelist + // are added in the archive. See the parameters description for the + // supported format of $p_filelist. + // When a directory is in the list, the directory and its content is added + // in the archive. + // In this synopsis, the function takes an optional variable list of + // options. See bellow the supported options. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function create($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove from the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Invalid number / type of arguments"); + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + if ($v_string != '') { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + else { + } + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // add($p_filelist, $p_add_dir="", $p_remove_dir="") + // add($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two synopsis. The first one is historical. + // This methods add the list of files in an existing archive. + // If a file with the same name already exists, it is added at the end of the + // archive, the first one is still present. + // If the archive does not exist, it is created. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_OPT_ADD_COMMENT : + // PCLZIP_OPT_PREPEND_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function add($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_ADD_COMMENT => 'optional', + PCLZIP_OPT_PREPEND_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : listContent() + // Description : + // This public method, gives the list of the files and directories, with their + // properties. + // The properties of each entries in the list are (used also in other functions) : + // filename : Name of the file. For a create or add action it is the filename + // given by the user. For an extract function it is the filename + // of the extracted file. + // stored_filename : Name of the file / directory stored in the archive. + // size : Size of the stored file. + // compressed_size : Size of the file's data compressed in the archive + // (without the headers overhead) + // mtime : Last known modification date of the file (UNIX timestamp) + // comment : Comment associated with the file + // folder : true | false + // index : index of the file in the archive + // status : status of the action (depending of the action) : + // Values are : + // ok : OK ! + // filtered : the file / dir is not extracted (filtered by user) + // already_a_directory : the file can not be extracted because a + // directory with the same name already exists + // write_protected : the file can not be extracted because a file + // with the same name already exists and is + // write protected + // newer_exist : the file was not extracted because a newer file exists + // path_creation_fail : the file is not extracted because the folder + // does not exist and can not be created + // write_error : the file was not extracted because there was a + // error while writing the file + // read_error : the file was not extracted because there was a error + // while reading the file + // invalid_header : the file was not extracted because of an archive + // format error (bad file header) + // Note that each time a method can continue operating when there + // is an action error on a file, the error is only logged in the file status. + // Return Values : + // 0 on an unrecoverable failure, + // The list of the files in the archive. + // -------------------------------------------------------------------------------- + function listContent() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Call the extracting fct + $p_list = array(); + if (($v_result = $this->privList($p_list)) != 1) + { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // extract($p_path="./", $p_remove_path="") + // extract([$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method extract all the files / directories from the archive to the + // folder indicated in $p_path. + // If you want to ignore the 'root' part of path of the memorized files + // you can indicate this in the optional $p_remove_path parameter. + // By default, if a newer file with the same name already exists, the + // file is not extracted. + // + // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions + // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append + // at the end of the path value of PCLZIP_OPT_PATH. + // Parameters : + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 or a negative value on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function extract() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Trace + + // ----- Call the extracting fct + $p_list = array(); + $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, + $v_remove_all_path, $v_options); + if ($v_result < 1) { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + + // -------------------------------------------------------------------------------- + // Function : + // extractByIndex($p_index, $p_path="./", $p_remove_path="") + // extractByIndex($p_index, [$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method is doing a partial extract of the archive. + // The extracted files or folders are identified by their index in the + // archive (from 0 to n). + // Note that if the index identify a folder, only the folder entry is + // extracted, not all the files included in the archive. + // Parameters : + // $p_index : A single index (integer) or a string of indexes of files to + // extract. The form of the string is "0,4-6,8-12" with only numbers + // and '-' for range or ',' to separate ranges. No spaces or ';' + // are allowed. + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and + // not as files. + // The resulting content is in a new field 'content' in the file + // structure. + // This option must be used alone (any other options are ignored). + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + //function extractByIndex($p_index, options...) + function extractByIndex($p_index) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) { + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + } + else { + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Trace + + // ----- Trick + // Here I want to reuse extractByRule(), so I need to parse the $p_index + // with privParseOptions() + $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index); + $v_options_trick = array(); + $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, + array (PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX]; + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Call the extracting fct + if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) { + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // delete([$p_option, $p_option_value, ...]) + // Description : + // This method removes files from the archive. + // If no parameters are given, then all the archive is emptied. + // Parameters : + // None or optional arguments. + // Options : + // PCLZIP_OPT_BY_INDEX : + // PCLZIP_OPT_BY_NAME : + // PCLZIP_OPT_BY_EREG : + // PCLZIP_OPT_BY_PREG : + // Return Values : + // 0 on failure, + // The list of the files which are still present in the archive. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function delete() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Call the delete fct + $v_list = array(); + if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) { + $this->privSwapBackMagicQuotes(); + unset($v_list); + return(0); + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : deleteByIndex() + // Description : + // ***** Deprecated ***** + // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered. + // -------------------------------------------------------------------------------- + function deleteByIndex($p_index) + { + + $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index); + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : properties() + // Description : + // This method gives the properties of the archive. + // The properties are : + // nb : Number of files in the archive + // comment : Comment associated with the archive file + // status : not_exist, ok + // Parameters : + // None + // Return Values : + // 0 on failure, + // An array with the archive properties. + // -------------------------------------------------------------------------------- + function properties() + { + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + $this->privSwapBackMagicQuotes(); + return(0); + } + + // ----- Default properties + $v_prop = array(); + $v_prop['comment'] = ''; + $v_prop['nb'] = 0; + $v_prop['status'] = 'not_exist'; + + // ----- Look if file exists + if (@is_file($this->zipname)) + { + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return 0; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return 0; + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Set the user attributes + $v_prop['comment'] = $v_central_dir['comment']; + $v_prop['nb'] = $v_central_dir['entries']; + $v_prop['status'] = 'ok'; + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_prop; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : duplicate() + // Description : + // This method creates an archive by copying the content of an other one. If + // the archive already exist, it is replaced by the new one without any warning. + // Parameters : + // $p_archive : The filename of a valid archive, or + // a valid PclZip object. + // Return Values : + // 1 on success. + // 0 or a negative value on error (error code). + // -------------------------------------------------------------------------------- + function duplicate($p_archive) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the $p_archive is a PclZip object + if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) + { + + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive->zipname); + } + + // ----- Look if the $p_archive is a string (so a filename) + else if (is_string($p_archive)) + { + + // ----- Check that $p_archive is a valid zip file + // TBC : Should also check the archive format + if (!is_file($p_archive)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'"); + $v_result = PCLZIP_ERR_MISSING_FILE; + } + else { + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive); + } + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : merge() + // Description : + // This method merge the $p_archive_to_add archive at the end of the current + // one ($this). + // If the archive ($this) does not exist, the merge becomes a duplicate. + // If the $p_archive_to_add archive does not exist, the merge is a success. + // Parameters : + // $p_archive_to_add : It can be directly the filename of a valid zip archive, + // or a PclZip object archive. + // Return Values : + // 1 on success, + // 0 or negative values on error (see below). + // -------------------------------------------------------------------------------- + function merge($p_archive_to_add) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Look if the $p_archive_to_add is a PclZip object + if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) + { + + // ----- Merge the archive + $v_result = $this->privMerge($p_archive_to_add); + } + + // ----- Look if the $p_archive_to_add is a string (so a filename) + else if (is_string($p_archive_to_add)) + { + + // ----- Create a temporary archive + $v_object_archive = new PclZip($p_archive_to_add); + + // ----- Merge the archive + $v_result = $this->privMerge($v_object_archive); + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : errorCode() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorCode() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorCode()); + } + else { + return($this->error_code); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorName() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorName($p_with_code=false) + { + $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR', + PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL', + PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL', + PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER', + PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE', + PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG', + PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP', + PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE', + PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL', + PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION', + PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT', + PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL', + PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL', + PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM', + PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', + PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE', + PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE', + PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', + PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' + ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE' + ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION' + ); + + if (isset($v_name[$this->error_code])) { + $v_value = $v_name[$this->error_code]; + } + else { + $v_value = 'NoName'; + } + + if ($p_with_code) { + return($v_value.' ('.$this->error_code.')'); + } + else { + return($v_value); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorInfo() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorInfo($p_full=false) + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorString()); + } + else { + if ($p_full) { + return($this->errorName(true)." : ".$this->error_string); + } + else { + return($this->error_string." [code ".$this->error_code."]"); + } + } + } + // -------------------------------------------------------------------------------- + + +// -------------------------------------------------------------------------------- +// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** +// ***** ***** +// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** +// -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : privCheckFormat() + // Description : + // This method check that the archive exists and is a valid zip archive. + // Several level of check exists. (futur) + // Parameters : + // $p_level : Level of check. Default 0. + // 0 : Check the first bytes (magic codes) (default value)) + // 1 : 0 + Check the central directory (futur) + // 2 : 1 + Check each file header (futur) + // Return Values : + // true on success, + // false on error, the error code is set. + // -------------------------------------------------------------------------------- + function privCheckFormat($p_level=0) + { + $v_result = true; + + // ----- Reset the file system cache + clearstatcache(); + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the file exits + if (!is_file($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'"); + return(false); + } + + // ----- Check that the file is readeable + if (!is_readable($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'"); + return(false); + } + + // ----- Check the magic code + // TBC + + // ----- Check the central header + // TBC + + // ----- Check each file header + // TBC + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privParseOptions() + // Description : + // This internal methods reads the variable list of arguments ($p_options_list, + // $p_size) and generate an array with the options and values ($v_result_list). + // $v_requested_options contains the options that can be present and those that + // must be present. + // $v_requested_options is an array, with the option value as key, and 'optional', + // or 'mandatory' as value. + // Parameters : + // See above. + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false) + { + $v_result=1; + + // ----- Read the options + $i=0; + while ($i<$p_size) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$p_options_list[$i]])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for next option + switch ($p_options_list[$i]) { + // ----- Look for options that request a path value + case PCLZIP_OPT_PATH : + case PCLZIP_OPT_REMOVE_PATH : + case PCLZIP_OPT_ADD_PATH : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_THRESHOLD : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + // ----- Check the value + $v_value = $p_options_list[$i+1]; + if ((!is_integer($v_value)) || ($v_value<0)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Get the value (and convert it in bytes) + $v_result_list[$p_options_list[$i]] = $v_value*1048576; + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_ON : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_TEMP_FILE_OFF : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'"); + return PclZip::errorCode(); + } + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if ( is_string($p_options_list[$i+1]) + && ($p_options_list[$i+1] != '')) { + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + } + else { + } + break; + + // ----- Look for options that request an array of string for value + case PCLZIP_OPT_BY_NAME : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an EREG or PREG expression + case PCLZIP_OPT_BY_EREG : + // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG + // to PCLZIP_OPT_BY_PREG + $p_options_list[$i] = PCLZIP_OPT_BY_PREG; + case PCLZIP_OPT_BY_PREG : + //case PCLZIP_OPT_CRYPT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that takes a string + case PCLZIP_OPT_COMMENT : + case PCLZIP_OPT_ADD_COMMENT : + case PCLZIP_OPT_PREPEND_COMMENT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, + "Missing parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, + "Wrong parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an array of index + case PCLZIP_OPT_BY_INDEX : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_work_list = array(); + if (is_string($p_options_list[$i+1])) { + + // ----- Remove spaces + $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', ''); + + // ----- Parse items + $v_work_list = explode(",", $p_options_list[$i+1]); + } + else if (is_integer($p_options_list[$i+1])) { + $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_work_list = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Reduce the index list + // each index item in the list must be a couple with a start and + // an end value : [0,3], [5-5], [8-10], ... + // ----- Check the format of each item + $v_sort_flag=false; + $v_sort_value=0; + for ($j=0; $j= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + $i++; + break; + + // ----- Look for options that request a call-back + case PCLZIP_CB_PRE_EXTRACT : + case PCLZIP_CB_POST_EXTRACT : + case PCLZIP_CB_PRE_ADD : + case PCLZIP_CB_POST_ADD : + /* for futur use + case PCLZIP_CB_PRE_DELETE : + case PCLZIP_CB_POST_DELETE : + case PCLZIP_CB_PRE_LIST : + case PCLZIP_CB_POST_LIST : + */ + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_function_name = $p_options_list[$i+1]; + + // ----- Check that the value is a valid existing function + if (!function_exists($v_function_name)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Set the attribute + $v_result_list[$p_options_list[$i]] = $v_function_name; + $i++; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '" + .$p_options_list[$i]."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Next options + $i++; + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($v_result_list[$key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + + // ----- Return + return PclZip::errorCode(); + } + } + } + } + + // ----- Look for default values + if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOptionDefaultThreshold() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privOptionDefaultThreshold(&$p_options) + { + $v_result=1; + + if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) { + return $v_result; + } + + // ----- Get 'memory_limit' configuration value + $v_memory_limit = ini_get('memory_limit'); + $v_memory_limit = trim($v_memory_limit); + $last = strtolower(substr($v_memory_limit, -1)); + + if($last == 'g') + //$v_memory_limit = $v_memory_limit*1024*1024*1024; + $v_memory_limit = $v_memory_limit*1073741824; + if($last == 'm') + //$v_memory_limit = $v_memory_limit*1024*1024; + $v_memory_limit = $v_memory_limit*1048576; + if($last == 'k') + $v_memory_limit = $v_memory_limit*1024; + + $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO); + + + // ----- Sanity check : No threshold if value lower than 1M + if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) { + unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrParseAtt() + // Description : + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false) + { + $v_result=1; + + // ----- For each file in the list check the attributes + foreach ($p_file_list as $v_key => $v_value) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$v_key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for attribute + switch ($v_key) { + case PCLZIP_ATT_FILE_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['filename'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['filename'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + break; + + case PCLZIP_ATT_FILE_NEW_SHORT_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_short_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + case PCLZIP_ATT_FILE_NEW_FULL_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_full_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + // ----- Look for options that takes a string + case PCLZIP_ATT_FILE_COMMENT : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['comment'] = $v_value; + break; + + case PCLZIP_ATT_FILE_MTIME : + if (!is_integer($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['mtime'] = $v_value; + break; + + case PCLZIP_ATT_FILE_CONTENT : + $p_filedescr['content'] = $v_value; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '".$v_key."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($p_file_list[$key])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + return PclZip::errorCode(); + } + } + } + } + + // end foreach + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrExpand() + // Description : + // This method look for each item of the list to see if its a file, a folder + // or a string to be added as file. For any other type of files (link, other) + // just ignore the item. + // Then prepare the information that will be stored for that file. + // When its a folder, expand the folder with all the files that are in that + // folder (recursively). + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrExpand(&$p_filedescr_list, &$p_options) + { + $v_result=1; + + // ----- Create a result list + $v_result_list = array(); + + // ----- Look each entry + for ($i=0; $iprivCalculateStoredFilename($v_descr, $p_options); + + // ----- Add the descriptor in result list + $v_result_list[sizeof($v_result_list)] = $v_descr; + + // ----- Look for folder + if ($v_descr['type'] == 'folder') { + // ----- List of items in folder + $v_dirlist_descr = array(); + $v_dirlist_nb = 0; + if ($v_folder_handler = @opendir($v_descr['filename'])) { + while (($v_item_handler = @readdir($v_folder_handler)) !== false) { + + // ----- Skip '.' and '..' + if (($v_item_handler == '.') || ($v_item_handler == '..')) { + continue; + } + + // ----- Compose the full filename + $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler; + + // ----- Look for different stored filename + // Because the name of the folder was changed, the name of the + // files/sub-folders also change + if (($v_descr['stored_filename'] != $v_descr['filename']) + && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) { + if ($v_descr['stored_filename'] != '') { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler; + } + else { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler; + } + } + + $v_dirlist_nb++; + } + + @closedir($v_folder_handler); + } + else { + // TBC : unable to open folder in read mode + } + + // ----- Expand each element of the list + if ($v_dirlist_nb != 0) { + // ----- Expand + if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) { + return $v_result; + } + + // ----- Concat the resulting list + $v_result_list = array_merge($v_result_list, $v_dirlist_descr); + } + else { + } + + // ----- Free local array + unset($v_dirlist_descr); + } + } + + // ----- Get the result list + $p_filedescr_list = $v_result_list; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCreate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCreate($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the file in write mode + if (($v_result = $this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Add the list of files + $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options); + + // ----- Close + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAdd() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAdd($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Look if the archive exists or is empty + if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) + { + + // ----- Do a create + $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options); + + // ----- Return + return $v_result; + } + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Create the Central Dir files header + for ($i=0, $v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = $v_central_dir['comment']; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) { + $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOpenFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privOpenFd($p_mode) + { + $v_result=1; + + // ----- Look if already open + if ($this->zip_fd != 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCloseFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privCloseFd() + { + $v_result=1; + + if ($this->zip_fd != 0) + @fclose($this->zip_fd); + $this->zip_fd = 0; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddList() + // Description : + // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is + // different from the real path of the file. This is usefull if you want to have PclTar + // running in any directory, and memorize relative path from an other directory. + // Parameters : + // $p_list : An array containing the file or directory names to add in the tar + // $p_result_list : list of added files with their properties (specially the status field) + // $p_add_dir : Path to add in the filename path archived + // $p_remove_dir : Path to remove in the filename path archived + // Return Values : + // -------------------------------------------------------------------------------- +// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) + function privAddList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Create the Central Dir files header + for ($i=0,$v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileList() + // Description : + // Parameters : + // $p_filedescr_list : An array containing the file description + // or directory names to add in the zip + // $p_result_list : list of added files with their properties (specially the status field) + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_header = array(); + + // ----- Recuperate the current number of elt in list + $v_nb = sizeof($p_result_list); + + // ----- Loop on the files + for ($j=0; ($jprivAddFile($p_filedescr_list[$j], $v_header, + $p_options); + if ($v_result != 1) { + return $v_result; + } + + // ----- Store the file infos + $p_result_list[$v_nb++] = $v_header; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=1; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + // TBC : Already done in the fileAtt check ... ? + if ($p_filename == "") { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for a stored different filename + /* TBC : Removed + if (isset($p_filedescr['stored_filename'])) { + $v_stored_filename = $p_filedescr['stored_filename']; + } + else { + $v_stored_filename = $p_filedescr['stored_filename']; + } + */ + + // ----- Set the file properties + clearstatcache(); + $p_header['version'] = 20; + $p_header['version_extracted'] = 10; + $p_header['flag'] = 0; + $p_header['compression'] = 0; + $p_header['crc'] = 0; + $p_header['compressed_size'] = 0; + $p_header['filename_len'] = strlen($p_filename); + $p_header['extra_len'] = 0; + $p_header['disk'] = 0; + $p_header['internal'] = 0; + $p_header['offset'] = 0; + $p_header['filename'] = $p_filename; +// TBC : Removed $p_header['stored_filename'] = $v_stored_filename; + $p_header['stored_filename'] = $p_filedescr['stored_filename']; + $p_header['extra'] = ''; + $p_header['status'] = 'ok'; + $p_header['index'] = -1; + + // ----- Look for regular file + if ($p_filedescr['type']=='file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for regular folder + else if ($p_filedescr['type']=='folder') { + $p_header['external'] = 0x00000010; + $p_header['mtime'] = filemtime($p_filename); + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for virtual file + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = strlen($p_filedescr['content']); + } + + + // ----- Look for filetime + if (isset($p_filedescr['mtime'])) { + $p_header['mtime'] = $p_filedescr['mtime']; + } + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['mtime'] = time(); + } + else { + $p_header['mtime'] = filemtime($p_filename); + } + + // ------ Look for file comment + if (isset($p_filedescr['comment'])) { + $p_header['comment_len'] = strlen($p_filedescr['comment']); + $p_header['comment'] = $p_filedescr['comment']; + } + else { + $p_header['comment_len'] = 0; + $p_header['comment'] = ''; + } + + // ----- Look for pre-add callback + if (isset($p_options[PCLZIP_CB_PRE_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_header['status'] = "skipped"; + $v_result = 1; + } + + // ----- Update the informations + // Only some fields can be modified + if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { + $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']); + } + } + + // ----- Look for empty stored filename + if ($p_header['stored_filename'] == "") { + $p_header['status'] = "filtered"; + } + + // ----- Check the path length + if (strlen($p_header['stored_filename']) > 0xFF) { + $p_header['status'] = 'filename_too_long'; + } + + // ----- Look if no error, or file not skipped + if ($p_header['status'] == 'ok') { + + // ----- Look for a file + if ($p_filedescr['type'] == 'file') { + // ----- Look for using temporary file to zip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) { + $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Use "in memory" zip algo + else { + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Read the file content + $v_content = @fread($v_file, $p_header['size']); + + // ----- Close the file + @fclose($v_file); + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + + } + + } + + // ----- Look for a virtual file (a file from string) + else if ($p_filedescr['type'] == 'virtual_file') { + + $v_content = $p_filedescr['content']; + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + } + + // ----- Look for a directory + else if ($p_filedescr['type'] == 'folder') { + // ----- Look for directory last '/' + if (@substr($p_header['stored_filename'], -1) != '/') { + $p_header['stored_filename'] .= '/'; + } + + // ----- Set the file properties + $p_header['size'] = 0; + //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked + $p_header['external'] = 0x00000010; // Value for a folder : to be checked + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) + { + return $v_result; + } + } + } + + // ----- Look for post-add callback + if (isset($p_options[PCLZIP_CB_POST_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Ignored + $v_result = 1; + } + + // ----- Update the informations + // Nothing can be modified + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=PCLZIP_ERR_NO_ERROR; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Creates a compressed temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = filesize($p_filename); + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @gzputs($v_file_compressed, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file); + @gzclose($v_file_compressed); + + // ----- Check the minimum file size + if (filesize($v_gzip_temp_name) < 18) { + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes'); + return PclZip::errorCode(); + } + + // ----- Extract the compressed attributes + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the gzip file header + $v_binary_data = @fread($v_file_compressed, 10); + $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data); + + // ----- Check some parameters + $v_data_header['os'] = bin2hex($v_data_header['os']); + + // ----- Read the gzip file footer + @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8); + $v_binary_data = @fread($v_file_compressed, 8); + $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data); + + // ----- Set the attributes + $p_header['compression'] = ord($v_data_header['cm']); + //$p_header['mtime'] = $v_data_header['mtime']; + $p_header['crc'] = $v_data_footer['crc']; + $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18; + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + return $v_result; + } + + // ----- Add the compressed data + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) + { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + fseek($v_file_compressed, 10); + $v_size = $p_header['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file_compressed, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Unlink the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCalculateStoredFilename() + // Description : + // Based on file descriptor properties and global options, this method + // calculate the filename that will be stored in the archive. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCalculateStoredFilename(&$p_filedescr, &$p_options) + { + $v_result=1; + + // ----- Working variables + $p_filename = $p_filedescr['filename']; + if (isset($p_options[PCLZIP_OPT_ADD_PATH])) { + $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH]; + } + else { + $p_add_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) { + $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH]; + } + else { + $p_remove_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + else { + $p_remove_all_dir = 0; + } + + + // ----- Look for full name change + if (isset($p_filedescr['new_full_name'])) { + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']); + } + + // ----- Look for path and/or short name change + else { + + // ----- Look for short name change + // Its when we cahnge just the filename but not the path + if (isset($p_filedescr['new_short_name'])) { + $v_path_info = pathinfo($p_filename); + $v_dir = ''; + if ($v_path_info['dirname'] != '') { + $v_dir = $v_path_info['dirname'].'/'; + } + $v_stored_filename = $v_dir.$p_filedescr['new_short_name']; + } + else { + // ----- Calculate the stored filename + $v_stored_filename = $p_filename; + } + + // ----- Look for all path to remove + if ($p_remove_all_dir) { + $v_stored_filename = basename($p_filename); + } + // ----- Look for partial path remove + else if ($p_remove_dir != "") { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= "/"; + + if ( (substr($p_filename, 0, 2) == "./") + || (substr($p_remove_dir, 0, 2) == "./")) { + + if ( (substr($p_filename, 0, 2) == "./") + && (substr($p_remove_dir, 0, 2) != "./")) { + $p_remove_dir = "./".$p_remove_dir; + } + if ( (substr($p_filename, 0, 2) != "./") + && (substr($p_remove_dir, 0, 2) == "./")) { + $p_remove_dir = substr($p_remove_dir, 2); + } + } + + $v_compare = PclZipUtilPathInclusion($p_remove_dir, + $v_stored_filename); + if ($v_compare > 0) { + if ($v_compare == 2) { + $v_stored_filename = ""; + } + else { + $v_stored_filename = substr($v_stored_filename, + strlen($p_remove_dir)); + } + } + } + + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename); + + // ----- Look for path to add + if ($p_add_dir != "") { + if (substr($p_add_dir, -1) == "/") + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir."/".$v_stored_filename; + } + } + + // ----- Filename (reduce the path of stored name) + $v_stored_filename = PclZipUtilPathReduction($v_stored_filename); + $p_filedescr['stored_filename'] = $v_stored_filename; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteFileHeader(&$p_header) + { + $v_result=1; + + // ----- Store the offset position of the file + $p_header['offset'] = ftell($this->zip_fd); + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + // ----- Packed data + $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, + $p_header['version_extracted'], $p_header['flag'], + $p_header['compression'], $v_mtime, $v_mdate, + $p_header['crc'], $p_header['compressed_size'], + $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len']); + + // ----- Write the first 148 bytes of the header in the archive + fputs($this->zip_fd, $v_binary_data, 30); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralFileHeader(&$p_header) + { + $v_result=1; + + // TBC + //for(reset($p_header); $key = key($p_header); next($p_header)) { + //} + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + + // ----- Packed data + $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, + $p_header['version'], $p_header['version_extracted'], + $p_header['flag'], $p_header['compression'], + $v_mtime, $v_mdate, $p_header['crc'], + $p_header['compressed_size'], $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len'], $p_header['comment_len'], + $p_header['disk'], $p_header['internal'], + $p_header['external'], $p_header['offset']); + + // ----- Write the 42 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 46); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + if ($p_header['comment_len'] != 0) + { + fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) + { + $v_result=1; + + // ----- Packed data + $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, + $p_nb_entries, $p_size, + $p_offset, strlen($p_comment)); + + // ----- Write the 22 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 22); + + // ----- Write the variable fields + if (strlen($p_comment) != 0) + { + fputs($this->zip_fd, $p_comment, strlen($p_comment)); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privList() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privList(&$p_list) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of Central Dir + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_central_dir['offset'])) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + for ($i=0; $i<$v_central_dir['entries']; $i++) + { + // ----- Read the file header + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + $v_header['index'] = $i; + + // ----- Get the only interesting attributes + $this->privConvertHeader2FileInfo($v_header, $p_list[$i]); + unset($v_header); + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privConvertHeader2FileInfo() + // Description : + // This function takes the file informations from the central directory + // entries and extract the interesting parameters that will be given back. + // The resulting file infos are set in the array $p_info + // $p_info['filename'] : Filename with full path. Given by user (add), + // extracted in the filesystem (extract). + // $p_info['stored_filename'] : Stored filename in the archive. + // $p_info['size'] = Size of the file. + // $p_info['compressed_size'] = Compressed size of the file. + // $p_info['mtime'] = Last modification date of the file. + // $p_info['comment'] = Comment associated with the file. + // $p_info['folder'] = true/false : indicates if the entry is a folder or not. + // $p_info['status'] = status of the action on the file. + // $p_info['crc'] = CRC of the file content. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privConvertHeader2FileInfo($p_header, &$p_info) + { + $v_result=1; + + // ----- Get the interesting attributes + $v_temp_path = PclZipUtilPathReduction($p_header['filename']); + $p_info['filename'] = $v_temp_path; + $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']); + $p_info['stored_filename'] = $v_temp_path; + $p_info['size'] = $p_header['size']; + $p_info['compressed_size'] = $p_header['compressed_size']; + $p_info['mtime'] = $p_header['mtime']; + $p_info['comment'] = $p_header['comment']; + $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); + $p_info['index'] = $p_header['index']; + $p_info['status'] = $p_header['status']; + $p_info['crc'] = $p_header['crc']; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractByRule() + // Description : + // Extract a file or directory depending of rules (by index, by name, ...) + // Parameters : + // $p_file_list : An array where will be placed the properties of each + // extracted file + // $p_path : Path to add while writing the extracted files + // $p_remove_path : Path to remove (from the file memorized path) while writing the + // extracted files. If the path does not match the file path, + // the file is extracted with its memorized path. + // $p_remove_path does not apply to 'list' mode. + // $p_path and $p_remove_path are commulative. + // Return Values : + // 1 on success,0 or less on error (see error code list) + // -------------------------------------------------------------------------------- + function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check the path + if ( ($p_path == "") + || ( (substr($p_path, 0, 1) != "/") + && (substr($p_path, 0, 3) != "../") + && (substr($p_path,1,2)!=":/"))) + $p_path = "./".$p_path; + + // ----- Reduce the path last (and duplicated) '/' + if (($p_path != "./") && ($p_path != "/")) + { + // ----- Look for the path end '/' + while (substr($p_path, -1) == "/") + { + $p_path = substr($p_path, 0, strlen($p_path)-1); + } + } + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) + { + $p_remove_path .= '/'; + } + $p_remove_path_size = strlen($p_remove_path); + + // ----- Open the zip file + if (($v_result = $this->privOpenFd('rb')) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + + // ----- Read each entry + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read next Central dir entry + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Store the index + $v_header['index'] = $i; + + // ----- Store the file position + $v_pos_entry = ftell($this->zip_fd); + + // ----- Look for the specific extract rules + $v_extract = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_extract = true; + } + } + // ----- Look for a filename + elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_extract = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_extract = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + + // ----- Look for no rule, which means extract all the archive + else { + $v_extract = true; + } + + // ----- Check compression method + if ( ($v_extract) + && ( ($v_header['compression'] != 8) + && ($v_header['compression'] != 0))) { + $v_header['status'] = 'unsupported_compression'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION, + "Filename '".$v_header['stored_filename']."' is " + ."compressed by an unsupported compression " + ."method (".$v_header['compression'].") "); + + return PclZip::errorCode(); + } + } + + // ----- Check encrypted files + if (($v_extract) && (($v_header['flag'] & 1) == 1)) { + $v_header['status'] = 'unsupported_encryption'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, + "Unsupported encryption for " + ." filename '".$v_header['stored_filename'] + ."'"); + + return PclZip::errorCode(); + } + } + + // ----- Look for real extraction + if (($v_extract) && ($v_header['status'] != 'ok')) { + $v_result = $this->privConvertHeader2FileInfo($v_header, + $p_file_list[$v_nb_extracted++]); + if ($v_result != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + $v_extract = false; + } + + // ----- Look for real extraction + if ($v_extract) + { + + // ----- Go to the file position + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_header['offset'])) + { + // ----- Close the zip file + $this->privCloseFd(); + + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for extraction as string + if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) { + + $v_string = ''; + + // ----- Extracting the file + $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Set the file content + $p_file_list[$v_nb_extracted]['content'] = $v_string; + + // ----- Next extracted file + $v_nb_extracted++; + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for extraction in standard output + elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) + && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) { + // ----- Extracting the file in standard output + $v_result1 = $this->privExtractFileInOutput($v_header, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for normal extraction + else { + // ----- Extracting the file + $v_result1 = $this->privExtractFile($v_header, + $p_path, $p_remove_path, + $p_remove_all_path, + $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + } + } + + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFile() + // Description : + // Parameters : + // Return Values : + // + // 1 : ... ? + // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback + // -------------------------------------------------------------------------------- + function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for all path to remove + if ($p_remove_all_path == true) { + // ----- Look for folder entry that not need to be extracted + if (($p_entry['external']&0x00000010)==0x00000010) { + + $p_entry['status'] = "filtered"; + + return $v_result; + } + + // ----- Get the basename of the path + $p_entry['filename'] = basename($p_entry['filename']); + } + + // ----- Look for path to remove + else if ($p_remove_path != "") + { + if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) + { + + // ----- Change the file status + $p_entry['status'] = "filtered"; + + // ----- Return + return $v_result; + } + + $p_remove_path_size = strlen($p_remove_path); + if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) + { + + // ----- Remove the path + $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); + + } + } + + // ----- Add the path + if ($p_path != '') { + $p_entry['filename'] = $p_path."/".$p_entry['filename']; + } + + // ----- Check a base_dir_restriction + if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) { + $v_inclusion + = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], + $p_entry['filename']); + if ($v_inclusion == 0) { + + PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, + "Filename '".$p_entry['filename']."' is " + ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION"); + + return PclZip::errorCode(); + } + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Look for specific actions while the file exist + if (file_exists($p_entry['filename'])) + { + + // ----- Look if file is a directory + if (is_dir($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "already_a_directory"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, + "Filename '".$p_entry['filename']."' is " + ."already used by an existing directory"); + + return PclZip::errorCode(); + } + } + // ----- Look if file is write protected + else if (!is_writeable($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "write_protected"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Filename '".$p_entry['filename']."' exists " + ."and is write protected"); + + return PclZip::errorCode(); + } + } + + // ----- Look if the extracted file is older + else if (filemtime($p_entry['filename']) > $p_entry['mtime']) + { + // ----- Change the file status + if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER])) + && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) { + } + else { + $p_entry['status'] = "newer_exist"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Newer version of '".$p_entry['filename']."' exists " + ."and option PCLZIP_OPT_REPLACE_NEWER is not selected"); + + return PclZip::errorCode(); + } + } + } + else { + } + } + + // ----- Check the directory availability and create it if necessary + else { + if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) + $v_dir_to_check = $p_entry['filename']; + else if (!strstr($p_entry['filename'], "/")) + $v_dir_to_check = ""; + else + $v_dir_to_check = dirname($p_entry['filename']); + + if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { + + // ----- Change the file status + $p_entry['status'] = "path_creation_fail"; + + // ----- Return + //return $v_result; + $v_result = 1; + } + } + } + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) + { + // ----- Look for not compressed file + if ($p_entry['compression'] == 0) { + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) + { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + // ----- Return + return $v_result; + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + /* Try to speed up the code + $v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_binary_data, $v_read_size); + */ + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Closing the destination file + fclose($v_dest_file); + + // ----- Change the file mtime + touch($p_entry['filename'], $p_entry['mtime']); + + + } + else { + // ----- TBC + // Need to be finished + if (($p_entry['flag'] & 1) == 1) { + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.'); + return PclZip::errorCode(); + } + + + // ----- Look for using temporary file to unzip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) { + $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Look for extract in memory + else { + + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = @gzinflate($v_buffer); + unset($v_buffer); + if ($v_file_content === FALSE) { + + // ----- Change the file status + // TBC + $p_entry['status'] = "error"; + + return $v_result; + } + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + return $v_result; + } + + // ----- Write the uncompressed data + @fwrite($v_dest_file, $v_file_content, $p_entry['size']); + unset($v_file_content); + + // ----- Closing the destination file + @fclose($v_dest_file); + + } + + // ----- Change the file mtime + @touch($p_entry['filename'], $p_entry['mtime']); + } + + // ----- Look for chmod option + if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) { + + // ----- Change the mode of the file + @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]); + } + + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileUsingTempFile(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Creates a temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + + // ----- Write gz file format header + $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3)); + @fwrite($v_dest_file, $v_binary_data, 10); + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Write gz file format footer + $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']); + @fwrite($v_dest_file, $v_binary_data, 8); + + // ----- Close the temporary file + @fclose($v_dest_file); + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + $p_entry['status'] = "write_error"; + return $v_result; + } + + // ----- Open the temporary gz file + if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) { + @fclose($v_dest_file); + $p_entry['status'] = "read_error"; + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['size']; + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($v_src_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + @fclose($v_dest_file); + @gzclose($v_src_file); + + // ----- Delete the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileInOutput() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileInOutput(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) { + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + // ----- Trace + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + if ($p_entry['compressed_size'] == $p_entry['size']) { + + // ----- Read the file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Send the file to the output + echo $v_buffer; + unset($v_buffer); + } + else { + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = gzinflate($v_buffer); + unset($v_buffer); + + // ----- Send the file to the output + echo $v_file_content; + unset($v_file_content); + } + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileAsString() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileAsString(&$p_entry, &$p_string, &$p_options) + { + $v_result=1; + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + // if ($p_entry['compressed_size'] == $p_entry['size']) + if ($p_entry['compression'] == 0) { + + // ----- Reading the file + $p_string = @fread($this->zip_fd, $p_entry['compressed_size']); + } + else { + + // ----- Reading the file + $v_data = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + if (($p_string = @gzinflate($v_data)) === FALSE) { + // TBC + } + } + + // ----- Trace + } + else { + // TBC : error : can not extract a folder in a string + } + + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Swap the content to header + $v_local_header['content'] = $p_string; + $p_string = ''; + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Swap back the content to header + $p_string = $v_local_header['content']; + unset($v_local_header['content']); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x04034b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 26); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 26) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); + + // ----- Get filename + $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']); + + // ----- Get extra_fields + if ($v_data['extra_len'] != 0) { + $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']); + } + else { + $p_header['extra'] = ''; + } + + // ----- Extract properties + $p_header['version_extracted'] = $v_data['version']; + $p_header['compression'] = $v_data['compression']; + $p_header['size'] = $v_data['size']; + $p_header['compressed_size'] = $v_data['compressed_size']; + $p_header['crc'] = $v_data['crc']; + $p_header['flag'] = $v_data['flag']; + $p_header['filename_len'] = $v_data['filename_len']; + + // ----- Recuperate date in UNIX format + $p_header['mdate'] = $v_data['mdate']; + $p_header['mtime'] = $v_data['mtime']; + if ($p_header['mdate'] && $p_header['mtime']) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // TBC + //for(reset($v_data); $key = key($v_data); next($v_data)) { + //} + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set the status field + $p_header['status'] = "ok"; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadCentralFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x02014b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 42); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 42) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); + + // ----- Get filename + if ($p_header['filename_len'] != 0) + $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']); + else + $p_header['filename'] = ''; + + // ----- Get extra + if ($p_header['extra_len'] != 0) + $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']); + else + $p_header['extra'] = ''; + + // ----- Get comment + if ($p_header['comment_len'] != 0) + $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']); + else + $p_header['comment'] = ''; + + // ----- Extract properties + + // ----- Recuperate date in UNIX format + //if ($p_header['mdate'] && $p_header['mtime']) + // TBC : bug : this was ignoring time with 0/0/0 + if (1) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set default status to ok + $p_header['status'] = 'ok'; + + // ----- Look if it is a directory + if (substr($p_header['filename'], -1) == '/') { + //$p_header['external'] = 0x41FF0010; + $p_header['external'] = 0x00000010; + } + + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCheckFileHeaders() + // Description : + // Parameters : + // Return Values : + // 1 on success, + // 0 on error; + // -------------------------------------------------------------------------------- + function privCheckFileHeaders(&$p_local_header, &$p_central_header) + { + $v_result=1; + + // ----- Check the static values + // TBC + if ($p_local_header['filename'] != $p_central_header['filename']) { + } + if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) { + } + if ($p_local_header['flag'] != $p_central_header['flag']) { + } + if ($p_local_header['compression'] != $p_central_header['compression']) { + } + if ($p_local_header['mtime'] != $p_central_header['mtime']) { + } + if ($p_local_header['filename_len'] != $p_central_header['filename_len']) { + } + + // ----- Look for flag bit 3 + if (($p_local_header['flag'] & 8) == 8) { + $p_local_header['size'] = $p_central_header['size']; + $p_local_header['compressed_size'] = $p_central_header['compressed_size']; + $p_local_header['crc'] = $p_central_header['crc']; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadEndCentralDir() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadEndCentralDir(&$p_central_dir) + { + $v_result=1; + + // ----- Go to the end of the zip file + $v_size = filesize($this->zipname); + @fseek($this->zip_fd, $v_size); + if (@ftell($this->zip_fd) != $v_size) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- First try : look if this is an archive with no commentaries (most of the time) + // in this case the end of central dir is at 22 bytes of the file end + $v_found = 0; + if ($v_size > 26) { + @fseek($this->zip_fd, $v_size-22); + if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read for bytes + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = @unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] == 0x06054b50) { + $v_found = 1; + } + + $v_pos = ftell($this->zip_fd); + } + + // ----- Go back to the maximum possible size of the Central Dir End Record + if (!$v_found) { + $v_maximum_size = 65557; // 0xFFFF + 22; + if ($v_maximum_size > $v_size) + $v_maximum_size = $v_size; + @fseek($this->zip_fd, $v_size-$v_maximum_size); + if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read byte per byte in order to find the signature + $v_pos = ftell($this->zip_fd); + $v_bytes = 0x00000000; + while ($v_pos < $v_size) + { + // ----- Read a byte + $v_byte = @fread($this->zip_fd, 1); + + // ----- Add the byte + //$v_bytes = ($v_bytes << 8) | Ord($v_byte); + // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number + // Otherwise on systems where we have 64bit integers the check below for the magic number will fail. + $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte); + + // ----- Compare the bytes + if ($v_bytes == 0x504b0506) + { + $v_pos++; + break; + } + + $v_pos++; + } + + // ----- Look if not found end of central dir + if ($v_pos == $v_size) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature"); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Read the first 18 bytes of the header + $v_binary_data = fread($this->zip_fd, 18); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 18) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); + + // ----- Check the global size + if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { + + // ----- Removed in release 2.2 see readme file + // The check of the file size is a little too strict. + // Some bugs where found when a zip is encrypted/decrypted with 'crypt'. + // While decrypted, zip has training 0 bytes + if (0) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, + 'The central dir is not at the end of the archive.' + .' Some trailing bytes exists after the archive.'); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Get comment + if ($v_data['comment_size'] != 0) { + $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']); + } + else + $p_central_dir['comment'] = ''; + + $p_central_dir['entries'] = $v_data['entries']; + $p_central_dir['disk_entries'] = $v_data['disk_entries']; + $p_central_dir['offset'] = $v_data['offset']; + $p_central_dir['size'] = $v_data['size']; + $p_central_dir['disk'] = $v_data['disk']; + $p_central_dir['disk_start'] = $v_data['disk_start']; + + // TBC + //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) { + //} + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDeleteByRule() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDeleteByRule(&$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Scan all the files + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + $v_header_list = array(); + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read the file header + $v_header_list[$v_nb_extracted] = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + + return $v_result; + } + + + // ----- Store the index + $v_header_list[$v_nb_extracted]['index'] = $i; + + // ----- Look for the specific extract rules + $v_found = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ + && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + } + // ----- Look for a filename + elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_found = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_found = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + else { + $v_found = true; + } + + // ----- Look for deletion + if ($v_found) + { + unset($v_header_list[$v_nb_extracted]); + } + else + { + $v_nb_extracted++; + } + } + + // ----- Look if something need to be deleted + if ($v_nb_extracted > 0) { + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Creates a temporary zip archive + $v_temp_zip = new PclZip($v_zip_temp_name); + + // ----- Open the temporary zip file in write mode + if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Look which file need to be kept + for ($i=0; $izip_fd); + if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_local_header = array(); + if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Check that local file header is same as central file header + if ($this->privCheckFileHeaders($v_local_header, + $v_header_list[$i]) != 1) { + // TBC + } + unset($v_local_header); + + // ----- Write the file header + if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Read/write the data block + if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_temp_zip->zip_fd); + + // ----- Re-Create the Central Dir files header + for ($i=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Transform the header to a 'usable' info + $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) { + // ----- Reset the file list + unset($v_header_list); + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Close + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Destroy the temporary archive + unset($v_temp_zip); + } + + // ----- Remove every files : reset the file + else if ($v_central_dir['entries'] != 0) { + $this->privCloseFd(); + + if (($v_result = $this->privOpenFd('wb')) != 1) { + return $v_result; + } + + if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) { + return $v_result; + } + + $this->privCloseFd(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDirCheck() + // Description : + // Check if a directory exists, if not it creates it and all the parents directory + // which may be useful. + // Parameters : + // $p_dir : Directory path to check. + // Return Values : + // 1 : OK + // -1 : Unable to create directory + // -------------------------------------------------------------------------------- + function privDirCheck($p_dir, $p_is_dir=false) + { + $v_result = 1; + + + // ----- Remove the final '/' + if (($p_is_dir) && (substr($p_dir, -1)=='/')) + { + $p_dir = substr($p_dir, 0, strlen($p_dir)-1); + } + + // ----- Check the directory availability + if ((is_dir($p_dir)) || ($p_dir == "")) + { + return 1; + } + + // ----- Extract parent directory + $p_parent_dir = dirname($p_dir); + + // ----- Just a check + if ($p_parent_dir != $p_dir) + { + // ----- Look for parent directory + if ($p_parent_dir != "") + { + if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) + { + return $v_result; + } + } + } + + // ----- Create the directory + if (!@mkdir($p_dir, 0777)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privMerge() + // Description : + // If $p_archive_to_add does not exist, the function exit with a success result. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privMerge(&$p_archive_to_add) + { + $v_result=1; + + // ----- Look if the archive_to_add exists + if (!is_file($p_archive_to_add->zipname)) + { + + // ----- Nothing to merge, so merge is a success + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Look if the archive exists + if (!is_file($this->zipname)) + { + + // ----- Do a duplicate + $v_result = $this->privDuplicate($p_archive_to_add->zipname); + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Open the archive_to_add file + if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) + { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir_to_add = array(); + if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + return $v_result; + } + + // ----- Go to beginning of File + @rewind($p_archive_to_add->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the files from the archive_to_add into the temporary file + $v_size = $v_central_dir_to_add['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_zip_temp_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the block of file headers from the archive_to_add + $v_size = $v_central_dir_to_add['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Merge the file comments + $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment']; + + // ----- Calculate the size of the (new) central header + $v_size = @ftell($v_zip_temp_fd)-$v_offset; + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive fd + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + @fclose($v_zip_temp_fd); + $this->zip_fd = null; + + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDuplicate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDuplicate($p_archive_filename) + { + $v_result=1; + + // ----- Look if the $p_archive_filename exists + if (!is_file($p_archive_filename)) + { + + // ----- Nothing to duplicate, so duplicate is a success. + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) + { + $this->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = filesize($p_archive_filename); + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorLog() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorLog($p_error_code=0, $p_error_string='') + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclError($p_error_code, $p_error_string); + } + else { + $this->error_code = $p_error_code; + $this->error_string = $p_error_string; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorReset() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorReset() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclErrorReset(); + } + else { + $this->error_code = 0; + $this->error_string = ''; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDisableMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDisableMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if already done + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Get and memorize the magic_quote value + $this->magic_quotes_status = @get_magic_quotes_runtime(); + + // ----- Disable magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime(0); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privSwapBackMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privSwapBackMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if something to do + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Swap back magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime($this->magic_quotes_status); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + } + // End of class + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathReduction() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilPathReduction($p_dir) + { + $v_result = ""; + + // ----- Look for not empty path + if ($p_dir != "") { + // ----- Explode path by directory names + $v_list = explode("/", $p_dir); + + // ----- Study directories from last to first + $v_skip = 0; + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + $v_skip++; + } + else if ($v_list[$i] == "") { + // ----- First '/' i.e. root slash + if ($i == 0) { + $v_result = "/".$v_result; + if ($v_skip > 0) { + // ----- It is an invalid path, so the path is not modified + // TBC + $v_result = $p_dir; + $v_skip = 0; + } + } + // ----- Last '/' i.e. indicates a directory + else if ($i == (sizeof($v_list)-1)) { + $v_result = $v_list[$i]; + } + // ----- Double '/' inside the path + else { + // ----- Ignore only the double '//' in path, + // but not the first and last '/' + } + } + else { + // ----- Look for item to skip + if ($v_skip > 0) { + $v_skip--; + } + else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); + } + } + } + + // ----- Look for skip + if ($v_skip > 0) { + while ($v_skip > 0) { + $v_result = '../'.$v_result; + $v_skip--; + } + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathInclusion() + // Description : + // This function indicates if the path $p_path is under the $p_dir tree. Or, + // said in an other way, if the file or sub-dir $p_path is inside the dir + // $p_dir. + // The function indicates also if the path is exactly the same as the dir. + // This function supports path with duplicated '/' like '//', but does not + // support '.' or '..' statements. + // Parameters : + // Return Values : + // 0 if $p_path is not inside directory $p_dir + // 1 if $p_path is inside directory $p_dir + // 2 if $p_path is exactly the same as $p_dir + // -------------------------------------------------------------------------------- + function PclZipUtilPathInclusion($p_dir, $p_path) + { + $v_result = 1; + + // ----- Look for path beginning by ./ + if ( ($p_dir == '.') + || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) { + $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1); + } + if ( ($p_path == '.') + || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) { + $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1); + } + + // ----- Explode dir and path by directory separator + $v_list_dir = explode("/", $p_dir); + $v_list_dir_size = sizeof($v_list_dir); + $v_list_path = explode("/", $p_path); + $v_list_path_size = sizeof($v_list_path); + + // ----- Study directories paths + $i = 0; + $j = 0; + while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { + + // ----- Look for empty dir (path reduction) + if ($v_list_dir[$i] == '') { + $i++; + continue; + } + if ($v_list_path[$j] == '') { + $j++; + continue; + } + + // ----- Compare the items + if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) { + $v_result = 0; + } + + // ----- Next items + $i++; + $j++; + } + + // ----- Look if everything seems to be the same + if ($v_result) { + // ----- Skip all the empty items + while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; + while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; + + if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { + // ----- There are exactly the same + $v_result = 2; + } + else if ($i < $v_list_dir_size) { + // ----- The path is shorter than the dir + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilCopyBlock() + // Description : + // Parameters : + // $p_mode : read/write compression mode + // 0 : src & dest normal + // 1 : src gzip, dest normal + // 2 : src normal, dest gzip + // 3 : src & dest gzip + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0) + { + $v_result = 1; + + if ($p_mode==0) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==1) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==2) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==3) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilRename() + // Description : + // This function tries to do a simple rename() function. If it fails, it + // tries to copy the $p_src file in a new $p_dest file and then unlink the + // first one. + // Parameters : + // $p_src : Old filename + // $p_dest : New filename + // Return Values : + // 1 on success, 0 on failure. + // -------------------------------------------------------------------------------- + function PclZipUtilRename($p_src, $p_dest) + { + $v_result = 1; + + // ----- Try to rename the files + if (!@rename($p_src, $p_dest)) { + + // ----- Try to copy & unlink the src + if (!@copy($p_src, $p_dest)) { + $v_result = 0; + } + else if (!@unlink($p_src)) { + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilOptionText() + // Description : + // Translate option value in text. Mainly for debug purpose. + // Parameters : + // $p_option : the option value. + // Return Values : + // The option text value. + // -------------------------------------------------------------------------------- + function PclZipUtilOptionText($p_option) + { + + $v_list = get_defined_constants(); + for (reset($v_list); $v_key = key($v_list); next($v_list)) { + $v_prefix = substr($v_key, 0, 10); + if (( ($v_prefix == 'PCLZIP_OPT') + || ($v_prefix == 'PCLZIP_CB_') + || ($v_prefix == 'PCLZIP_ATT')) + && ($v_list[$v_key] == $p_option)) { + return $v_key; + } + } + + $v_result = 'Unknown'; + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilTranslateWinPath() + // Description : + // Translate windows path by replacing '\' by '/' and optionally removing + // drive letter. + // Parameters : + // $p_path : path to translate. + // $p_remove_disk_letter : true | false + // Return Values : + // The path translated. + // -------------------------------------------------------------------------------- + function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true) + { + if (stristr(php_uname(), 'windows')) { + // ----- Look for potential disk letter + if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // -------------------------------------------------------------------------------- + + +?> diff --git a/sources/wp-admin/includes/class-wp-comments-list-table.php b/sources/wp-admin/includes/class-wp-comments-list-table.php new file mode 100644 index 0000000..345bda2 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-comments-list-table.php @@ -0,0 +1,564 @@ + 'comments', + 'singular' => 'comment', + 'ajax' => true, + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + } + + function ajax_user_can() { + return current_user_can('edit_posts'); + } + + function prepare_items() { + global $post_id, $comment_status, $search, $comment_type; + + $comment_status = isset( $_REQUEST['comment_status'] ) ? $_REQUEST['comment_status'] : 'all'; + if ( !in_array( $comment_status, array( 'all', 'moderated', 'approved', 'spam', 'trash' ) ) ) + $comment_status = 'all'; + + $comment_type = !empty( $_REQUEST['comment_type'] ) ? $_REQUEST['comment_type'] : ''; + + $search = ( isset( $_REQUEST['s'] ) ) ? $_REQUEST['s'] : ''; + + $post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_key( $_REQUEST['post_type'] ) : ''; + + $user_id = ( isset( $_REQUEST['user_id'] ) ) ? $_REQUEST['user_id'] : ''; + + $orderby = ( isset( $_REQUEST['orderby'] ) ) ? $_REQUEST['orderby'] : ''; + $order = ( isset( $_REQUEST['order'] ) ) ? $_REQUEST['order'] : ''; + + $comments_per_page = $this->get_per_page( $comment_status ); + + $doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX; + + if ( isset( $_REQUEST['number'] ) ) { + $number = (int) $_REQUEST['number']; + } + else { + $number = $comments_per_page + min( 8, $comments_per_page ); // Grab a few extra + } + + $page = $this->get_pagenum(); + + if ( isset( $_REQUEST['start'] ) ) { + $start = $_REQUEST['start']; + } else { + $start = ( $page - 1 ) * $comments_per_page; + } + + if ( $doing_ajax && isset( $_REQUEST['offset'] ) ) { + $start += $_REQUEST['offset']; + } + + $status_map = array( + 'moderated' => 'hold', + 'approved' => 'approve', + 'all' => '', + ); + + $args = array( + 'status' => isset( $status_map[$comment_status] ) ? $status_map[$comment_status] : $comment_status, + 'search' => $search, + 'user_id' => $user_id, + 'offset' => $start, + 'number' => $number, + 'post_id' => $post_id, + 'type' => $comment_type, + 'orderby' => $orderby, + 'order' => $order, + 'post_type' => $post_type, + ); + + $_comments = get_comments( $args ); + + update_comment_cache( $_comments ); + + $this->items = array_slice( $_comments, 0, $comments_per_page ); + $this->extra_items = array_slice( $_comments, $comments_per_page ); + + $total_comments = get_comments( array_merge( $args, array('count' => true, 'offset' => 0, 'number' => 0) ) ); + + $_comment_post_ids = array(); + foreach ( $_comments as $_c ) { + $_comment_post_ids[] = $_c->comment_post_ID; + } + + $_comment_post_ids = array_unique( $_comment_post_ids ); + + $this->pending_count = get_pending_comments_num( $_comment_post_ids ); + + $this->set_pagination_args( array( + 'total_items' => $total_comments, + 'per_page' => $comments_per_page, + ) ); + } + + function get_per_page( $comment_status = 'all' ) { + $comments_per_page = $this->get_items_per_page( 'edit_comments_per_page' ); + $comments_per_page = apply_filters( 'comments_per_page', $comments_per_page, $comment_status ); + return $comments_per_page; + } + + function no_items() { + global $comment_status; + + if ( 'moderated' == $comment_status ) + _e( 'No comments awaiting moderation.' ); + else + _e( 'No comments found.' ); + } + + function get_views() { + global $post_id, $comment_status, $comment_type; + + $status_links = array(); + $num_comments = ( $post_id ) ? wp_count_comments( $post_id ) : wp_count_comments(); + //, number_format_i18n($num_comments->moderated) ), "" . number_format_i18n($num_comments->moderated) . ""), + //, number_format_i18n($num_comments->spam) ), "" . number_format_i18n($num_comments->spam) . "") + $stati = array( + 'all' => _nx_noop('All', 'All', 'comments'), // singular not used + 'moderated' => _n_noop('Pending (%s)', 'Pending (%s)'), + 'approved' => _n_noop('Approved', 'Approved'), // singular not used + 'spam' => _n_noop('Spam (%s)', 'Spam (%s)'), + 'trash' => _n_noop('Trash (%s)', 'Trash (%s)') + ); + + if ( !EMPTY_TRASH_DAYS ) + unset($stati['trash']); + + $link = 'edit-comments.php'; + if ( !empty($comment_type) && 'all' != $comment_type ) + $link = add_query_arg( 'comment_type', $comment_type, $link ); + + foreach ( $stati as $status => $label ) { + $class = ( $status == $comment_status ) ? ' class="current"' : ''; + + if ( !isset( $num_comments->$status ) ) + $num_comments->$status = 10; + $link = add_query_arg( 'comment_status', $status, $link ); + if ( $post_id ) + $link = add_query_arg( 'p', absint( $post_id ), $link ); + /* + // I toyed with this, but decided against it. Leaving it in here in case anyone thinks it is a good idea. ~ Mark + if ( !empty( $_REQUEST['s'] ) ) + $link = add_query_arg( 's', esc_attr( wp_unslash( $_REQUEST['s'] ) ), $link ); + */ + $status_links[$status] = "" . sprintf( + translate_nooped_plural( $label, $num_comments->$status ), + number_format_i18n( $num_comments->$status ) + ) . ''; + } + + $status_links = apply_filters( 'comment_status_links', $status_links ); + return $status_links; + } + + function get_bulk_actions() { + global $comment_status; + + $actions = array(); + if ( in_array( $comment_status, array( 'all', 'approved' ) ) ) + $actions['unapprove'] = __( 'Unapprove' ); + if ( in_array( $comment_status, array( 'all', 'moderated' ) ) ) + $actions['approve'] = __( 'Approve' ); + if ( in_array( $comment_status, array( 'all', 'moderated', 'approved' ) ) ) + $actions['spam'] = _x( 'Mark as Spam', 'comment' ); + + if ( 'trash' == $comment_status ) + $actions['untrash'] = __( 'Restore' ); + elseif ( 'spam' == $comment_status ) + $actions['unspam'] = _x( 'Not Spam', 'comment' ); + + if ( in_array( $comment_status, array( 'trash', 'spam' ) ) || !EMPTY_TRASH_DAYS ) + $actions['delete'] = __( 'Delete Permanently' ); + else + $actions['trash'] = __( 'Move to Trash' ); + + return $actions; + } + + function extra_tablenav( $which ) { + global $comment_status, $comment_type; +?> +
+ + + 'post-query-submit' ) ); + } + + if ( ( 'spam' == $comment_status || 'trash' == $comment_status ) && current_user_can( 'moderate_comments' ) ) { + wp_nonce_field( 'bulk-destroy', '_destroy_nonce' ); + $title = ( 'spam' == $comment_status ) ? esc_attr__( 'Empty Spam' ) : esc_attr__( 'Empty Trash' ); + submit_button( $title, 'apply', 'delete_all', false ); + } + do_action( 'manage_comments_nav', $comment_status ); + echo '
'; + } + + function current_action() { + if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) + return 'delete_all'; + + return parent::current_action(); + } + + function get_columns() { + global $post_id; + + $columns = array(); + + if ( $this->checkbox ) + $columns['cb'] = ''; + + $columns['author'] = __( 'Author' ); + $columns['comment'] = _x( 'Comment', 'column name' ); + + if ( !$post_id ) + $columns['response'] = _x( 'In Response To', 'column name' ); + + return $columns; + } + + function get_sortable_columns() { + return array( + 'author' => 'comment_author', + 'response' => 'comment_post_ID' + ); + } + + function display() { + extract( $this->_args ); + + wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); + + $this->display_tablenav( 'top' ); + +?> + + + + print_column_headers(); ?> + + + + + + print_column_headers( false ); ?> + + + + + display_rows_or_placeholder(); ?> + + + + items = $this->extra_items; $this->display_rows(); ?> + +
+display_tablenav( 'bottom' ); + } + + function single_row( $a_comment ) { + global $post, $comment; + + $comment = $a_comment; + $the_comment_class = join( ' ', get_comment_class( wp_get_comment_status( $comment->comment_ID ) ) ); + + $post = get_post( $comment->comment_post_ID ); + + $this->user_can = current_user_can( 'edit_comment', $comment->comment_ID ); + + echo ""; + $this->single_row_columns( $comment ); + echo "\n"; + } + + function column_cb( $comment ) { + if ( $this->user_can ) { ?> + + + user_can; + + $comment_url = esc_url( get_comment_link( $comment->comment_ID ) ); + $the_comment_status = wp_get_comment_status( $comment->comment_ID ); + + if ( $user_can ) { + $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); + $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); + + $url = "comment.php?c=$comment->comment_ID"; + + $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" ); + $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" ); + $spam_url = esc_url( $url . "&action=spamcomment&$del_nonce" ); + $unspam_url = esc_url( $url . "&action=unspamcomment&$del_nonce" ); + $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" ); + $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" ); + $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" ); + } + + echo ''; + comment_text(); + if ( $user_can ) { ?> + + '', 'unapprove' => '', + 'reply' => '', + 'quickedit' => '', + 'edit' => '', + 'spam' => '', 'unspam' => '', + 'trash' => '', 'untrash' => '', 'delete' => '' + ); + + if ( $comment_status && 'all' != $comment_status ) { // not looking at all comments + if ( 'approved' == $the_comment_status ) + $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; + else if ( 'unapproved' == $the_comment_status ) + $actions['approve'] = "" . __( 'Approve' ) . ''; + } else { + $actions['approve'] = "" . __( 'Approve' ) . ''; + $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; + } + + if ( 'spam' != $the_comment_status && 'trash' != $the_comment_status ) { + $actions['spam'] = "" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . ''; + } elseif ( 'spam' == $the_comment_status ) { + $actions['unspam'] = "" . _x( 'Not Spam', 'comment' ) . ''; + } elseif ( 'trash' == $the_comment_status ) { + $actions['untrash'] = "" . __( 'Restore' ) . ''; + } + + if ( 'spam' == $the_comment_status || 'trash' == $the_comment_status || !EMPTY_TRASH_DAYS ) { + $actions['delete'] = "" . __( 'Delete Permanently' ) . ''; + } else { + $actions['trash'] = "" . _x( 'Trash', 'verb' ) . ''; + } + + if ( 'spam' != $the_comment_status && 'trash' != $the_comment_status ) { + $actions['edit'] = "". __( 'Edit' ) . ''; + $actions['quickedit'] = '' . __( 'Quick Edit' ) . ''; + $actions['reply'] = '' . __( 'Reply' ) . ''; + } + + $actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment ); + + $i = 0; + echo '
'; + foreach ( $actions as $action => $link ) { + ++$i; + ( ( ( 'approve' == $action || 'unapprove' == $action ) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | '; + + // Reply and quickedit need a hide-if-no-js span when not added with ajax + if ( ( 'reply' == $action || 'quickedit' == $action ) && ! defined('DOING_AJAX') ) + $action .= ' hide-if-no-js'; + elseif ( ( $action == 'untrash' && $the_comment_status == 'trash' ) || ( $action == 'unspam' && $the_comment_status == 'spam' ) ) { + if ( '1' == get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true ) ) + $action .= ' approve'; + else + $action .= ' unapprove'; + } + + echo "$sep$link"; + } + echo '
'; + } + } + + function column_author( $comment ) { + global $comment_status; + + $author_url = get_comment_author_url(); + if ( 'http://' == $author_url ) + $author_url = ''; + $author_url_display = preg_replace( '|http://(www\.)?|i', '', $author_url ); + if ( strlen( $author_url_display ) > 50 ) + $author_url_display = substr( $author_url_display, 0, 49 ) . '…'; + + echo ""; comment_author(); echo '
'; + if ( !empty( $author_url ) ) + echo "$author_url_display
"; + + if ( $this->user_can ) { + if ( !empty( $comment->comment_author_email ) ) { + comment_author_email_link(); + echo '
'; + } + echo ''; + comment_author_IP(); + echo ''; + } + } + + function column_date( $comment ) { + return get_comment_date( __( 'Y/m/d \a\t g:ia' ) ); + } + + function column_response( $comment ) { + $post = get_post(); + + if ( isset( $this->pending_count[$post->ID] ) ) { + $pending_comments = $this->pending_count[$post->ID]; + } else { + $_pending_count_temp = get_pending_comments_num( array( $post->ID ) ); + $pending_comments = $this->pending_count[$post->ID] = $_pending_count_temp[$post->ID]; + } + + if ( current_user_can( 'edit_post', $post->ID ) ) { + $post_link = ""; + $post_link .= get_the_title( $post->ID ) . ''; + } else { + $post_link = get_the_title( $post->ID ); + } + + echo ''; + if ( 'attachment' == $post->post_type && ( $thumb = wp_get_attachment_image( $post->ID, array( 80, 60 ), true ) ) ) + echo $thumb; + } + + function column_default( $comment, $column_name ) { + do_action( 'manage_comments_custom_column', $column_name, $comment->comment_ID ); + } +} + +/** + * Post Comments List Table class. + * + * @package WordPress + * @subpackage List_Table + * @since 3.1.0 + * @access private + * + * @see WP_Comments_Table + */ +class WP_Post_Comments_List_Table extends WP_Comments_List_Table { + + function get_column_info() { + $this->_column_headers = array( + array( + 'author' => __( 'Author' ), + 'comment' => _x( 'Comment', 'column name' ), + ), + array(), + array(), + ); + + return $this->_column_headers; + } + + function get_table_classes() { + $classes = parent::get_table_classes(); + $classes[] = 'comments-box'; + return $classes; + } + + function display( $output_empty = false ) { + extract( $this->_args ); + + wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); +?> + + > + display_rows_or_placeholder(); ?> + + +find_folder(ABSPATH); + // Perhaps the FTP folder is rooted at the WordPress install, Check for wp-includes folder in root, Could have some false positives, but rare. + if ( ! $folder && $this->is_dir('/wp-includes') ) + $folder = '/'; + return $folder; + } + + /** + * Return the path on the remote filesystem of WP_CONTENT_DIR. + * + * @access public + * @since 2.7.0 + * + * @return string The location of the remote path. + */ + function wp_content_dir() { + return $this->find_folder(WP_CONTENT_DIR); + } + + /** + * Return the path on the remote filesystem of WP_PLUGIN_DIR. + * + * @access public + * @since 2.7.0 + * + * @return string The location of the remote path. + */ + function wp_plugins_dir() { + return $this->find_folder(WP_PLUGIN_DIR); + } + + /** + * Return the path on the remote filesystem of the Themes Directory. + * + * @access public + * @since 2.7.0 + * + * @param string $theme The Theme stylesheet or template for the directory. + * @return string The location of the remote path. + */ + function wp_themes_dir( $theme = false ) { + $theme_root = get_theme_root( $theme ); + + // Account for relative theme roots + if ( '/themes' == $theme_root || ! is_dir( $theme_root ) ) + $theme_root = WP_CONTENT_DIR . $theme_root; + + return $this->find_folder( $theme_root ); + } + + /** + * Return the path on the remote filesystem of WP_LANG_DIR. + * + * @access public + * @since 3.2.0 + * + * @return string The location of the remote path. + */ + function wp_lang_dir() { + return $this->find_folder(WP_LANG_DIR); + } + + /** + * Locate a folder on the remote filesystem. + * + * @access public + * @since 2.5.0 + * @deprecated 2.7.0 use WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir() instead. + * @see WP_Filesystem::abspath() + * @see WP_Filesystem::wp_content_dir() + * @see WP_Filesystem::wp_plugins_dir() + * @see WP_Filesystem::wp_themes_dir() + * @see WP_Filesystem::wp_lang_dir() + * + * @param string $base The folder to start searching from. + * @param bool $echo True to display debug information. + * Default false. + * @return string The location of the remote path. + */ + function find_base_dir( $base = '.', $echo = false ) { + _deprecated_function(__FUNCTION__, '2.7', 'WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir()' ); + $this->verbose = $echo; + return $this->abspath(); + } + + /** + * Locate a folder on the remote filesystem. + * + * @access public + * @since 2.5.0 + * @deprecated 2.7.0 use WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir() methods instead. + * @see WP_Filesystem::abspath() + * @see WP_Filesystem::wp_content_dir() + * @see WP_Filesystem::wp_plugins_dir() + * @see WP_Filesystem::wp_themes_dir() + * @see WP_Filesystem::wp_lang_dir() + * + * @param string $base The folder to start searching from. + * @param bool $echo True to display debug information. + * @return string The location of the remote path. + */ + function get_base_dir( $base = '.', $echo = false ) { + _deprecated_function(__FUNCTION__, '2.7', 'WP_Filesystem::abspath() or WP_Filesystem::wp_*_dir()' ); + $this->verbose = $echo; + return $this->abspath(); + } + + /** + * Locate a folder on the remote filesystem. + * + * Assumes that on Windows systems, Stripping off the Drive + * letter is OK Sanitizes \\ to / in windows filepaths. + * + * @access public + * @since 2.7.0 + * + * @param string $folder the folder to locate. + * @return string The location of the remote path. + */ + function find_folder( $folder ) { + + if ( isset( $this->cache[ $folder ] ) ) + return $this->cache[ $folder ]; + + if ( stripos($this->method, 'ftp') !== false ) { + $constant_overrides = array( + 'FTP_BASE' => ABSPATH, + 'FTP_CONTENT_DIR' => WP_CONTENT_DIR, + 'FTP_PLUGIN_DIR' => WP_PLUGIN_DIR, + 'FTP_LANG_DIR' => WP_LANG_DIR + ); + + // Direct matches ( folder = CONSTANT/ ) + foreach ( $constant_overrides as $constant => $dir ) { + if ( ! defined( $constant ) ) + continue; + if ( $folder === $dir ) + return trailingslashit( constant( $constant ) ); + } + + // Prefix Matches ( folder = CONSTANT/subdir ) + foreach ( $constant_overrides as $constant => $dir ) { + if ( ! defined( $constant ) ) + continue; + if ( 0 === stripos( $folder, $dir ) ) { // $folder starts with $dir + $potential_folder = preg_replace( '#^' . preg_quote( $dir, '#' ) . '/#i', trailingslashit( constant( $constant ) ), $folder ); + $potential_folder = trailingslashit( $potential_folder ); + + if ( $this->is_dir( $potential_folder ) ) { + $this->cache[ $folder ] = $potential_folder; + return $potential_folder; + } + } + } + } elseif ( 'direct' == $this->method ) { + $folder = str_replace('\\', '/', $folder); // Windows path sanitisation + return trailingslashit($folder); + } + + $folder = preg_replace('|^([a-z]{1}):|i', '', $folder); // Strip out windows drive letter if it's there. + $folder = str_replace('\\', '/', $folder); // Windows path sanitisation + + if ( isset($this->cache[ $folder ] ) ) + return $this->cache[ $folder ]; + + if ( $this->exists($folder) ) { // Folder exists at that absolute path. + $folder = trailingslashit($folder); + $this->cache[ $folder ] = $folder; + return $folder; + } + if ( $return = $this->search_for_folder($folder) ) + $this->cache[ $folder ] = $return; + return $return; + } + + /** + * Locate a folder on the remote filesystem. + * + * Expects Windows sanitized path. + * + * @access private + * @since 2.7.0 + * + * @param string $folder The folder to locate. + * @param string $base The folder to start searching from. + * @param bool $loop If the function has recursed, Internal use only. + * @return string The location of the remote path. + */ + function search_for_folder( $folder, $base = '.', $loop = false ) { + if ( empty( $base ) || '.' == $base ) + $base = trailingslashit($this->cwd()); + + $folder = untrailingslashit($folder); + + if ( $this->verbose ) + printf( "\n" . __('Looking for %1$s in %2$s') . "
\n", $folder, $base ); + + $folder_parts = explode('/', $folder); + $folder_part_keys = array_keys( $folder_parts ); + $last_index = array_pop( $folder_part_keys ); + $last_path = $folder_parts[ $last_index ]; + + $files = $this->dirlist( $base ); + + foreach ( $folder_parts as $index => $key ) { + if ( $index == $last_index ) + continue; // We want this to be caught by the next code block. + + // Working from /home/ to /user/ to /wordpress/ see if that file exists within the current folder, + // If it's found, change into it and follow through looking for it. + // If it cant find WordPress down that route, it'll continue onto the next folder level, and see if that matches, and so on. + // If it reaches the end, and still cant find it, it'll return false for the entire function. + if ( isset($files[ $key ]) ){ + // Lets try that folder: + $newdir = trailingslashit(path_join($base, $key)); + if ( $this->verbose ) + printf( "\n" . __('Changing to %s') . "
\n", $newdir ); + // only search for the remaining path tokens in the directory, not the full path again + $newfolder = implode( '/', array_slice( $folder_parts, $index + 1 ) ); + if ( $ret = $this->search_for_folder( $newfolder, $newdir, $loop) ) + return $ret; + } + } + + // Only check this as a last resort, to prevent locating the incorrect install. All above procedures will fail quickly if this is the right branch to take. + if (isset( $files[ $last_path ] ) ) { + if ( $this->verbose ) + printf( "\n" . __('Found %s') . "
\n", $base . $last_path ); + return trailingslashit($base . $last_path); + } + + // Prevent this function from looping again. + // No need to proceed if we've just searched in / + if ( $loop || '/' == $base ) + return false; + + // As an extra last resort, Change back to / if the folder wasn't found. + // This comes into effect when the CWD is /home/user/ but WP is at /var/www/.... + return $this->search_for_folder( $folder, '/', true ); + + } + + /** + * Return the *nix-style file permissions for a file. + * + * From the PHP documentation page for fileperms(). + * + * @link http://docs.php.net/fileperms + * + * @access public + * @since 2.5.0 + * + * @param string $file String filename. + * @return string The *nix-style representation of permissions. + */ + function gethchmod( $file ){ + $perms = $this->getchmod($file); + if (($perms & 0xC000) == 0xC000) // Socket + $info = 's'; + elseif (($perms & 0xA000) == 0xA000) // Symbolic Link + $info = 'l'; + elseif (($perms & 0x8000) == 0x8000) // Regular + $info = '-'; + elseif (($perms & 0x6000) == 0x6000) // Block special + $info = 'b'; + elseif (($perms & 0x4000) == 0x4000) // Directory + $info = 'd'; + elseif (($perms & 0x2000) == 0x2000) // Character special + $info = 'c'; + elseif (($perms & 0x1000) == 0x1000) // FIFO pipe + $info = 'p'; + else // Unknown + $info = 'u'; + + // Owner + $info .= (($perms & 0x0100) ? 'r' : '-'); + $info .= (($perms & 0x0080) ? 'w' : '-'); + $info .= (($perms & 0x0040) ? + (($perms & 0x0800) ? 's' : 'x' ) : + (($perms & 0x0800) ? 'S' : '-')); + + // Group + $info .= (($perms & 0x0020) ? 'r' : '-'); + $info .= (($perms & 0x0010) ? 'w' : '-'); + $info .= (($perms & 0x0008) ? + (($perms & 0x0400) ? 's' : 'x' ) : + (($perms & 0x0400) ? 'S' : '-')); + + // World + $info .= (($perms & 0x0004) ? 'r' : '-'); + $info .= (($perms & 0x0002) ? 'w' : '-'); + $info .= (($perms & 0x0001) ? + (($perms & 0x0200) ? 't' : 'x' ) : + (($perms & 0x0200) ? 'T' : '-')); + return $info; + } + + /** + * Convert *nix-style file permissions to a octal number. + * + * Converts '-rw-r--r--' to 0644 + * From "info at rvgate dot nl"'s comment on the PHP documentation for chmod() + * + * @link http://docs.php.net/manual/en/function.chmod.php#49614 + * + * @access public + * @since 2.5.0 + * + * @param string $mode string The *nix-style file permission. + * @return int octal representation + */ + function getnumchmodfromh( $mode ) { + $realmode = ''; + $legal = array('', 'w', 'r', 'x', '-'); + $attarray = preg_split('//', $mode); + + for ($i=0; $i < count($attarray); $i++) + if ($key = array_search($attarray[$i], $legal)) + $realmode .= $legal[$key]; + + $mode = str_pad($realmode, 10, '-', STR_PAD_LEFT); + $trans = array('-'=>'0', 'r'=>'4', 'w'=>'2', 'x'=>'1'); + $mode = strtr($mode,$trans); + + $newmode = $mode[0]; + $newmode .= $mode[1] + $mode[2] + $mode[3]; + $newmode .= $mode[4] + $mode[5] + $mode[6]; + $newmode .= $mode[7] + $mode[8] + $mode[9]; + return $newmode; + } + + /** + * Determine if the string provided contains binary characters. + * + * @access private + * @since 2.7.0 + * + * @param string $text String to test against. + * @return bool true if string is binary, false otherwise. + */ + function is_binary( $text ) { + return (bool) preg_match( '|[^\x20-\x7E]|', $text ); // chr(32)..chr(127) + } + + /** + * Change the ownership of a file / folder. + * + * Default behavior is to do nothing, override this in your subclass, if desired. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param mixed $owner A user name or number. + * @param bool $recursive Optional. If set True changes file owner recursivly. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chown( $file, $owner, $recursive = false ) { + return false; + } + + /** + * Connect filesystem. + * + * @since 2.5.0 + * + * @return bool True on success or false on failure (always true for WP_Filesystem_Direct). + */ + function connect() { + return true; + } + + /** + * Read entire file into a string. + * + * @since 2.5.0 + * + * @param string $file Name of the file to read. + * @return string|bool Returns the read data or false on failure. + */ + function get_contents( $file ) { + return false; + } + + /** + * Read entire file into an array. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return array|bool the file contents in an array or false on failure. + */ + function get_contents_array( $file ) { + return false; + } + + /** + * Write a string to a file. + * + * @since 2.5.0 + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int $mode Optional. The file permissions as octal number, usually 0644. + * @return bool False on failure. + */ + function put_contents( $file, $contents, $mode = false ) { + return false; + } + + /** + * Get the current working directory. + * + * @since 2.5.0 + * + * @return string|bool The current working directory on success, or false on failure. + */ + function cwd() { + return false; + } + + /** + * Change current directory. + * + * @since 2.5.0 + * + * @param string $dir The new current directory. + * @return bool Returns true on success or false on failure. + */ + function chdir( $dir ) { + return false; + } + + /** + * Change the file group. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param mixed $group A group name or number. + * @param bool $recursive Optional. If set True changes file group recursively. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chgrp( $file, $group, $recursive = false ) { + return false; + } + + /** + * Change filesystem permissions. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param int $mode Optional. The permissions as octal number, usually 0644 for files, 0755 for dirs. + * @param bool $recursive Optional. If set True changes file group recursively. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chmod( $file, $mode = false, $recursive = false ) { + return false; + } + + /** + * Get the file owner. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|bool Username of the user or false on error. + */ + function owner( $file ) { + return false; + } + + /** + * Get the file's group. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @return string|bool The group or false on error. + */ + function group( $file ) { + return false; + } + + /** + * Copy a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @param int $mode Optional. The permissions as octal number, usually 0644 for files, 0755 for dirs. + * Default false. + * @return bool True if file copied successfully, False otherwise. + */ + function copy( $source, $destination, $overwrite = false, $mode = false ) { + return false; + } + + /** + * Move a file. + * + * @since 2.5.0 + * + * @param string $source Path to the source file. + * @param string $destination Path to the destination file. + * @param bool $overwrite Optional. Whether to overwrite the destination file if it exists. + * Default false. + * @return bool True if file copied successfully, False otherwise. + */ + function move( $source, $destination, $overwrite = false ) { + return false; + } + + /** + * Delete a file or directory. + * + * @since 2.5.0 + * + * @param string $file Path to the file. + * @param bool $recursive Optional. If set True changes file group recursively. Defaults to False. + * Default false. + * @param bool $type Type of resource. 'f' for file, 'd' for directory. + * Default false. + * @return bool True if the file or directory was deleted, false on failure. + */ + function delete( $file, $recursive = false, $type = false ) { + return false; + } + + /** + * Check if a file or directory exists. + * + * @since 2.5.0 + * + * @param string $file Path to file/directory. + * @return bool Whether $file exists or not. + */ + function exists( $file ) { + return false; + } + + /** + * Check if resource is a file. + * + * @since 2.5.0 + * + * @param string $file File path. + * @return bool Whether $file is a file. + */ + function is_file( $file ) { + return false; + } + + /** + * Check if resource is a directory. + * + * @since 2.5.0 + * + * @param string $path Directory path. + * @return bool Whether $path is a directory. + */ + function is_dir( $path ) { + return false; + } + + /** + * Check if a file is readable. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return bool Whether $file is readable. + */ + function is_readable( $file ) { + return false; + } + + /** + * Check if a file or directory is writable. + * + * @since 2.5.0 + * + * @param string $path Path to file/directory. + * @return bool Whether $file is writable. + */ + function is_writable( $file ) { + return false; + } + + /** + * Gets the file's last access time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int Unix timestamp representing last access time. + */ + function atime( $file ) { + return false; + } + + /** + * Gets the file modification time. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int Unix timestamp representing modification time. + */ + function mtime( $file ) { + return false; + } + + /** + * Gets the file size (in bytes). + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @return int Size of the file in bytes. + */ + function size( $file ) { + return false; + } + + /** + * Set the access and modification times of a file. + * + * Note: If $file doesn't exist, it will be created. + * + * @since 2.5.0 + * + * @param string $file Path to file. + * @param int $time Optional. Modified time to set for file. + * Default 0. + * @param int $atime Optional. Access time to set for file. + * Default 0. + * @return bool Whether operation was successful or not. + */ + function touch( $file, $time = 0, $atime = 0 ) { + return false; + } + + /** + * Create a directory. + * + * @since 2.5.0 + * + * @param string $path Path for new directory. + * @param mixed $chmod Optional. The permissions as octal number, (or False to skip chmod) + * Default false. + * @param mixed $chown Optional. A user name or number (or False to skip chown) + * Default false. + * @param mixed $chgrp Optional. A group name or number (or False to skip chgrp). + * Default false. + * @return bool False if directory cannot be created, true otherwise. + */ + function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) { + return false; + } + + /** + * Delete a directory. + * + * @since 2.5.0 + * + * @param string $path Path to directory. + * @param bool $recursive Optional. Whether to recursively remove files/directories. + * Default false. + * @return bool Whether directory is deleted successfully or not. + */ + function rmdir( $path, $recursive = false ) { + return false; + } + + /** + * Get details for files in a directory or a specific file. + * + * @since 2.5.0 + * + * @param string $path Path to directory or file. + * @param bool $include_hidden Optional. Whether to include details of hidden ("." prefixed) files. + * Default true. + * @param bool $recursive Optional. Whether to recursively include file details in nested directories. + * Default false. + * @return array|bool { + * Array of files. False if unable to list directory contents. + * + * @type string 'name' Name of the file/directory. + * @type string 'perms' *nix representation of permissions. + * @type int 'permsn' Octal representation of permissions. + * @type string 'owner' Owner name or ID. + * @type int 'size' Size of file in bytes. + * @type int 'lastmodunix' Last modified unix timestamp. + * @type mixed 'lastmod' Last modified month (3 letter) and day (without leading 0). + * @type int 'time' Last modified time. + * @type string 'type' Type of resource. 'f' for file, 'd' for directory. + * @type mixed 'files' If a directory and $recursive is true, contains another array of files. + * } + */ + function dirlist( $path, $include_hidden = true, $recursive = false ) { + return false; + } + +} // WP_Filesystem_Base diff --git a/sources/wp-admin/includes/class-wp-filesystem-direct.php b/sources/wp-admin/includes/class-wp-filesystem-direct.php new file mode 100644 index 0000000..d07305b --- /dev/null +++ b/sources/wp-admin/includes/class-wp-filesystem-direct.php @@ -0,0 +1,384 @@ +method = 'direct'; + $this->errors = new WP_Error(); + } + + /** + * Reads entire file into a string + * + * @param string $file Name of the file to read. + * @return string|bool The function returns the read data or false on failure. + */ + function get_contents($file) { + return @file_get_contents($file); + } + + /** + * Reads entire file into an array + * + * @param string $file Path to the file. + * @return array|bool the file contents in an array or false on failure. + */ + function get_contents_array($file) { + return @file($file); + } + + /** + * Write a string to a file + * + * @param string $file Remote path to the file where to write the data. + * @param string $contents The data to write. + * @param int $mode (optional) The file permissions as octal number, usually 0644. + * @return bool False upon failure. + */ + function put_contents( $file, $contents, $mode = false ) { + $fp = @fopen( $file, 'wb' ); + if ( ! $fp ) + return false; + + mbstring_binary_safe_encoding(); + + $data_length = strlen( $contents ); + + $bytes_written = fwrite( $fp, $contents ); + + reset_mbstring_encoding(); + + fclose( $fp ); + + if ( $data_length !== $bytes_written ) + return false; + + $this->chmod( $file, $mode ); + + return true; + } + + /** + * Gets the current working directory + * + * @return string|bool the current working directory on success, or false on failure. + */ + function cwd() { + return @getcwd(); + } + + /** + * Change directory + * + * @param string $dir The new current directory. + * @return bool Returns true on success or false on failure. + */ + function chdir($dir) { + return @chdir($dir); + } + + /** + * Changes file group + * + * @param string $file Path to the file. + * @param mixed $group A group name or number. + * @param bool $recursive (optional) If set True changes file group recursively. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chgrp($file, $group, $recursive = false) { + if ( ! $this->exists($file) ) + return false; + if ( ! $recursive ) + return @chgrp($file, $group); + if ( ! $this->is_dir($file) ) + return @chgrp($file, $group); + // Is a directory, and we want recursive + $file = trailingslashit($file); + $filelist = $this->dirlist($file); + foreach ($filelist as $filename) + $this->chgrp($file . $filename, $group, $recursive); + + return true; + } + + /** + * Changes filesystem permissions + * + * @param string $file Path to the file. + * @param int $mode (optional) The permissions as octal number, usually 0644 for files, 0755 for dirs. + * @param bool $recursive (optional) If set True changes file group recursively. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chmod($file, $mode = false, $recursive = false) { + if ( ! $mode ) { + if ( $this->is_file($file) ) + $mode = FS_CHMOD_FILE; + elseif ( $this->is_dir($file) ) + $mode = FS_CHMOD_DIR; + else + return false; + } + + if ( ! $recursive || ! $this->is_dir($file) ) + return @chmod($file, $mode); + // Is a directory, and we want recursive + $file = trailingslashit($file); + $filelist = $this->dirlist($file); + foreach ( (array)$filelist as $filename => $filemeta) + $this->chmod($file . $filename, $mode, $recursive); + + return true; + } + + /** + * Changes file owner + * + * @param string $file Path to the file. + * @param mixed $owner A user name or number. + * @param bool $recursive (optional) If set True changes file owner recursively. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chown($file, $owner, $recursive = false) { + if ( ! $this->exists($file) ) + return false; + if ( ! $recursive ) + return @chown($file, $owner); + if ( ! $this->is_dir($file) ) + return @chown($file, $owner); + // Is a directory, and we want recursive + $filelist = $this->dirlist($file); + foreach ($filelist as $filename) { + $this->chown($file . '/' . $filename, $owner, $recursive); + } + return true; + } + + /** + * Gets file owner + * + * @param string $file Path to the file. + * @return string|bool Username of the user or false on error. + */ + function owner($file) { + $owneruid = @fileowner($file); + if ( ! $owneruid ) + return false; + if ( ! function_exists('posix_getpwuid') ) + return $owneruid; + $ownerarray = posix_getpwuid($owneruid); + return $ownerarray['name']; + } + + /** + * Gets file permissions + * + * FIXME does not handle errors in fileperms() + * + * @param string $file Path to the file. + * @return string Mode of the file (last 4 digits). + */ + function getchmod($file) { + return substr(decoct(@fileperms($file)),3); + } + + function group($file) { + $gid = @filegroup($file); + if ( ! $gid ) + return false; + if ( ! function_exists('posix_getgrgid') ) + return $gid; + $grouparray = posix_getgrgid($gid); + return $grouparray['name']; + } + + function copy($source, $destination, $overwrite = false, $mode = false) { + if ( ! $overwrite && $this->exists($destination) ) + return false; + + $rtval = copy($source, $destination); + if ( $mode ) + $this->chmod($destination, $mode); + return $rtval; + } + + function move($source, $destination, $overwrite = false) { + if ( ! $overwrite && $this->exists($destination) ) + return false; + + // try using rename first. if that fails (for example, source is read only) try copy + if ( @rename($source, $destination) ) + return true; + + if ( $this->copy($source, $destination, $overwrite) && $this->exists($destination) ) { + $this->delete($source); + return true; + } else { + return false; + } + } + + function delete($file, $recursive = false, $type = false) { + if ( empty( $file ) ) // Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem. + return false; + $file = str_replace( '\\', '/', $file ); // for win32, occasional problems deleting files otherwise + + if ( 'f' == $type || $this->is_file($file) ) + return @unlink($file); + if ( ! $recursive && $this->is_dir($file) ) + return @rmdir($file); + + // At this point it's a folder, and we're in recursive mode + $file = trailingslashit($file); + $filelist = $this->dirlist($file, true); + + $retval = true; + if ( is_array( $filelist ) ) { + foreach ( $filelist as $filename => $fileinfo ) { + if ( ! $this->delete($file . $filename, $recursive, $fileinfo['type']) ) + $retval = false; + } + } + + if ( file_exists($file) && ! @rmdir($file) ) + $retval = false; + + return $retval; + } + + function exists($file) { + return @file_exists($file); + } + + function is_file($file) { + return @is_file($file); + } + + function is_dir($path) { + return @is_dir($path); + } + + function is_readable($file) { + return @is_readable($file); + } + + function is_writable($file) { + return @is_writable($file); + } + + function atime($file) { + return @fileatime($file); + } + + function mtime($file) { + return @filemtime($file); + } + + function size($file) { + return @filesize($file); + } + + function touch($file, $time = 0, $atime = 0) { + if ($time == 0) + $time = time(); + if ($atime == 0) + $atime = time(); + return @touch($file, $time, $atime); + } + + function mkdir($path, $chmod = false, $chown = false, $chgrp = false) { + // safe mode fails with a trailing slash under certain PHP versions. + $path = untrailingslashit($path); + if ( empty($path) ) + return false; + + if ( ! $chmod ) + $chmod = FS_CHMOD_DIR; + + if ( ! @mkdir($path) ) + return false; + $this->chmod($path, $chmod); + if ( $chown ) + $this->chown($path, $chown); + if ( $chgrp ) + $this->chgrp($path, $chgrp); + return true; + } + + function rmdir($path, $recursive = false) { + return $this->delete($path, $recursive); + } + + function dirlist($path, $include_hidden = true, $recursive = false) { + if ( $this->is_file($path) ) { + $limit_file = basename($path); + $path = dirname($path); + } else { + $limit_file = false; + } + + if ( ! $this->is_dir($path) ) + return false; + + $dir = @dir($path); + if ( ! $dir ) + return false; + + $ret = array(); + + while (false !== ($entry = $dir->read()) ) { + $struc = array(); + $struc['name'] = $entry; + + if ( '.' == $struc['name'] || '..' == $struc['name'] ) + continue; + + if ( ! $include_hidden && '.' == $struc['name'][0] ) + continue; + + if ( $limit_file && $struc['name'] != $limit_file) + continue; + + $struc['perms'] = $this->gethchmod($path.'/'.$entry); + $struc['permsn'] = $this->getnumchmodfromh($struc['perms']); + $struc['number'] = false; + $struc['owner'] = $this->owner($path.'/'.$entry); + $struc['group'] = $this->group($path.'/'.$entry); + $struc['size'] = $this->size($path.'/'.$entry); + $struc['lastmodunix']= $this->mtime($path.'/'.$entry); + $struc['lastmod'] = date('M j',$struc['lastmodunix']); + $struc['time'] = date('h:i:s',$struc['lastmodunix']); + $struc['type'] = $this->is_dir($path.'/'.$entry) ? 'd' : 'f'; + + if ( 'd' == $struc['type'] ) { + if ( $recursive ) + $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive); + else + $struc['files'] = array(); + } + + $ret[ $struc['name'] ] = $struc; + } + $dir->close(); + unset($dir); + return $ret; + } +} diff --git a/sources/wp-admin/includes/class-wp-filesystem-ftpext.php b/sources/wp-admin/includes/class-wp-filesystem-ftpext.php new file mode 100644 index 0000000..b9e32cd --- /dev/null +++ b/sources/wp-admin/includes/class-wp-filesystem-ftpext.php @@ -0,0 +1,415 @@ +method = 'ftpext'; + $this->errors = new WP_Error(); + + // Check if possible to use ftp functions. + if ( ! extension_loaded('ftp') ) { + $this->errors->add('no_ftp_ext', __('The ftp PHP extension is not available')); + return false; + } + + // This Class uses the timeout on a per-connection basis, Others use it on a per-action basis. + + if ( ! defined('FS_TIMEOUT') ) + define('FS_TIMEOUT', 240); + + if ( empty($opt['port']) ) + $this->options['port'] = 21; + else + $this->options['port'] = $opt['port']; + + if ( empty($opt['hostname']) ) + $this->errors->add('empty_hostname', __('FTP hostname is required')); + else + $this->options['hostname'] = $opt['hostname']; + + if ( ! empty($opt['base']) ) + $this->wp_base = $opt['base']; + + // Check if the options provided are OK. + if ( empty($opt['username']) ) + $this->errors->add('empty_username', __('FTP username is required')); + else + $this->options['username'] = $opt['username']; + + if ( empty($opt['password']) ) + $this->errors->add('empty_password', __('FTP password is required')); + else + $this->options['password'] = $opt['password']; + + $this->options['ssl'] = false; + if ( isset($opt['connection_type']) && 'ftps' == $opt['connection_type'] ) + $this->options['ssl'] = true; + } + + function connect() { + if ( isset($this->options['ssl']) && $this->options['ssl'] && function_exists('ftp_ssl_connect') ) + $this->link = @ftp_ssl_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT); + else + $this->link = @ftp_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT); + + if ( ! $this->link ) { + $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port'])); + return false; + } + + if ( ! @ftp_login($this->link,$this->options['username'], $this->options['password']) ) { + $this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username'])); + return false; + } + + // Set the Connection to use Passive FTP + @ftp_pasv( $this->link, true ); + if ( @ftp_get_option($this->link, FTP_TIMEOUT_SEC) < FS_TIMEOUT ) + @ftp_set_option($this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT); + + return true; + } + + function get_contents( $file ) { + $tempfile = wp_tempnam($file); + $temp = fopen($tempfile, 'w+'); + + if ( ! $temp ) + return false; + + if ( ! @ftp_fget($this->link, $temp, $file, FTP_BINARY ) ) + return false; + + fseek( $temp, 0 ); // Skip back to the start of the file being written to + $contents = ''; + + while ( ! feof($temp) ) + $contents .= fread($temp, 8192); + + fclose($temp); + unlink($tempfile); + return $contents; + } + + function get_contents_array($file) { + return explode("\n", $this->get_contents($file)); + } + + function put_contents($file, $contents, $mode = false ) { + $tempfile = wp_tempnam($file); + $temp = fopen( $tempfile, 'wb+' ); + if ( ! $temp ) + return false; + + mbstring_binary_safe_encoding(); + + $data_length = strlen( $contents ); + $bytes_written = fwrite( $temp, $contents ); + + reset_mbstring_encoding(); + + if ( $data_length !== $bytes_written ) { + fclose( $temp ); + unlink( $tempfile ); + return false; + } + + fseek( $temp, 0 ); // Skip back to the start of the file being written to + + $ret = @ftp_fput( $this->link, $file, $temp, FTP_BINARY ); + + fclose($temp); + unlink($tempfile); + + $this->chmod($file, $mode); + + return $ret; + } + + function cwd() { + $cwd = @ftp_pwd($this->link); + if ( $cwd ) + $cwd = trailingslashit($cwd); + return $cwd; + } + + function chdir($dir) { + return @ftp_chdir($this->link, $dir); + } + + function chgrp($file, $group, $recursive = false ) { + return false; + } + + function chmod($file, $mode = false, $recursive = false) { + if ( ! $mode ) { + if ( $this->is_file($file) ) + $mode = FS_CHMOD_FILE; + elseif ( $this->is_dir($file) ) + $mode = FS_CHMOD_DIR; + else + return false; + } + + // chmod any sub-objects if recursive. + if ( $recursive && $this->is_dir($file) ) { + $filelist = $this->dirlist($file); + foreach ( (array)$filelist as $filename => $filemeta ) + $this->chmod($file . '/' . $filename, $mode, $recursive); + } + + // chmod the file or directory + if ( ! function_exists('ftp_chmod') ) + return (bool)@ftp_site($this->link, sprintf('CHMOD %o %s', $mode, $file)); + return (bool)@ftp_chmod($this->link, $mode, $file); + } + + function owner($file) { + $dir = $this->dirlist($file); + return $dir[$file]['owner']; + } + + function getchmod($file) { + $dir = $this->dirlist($file); + return $dir[$file]['permsn']; + } + + function group($file) { + $dir = $this->dirlist($file); + return $dir[$file]['group']; + } + + function copy($source, $destination, $overwrite = false, $mode = false) { + if ( ! $overwrite && $this->exists($destination) ) + return false; + $content = $this->get_contents($source); + if ( false === $content ) + return false; + return $this->put_contents($destination, $content, $mode); + } + + function move($source, $destination, $overwrite = false) { + return ftp_rename($this->link, $source, $destination); + } + + function delete($file, $recursive = false, $type = false) { + if ( empty($file) ) + return false; + if ( 'f' == $type || $this->is_file($file) ) + return @ftp_delete($this->link, $file); + if ( !$recursive ) + return @ftp_rmdir($this->link, $file); + + $filelist = $this->dirlist( trailingslashit($file) ); + if ( !empty($filelist) ) + foreach ( $filelist as $delete_file ) + $this->delete( trailingslashit($file) . $delete_file['name'], $recursive, $delete_file['type'] ); + return @ftp_rmdir($this->link, $file); + } + + function exists($file) { + $list = @ftp_nlist($this->link, $file); + return !empty($list); //empty list = no file, so invert. + } + + function is_file($file) { + return $this->exists($file) && !$this->is_dir($file); + } + + function is_dir($path) { + $cwd = $this->cwd(); + $result = @ftp_chdir($this->link, trailingslashit($path) ); + if ( $result && $path == $this->cwd() || $this->cwd() != $cwd ) { + @ftp_chdir($this->link, $cwd); + return true; + } + return false; + } + + function is_readable($file) { + return true; + } + + function is_writable($file) { + return true; + } + + function atime($file) { + return false; + } + + function mtime($file) { + return ftp_mdtm($this->link, $file); + } + + function size($file) { + return ftp_size($this->link, $file); + } + + function touch($file, $time = 0, $atime = 0) { + return false; + } + + function mkdir($path, $chmod = false, $chown = false, $chgrp = false) { + $path = untrailingslashit($path); + if ( empty($path) ) + return false; + + if ( !@ftp_mkdir($this->link, $path) ) + return false; + $this->chmod($path, $chmod); + if ( $chown ) + $this->chown($path, $chown); + if ( $chgrp ) + $this->chgrp($path, $chgrp); + return true; + } + + function rmdir($path, $recursive = false) { + return $this->delete($path, $recursive); + } + + function parselisting($line) { + static $is_windows; + if ( is_null($is_windows) ) + $is_windows = stripos( ftp_systype($this->link), 'win') !== false; + + if ( $is_windows && preg_match('/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|) +(.+)/', $line, $lucifer) ) { + $b = array(); + if ( $lucifer[3] < 70 ) + $lucifer[3] +=2000; + else + $lucifer[3] += 1900; // 4digit year fix + $b['isdir'] = ( $lucifer[7] == ''); + if ( $b['isdir'] ) + $b['type'] = 'd'; + else + $b['type'] = 'f'; + $b['size'] = $lucifer[7]; + $b['month'] = $lucifer[1]; + $b['day'] = $lucifer[2]; + $b['year'] = $lucifer[3]; + $b['hour'] = $lucifer[4]; + $b['minute'] = $lucifer[5]; + $b['time'] = @mktime($lucifer[4] + (strcasecmp($lucifer[6], "PM") == 0 ? 12 : 0), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3]); + $b['am/pm'] = $lucifer[6]; + $b['name'] = $lucifer[8]; + } elseif ( !$is_windows && $lucifer = preg_split('/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY)) { + //echo $line."\n"; + $lcount = count($lucifer); + if ( $lcount < 8 ) + return ''; + $b = array(); + $b['isdir'] = $lucifer[0]{0} === 'd'; + $b['islink'] = $lucifer[0]{0} === 'l'; + if ( $b['isdir'] ) + $b['type'] = 'd'; + elseif ( $b['islink'] ) + $b['type'] = 'l'; + else + $b['type'] = 'f'; + $b['perms'] = $lucifer[0]; + $b['number'] = $lucifer[1]; + $b['owner'] = $lucifer[2]; + $b['group'] = $lucifer[3]; + $b['size'] = $lucifer[4]; + if ( $lcount == 8 ) { + sscanf($lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day']); + sscanf($lucifer[6], '%d:%d', $b['hour'], $b['minute']); + $b['time'] = @mktime($b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year']); + $b['name'] = $lucifer[7]; + } else { + $b['month'] = $lucifer[5]; + $b['day'] = $lucifer[6]; + if ( preg_match('/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2) ) { + $b['year'] = date("Y"); + $b['hour'] = $l2[1]; + $b['minute'] = $l2[2]; + } else { + $b['year'] = $lucifer[7]; + $b['hour'] = 0; + $b['minute'] = 0; + } + $b['time'] = strtotime( sprintf('%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute']) ); + $b['name'] = $lucifer[8]; + } + } + + // Replace symlinks formatted as "source -> target" with just the source name + if ( $b['islink'] ) + $b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] ); + + return $b; + } + + function dirlist($path = '.', $include_hidden = true, $recursive = false) { + if ( $this->is_file($path) ) { + $limit_file = basename($path); + $path = dirname($path) . '/'; + } else { + $limit_file = false; + } + + $pwd = @ftp_pwd($this->link); + if ( ! @ftp_chdir($this->link, $path) ) // Cant change to folder = folder doesn't exist + return false; + $list = @ftp_rawlist($this->link, '-a', false); + @ftp_chdir($this->link, $pwd); + + if ( empty($list) ) // Empty array = non-existent folder (real folder will show . at least) + return false; + + $dirlist = array(); + foreach ( $list as $k => $v ) { + $entry = $this->parselisting($v); + if ( empty($entry) ) + continue; + + if ( '.' == $entry['name'] || '..' == $entry['name'] ) + continue; + + if ( ! $include_hidden && '.' == $entry['name'][0] ) + continue; + + if ( $limit_file && $entry['name'] != $limit_file) + continue; + + $dirlist[ $entry['name'] ] = $entry; + } + + $ret = array(); + foreach ( (array)$dirlist as $struc ) { + if ( 'd' == $struc['type'] ) { + if ( $recursive ) + $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive); + else + $struc['files'] = array(); + } + + $ret[ $struc['name'] ] = $struc; + } + return $ret; + } + + function __destruct() { + if ( $this->link ) + ftp_close($this->link); + } +} diff --git a/sources/wp-admin/includes/class-wp-filesystem-ftpsockets.php b/sources/wp-admin/includes/class-wp-filesystem-ftpsockets.php new file mode 100644 index 0000000..817dd08 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-filesystem-ftpsockets.php @@ -0,0 +1,351 @@ +method = 'ftpsockets'; + $this->errors = new WP_Error(); + + // Check if possible to use ftp functions. + if ( ! @include_once ABSPATH . 'wp-admin/includes/class-ftp.php' ) + return false; + $this->ftp = new ftp(); + + if ( empty($opt['port']) ) + $this->options['port'] = 21; + else + $this->options['port'] = $opt['port']; + + if ( empty($opt['hostname']) ) + $this->errors->add('empty_hostname', __('FTP hostname is required')); + else + $this->options['hostname'] = $opt['hostname']; + + if ( ! empty($opt['base']) ) + $this->wp_base = $opt['base']; + + // Check if the options provided are OK. + if ( empty ($opt['username']) ) + $this->errors->add('empty_username', __('FTP username is required')); + else + $this->options['username'] = $opt['username']; + + if ( empty ($opt['password']) ) + $this->errors->add('empty_password', __('FTP password is required')); + else + $this->options['password'] = $opt['password']; + } + + function connect() { + if ( ! $this->ftp ) + return false; + + $this->ftp->setTimeout(FS_CONNECT_TIMEOUT); + + if ( ! $this->ftp->SetServer($this->options['hostname'], $this->options['port']) ) { + $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port'])); + return false; + } + + if ( ! $this->ftp->connect() ) { + $this->errors->add('connect', sprintf(__('Failed to connect to FTP Server %1$s:%2$s'), $this->options['hostname'], $this->options['port'])); + return false; + } + + if ( ! $this->ftp->login($this->options['username'], $this->options['password']) ) { + $this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username'])); + return false; + } + + $this->ftp->SetType( FTP_BINARY ); + $this->ftp->Passive( true ); + $this->ftp->setTimeout( FS_TIMEOUT ); + return true; + } + + function get_contents( $file ) { + if ( ! $this->exists($file) ) + return false; + + $temp = wp_tempnam( $file ); + + if ( ! $temphandle = fopen($temp, 'w+') ) + return false; + + mbstring_binary_safe_encoding(); + + if ( ! $this->ftp->fget($temphandle, $file) ) { + fclose($temphandle); + unlink($temp); + + reset_mbstring_encoding(); + + return ''; // Blank document, File does exist, It's just blank. + } + + reset_mbstring_encoding(); + + fseek( $temphandle, 0 ); // Skip back to the start of the file being written to + $contents = ''; + + while ( ! feof($temphandle) ) + $contents .= fread($temphandle, 8192); + + fclose($temphandle); + unlink($temp); + return $contents; + } + + function get_contents_array($file) { + return explode("\n", $this->get_contents($file) ); + } + + function put_contents($file, $contents, $mode = false ) { + $temp = wp_tempnam( $file ); + if ( ! $temphandle = @fopen($temp, 'w+') ) { + unlink($temp); + return false; + } + + // The FTP class uses string functions internally during file download/upload + mbstring_binary_safe_encoding(); + + $bytes_written = fwrite( $temphandle, $contents ); + if ( false === $bytes_written || $bytes_written != strlen( $contents ) ) { + fclose( $temphandle ); + unlink( $temp ); + + reset_mbstring_encoding(); + + return false; + } + + fseek( $temphandle, 0 ); // Skip back to the start of the file being written to + + $ret = $this->ftp->fput($file, $temphandle); + + reset_mbstring_encoding(); + + fclose($temphandle); + unlink($temp); + + $this->chmod($file, $mode); + + return $ret; + } + + function cwd() { + $cwd = $this->ftp->pwd(); + if ( $cwd ) + $cwd = trailingslashit($cwd); + return $cwd; + } + + function chdir($file) { + return $this->ftp->chdir($file); + } + + function chgrp($file, $group, $recursive = false ) { + return false; + } + + function chmod($file, $mode = false, $recursive = false ) { + if ( ! $mode ) { + if ( $this->is_file($file) ) + $mode = FS_CHMOD_FILE; + elseif ( $this->is_dir($file) ) + $mode = FS_CHMOD_DIR; + else + return false; + } + + // chmod any sub-objects if recursive. + if ( $recursive && $this->is_dir($file) ) { + $filelist = $this->dirlist($file); + foreach ( (array)$filelist as $filename => $filemeta ) + $this->chmod($file . '/' . $filename, $mode, $recursive); + } + + // chmod the file or directory + return $this->ftp->chmod($file, $mode); + } + + function owner($file) { + $dir = $this->dirlist($file); + return $dir[$file]['owner']; + } + + function getchmod($file) { + $dir = $this->dirlist($file); + return $dir[$file]['permsn']; + } + + function group($file) { + $dir = $this->dirlist($file); + return $dir[$file]['group']; + } + + function copy($source, $destination, $overwrite = false, $mode = false) { + if ( ! $overwrite && $this->exists($destination) ) + return false; + + $content = $this->get_contents($source); + if ( false === $content ) + return false; + + return $this->put_contents($destination, $content, $mode); + } + + function move($source, $destination, $overwrite = false ) { + return $this->ftp->rename($source, $destination); + } + + function delete($file, $recursive = false, $type = false) { + if ( empty($file) ) + return false; + if ( 'f' == $type || $this->is_file($file) ) + return $this->ftp->delete($file); + if ( !$recursive ) + return $this->ftp->rmdir($file); + + return $this->ftp->mdel($file); + } + + function exists( $file ) { + $list = $this->ftp->nlist( $file ); + return !empty( $list ); //empty list = no file, so invert. + // return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server + } + + function is_file($file) { + if ( $this->is_dir($file) ) + return false; + if ( $this->exists($file) ) + return true; + return false; + } + + function is_dir($path) { + $cwd = $this->cwd(); + if ( $this->chdir($path) ) { + $this->chdir($cwd); + return true; + } + return false; + } + + function is_readable($file) { + return true; + } + + function is_writable($file) { + return true; + } + + function atime($file) { + return false; + } + + function mtime($file) { + return $this->ftp->mdtm($file); + } + + function size($file) { + return $this->ftp->filesize($file); + } + + function touch($file, $time = 0, $atime = 0 ) { + return false; + } + + function mkdir($path, $chmod = false, $chown = false, $chgrp = false ) { + $path = untrailingslashit($path); + if ( empty($path) ) + return false; + + if ( ! $this->ftp->mkdir($path) ) + return false; + if ( ! $chmod ) + $chmod = FS_CHMOD_DIR; + $this->chmod($path, $chmod); + if ( $chown ) + $this->chown($path, $chown); + if ( $chgrp ) + $this->chgrp($path, $chgrp); + return true; + } + + function rmdir($path, $recursive = false ) { + $this->delete($path, $recursive); + } + + function dirlist($path = '.', $include_hidden = true, $recursive = false ) { + if ( $this->is_file($path) ) { + $limit_file = basename($path); + $path = dirname($path) . '/'; + } else { + $limit_file = false; + } + + mbstring_binary_safe_encoding(); + + $list = $this->ftp->dirlist($path); + if ( empty( $list ) && ! $this->exists( $path ) ) { + + reset_mbstring_encoding(); + + return false; + } + + $ret = array(); + foreach ( $list as $struc ) { + + if ( '.' == $struc['name'] || '..' == $struc['name'] ) + continue; + + if ( ! $include_hidden && '.' == $struc['name'][0] ) + continue; + + if ( $limit_file && $struc['name'] != $limit_file ) + continue; + + if ( 'd' == $struc['type'] ) { + if ( $recursive ) + $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive); + else + $struc['files'] = array(); + } + + // Replace symlinks formatted as "source -> target" with just the source name + if ( $struc['islink'] ) + $struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] ); + + $ret[ $struc['name'] ] = $struc; + } + + reset_mbstring_encoding(); + + return $ret; + } + + function __destruct() { + $this->ftp->quit(); + } +} diff --git a/sources/wp-admin/includes/class-wp-filesystem-ssh2.php b/sources/wp-admin/includes/class-wp-filesystem-ssh2.php new file mode 100644 index 0000000..f942989 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-filesystem-ssh2.php @@ -0,0 +1,391 @@ +method = 'ssh2'; + $this->errors = new WP_Error(); + + //Check if possible to use ssh2 functions. + if ( ! extension_loaded('ssh2') ) { + $this->errors->add('no_ssh2_ext', __('The ssh2 PHP extension is not available')); + return false; + } + if ( !function_exists('stream_get_contents') ) { + $this->errors->add('ssh2_php_requirement', __('The ssh2 PHP extension is available, however, we require the PHP5 function stream_get_contents()')); + return false; + } + + // Set defaults: + if ( empty($opt['port']) ) + $this->options['port'] = 22; + else + $this->options['port'] = $opt['port']; + + if ( empty($opt['hostname']) ) + $this->errors->add('empty_hostname', __('SSH2 hostname is required')); + else + $this->options['hostname'] = $opt['hostname']; + + if ( ! empty($opt['base']) ) + $this->wp_base = $opt['base']; + + // Check if the options provided are OK. + if ( !empty ($opt['public_key']) && !empty ($opt['private_key']) ) { + $this->options['public_key'] = $opt['public_key']; + $this->options['private_key'] = $opt['private_key']; + + $this->options['hostkey'] = array('hostkey' => 'ssh-rsa'); + + $this->keys = true; + } elseif ( empty ($opt['username']) ) { + $this->errors->add('empty_username', __('SSH2 username is required')); + } + + if ( !empty($opt['username']) ) + $this->options['username'] = $opt['username']; + + if ( empty ($opt['password']) ) { + if ( !$this->keys ) //password can be blank if we are using keys + $this->errors->add('empty_password', __('SSH2 password is required')); + } else { + $this->options['password'] = $opt['password']; + } + + } + + function connect() { + if ( ! $this->keys ) { + $this->link = @ssh2_connect($this->options['hostname'], $this->options['port']); + } else { + $this->link = @ssh2_connect($this->options['hostname'], $this->options['port'], $this->options['hostkey']); + } + + if ( ! $this->link ) { + $this->errors->add('connect', sprintf(__('Failed to connect to SSH2 Server %1$s:%2$s'), $this->options['hostname'], $this->options['port'])); + return false; + } + + if ( !$this->keys ) { + if ( ! @ssh2_auth_password($this->link, $this->options['username'], $this->options['password']) ) { + $this->errors->add('auth', sprintf(__('Username/Password incorrect for %s'), $this->options['username'])); + return false; + } + } else { + if ( ! @ssh2_auth_pubkey_file($this->link, $this->options['username'], $this->options['public_key'], $this->options['private_key'], $this->options['password'] ) ) { + $this->errors->add('auth', sprintf(__('Public and Private keys incorrect for %s'), $this->options['username'])); + return false; + } + } + + $this->sftp_link = ssh2_sftp($this->link); + + return true; + } + + function run_command( $command, $returnbool = false) { + + if ( ! $this->link ) + return false; + + if ( ! ($stream = ssh2_exec($this->link, $command)) ) { + $this->errors->add('command', sprintf(__('Unable to perform command: %s'), $command)); + } else { + stream_set_blocking( $stream, true ); + stream_set_timeout( $stream, FS_TIMEOUT ); + $data = stream_get_contents( $stream ); + fclose( $stream ); + + if ( $returnbool ) + return ( $data === false ) ? false : '' != trim($data); + else + return $data; + } + return false; + } + + function get_contents( $file ) { + $file = ltrim($file, '/'); + return file_get_contents('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function get_contents_array($file) { + $file = ltrim($file, '/'); + return file('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function put_contents($file, $contents, $mode = false ) { + $ret = file_put_contents( 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim( $file, '/' ), $contents ); + + if ( $ret !== strlen( $contents ) ) + return false; + + $this->chmod($file, $mode); + + return true; + } + + function cwd() { + $cwd = $this->run_command('pwd'); + if ( $cwd ) + $cwd = trailingslashit($cwd); + return $cwd; + } + + function chdir($dir) { + return $this->run_command('cd ' . $dir, true); + } + + function chgrp($file, $group, $recursive = false ) { + if ( ! $this->exists($file) ) + return false; + if ( ! $recursive || ! $this->is_dir($file) ) + return $this->run_command(sprintf('chgrp %s %s', escapeshellarg($group), escapeshellarg($file)), true); + return $this->run_command(sprintf('chgrp -R %s %s', escapeshellarg($group), escapeshellarg($file)), true); + } + + function chmod($file, $mode = false, $recursive = false) { + if ( ! $this->exists($file) ) + return false; + + if ( ! $mode ) { + if ( $this->is_file($file) ) + $mode = FS_CHMOD_FILE; + elseif ( $this->is_dir($file) ) + $mode = FS_CHMOD_DIR; + else + return false; + } + + if ( ! $recursive || ! $this->is_dir($file) ) + return $this->run_command(sprintf('chmod %o %s', $mode, escapeshellarg($file)), true); + return $this->run_command(sprintf('chmod -R %o %s', $mode, escapeshellarg($file)), true); + } + + /** + * Change the ownership of a file / folder. + * + * @since Unknown + * + * @param string $file Path to the file. + * @param mixed $owner A user name or number. + * @param bool $recursive Optional. If set True changes file owner recursivly. Defaults to False. + * @return bool Returns true on success or false on failure. + */ + function chown( $file, $owner, $recursive = false ) { + if ( ! $this->exists($file) ) + return false; + if ( ! $recursive || ! $this->is_dir($file) ) + return $this->run_command(sprintf('chown %s %s', escapeshellarg($owner), escapeshellarg($file)), true); + return $this->run_command(sprintf('chown -R %s %s', escapeshellarg($owner), escapeshellarg($file)), true); + } + + function owner($file) { + $owneruid = @fileowner('ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/')); + if ( ! $owneruid ) + return false; + if ( ! function_exists('posix_getpwuid') ) + return $owneruid; + $ownerarray = posix_getpwuid($owneruid); + return $ownerarray['name']; + } + + function getchmod($file) { + return substr(decoct(@fileperms( 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/') )),3); + } + + function group($file) { + $gid = @filegroup('ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/')); + if ( ! $gid ) + return false; + if ( ! function_exists('posix_getgrgid') ) + return $gid; + $grouparray = posix_getgrgid($gid); + return $grouparray['name']; + } + + function copy($source, $destination, $overwrite = false, $mode = false) { + if ( ! $overwrite && $this->exists($destination) ) + return false; + $content = $this->get_contents($source); + if ( false === $content) + return false; + return $this->put_contents($destination, $content, $mode); + } + + function move($source, $destination, $overwrite = false) { + return @ssh2_sftp_rename($this->link, $source, $destination); + } + + function delete($file, $recursive = false, $type = false) { + if ( 'f' == $type || $this->is_file($file) ) + return ssh2_sftp_unlink($this->sftp_link, $file); + if ( ! $recursive ) + return ssh2_sftp_rmdir($this->sftp_link, $file); + $filelist = $this->dirlist($file); + if ( is_array($filelist) ) { + foreach ( $filelist as $filename => $fileinfo) { + $this->delete($file . '/' . $filename, $recursive, $fileinfo['type']); + } + } + return ssh2_sftp_rmdir($this->sftp_link, $file); + } + + function exists($file) { + $file = ltrim($file, '/'); + return file_exists('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function is_file($file) { + $file = ltrim($file, '/'); + return is_file('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function is_dir($path) { + $path = ltrim($path, '/'); + return is_dir('ssh2.sftp://' . $this->sftp_link . '/' . $path); + } + + function is_readable($file) { + $file = ltrim($file, '/'); + return is_readable('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function is_writable($file) { + $file = ltrim($file, '/'); + return is_writable('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function atime($file) { + $file = ltrim($file, '/'); + return fileatime('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function mtime($file) { + $file = ltrim($file, '/'); + return filemtime('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function size($file) { + $file = ltrim($file, '/'); + return filesize('ssh2.sftp://' . $this->sftp_link . '/' . $file); + } + + function touch($file, $time = 0, $atime = 0) { + //Not implemented. + } + + function mkdir($path, $chmod = false, $chown = false, $chgrp = false) { + $path = untrailingslashit($path); + if ( empty($path) ) + return false; + + if ( ! $chmod ) + $chmod = FS_CHMOD_DIR; + if ( ! ssh2_sftp_mkdir($this->sftp_link, $path, $chmod, true) ) + return false; + if ( $chown ) + $this->chown($path, $chown); + if ( $chgrp ) + $this->chgrp($path, $chgrp); + return true; + } + + function rmdir($path, $recursive = false) { + return $this->delete($path, $recursive); + } + + function dirlist($path, $include_hidden = true, $recursive = false) { + if ( $this->is_file($path) ) { + $limit_file = basename($path); + $path = dirname($path); + } else { + $limit_file = false; + } + + if ( ! $this->is_dir($path) ) + return false; + + $ret = array(); + $dir = @dir('ssh2.sftp://' . $this->sftp_link .'/' . ltrim($path, '/') ); + + if ( ! $dir ) + return false; + + while (false !== ($entry = $dir->read()) ) { + $struc = array(); + $struc['name'] = $entry; + + if ( '.' == $struc['name'] || '..' == $struc['name'] ) + continue; //Do not care about these folders. + + if ( ! $include_hidden && '.' == $struc['name'][0] ) + continue; + + if ( $limit_file && $struc['name'] != $limit_file ) + continue; + + $struc['perms'] = $this->gethchmod($path.'/'.$entry); + $struc['permsn'] = $this->getnumchmodfromh($struc['perms']); + $struc['number'] = false; + $struc['owner'] = $this->owner($path.'/'.$entry); + $struc['group'] = $this->group($path.'/'.$entry); + $struc['size'] = $this->size($path.'/'.$entry); + $struc['lastmodunix']= $this->mtime($path.'/'.$entry); + $struc['lastmod'] = date('M j',$struc['lastmodunix']); + $struc['time'] = date('h:i:s',$struc['lastmodunix']); + $struc['type'] = $this->is_dir($path.'/'.$entry) ? 'd' : 'f'; + + if ( 'd' == $struc['type'] ) { + if ( $recursive ) + $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive); + else + $struc['files'] = array(); + } + + $ret[ $struc['name'] ] = $struc; + } + $dir->close(); + unset($dir); + return $ret; + } +} diff --git a/sources/wp-admin/includes/class-wp-importer.php b/sources/wp-admin/includes/class-wp-importer.php new file mode 100644 index 0000000..57ff7f4 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-importer.php @@ -0,0 +1,302 @@ +prepare( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '%s' LIMIT %d,%d", $meta_key, $offset, $limit ); + $results = $wpdb->get_results( $sql ); + + // Increment offset + $offset = ( $limit + $offset ); + + if ( !empty( $results ) ) { + foreach ( $results as $r ) { + // Set permalinks into array + $hashtable[$r->meta_value] = intval( $r->post_id ); + } + } + } while ( count( $results ) == $limit ); + + // unset to save memory + unset( $results, $r ); + + return $hashtable; + } + + /** + * Return count of imported permalinks from WordPress database + * + * @param string $bid + * @return int + */ + function count_imported_posts( $importer_name, $bid ) { + global $wpdb; + + $count = 0; + + // Get count of permalinks + $meta_key = $importer_name . '_' . $bid . '_permalink'; + $sql = $wpdb->prepare( "SELECT COUNT( post_id ) AS cnt FROM $wpdb->postmeta WHERE meta_key = '%s'", $meta_key ); + + $result = $wpdb->get_results( $sql ); + + if ( !empty( $result ) ) + $count = intval( $result[0]->cnt ); + + // unset to save memory + unset( $results ); + + return $count; + } + + /** + * Set array with imported comments from WordPress database + * + * @param string $bid + * @return array + */ + function get_imported_comments( $bid ) { + global $wpdb; + + $hashtable = array(); + + $limit = 100; + $offset = 0; + + // Grab all comments in chunks + do { + $sql = $wpdb->prepare( "SELECT comment_ID, comment_agent FROM $wpdb->comments LIMIT %d,%d", $offset, $limit ); + $results = $wpdb->get_results( $sql ); + + // Increment offset + $offset = ( $limit + $offset ); + + if ( !empty( $results ) ) { + foreach ( $results as $r ) { + // Explode comment_agent key + list ( $ca_bid, $source_comment_id ) = explode( '-', $r->comment_agent ); + $source_comment_id = intval( $source_comment_id ); + + // Check if this comment came from this blog + if ( $bid == $ca_bid ) { + $hashtable[$source_comment_id] = intval( $r->comment_ID ); + } + } + } + } while ( count( $results ) == $limit ); + + // unset to save memory + unset( $results, $r ); + + return $hashtable; + } + + function set_blog( $blog_id ) { + if ( is_numeric( $blog_id ) ) { + $blog_id = (int) $blog_id; + } else { + $blog = 'http://' . preg_replace( '#^https?://#', '', $blog_id ); + if ( ( !$parsed = parse_url( $blog ) ) || empty( $parsed['host'] ) ) { + fwrite( STDERR, "Error: can not determine blog_id from $blog_id\n" ); + exit(); + } + if ( empty( $parsed['path'] ) ) + $parsed['path'] = '/'; + $blog = get_blog_details( array( 'domain' => $parsed['host'], 'path' => $parsed['path'] ) ); + if ( !$blog ) { + fwrite( STDERR, "Error: Could not find blog\n" ); + exit(); + } + $blog_id = (int) $blog->blog_id; + } + + if ( function_exists( 'is_multisite' ) ) { + if ( is_multisite() ) + switch_to_blog( $blog_id ); + } + + return $blog_id; + } + + function set_user( $user_id ) { + if ( is_numeric( $user_id ) ) { + $user_id = (int) $user_id; + } else { + $user_id = (int) username_exists( $user_id ); + } + + if ( !$user_id || !wp_set_current_user( $user_id ) ) { + fwrite( STDERR, "Error: can not find user\n" ); + exit(); + } + + return $user_id; + } + + /** + * Sort by strlen, longest string first + * + * @param string $a + * @param string $b + * @return int + */ + function cmpr_strlen( $a, $b ) { + return strlen( $b ) - strlen( $a ); + } + + /** + * GET URL + * + * @param string $url + * @param string $username + * @param string $password + * @param bool $head + * @return array + */ + function get_page( $url, $username = '', $password = '', $head = false ) { + // Increase the timeout + add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) ); + + $headers = array(); + $args = array(); + if ( true === $head ) + $args['method'] = 'HEAD'; + if ( !empty( $username ) && !empty( $password ) ) + $headers['Authorization'] = 'Basic ' . base64_encode( "$username:$password" ); + + $args['headers'] = $headers; + + return wp_safe_remote_request( $url, $args ); + } + + /** + * Bump up the request timeout for http requests + * + * @param int $val + * @return int + */ + function bump_request_timeout( $val ) { + return 60; + } + + /** + * Check if user has exceeded disk quota + * + * @return bool + */ + function is_user_over_quota() { + if ( function_exists( 'upload_is_user_over_quota' ) ) { + if ( upload_is_user_over_quota( 1 ) ) { + echo "Sorry, you have used your upload quota.\n"; + return true; + } + } + + return false; + } + + /** + * Replace newlines, tabs, and multiple spaces with a single space + * + * @param string $string + * @return string + */ + function min_whitespace( $string ) { + return preg_replace( '|[\r\n\t ]+|', ' ', $string ); + } + + /** + * Reset global variables that grow out of control during imports + * + * @return void + */ + function stop_the_insanity() { + global $wpdb, $wp_actions; + // Or define( 'WP_IMPORTING', true ); + $wpdb->queries = array(); + // Reset $wp_actions to keep it from growing out of control + $wp_actions = array(); + } +} + +/** + * Returns value of command line params. + * Exits when a required param is not set. + * + * @param string $param + * @param bool $required + * @return mixed + */ +function get_cli_args( $param, $required = false ) { + $args = $_SERVER['argv']; + + $out = array(); + + $last_arg = null; + $return = null; + + $il = sizeof( $args ); + + for ( $i = 1, $il; $i < $il; $i++ ) { + if ( (bool) preg_match( "/^--(.+)/", $args[$i], $match ) ) { + $parts = explode( "=", $match[1] ); + $key = preg_replace( "/[^a-z0-9]+/", "", $parts[0] ); + + if ( isset( $parts[1] ) ) { + $out[$key] = $parts[1]; + } else { + $out[$key] = true; + } + + $last_arg = $key; + } else if ( (bool) preg_match( "/^-([a-zA-Z0-9]+)/", $args[$i], $match ) ) { + for ( $j = 0, $jl = strlen( $match[1] ); $j < $jl; $j++ ) { + $key = $match[1]{$j}; + $out[$key] = true; + } + + $last_arg = $key; + } else if ( $last_arg !== null ) { + $out[$last_arg] = $args[$i]; + } + } + + // Check array for specified param + if ( isset( $out[$param] ) ) { + // Set return value + $return = $out[$param]; + } + + // Check for missing required param + if ( !isset( $out[$param] ) && $required ) { + // Display message and exit + echo "\"$param\" parameter is required but was not specified\n"; + exit(); + } + + return $return; +} diff --git a/sources/wp-admin/includes/class-wp-links-list-table.php b/sources/wp-admin/includes/class-wp-links-list-table.php new file mode 100644 index 0000000..e1c5f18 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-links-list-table.php @@ -0,0 +1,189 @@ + 'bookmarks', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + } + + function ajax_user_can() { + return current_user_can( 'manage_links' ); + } + + function prepare_items() { + global $cat_id, $s, $orderby, $order; + + wp_reset_vars( array( 'action', 'cat_id', 'link_id', 'orderby', 'order', 's' ) ); + + $args = array( 'hide_invisible' => 0, 'hide_empty' => 0 ); + + if ( 'all' != $cat_id ) + $args['category'] = $cat_id; + if ( !empty( $s ) ) + $args['search'] = $s; + if ( !empty( $orderby ) ) + $args['orderby'] = $orderby; + if ( !empty( $order ) ) + $args['order'] = $order; + + $this->items = get_bookmarks( $args ); + } + + function no_items() { + _e( 'No links found.' ); + } + + function get_bulk_actions() { + $actions = array(); + $actions['delete'] = __( 'Delete' ); + + return $actions; + } + + function extra_tablenav( $which ) { + global $cat_id; + + if ( 'top' != $which ) + return; +?> +
+ $cat_id, + 'name' => 'cat_id', + 'taxonomy' => 'link_category', + 'show_option_all' => __( 'View all categories' ), + 'hide_empty' => true, + 'hierarchical' => 1, + 'show_count' => 0, + 'orderby' => 'name', + ); + wp_dropdown_categories( $dropdown_options ); + submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); +?> +
+ '', + 'name' => _x( 'Name', 'link name' ), + 'url' => __( 'URL' ), + 'categories' => __( 'Categories' ), + 'rel' => __( 'Relationship' ), + 'visible' => __( 'Visible' ), + 'rating' => __( 'Rating' ) + ); + } + + function get_sortable_columns() { + return array( + 'name' => 'name', + 'url' => 'url', + 'visible' => 'visible', + 'rating' => 'rating' + ); + } + + function display_rows() { + global $cat_id; + + $alt = 0; + + foreach ( $this->items as $link ) { + $link = sanitize_bookmark( $link ); + $link->link_name = esc_attr( $link->link_name ); + $link->link_category = wp_get_link_cats( $link->link_id ); + + $short_url = url_shorten( $link->link_url ); + + $visible = ( $link->link_visible == 'Y' ) ? __( 'Yes' ) : __( 'No' ); + $rating = $link->link_rating; + $style = ( $alt++ % 2 ) ? '' : ' class="alternate"'; + + $edit_link = get_edit_bookmark_link( $link ); +?> + > +get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $class = "class='column-$column_name'"; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = $class . $style; + + switch ( $column_name ) { + case 'cb': ?> + + + + + link_name ) ) . "'>$link->link_name
"; + + $actions = array(); + $actions['edit'] = '' . __( 'Edit' ) . ''; + $actions['delete'] = "link_id ) . "' onclick=\"if ( confirm( '" . esc_js( sprintf( __( "You are about to delete this link '%s'\n 'Cancel' to stop, 'OK' to delete." ), $link->link_name ) ) . "' ) ) { return true;}return false;\">" . __( 'Delete' ) . ""; + echo $this->row_actions( $actions ); + + echo ''; + break; + case 'url': + echo "link_name ) )."'>$short_url"; + break; + case 'categories': + ?>>link_category as $category ) { + $cat = get_term( $category, 'link_category', OBJECT, 'display' ); + if ( is_wp_error( $cat ) ) + echo $cat->get_error_message(); + $cat_name = $cat->name; + if ( $cat_id != $category ) + $cat_name = "$cat_name"; + $cat_names[] = $cat_name; + } + echo implode( ', ', $cat_names ); + ?>>link_rel ) ? '
' : $link->link_rel; ?>>> + >link_id ); ?> + + + '', + 'singular' => '', + 'ajax' => false, + 'screen' => null, + ) ); + + $this->screen = convert_to_screen( $args['screen'] ); + + add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 ); + + if ( !$args['plural'] ) + $args['plural'] = $this->screen->base; + + $args['plural'] = sanitize_key( $args['plural'] ); + $args['singular'] = sanitize_key( $args['singular'] ); + + $this->_args = $args; + + if ( $args['ajax'] ) { + // wp_enqueue_script( 'list-table' ); + add_action( 'admin_footer', array( $this, '_js_vars' ) ); + } + } + + /** + * Checks the current user's permissions + * @uses wp_die() + * + * @since 3.1.0 + * @access public + * @abstract + */ + function ajax_user_can() { + die( 'function WP_List_Table::ajax_user_can() must be over-ridden in a sub-class.' ); + } + + /** + * Prepares the list of items for displaying. + * @uses WP_List_Table::set_pagination_args() + * + * @since 3.1.0 + * @access public + * @abstract + */ + function prepare_items() { + die( 'function WP_List_Table::prepare_items() must be over-ridden in a sub-class.' ); + } + + /** + * An internal method that sets all the necessary pagination arguments + * + * @param array $args An associative array with information about the pagination + * @access protected + */ + function set_pagination_args( $args ) { + $args = wp_parse_args( $args, array( + 'total_items' => 0, + 'total_pages' => 0, + 'per_page' => 0, + ) ); + + if ( !$args['total_pages'] && $args['per_page'] > 0 ) + $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] ); + + // redirect if page number is invalid and headers are not already sent + if ( ! headers_sent() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) { + wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) ); + exit; + } + + $this->_pagination_args = $args; + } + + /** + * Access the pagination args + * + * @since 3.1.0 + * @access public + * + * @param string $key + * @return array + */ + function get_pagination_arg( $key ) { + if ( 'page' == $key ) + return $this->get_pagenum(); + + if ( isset( $this->_pagination_args[$key] ) ) + return $this->_pagination_args[$key]; + } + + /** + * Whether the table has items to display or not + * + * @since 3.1.0 + * @access public + * + * @return bool + */ + function has_items() { + return !empty( $this->items ); + } + + /** + * Message to be displayed when there are no items + * + * @since 3.1.0 + * @access public + */ + function no_items() { + _e( 'No items found.' ); + } + + /** + * Display the search box. + * + * @since 3.1.0 + * @access public + * + * @param string $text The search button text + * @param string $input_id The search input id + */ + function search_box( $text, $input_id ) { + if ( empty( $_REQUEST['s'] ) && !$this->has_items() ) + return; + + $input_id = $input_id . '-search-input'; + + if ( ! empty( $_REQUEST['orderby'] ) ) + echo ''; + if ( ! empty( $_REQUEST['order'] ) ) + echo ''; + if ( ! empty( $_REQUEST['post_mime_type'] ) ) + echo ''; + if ( ! empty( $_REQUEST['detached'] ) ) + echo ''; +?> + + link ) with the list + * of views available on this table. + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + function get_views() { + return array(); + } + + /** + * Display the list of views available on this table. + * + * @since 3.1.0 + * @access public + */ + function views() { + $views = $this->get_views(); + $views = apply_filters( 'views_' . $this->screen->id, $views ); + + if ( empty( $views ) ) + return; + + echo "
    \n"; + foreach ( $views as $class => $view ) { + $views[ $class ] = "\t
  • $view"; + } + echo implode( " |
  • \n", $views ) . "\n"; + echo "
"; + } + + /** + * Get an associative array ( option_name => option_title ) with the list + * of bulk actions available on this table. + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + function get_bulk_actions() { + return array(); + } + + /** + * Display the bulk actions dropdown. + * + * @since 3.1.0 + * @access public + */ + function bulk_actions() { + if ( is_null( $this->_actions ) ) { + $no_new_actions = $this->_actions = $this->get_bulk_actions(); + // This filter can currently only be used to remove actions. + $this->_actions = apply_filters( 'bulk_actions-' . $this->screen->id, $this->_actions ); + $this->_actions = array_intersect_assoc( $this->_actions, $no_new_actions ); + $two = ''; + } else { + $two = '2'; + } + + if ( empty( $this->_actions ) ) + return; + + echo "\n"; + + submit_button( __( 'Apply' ), 'action', false, false, array( 'id' => "doaction$two" ) ); + echo "\n"; + } + + /** + * Get the current action selected from the bulk actions dropdown. + * + * @since 3.1.0 + * @access public + * + * @return string|bool The action name or False if no action was selected + */ + function current_action() { + if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) + return $_REQUEST['action']; + + if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) + return $_REQUEST['action2']; + + return false; + } + + /** + * Generate row actions div + * + * @since 3.1.0 + * @access protected + * + * @param array $actions The list of actions + * @param bool $always_visible Whether the actions should be always visible + * @return string + */ + function row_actions( $actions, $always_visible = false ) { + $action_count = count( $actions ); + $i = 0; + + if ( !$action_count ) + return ''; + + $out = '
'; + foreach ( $actions as $action => $link ) { + ++$i; + ( $i == $action_count ) ? $sep = '' : $sep = ' | '; + $out .= "$link$sep"; + } + $out .= '
'; + + return $out; + } + + /** + * Display a monthly dropdown for filtering items + * + * @since 3.1.0 + * @access protected + */ + function months_dropdown( $post_type ) { + global $wpdb, $wp_locale; + + $months = $wpdb->get_results( $wpdb->prepare( " + SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month + FROM $wpdb->posts + WHERE post_type = %s + ORDER BY post_date DESC + ", $post_type ) ); + + /** + * Filter the months dropdown results. + * + * @since 3.7.0 + * + * @param object $months The months dropdown query results. + * @param string $post_type The post type. + */ + $months = apply_filters( 'months_dropdown_results', $months, $post_type ); + + $month_count = count( $months ); + + if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) + return; + + $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0; +?> + + __( 'List View' ), + 'excerpt' => __( 'Excerpt View' ) + ); + +?> + +
+ $title ) { + $class = ( $current_mode == $mode ) ? 'class="current"' : ''; + echo "$title\n"; + } + ?> +
+'; + + echo "" . number_format_i18n( get_comments_number() ) . ""; + + if ( $pending_comments ) + echo ''; + } + + /** + * Get the current page number + * + * @since 3.1.0 + * @access protected + * + * @return int + */ + function get_pagenum() { + $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0; + + if( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] ) + $pagenum = $this->_pagination_args['total_pages']; + + return max( 1, $pagenum ); + } + + /** + * Get number of items to display on a single page + * + * @since 3.1.0 + * @access protected + * + * @return int + */ + function get_items_per_page( $option, $default = 20 ) { + $per_page = (int) get_user_option( $option ); + if ( empty( $per_page ) || $per_page < 1 ) + $per_page = $default; + + return (int) apply_filters( $option, $per_page ); + } + + /** + * Display the pagination. + * + * @since 3.1.0 + * @access protected + */ + function pagination( $which ) { + if ( empty( $this->_pagination_args ) ) + return; + + extract( $this->_pagination_args, EXTR_SKIP ); + + $output = '' . sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . ''; + + $current = $this->get_pagenum(); + + $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + + $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url ); + + $page_links = array(); + + $disable_first = $disable_last = ''; + if ( $current == 1 ) + $disable_first = ' disabled'; + if ( $current == $total_pages ) + $disable_last = ' disabled'; + + $page_links[] = sprintf( "%s", + 'first-page' . $disable_first, + esc_attr__( 'Go to the first page' ), + esc_url( remove_query_arg( 'paged', $current_url ) ), + '«' + ); + + $page_links[] = sprintf( "%s", + 'prev-page' . $disable_first, + esc_attr__( 'Go to the previous page' ), + esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ), + '‹' + ); + + if ( 'bottom' == $which ) + $html_current_page = $current; + else + $html_current_page = sprintf( "", + esc_attr__( 'Current page' ), + $current, + strlen( $total_pages ) + ); + + $html_total_pages = sprintf( "%s", number_format_i18n( $total_pages ) ); + $page_links[] = '' . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . ''; + + $page_links[] = sprintf( "%s", + 'next-page' . $disable_last, + esc_attr__( 'Go to the next page' ), + esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ), + '›' + ); + + $page_links[] = sprintf( "%s", + 'last-page' . $disable_last, + esc_attr__( 'Go to the last page' ), + esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ), + '»' + ); + + $pagination_links_class = 'pagination-links'; + if ( ! empty( $infinite_scroll ) ) + $pagination_links_class = ' hide-if-js'; + $output .= "\n" . join( "\n", $page_links ) . ''; + + if ( $total_pages ) + $page_class = $total_pages < 2 ? ' one-page' : ''; + else + $page_class = ' no-pages'; + + $this->_pagination = "
$output
"; + + echo $this->_pagination; + } + + /** + * Get a list of columns. The format is: + * 'internal-name' => 'Title' + * + * @since 3.1.0 + * @access protected + * @abstract + * + * @return array + */ + function get_columns() { + die( 'function WP_List_Table::get_columns() must be over-ridden in a sub-class.' ); + } + + /** + * Get a list of sortable columns. The format is: + * 'internal-name' => 'orderby' + * or + * 'internal-name' => array( 'orderby', true ) + * + * The second format will make the initial sorting order be descending + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + function get_sortable_columns() { + return array(); + } + + /** + * Get a list of all, hidden and sortable columns, with filter applied + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + function get_column_info() { + if ( isset( $this->_column_headers ) ) + return $this->_column_headers; + + $columns = get_column_headers( $this->screen ); + $hidden = get_hidden_columns( $this->screen ); + + $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $this->get_sortable_columns() ); + + $sortable = array(); + foreach ( $_sortable as $id => $data ) { + if ( empty( $data ) ) + continue; + + $data = (array) $data; + if ( !isset( $data[1] ) ) + $data[1] = false; + + $sortable[$id] = $data; + } + + $this->_column_headers = array( $columns, $hidden, $sortable ); + + return $this->_column_headers; + } + + /** + * Return number of visible columns + * + * @since 3.1.0 + * @access public + * + * @return int + */ + function get_column_count() { + list ( $columns, $hidden ) = $this->get_column_info(); + $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) ); + return count( $columns ) - count( $hidden ); + } + + /** + * Print column headers, accounting for hidden and sortable columns. + * + * @since 3.1.0 + * @access protected + * + * @param bool $with_id Whether to set the id attribute or not + */ + function print_column_headers( $with_id = true ) { + list( $columns, $hidden, $sortable ) = $this->get_column_info(); + + $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); + $current_url = remove_query_arg( 'paged', $current_url ); + + if ( isset( $_GET['orderby'] ) ) + $current_orderby = $_GET['orderby']; + else + $current_orderby = ''; + + if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] ) + $current_order = 'desc'; + else + $current_order = 'asc'; + + if ( ! empty( $columns['cb'] ) ) { + static $cb_counter = 1; + $columns['cb'] = '' + . ''; + $cb_counter++; + } + + foreach ( $columns as $column_key => $column_display_name ) { + $class = array( 'manage-column', "column-$column_key" ); + + $style = ''; + if ( in_array( $column_key, $hidden ) ) + $style = 'display:none;'; + + $style = ' style="' . $style . '"'; + + if ( 'cb' == $column_key ) + $class[] = 'check-column'; + elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) ) + $class[] = 'num'; + + if ( isset( $sortable[$column_key] ) ) { + list( $orderby, $desc_first ) = $sortable[$column_key]; + + if ( $current_orderby == $orderby ) { + $order = 'asc' == $current_order ? 'desc' : 'asc'; + $class[] = 'sorted'; + $class[] = $current_order; + } else { + $order = $desc_first ? 'desc' : 'asc'; + $class[] = 'sortable'; + $class[] = $desc_first ? 'asc' : 'desc'; + } + + $column_display_name = '' . $column_display_name . ''; + } + + $id = $with_id ? "id='$column_key'" : ''; + + if ( !empty( $class ) ) + $class = "class='" . join( ' ', $class ) . "'"; + + echo "$column_display_name"; + } + } + + /** + * Display the table + * + * @since 3.1.0 + * @access public + */ + function display() { + extract( $this->_args ); + + $this->display_tablenav( 'top' ); + +?> + + + + print_column_headers(); ?> + + + + + + print_column_headers( false ); ?> + + + + > + display_rows_or_placeholder(); ?> + +
+display_tablenav( 'bottom' ); + } + + /** + * Get a list of CSS classes for the tag + * + * @since 3.1.0 + * @access protected + * + * @return array + */ + function get_table_classes() { + return array( 'widefat', 'fixed', $this->_args['plural'] ); + } + + /** + * Generate the table navigation above or below the table + * + * @since 3.1.0 + * @access protected + */ + function display_tablenav( $which ) { + if ( 'top' == $which ) + wp_nonce_field( 'bulk-' . $this->_args['plural'] ); +?> +
+ +
+ bulk_actions(); ?> +
+extra_tablenav( $which ); + $this->pagination( $which ); +?> + +
+
+ part of the table + * + * @since 3.1.0 + * @access protected + */ + function display_rows_or_placeholder() { + if ( $this->has_items() ) { + $this->display_rows(); + } else { + list( $columns, $hidden ) = $this->get_column_info(); + echo ''; + } + } + + /** + * Generate the table rows + * + * @since 3.1.0 + * @access protected + */ + function display_rows() { + foreach ( $this->items as $item ) + $this->single_row( $item ); + } + + /** + * Generates content for a single row of the table + * + * @since 3.1.0 + * @access protected + * + * @param object $item The current item + */ + function single_row( $item ) { + static $row_class = ''; + $row_class = ( $row_class == '' ? ' class="alternate"' : '' ); + + echo ''; + $this->single_row_columns( $item ); + echo ''; + } + + /** + * Generates the columns for a single row of the table + * + * @since 3.1.0 + * @access protected + * + * @param object $item The current item + */ + function single_row_columns( $item ) { + list( $columns, $hidden ) = $this->get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $class = "class='$column_name column-$column_name'"; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = "$class$style"; + + if ( 'cb' == $column_name ) { + echo ''; + } + elseif ( method_exists( $this, 'column_' . $column_name ) ) { + echo ""; + } + else { + echo ""; + } + } + } + + /** + * Handle an incoming ajax request (called from admin-ajax.php) + * + * @since 3.1.0 + * @access public + */ + function ajax_response() { + $this->prepare_items(); + + extract( $this->_args ); + extract( $this->_pagination_args, EXTR_SKIP ); + + ob_start(); + if ( ! empty( $_REQUEST['no_placeholder'] ) ) + $this->display_rows(); + else + $this->display_rows_or_placeholder(); + + $rows = ob_get_clean(); + + $response = array( 'rows' => $rows ); + + if ( isset( $total_items ) ) + $response['total_items_i18n'] = sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ); + + if ( isset( $total_pages ) ) { + $response['total_pages'] = $total_pages; + $response['total_pages_i18n'] = number_format_i18n( $total_pages ); + } + + die( json_encode( $response ) ); + } + + /** + * Send required variables to JavaScript land + * + * @access private + */ + function _js_vars() { + $args = array( + 'class' => get_class( $this ), + 'screen' => array( + 'id' => $this->screen->id, + 'base' => $this->screen->base, + ) + ); + + printf( "\n", json_encode( $args ) ); + } +} diff --git a/sources/wp-admin/includes/class-wp-media-list-table.php b/sources/wp-admin/includes/class-wp-media-list-table.php new file mode 100644 index 0000000..1f0067d --- /dev/null +++ b/sources/wp-admin/includes/class-wp-media-list-table.php @@ -0,0 +1,437 @@ +detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] ); + + parent::__construct( array( + 'plural' => 'media', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + } + + function ajax_user_can() { + return current_user_can('upload_files'); + } + + function prepare_items() { + global $lost, $wpdb, $wp_query, $post_mime_types, $avail_post_mime_types; + + $q = $_REQUEST; + + if ( !empty( $lost ) ) + $q['post__in'] = implode( ',', $lost ); + + list( $post_mime_types, $avail_post_mime_types ) = wp_edit_attachments_query( $q ); + + $this->is_trash = isset( $_REQUEST['status'] ) && 'trash' == $_REQUEST['status']; + + $this->set_pagination_args( array( + 'total_items' => $wp_query->found_posts, + 'total_pages' => $wp_query->max_num_pages, + 'per_page' => $wp_query->query_vars['posts_per_page'], + ) ); + } + + function get_views() { + global $wpdb, $post_mime_types, $avail_post_mime_types; + + $type_links = array(); + $_num_posts = (array) wp_count_attachments(); + $_total_posts = array_sum($_num_posts) - $_num_posts['trash']; + $total_orphans = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1" ); + $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts)); + foreach ( $matches as $type => $reals ) + foreach ( $reals as $real ) + $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real]; + + $class = ( empty($_GET['post_mime_type']) && !$this->detached && !isset($_GET['status']) ) ? ' class="current"' : ''; + $type_links['all'] = "" . sprintf( _nx( 'All (%s)', 'All (%s)', $_total_posts, 'uploaded files' ), number_format_i18n( $_total_posts ) ) . ''; + foreach ( $post_mime_types as $mime_type => $label ) { + $class = ''; + + if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) ) + continue; + + if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) ) + $class = ' class="current"'; + if ( !empty( $num_posts[$mime_type] ) ) + $type_links[$mime_type] = "" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), number_format_i18n( $num_posts[$mime_type] )) . ''; + } + $type_links['detached'] = 'detached ? ' class="current"' : '' ) . '>' . sprintf( _nx( 'Unattached (%s)', 'Unattached (%s)', $total_orphans, 'detached files' ), number_format_i18n( $total_orphans ) ) . ''; + + if ( !empty($_num_posts['trash']) ) + $type_links['trash'] = '' . sprintf( _nx( 'Trash (%s)', 'Trash (%s)', $_num_posts['trash'], 'uploaded files' ), number_format_i18n( $_num_posts['trash'] ) ) . ''; + + return $type_links; + } + + function get_bulk_actions() { + $actions = array(); + $actions['delete'] = __( 'Delete Permanently' ); + if ( $this->detached ) + $actions['attach'] = __( 'Attach to a post' ); + + return $actions; + } + + function extra_tablenav( $which ) { +?> +
+detached && !$this->is_trash ) { + $this->months_dropdown( 'attachment' ); + + do_action( 'restrict_manage_posts' ); + submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); + } + + if ( $this->detached ) { + submit_button( __( 'Scan for lost attachments' ), 'secondary', 'find_detached', false ); + } elseif ( $this->is_trash && current_user_can( 'edit_others_posts' ) ) { + submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); + } ?> +
+'; + $posts_columns['icon'] = ''; + /* translators: column name */ + $posts_columns['title'] = _x( 'File', 'column name' ); + $posts_columns['author'] = __( 'Author' ); + + $taxonomies = array(); + + $taxonomies = get_taxonomies_for_attachments( 'objects' ); + $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); + + $taxonomies = apply_filters( 'manage_taxonomies_for_attachment_columns', $taxonomies, 'attachment' ); + $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' ); + + foreach ( $taxonomies as $taxonomy ) { + if ( 'category' == $taxonomy ) + $column_key = 'categories'; + elseif ( 'post_tag' == $taxonomy ) + $column_key = 'tags'; + else + $column_key = 'taxonomy-' . $taxonomy; + + $posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name; + } + + /* translators: column name */ + if ( !$this->detached ) { + $posts_columns['parent'] = _x( 'Uploaded to', 'column name' ); + if ( post_type_supports( 'attachment', 'comments' ) ) + $posts_columns['comments'] = '
'; + } + /* translators: column name */ + $posts_columns['date'] = _x( 'Date', 'column name' ); + $posts_columns = apply_filters( 'manage_media_columns', $posts_columns, $this->detached ); + + return $posts_columns; + } + + function get_sortable_columns() { + return array( + 'title' => 'title', + 'author' => 'author', + 'parent' => 'parent', + 'comments' => 'comment_count', + 'date' => array( 'date', true ), + ); + } + + function display_rows() { + global $post; + + add_filter( 'the_title','esc_html' ); + $alt = ''; + + while ( have_posts() ) : the_post(); + $user_can_edit = current_user_can( 'edit_post', $post->ID ); + + if ( $this->is_trash && $post->post_status != 'trash' + || !$this->is_trash && $post->post_status == 'trash' ) + continue; + + $alt = ( 'alternate' == $alt ) ? '' : 'alternate'; + $post_owner = ( get_current_user_id() == $post->post_author ) ? 'self' : 'other'; + $att_title = _draft_or_post_title(); +?> + post_status ); ?>' valign="top"> +get_column_info(); +foreach ( $columns as $column_name => $column_display_name ) { + $class = "class='$column_name column-$column_name'"; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = $class . $style; + + switch ( $column_name ) { + + case 'cb': +?> + + + + + + + + + +post_date ) { + $h_time = __( 'Unpublished' ); + } else { + $m_time = $post->post_date; + $time = get_post_time( 'G', true, $post, false ); + if ( ( abs( $t_diff = time() - $time ) ) < DAY_IN_SECONDS ) { + if ( $t_diff < 0 ) + $h_time = sprintf( __( '%s from now' ), human_time_diff( $time ) ); + else + $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); + } else { + $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); + } + } +?> + +post_parent > 0 ) + $parent = get_post( $post->post_parent ); + else + $parent = false; + + if ( $parent ) { + $title = _draft_or_post_title( $post->post_parent ); + $parent_type = get_post_type_object( $parent->post_type ); +?> + + + + + +'; + if ( $terms = get_the_terms( $post->ID, $taxonomy ) ) { + $out = array(); + foreach ( $terms as $t ) { + $posts_in_term_qv = array(); + $posts_in_term_qv['taxonomy'] = $taxonomy; + $posts_in_term_qv['term'] = $t->slug; + + $out[] = sprintf( '%s', + esc_url( add_query_arg( $posts_in_term_qv, 'upload.php' ) ), + esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) + ); + } + /* translators: used between list items, there is a space after the comma */ + echo join( __( ', ' ), $out ); + } else { + echo '—'; + } + echo ''; + break; + } +?> + + + +detached ) { + if ( current_user_can( 'edit_post', $post->ID ) ) + $actions['edit'] = '' . __( 'Edit' ) . ''; + if ( current_user_can( 'delete_post', $post->ID ) ) + if ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { + $actions['trash'] = "ID ) . "'>" . __( 'Trash' ) . ""; + } else { + $delete_ays = !MEDIA_TRASH ? " onclick='return showNotice.warn();'" : ''; + $actions['delete'] = "ID ) . "'>" . __( 'Delete Permanently' ) . ""; + } + $actions['view'] = '' . __( 'View' ) . ''; + if ( current_user_can( 'edit_post', $post->ID ) ) + $actions['attach'] = ''.__( 'Attach' ).''; + } + else { + if ( current_user_can( 'edit_post', $post->ID ) && !$this->is_trash ) + $actions['edit'] = '' . __( 'Edit' ) . ''; + if ( current_user_can( 'delete_post', $post->ID ) ) { + if ( $this->is_trash ) + $actions['untrash'] = "ID ) . "'>" . __( 'Restore' ) . ""; + elseif ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) + $actions['trash'] = "ID ) . "'>" . __( 'Trash' ) . ""; + if ( $this->is_trash || !EMPTY_TRASH_DAYS || !MEDIA_TRASH ) { + $delete_ays = ( !$this->is_trash && !MEDIA_TRASH ) ? " onclick='return showNotice.warn();'" : ''; + $actions['delete'] = "ID ) . "'>" . __( 'Delete Permanently' ) . ""; + } + } + if ( !$this->is_trash ) { + $title =_draft_or_post_title( $post->post_parent ); + $actions['view'] = '' . __( 'View' ) . ''; + } + } + + $actions = apply_filters( 'media_row_actions', $actions, $post, $this->detached ); + + return $actions; + } +} diff --git a/sources/wp-admin/includes/class-wp-ms-sites-list-table.php b/sources/wp-admin/includes/class-wp-ms-sites-list-table.php new file mode 100644 index 0000000..edc1146 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-ms-sites-list-table.php @@ -0,0 +1,346 @@ + 'sites', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + } + + function ajax_user_can() { + return current_user_can( 'manage_sites' ); + } + + function prepare_items() { + global $s, $mode, $wpdb, $current_site; + + $mode = ( empty( $_REQUEST['mode'] ) ) ? 'list' : $_REQUEST['mode']; + + $per_page = $this->get_items_per_page( 'sites_network_per_page' ); + + $pagenum = $this->get_pagenum(); + + $s = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST[ 's' ] ) ) : ''; + $wild = ''; + if ( false !== strpos($s, '*') ) { + $wild = '%'; + $s = trim($s, '*'); + } + + $like_s = esc_sql( like_escape( $s ) ); + + // If the network is large and a search is not being performed, show only the latest blogs with no paging in order + // to avoid expensive count queries. + if ( !$s && wp_is_large_network() ) { + if ( !isset($_REQUEST['orderby']) ) + $_GET['orderby'] = $_REQUEST['orderby'] = ''; + if ( !isset($_REQUEST['order']) ) + $_GET['order'] = $_REQUEST['order'] = 'DESC'; + } + + $query = "SELECT * FROM {$wpdb->blogs} WHERE site_id = '{$wpdb->siteid}' "; + + if ( empty($s) ) { + // Nothing to do. + } elseif ( preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $s ) || + preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s ) || + preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s ) || + preg_match( '/^[0-9]{1,3}\.$/', $s ) ) { + // IPv4 address + $reg_blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->registration_log} WHERE {$wpdb->registration_log}.IP LIKE ( '{$like_s}$wild' )" ); + + if ( !$reg_blog_ids ) + $reg_blog_ids = array( 0 ); + + $query = "SELECT * + FROM {$wpdb->blogs} + WHERE site_id = '{$wpdb->siteid}' + AND {$wpdb->blogs}.blog_id IN (" . implode( ', ', $reg_blog_ids ) . ")"; + } else { + if ( is_numeric($s) && empty( $wild ) ) { + $query .= " AND ( {$wpdb->blogs}.blog_id = '{$like_s}' )"; + } elseif ( is_subdomain_install() ) { + $blog_s = str_replace( '.' . $current_site->domain, '', $like_s ); + $blog_s .= $wild . '.' . $current_site->domain; + $query .= " AND ( {$wpdb->blogs}.domain LIKE '$blog_s' ) "; + } else { + if ( $like_s != trim('/', $current_site->path) ) + $blog_s = $current_site->path . $like_s . $wild . '/'; + else + $blog_s = $like_s; + $query .= " AND ( {$wpdb->blogs}.path LIKE '$blog_s' )"; + } + } + + $order_by = isset( $_REQUEST['orderby'] ) ? $_REQUEST['orderby'] : ''; + if ( $order_by == 'registered' ) { + $query .= ' ORDER BY registered '; + } elseif ( $order_by == 'lastupdated' ) { + $query .= ' ORDER BY last_updated '; + } elseif ( $order_by == 'blogname' ) { + if ( is_subdomain_install() ) + $query .= ' ORDER BY domain '; + else + $query .= ' ORDER BY path '; + } elseif ( $order_by == 'blog_id' ) { + $query .= ' ORDER BY blog_id '; + } else { + $order_by = null; + } + + if ( isset( $order_by ) ) { + $order = ( isset( $_REQUEST['order'] ) && 'DESC' == strtoupper( $_REQUEST['order'] ) ) ? "DESC" : "ASC"; + $query .= $order; + } + + // Don't do an unbounded count on large networks + if ( ! wp_is_large_network() ) + $total = $wpdb->get_var( str_replace( 'SELECT *', 'SELECT COUNT( blog_id )', $query ) ); + + $query .= " LIMIT " . intval( ( $pagenum - 1 ) * $per_page ) . ", " . intval( $per_page ); + $this->items = $wpdb->get_results( $query, ARRAY_A ); + + if ( wp_is_large_network() ) + $total = count($this->items); + + $this->set_pagination_args( array( + 'total_items' => $total, + 'per_page' => $per_page, + ) ); + } + + function no_items() { + _e( 'No sites found.' ); + } + + function get_bulk_actions() { + $actions = array(); + if ( current_user_can( 'delete_sites' ) ) + $actions['delete'] = __( 'Delete' ); + $actions['spam'] = _x( 'Mark as Spam', 'site' ); + $actions['notspam'] = _x( 'Not Spam', 'site' ); + + return $actions; + } + + function pagination( $which ) { + global $mode; + + parent::pagination( $which ); + + if ( 'top' == $which ) + $this->view_switcher( $mode ); + } + + function get_columns() { + $blogname_columns = ( is_subdomain_install() ) ? __( 'Domain' ) : __( 'Path' ); + $sites_columns = array( + 'cb' => '', + 'blogname' => $blogname_columns, + 'lastupdated' => __( 'Last Updated' ), + 'registered' => _x( 'Registered', 'site' ), + 'users' => __( 'Users' ) + ); + + if ( has_filter( 'wpmublogsaction' ) ) + $sites_columns['plugins'] = __( 'Actions' ); + + $sites_columns = apply_filters( 'wpmu_blogs_columns', $sites_columns ); + + return $sites_columns; + } + + function get_sortable_columns() { + return array( + 'blogname' => 'blogname', + 'lastupdated' => 'lastupdated', + 'registered' => 'blog_id', + ); + } + + function display_rows() { + global $current_site, $mode; + + $status_list = array( + 'archived' => array( 'site-archived', __( 'Archived' ) ), + 'spam' => array( 'site-spammed', _x( 'Spam', 'site' ) ), + 'deleted' => array( 'site-deleted', __( 'Deleted' ) ), + 'mature' => array( 'site-mature', __( 'Mature' ) ) + ); + + $class = ''; + foreach ( $this->items as $blog ) { + $class = ( 'alternate' == $class ) ? '' : 'alternate'; + reset( $status_list ); + + $blog_states = array(); + foreach ( $status_list as $status => $col ) { + if ( get_blog_status( $blog['blog_id'], $status ) == 1 ) { + $class = $col[0]; + $blog_states[] = $col[1]; + } + } + $blog_state = ''; + if ( ! empty( $blog_states ) ) { + $state_count = count( $blog_states ); + $i = 0; + $blog_state .= ' - '; + foreach ( $blog_states as $state ) { + ++$i; + ( $i == $state_count ) ? $sep = '' : $sep = ', '; + $blog_state .= "$state$sep"; + } + } + echo ""; + + $blogname = ( is_subdomain_install() ) ? str_replace( '.'.$current_site->domain, '', $blog['domain'] ) : $blog['path']; + + list( $columns, $hidden ) = $this->get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + switch ( $column_name ) { + case 'cb': ?> + + + + "; ?> + + ' . sprintf( _x( '%1$s – %2$s', '%1$s: site name. %2$s: site tagline.' ), get_option( 'blogname' ), get_option( 'blogdescription ' ) ) . '

'; + restore_current_blog(); + } + + // Preordered. + $actions = array( + 'edit' => '', 'backend' => '', + 'activate' => '', 'deactivate' => '', + 'archive' => '', 'unarchive' => '', + 'spam' => '', 'unspam' => '', + 'delete' => '', + 'visit' => '', + ); + + $actions['edit'] = '' . __( 'Edit' ) . ''; + $actions['backend'] = "" . __( 'Dashboard' ) . ''; + if ( $current_site->blog_id != $blog['blog_id'] ) { + if ( get_blog_status( $blog['blog_id'], 'deleted' ) == '1' ) + $actions['activate'] = '' . __( 'Activate' ) . ''; + else + $actions['deactivate'] = '' . __( 'Deactivate' ) . ''; + + if ( get_blog_status( $blog['blog_id'], 'archived' ) == '1' ) + $actions['unarchive'] = '' . __( 'Unarchive' ) . ''; + else + $actions['archive'] = '' . _x( 'Archive', 'verb; site' ) . ''; + + if ( get_blog_status( $blog['blog_id'], 'spam' ) == '1' ) + $actions['unspam'] = '' . _x( 'Not Spam', 'site' ) . ''; + else + $actions['spam'] = '' . _x( 'Spam', 'site' ) . ''; + + if ( current_user_can( 'delete_site', $blog['blog_id'] ) ) + $actions['delete'] = '' . __( 'Delete' ) . ''; + } + + $actions['visit'] = "" . __( 'Visit' ) . ''; + + $actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blogname ); + echo $this->row_actions( $actions ); + ?> + + "; + if ( 'list' == $mode ) + $date = 'Y/m/d'; + else + $date = 'Y/m/d \<\b\r \/\> g:i:s a'; + echo ( $blog['last_updated'] == '0000-00-00 00:00:00' ) ? __( 'Never' ) : mysql2date( $date, $blog['last_updated'] ); ?> + + "; + if ( $blog['registered'] == '0000-00-00 00:00:00' ) + echo '—'; + else + echo mysql2date( $date, $blog['registered'] ); + ?> + + "; + $blogusers = get_users( array( 'blog_id' => $blog['blog_id'], 'number' => 6) ); + if ( is_array( $blogusers ) ) { + $blogusers_warning = ''; + if ( count( $blogusers ) > 5 ) { + $blogusers = array_slice( $blogusers, 0, 5 ); + $blogusers_warning = __( 'Only showing first 5 users.' ) . ' ' . __( 'More' ) . ''; + } + foreach ( $blogusers as $user_object ) { + echo '' . esc_html( $user_object->user_login ) . ' '; + if ( 'list' != $mode ) + echo '( ' . $user_object->user_email . ' )'; + echo '
'; + } + if ( $blogusers_warning != '' ) + echo '' . $blogusers_warning . '
'; + } + ?> + + + "; + do_action( 'wpmublogsaction', $blog['blog_id'] ); ?> + + "; + do_action( 'manage_sites_custom_column', $column_name, $blog['blog_id'] ); + echo ""; + break; + } + } + ?> + + 'themes', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + + $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all'; + if ( !in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ) ) ) + $status = 'all'; + + $page = $this->get_pagenum(); + + $this->is_site_themes = ( 'site-themes-network' == $this->screen->id ) ? true : false; + + if ( $this->is_site_themes ) + $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; + } + + function get_table_classes() { + return array( 'widefat', 'plugins' ); // todo: remove and add CSS for .themes + } + + function ajax_user_can() { + if ( $this->is_site_themes ) + return current_user_can( 'manage_sites' ); + else + return current_user_can( 'manage_network_themes' ); + } + + function prepare_items() { + global $status, $totals, $page, $orderby, $order, $s; + + wp_reset_vars( array( 'orderby', 'order', 's' ) ); + + $themes = array( + 'all' => apply_filters( 'all_themes', wp_get_themes() ), + 'search' => array(), + 'enabled' => array(), + 'disabled' => array(), + 'upgrade' => array(), + 'broken' => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ), + ); + + if ( $this->is_site_themes ) { + $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' ); + $allowed_where = 'site'; + } else { + $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' ); + $allowed_where = 'network'; + } + + $maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current = get_site_transient( 'update_themes' ); + + foreach ( (array) $themes['all'] as $key => $theme ) { + if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) { + unset( $themes['all'][ $key ] ); + continue; + } + + if ( $maybe_update && isset( $current->response[ $key ] ) ) { + $themes['all'][ $key ]->update = true; + $themes['upgrade'][ $key ] = $themes['all'][ $key ]; + } + + $filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled'; + $themes[ $filter ][ $key ] = $themes['all'][ $key ]; + } + + if ( $s ) { + $status = 'search'; + $themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) ); + } + + $totals = array(); + foreach ( $themes as $type => $list ) + $totals[ $type ] = count( $list ); + + if ( empty( $themes[ $status ] ) && !in_array( $status, array( 'all', 'search' ) ) ) + $status = 'all'; + + $this->items = $themes[ $status ]; + WP_Theme::sort_by_name( $this->items ); + + $this->has_items = ! empty( $themes['all'] ); + $total_this_page = $totals[ $status ]; + + if ( $orderby ) { + $orderby = ucfirst( $orderby ); + $order = strtoupper( $order ); + + if ( $orderby == 'Name' ) { + if ( 'ASC' == $order ) + $this->items = array_reverse( $this->items ); + } else { + uasort( $this->items, array( $this, '_order_callback' ) ); + } + } + + $start = ( $page - 1 ) * $themes_per_page; + + if ( $total_this_page > $themes_per_page ) + $this->items = array_slice( $this->items, $start, $themes_per_page, true ); + + $this->set_pagination_args( array( + 'total_items' => $total_this_page, + 'per_page' => $themes_per_page, + ) ); + } + + function _search_callback( $theme ) { + static $term; + if ( is_null( $term ) ) + $term = wp_unslash( $_REQUEST['s'] ); + + foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) { + // Don't mark up; Do translate. + if ( false !== stripos( $theme->display( $field, false, true ), $term ) ) + return true; + } + + if ( false !== stripos( $theme->get_stylesheet(), $term ) ) + return true; + + if ( false !== stripos( $theme->get_template(), $term ) ) + return true; + + return false; + } + + // Not used by any core columns. + function _order_callback( $theme_a, $theme_b ) { + global $orderby, $order; + + $a = $theme_a[ $orderby ]; + $b = $theme_b[ $orderby ]; + + if ( $a == $b ) + return 0; + + if ( 'DESC' == $order ) + return ( $a < $b ) ? 1 : -1; + else + return ( $a < $b ) ? -1 : 1; + } + + function no_items() { + if ( ! $this->has_items ) + _e( 'No themes found.' ); + else + _e( 'You do not appear to have any themes available at this time.' ); + } + + function get_columns() { + global $status; + + return array( + 'cb' => '', + 'name' => __( 'Theme' ), + 'description' => __( 'Description' ), + ); + } + + function get_sortable_columns() { + return array( + 'name' => 'name', + ); + } + + function get_views() { + global $totals, $status; + + $status_links = array(); + foreach ( $totals as $type => $count ) { + if ( !$count ) + continue; + + switch ( $type ) { + case 'all': + $text = _nx( 'All (%s)', 'All (%s)', $count, 'themes' ); + break; + case 'enabled': + $text = _n( 'Enabled (%s)', 'Enabled (%s)', $count ); + break; + case 'disabled': + $text = _n( 'Disabled (%s)', 'Disabled (%s)', $count ); + break; + case 'upgrade': + $text = _n( 'Update Available (%s)', 'Update Available (%s)', $count ); + break; + case 'broken' : + $text = _n( 'Broken (%s)', 'Broken (%s)', $count ); + break; + } + + if ( $this->is_site_themes ) + $url = 'site-themes.php?id=' . $this->site_id; + else + $url = 'themes.php'; + + if ( 'search' != $type ) { + $status_links[$type] = sprintf( "%s", + esc_url( add_query_arg('theme_status', $type, $url) ), + ( $type == $status ) ? ' class="current"' : '', + sprintf( $text, number_format_i18n( $count ) ) + ); + } + } + + return $status_links; + } + + function get_bulk_actions() { + global $status; + + $actions = array(); + if ( 'enabled' != $status ) + $actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ); + if ( 'disabled' != $status ) + $actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ); + if ( ! $this->is_site_themes ) { + if ( current_user_can( 'update_themes' ) ) + $actions['update-selected'] = __( 'Update' ); + if ( current_user_can( 'delete_themes' ) ) + $actions['delete-selected'] = __( 'Delete' ); + } + return $actions; + } + + function display_rows() { + foreach ( $this->items as $theme ) + $this->single_row( $theme ); + } + + function single_row( $theme ) { + global $status, $page, $s, $totals; + + $context = $status; + + if ( $this->is_site_themes ) { + $url = "site-themes.php?id={$this->site_id}&"; + $allowed = $theme->is_allowed( 'site', $this->site_id ); + } else { + $url = 'themes.php?'; + $allowed = $theme->is_allowed( 'network' ); + } + + // preorder + $actions = array( + 'enable' => '', + 'disable' => '', + 'edit' => '', + 'delete' => '' + ); + + $stylesheet = $theme->get_stylesheet(); + $theme_key = urlencode( $stylesheet ); + + if ( ! $allowed ) { + if ( ! $theme->errors() ) + $actions['enable'] = '' . ( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) ) . ''; + } else { + $actions['disable'] = '' . ( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) ) . ''; + } + + if ( current_user_can('edit_themes') ) + $actions['edit'] = '' . __('Edit') . ''; + + if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $stylesheet != get_option( 'stylesheet' ) && $stylesheet != get_option( 'template' ) ) + $actions['delete'] = '' . __( 'Delete' ) . ''; + + $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme, $context ); + $actions = apply_filters( "theme_action_links_$stylesheet", $actions, $theme, $context ); + + $class = ! $allowed ? 'inactive' : 'active'; + $checkbox_id = "checkbox_" . md5( $theme->get('Name') ); + $checkbox = ""; + + $id = sanitize_html_class( $theme->get_stylesheet() ); + + if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) + $class .= ' update'; + + echo ""; + + list( $columns, $hidden ) = $this->get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + switch ( $column_name ) { + case 'cb': + echo ""; + break; + case 'name': + echo ""; + break; + case 'description': + echo ""; + break; + + default: + echo ""; + } + } + + echo ""; + + if ( $this->is_site_themes ) + remove_action( "after_theme_row_$stylesheet", 'wp_theme_update_row' ); + do_action( 'after_theme_row', $stylesheet, $theme, $status ); + do_action( "after_theme_row_$stylesheet", $stylesheet, $theme, $status ); + } +} diff --git a/sources/wp-admin/includes/class-wp-ms-users-list-table.php b/sources/wp-admin/includes/class-wp-ms-users-list-table.php new file mode 100644 index 0000000..ab1ee36 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-ms-users-list-table.php @@ -0,0 +1,272 @@ +get_items_per_page( 'users_network_per_page' ); + + $role = isset( $_REQUEST['role'] ) ? $_REQUEST['role'] : ''; + + $paged = $this->get_pagenum(); + + $args = array( + 'number' => $users_per_page, + 'offset' => ( $paged-1 ) * $users_per_page, + 'search' => $usersearch, + 'blog_id' => 0, + 'fields' => 'all_with_meta' + ); + + if ( wp_is_large_network( 'users' ) ) + $args['search'] = ltrim( $args['search'], '*' ); + + if ( $role == 'super' ) { + $logins = implode( "', '", get_super_admins() ); + $args['include'] = $wpdb->get_col( "SELECT ID FROM $wpdb->users WHERE user_login IN ('$logins')" ); + } + + // If the network is large and a search is not being performed, show only the latest users with no paging in order + // to avoid expensive count queries. + if ( !$usersearch && wp_is_large_network( 'users' ) ) { + if ( !isset($_REQUEST['orderby']) ) + $_GET['orderby'] = $_REQUEST['orderby'] = 'id'; + if ( !isset($_REQUEST['order']) ) + $_GET['order'] = $_REQUEST['order'] = 'DESC'; + $args['count_total'] = false; + } + + if ( isset( $_REQUEST['orderby'] ) ) + $args['orderby'] = $_REQUEST['orderby']; + + if ( isset( $_REQUEST['order'] ) ) + $args['order'] = $_REQUEST['order']; + + $mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode']; + + // Query the user IDs for this page + $wp_user_search = new WP_User_Query( $args ); + + $this->items = $wp_user_search->get_results(); + + $this->set_pagination_args( array( + 'total_items' => $wp_user_search->get_total(), + 'per_page' => $users_per_page, + ) ); + } + + function get_bulk_actions() { + $actions = array(); + if ( current_user_can( 'delete_users' ) ) + $actions['delete'] = __( 'Delete' ); + $actions['spam'] = _x( 'Mark as Spam', 'user' ); + $actions['notspam'] = _x( 'Not Spam', 'user' ); + + return $actions; + } + + function no_items() { + _e( 'No users found.' ); + } + + function get_views() { + global $wp_roles, $role; + + $total_users = get_user_count(); + $super_admins = get_super_admins(); + $total_admins = count( $super_admins ); + + $current_role = false; + $class = $role != 'super' ? ' class="current"' : ''; + $role_links = array(); + $role_links['all'] = "" . sprintf( _nx( 'All (%s)', 'All (%s)', $total_users, 'users' ), number_format_i18n( $total_users ) ) . ''; + $class = $role == 'super' ? ' class="current"' : ''; + $role_links['super'] = "" . sprintf( _n( 'Super Admin (%s)', 'Super Admins (%s)', $total_admins ), number_format_i18n( $total_admins ) ) . ''; + + return $role_links; + } + + function pagination( $which ) { + global $mode; + + parent::pagination ( $which ); + + if ( 'top' == $which ) + $this->view_switcher( $mode ); + } + + function get_columns() { + $users_columns = array( + 'cb' => '', + 'username' => __( 'Username' ), + 'name' => __( 'Name' ), + 'email' => __( 'E-mail' ), + 'registered' => _x( 'Registered', 'user' ), + 'blogs' => __( 'Sites' ) + ); + $users_columns = apply_filters( 'wpmu_users_columns', $users_columns ); + + return $users_columns; + } + + function get_sortable_columns() { + return array( + 'username' => 'login', + 'name' => 'name', + 'email' => 'email', + 'registered' => 'id', + ); + } + + function display_rows() { + global $current_site, $mode; + + $alt = ''; + $super_admins = get_super_admins(); + foreach ( $this->items as $user ) { + $alt = ( 'alternate' == $alt ) ? '' : 'alternate'; + + $status_list = array( 'spam' => 'site-spammed', 'deleted' => 'site-deleted' ); + + foreach ( $status_list as $status => $col ) { + if ( $user->$status ) + $alt .= " $col"; + } + + ?> + + get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) : + $class = "class='$column_name column-$column_name'"; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = "$class$style"; + + switch ( $column_name ) { + case 'cb': ?> + + user_email, 32 ); + $edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user->ID ) ) ); + + echo " + $user->first_name $user->last_name"; + break; + + case 'email': + echo ""; + break; + + case 'registered': + if ( 'list' == $mode ) + $date = 'Y/m/d'; + else + $date = 'Y/m/d \<\b\r \/\> g:i:s a'; + + echo ""; + break; + + case 'blogs': + $blogs = get_blogs_of_user( $user->ID, true ); + echo " + "; + echo apply_filters( 'manage_users_custom_column', '', $column_name, $user->ID ); + echo ""; + break; + } + endforeach + ?> + + get_pagenum(); + + $per_page = 30; + + // These are the tabs which are shown on the page + $tabs = array(); + $tabs['dashboard'] = __( 'Search' ); + if ( 'search' == $tab ) + $tabs['search'] = __( 'Search Results' ); + $tabs['upload'] = __( 'Upload' ); + $tabs['featured'] = _x( 'Featured', 'Plugin Installer' ); + $tabs['popular'] = _x( 'Popular', 'Plugin Installer' ); + $tabs['new'] = _x( 'Newest', 'Plugin Installer' ); + $tabs['favorites'] = _x( 'Favorites', 'Plugin Installer' ); + + $nonmenu_tabs = array( 'plugin-information' ); //Valid actions to perform which do not have a Menu item. + + /** + * Filter the tabs shown on the Plugin Install screen. + * + * @since 2.7.0 + * + * @param array $tabs The tabs shown on the Plugin Install screen. Defaults are 'dashboard', 'search', + * 'upload', 'featured', 'popular', 'new', and 'favorites'. + */ + $tabs = apply_filters( 'install_plugins_tabs', $tabs ); + + /** + * Filter tabs not associated with a menu item on the Plugin Install screen. + * + * @since 2.7.0 + * + * @param array $nonmenu_tabs The tabs that don't have a Menu item on the Plugin Install screen. + */ + $nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs ); + + // If a non-valid menu tab has been selected, And it's not a non-menu action. + if ( empty( $tab ) || ( !isset( $tabs[ $tab ] ) && !in_array( $tab, (array) $nonmenu_tabs ) ) ) + $tab = key( $tabs ); + + $args = array( 'page' => $paged, 'per_page' => $per_page ); + + switch ( $tab ) { + case 'search': + $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; + $term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : ''; + + switch ( $type ) { + case 'tag': + $args['tag'] = sanitize_title_with_dashes( $term ); + break; + case 'term': + $args['search'] = $term; + break; + case 'author': + $args['author'] = $term; + break; + } + + add_action( 'install_plugins_table_header', 'install_search_form', 10, 0 ); + break; + + case 'featured': + case 'popular': + case 'new': + $args['browse'] = $tab; + break; + + case 'favorites': + $user = isset( $_GET['user'] ) ? wp_unslash( $_GET['user'] ) : get_user_option( 'wporg_favorites' ); + update_user_meta( get_current_user_id(), 'wporg_favorites', $user ); + if ( $user ) + $args['user'] = $user; + else + $args = false; + + add_action( 'install_plugins_favorites', 'install_plugins_favorites_form', 9, 0 ); + break; + + default: + $args = false; + break; + } + + /** + * Filter API request arguments for each Plugin Install screen tab. + * + * The dynamic portion of the hook name, $tab, refers to the plugin install tabs. + * Default tabs are 'dashboard', 'search', 'upload', 'featured', 'popular', 'new', + * and 'favorites'. + * + * @since 3.7.0 + * + * @param array|bool $args Plugin Install API arguments. + */ + $args = apply_filters( "install_plugins_table_api_args_$tab", $args ); + + if ( !$args ) + return; + + $api = plugins_api( 'query_plugins', $args ); + + if ( is_wp_error( $api ) ) + wp_die( $api->get_error_message() . '

' . __( 'Try again' ) . '' ); + + $this->items = $api->plugins; + + $this->set_pagination_args( array( + 'total_items' => $api->info['results'], + 'per_page' => $per_page, + ) ); + } + + function no_items() { + _e( 'No plugins match your request.' ); + } + + function get_views() { + global $tabs, $tab; + + $display_tabs = array(); + foreach ( (array) $tabs as $action => $text ) { + $class = ( $action == $tab ) ? ' class="current"' : ''; + $href = self_admin_url('plugin-install.php?tab=' . $action); + $display_tabs['plugin-install-'.$action] = "$text"; + } + + return $display_tabs; + } + + function display_tablenav( $which ) { + if ( 'top' == $which ) { ?> +

+
+ +
+ pagination( $which ); ?> +
+
+ +
+ pagination( $which ); ?> +
+
+ _args ); + + return array( 'widefat', $plural ); + } + + function get_columns() { + return array( + 'name' => _x( 'Name', 'plugin name' ), + 'version' => __( 'Version' ), + 'rating' => __( 'Rating' ), + 'description' => __( 'Description' ), + ); + } + + function display_rows() { + $plugins_allowedtags = array( + 'a' => array( 'href' => array(),'title' => array(), 'target' => array() ), + 'abbr' => array( 'title' => array() ),'acronym' => array( 'title' => array() ), + 'code' => array(), 'pre' => array(), 'em' => array(),'strong' => array(), + 'ul' => array(), 'ol' => array(), 'li' => array(), 'p' => array(), 'br' => array() + ); + + list( $columns, $hidden ) = $this->get_column_info(); + + $style = array(); + foreach ( $columns as $column_name => $column_display_name ) { + $style[ $column_name ] = in_array( $column_name, $hidden ) ? 'style="display:none;"' : ''; + } + + foreach ( (array) $this->items as $plugin ) { + if ( is_object( $plugin ) ) + $plugin = (array) $plugin; + + $title = wp_kses( $plugin['name'], $plugins_allowedtags ); + //Limit description to 400char, and remove any HTML. + $description = strip_tags( $plugin['description'] ); + if ( strlen( $description ) > 400 ) + $description = mb_substr( $description, 0, 400 ) . '…'; + //remove any trailing entities + $description = preg_replace( '/&[^;\s]{0,6}$/', '', $description ); + //strip leading/trailing & multiple consecutive lines + $description = trim( $description ); + $description = preg_replace( "|(\r?\n)+|", "\n", $description ); + //\n =>
+ $description = nl2br( $description ); + $version = wp_kses( $plugin['version'], $plugins_allowedtags ); + + $name = strip_tags( $title . ' ' . $version ); + + $author = $plugin['author']; + if ( ! empty( $plugin['author'] ) ) + $author = ' ' . sprintf( __( 'By %s' ), $author ) . '.'; + + $author = wp_kses( $author, $plugins_allowedtags ); + + $action_links = array(); + $action_links[] = '' . __( 'Details' ) . ''; + + if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) { + $status = install_plugin_install_status( $plugin ); + + switch ( $status['status'] ) { + case 'install': + if ( $status['url'] ) + $action_links[] = '' . __( 'Install Now' ) . ''; + break; + case 'update_available': + if ( $status['url'] ) + $action_links[] = '' . sprintf( __( 'Update Now' ), $status['version'] ) . ''; + break; + case 'latest_installed': + case 'newer_installed': + $action_links[] = '' . _x( 'Installed', 'plugin' ) . ''; + break; + } + } + + /** + * Filter the install action links for a plugin. + * + * @since 2.7.0 + * + * @param array $action_links An array of plugin action hyperlinks. Defaults are links to Details and Install Now. + * @param array $plugin The plugin currently being listed. + */ + $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin ); + ?> + + + + + + + 'plugins', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + + $status = 'all'; + if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search' ) ) ) + $status = $_REQUEST['plugin_status']; + + if ( isset($_REQUEST['s']) ) + $_SERVER['REQUEST_URI'] = add_query_arg('s', wp_unslash($_REQUEST['s']) ); + + $page = $this->get_pagenum(); + } + + function get_table_classes() { + return array( 'widefat', $this->_args['plural'] ); + } + + function ajax_user_can() { + return current_user_can('activate_plugins'); + } + + function prepare_items() { + global $status, $plugins, $totals, $page, $orderby, $order, $s; + + wp_reset_vars( array( 'orderby', 'order', 's' ) ); + + $plugins = array( + 'all' => apply_filters( 'all_plugins', get_plugins() ), + 'search' => array(), + 'active' => array(), + 'inactive' => array(), + 'recently_activated' => array(), + 'upgrade' => array(), + 'mustuse' => array(), + 'dropins' => array() + ); + + $screen = $this->screen; + + if ( ! is_multisite() || ( $screen->in_admin( 'network' ) && current_user_can( 'manage_network_plugins' ) ) ) { + if ( apply_filters( 'show_advanced_plugins', true, 'mustuse' ) ) + $plugins['mustuse'] = get_mu_plugins(); + if ( apply_filters( 'show_advanced_plugins', true, 'dropins' ) ) + $plugins['dropins'] = get_dropins(); + + if ( current_user_can( 'update_plugins' ) ) { + $current = get_site_transient( 'update_plugins' ); + foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) { + if ( isset( $current->response[ $plugin_file ] ) ) { + $plugins['all'][ $plugin_file ]['update'] = true; + $plugins['upgrade'][ $plugin_file ] = $plugins['all'][ $plugin_file ]; + } + } + } + } + + set_transient( 'plugin_slugs', array_keys( $plugins['all'] ), DAY_IN_SECONDS ); + + if ( ! $screen->in_admin( 'network' ) ) { + $recently_activated = get_option( 'recently_activated', array() ); + + foreach ( $recently_activated as $key => $time ) + if ( $time + WEEK_IN_SECONDS < time() ) + unset( $recently_activated[$key] ); + update_option( 'recently_activated', $recently_activated ); + } + + foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) { + // Filter into individual sections + if ( is_multisite() && ! $screen->in_admin( 'network' ) && is_network_only_plugin( $plugin_file ) ) { + unset( $plugins['all'][ $plugin_file ] ); + } elseif ( ! $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) { + unset( $plugins['all'][ $plugin_file ] ); + } elseif ( ( ! $screen->in_admin( 'network' ) && is_plugin_active( $plugin_file ) ) + || ( $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) ) { + $plugins['active'][ $plugin_file ] = $plugin_data; + } else { + if ( ! $screen->in_admin( 'network' ) && isset( $recently_activated[ $plugin_file ] ) ) // Was the plugin recently activated? + $plugins['recently_activated'][ $plugin_file ] = $plugin_data; + $plugins['inactive'][ $plugin_file ] = $plugin_data; + } + } + + if ( $s ) { + $status = 'search'; + $plugins['search'] = array_filter( $plugins['all'], array( $this, '_search_callback' ) ); + } + + $totals = array(); + foreach ( $plugins as $type => $list ) + $totals[ $type ] = count( $list ); + + if ( empty( $plugins[ $status ] ) && !in_array( $status, array( 'all', 'search' ) ) ) + $status = 'all'; + + $this->items = array(); + foreach ( $plugins[ $status ] as $plugin_file => $plugin_data ) { + // Translate, Don't Apply Markup, Sanitize HTML + $this->items[$plugin_file] = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, false, true ); + } + + $total_this_page = $totals[ $status ]; + + if ( $orderby ) { + $orderby = ucfirst( $orderby ); + $order = strtoupper( $order ); + + uasort( $this->items, array( $this, '_order_callback' ) ); + } + + $plugins_per_page = $this->get_items_per_page( str_replace( '-', '_', $screen->id . '_per_page' ), 999 ); + + $start = ( $page - 1 ) * $plugins_per_page; + + if ( $total_this_page > $plugins_per_page ) + $this->items = array_slice( $this->items, $start, $plugins_per_page ); + + $this->set_pagination_args( array( + 'total_items' => $total_this_page, + 'per_page' => $plugins_per_page, + ) ); + } + + function _search_callback( $plugin ) { + static $term; + if ( is_null( $term ) ) + $term = wp_unslash( $_REQUEST['s'] ); + + foreach ( $plugin as $value ) + if ( stripos( $value, $term ) !== false ) + return true; + + return false; + } + + function _order_callback( $plugin_a, $plugin_b ) { + global $orderby, $order; + + $a = $plugin_a[$orderby]; + $b = $plugin_b[$orderby]; + + if ( $a == $b ) + return 0; + + if ( 'DESC' == $order ) + return ( $a < $b ) ? 1 : -1; + else + return ( $a < $b ) ? -1 : 1; + } + + function no_items() { + global $plugins; + + if ( !empty( $plugins['all'] ) ) + _e( 'No plugins found.' ); + else + _e( 'You do not appear to have any plugins available at this time.' ); + } + + function get_columns() { + global $status; + + return array( + 'cb' => !in_array( $status, array( 'mustuse', 'dropins' ) ) ? '' : '', + 'name' => __( 'Plugin' ), + 'description' => __( 'Description' ), + ); + } + + function get_sortable_columns() { + return array(); + } + + function get_views() { + global $totals, $status; + + $status_links = array(); + foreach ( $totals as $type => $count ) { + if ( !$count ) + continue; + + switch ( $type ) { + case 'all': + $text = _nx( 'All (%s)', 'All (%s)', $count, 'plugins' ); + break; + case 'active': + $text = _n( 'Active (%s)', 'Active (%s)', $count ); + break; + case 'recently_activated': + $text = _n( 'Recently Active (%s)', 'Recently Active (%s)', $count ); + break; + case 'inactive': + $text = _n( 'Inactive (%s)', 'Inactive (%s)', $count ); + break; + case 'mustuse': + $text = _n( 'Must-Use (%s)', 'Must-Use (%s)', $count ); + break; + case 'dropins': + $text = _n( 'Drop-ins (%s)', 'Drop-ins (%s)', $count ); + break; + case 'upgrade': + $text = _n( 'Update Available (%s)', 'Update Available (%s)', $count ); + break; + } + + if ( 'search' != $type ) { + $status_links[$type] = sprintf( "%s", + add_query_arg('plugin_status', $type, 'plugins.php'), + ( $type == $status ) ? ' class="current"' : '', + sprintf( $text, number_format_i18n( $count ) ) + ); + } + } + + return $status_links; + } + + function get_bulk_actions() { + global $status; + + $actions = array(); + + if ( 'active' != $status ) + $actions['activate-selected'] = $this->screen->in_admin( 'network' ) ? __( 'Network Activate' ) : __( 'Activate' ); + + if ( 'inactive' != $status && 'recent' != $status ) + $actions['deactivate-selected'] = $this->screen->in_admin( 'network' ) ? __( 'Network Deactivate' ) : __( 'Deactivate' ); + + if ( !is_multisite() || $this->screen->in_admin( 'network' ) ) { + if ( current_user_can( 'update_plugins' ) ) + $actions['update-selected'] = __( 'Update' ); + if ( current_user_can( 'delete_plugins' ) && ( 'active' != $status ) ) + $actions['delete-selected'] = __( 'Delete' ); + } + + return $actions; + } + + function bulk_actions() { + global $status; + + if ( in_array( $status, array( 'mustuse', 'dropins' ) ) ) + return; + + parent::bulk_actions(); + } + + function extra_tablenav( $which ) { + global $status; + + if ( ! in_array($status, array('recently_activated', 'mustuse', 'dropins') ) ) + return; + + echo '
'; + + if ( ! $this->screen->in_admin( 'network' ) && 'recently_activated' == $status ) + submit_button( __( 'Clear List' ), 'button', 'clear-recent-list', false ); + elseif ( 'top' == $which && 'mustuse' == $status ) + echo '

' . sprintf( __( 'Files in the %s directory are executed automatically.' ), str_replace( ABSPATH, '/', WPMU_PLUGIN_DIR ) ) . '

'; + elseif ( 'top' == $which && 'dropins' == $status ) + echo '

' . sprintf( __( 'Drop-ins are advanced plugins in the %s directory that replace WordPress functionality when present.' ), str_replace( ABSPATH, '', WP_CONTENT_DIR ) ) . '

'; + + echo '
'; + } + + function current_action() { + if ( isset($_POST['clear-recent-list']) ) + return 'clear-recent-list'; + + return parent::current_action(); + } + + function display_rows() { + global $status; + + if ( is_multisite() && ! $this->screen->in_admin( 'network' ) && in_array( $status, array( 'mustuse', 'dropins' ) ) ) + return; + + foreach ( $this->items as $plugin_file => $plugin_data ) + $this->single_row( array( $plugin_file, $plugin_data ) ); + } + + function single_row( $item ) { + global $status, $page, $s, $totals; + + list( $plugin_file, $plugin_data ) = $item; + $context = $status; + $screen = $this->screen; + + // preorder + $actions = array( + 'deactivate' => '', + 'activate' => '', + 'edit' => '', + 'delete' => '', + ); + + if ( 'mustuse' == $context ) { + $is_active = true; + } elseif ( 'dropins' == $context ) { + $dropins = _get_dropins(); + $plugin_name = $plugin_file; + if ( $plugin_file != $plugin_data['Name'] ) + $plugin_name .= '
' . $plugin_data['Name']; + if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant + $is_active = true; + $description = '

' . $dropins[ $plugin_file ][0] . '

'; + } elseif ( defined( $dropins[ $plugin_file ][1] ) && constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true + $is_active = true; + $description = '

' . $dropins[ $plugin_file ][0] . '

'; + } else { + $is_active = false; + $description = '

' . $dropins[ $plugin_file ][0] . ' ' . __('Inactive:') . ' ' . sprintf( __( 'Requires %s in wp-config.php.' ), "define('" . $dropins[ $plugin_file ][1] . "', true);" ) . '

'; + } + if ( $plugin_data['Description'] ) + $description .= '

' . $plugin_data['Description'] . '

'; + } else { + if ( $screen->in_admin( 'network' ) ) + $is_active = is_plugin_active_for_network( $plugin_file ); + else + $is_active = is_plugin_active( $plugin_file ); + + if ( $screen->in_admin( 'network' ) ) { + if ( $is_active ) { + if ( current_user_can( 'manage_network_plugins' ) ) + $actions['deactivate'] = '' . __('Network Deactivate') . ''; + } else { + if ( current_user_can( 'manage_network_plugins' ) ) + $actions['activate'] = '' . __('Network Activate') . ''; + if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) + $actions['delete'] = '' . __('Delete') . ''; + } + } else { + if ( $is_active ) { + $actions['deactivate'] = '' . __('Deactivate') . ''; + } else { + $actions['activate'] = '' . __('Activate') . ''; + + if ( ! is_multisite() && current_user_can('delete_plugins') ) + $actions['delete'] = '' . __('Delete') . ''; + } // end if $is_active + } // end if $screen->in_admin( 'network' ) + + if ( ( ! is_multisite() || $screen->in_admin( 'network' ) ) && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) ) + $actions['edit'] = '' . __('Edit') . ''; + } // end if $context + + $prefix = $screen->in_admin( 'network' ) ? 'network_admin_' : ''; + $actions = apply_filters( $prefix . 'plugin_action_links', array_filter( $actions ), $plugin_file, $plugin_data, $context ); + $actions = apply_filters( $prefix . "plugin_action_links_$plugin_file", $actions, $plugin_file, $plugin_data, $context ); + + $class = $is_active ? 'active' : 'inactive'; + $checkbox_id = "checkbox_" . md5($plugin_data['Name']); + if ( in_array( $status, array( 'mustuse', 'dropins' ) ) ) { + $checkbox = ''; + } else { + $checkbox = "" + . ""; + } + if ( 'dropins' != $context ) { + $description = '

' . ( $plugin_data['Description'] ? $plugin_data['Description'] : ' ' ) . '

'; + $plugin_name = $plugin_data['Name']; + } + + $id = sanitize_title( $plugin_name ); + if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) ) + $class .= ' update'; + + echo ""; + + list( $columns, $hidden ) = $this->get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + switch ( $column_name ) { + case 'cb': + echo ""; + break; + case 'name': + echo ""; + break; + case 'description': + echo ""; + break; + default: + echo ""; + } + } + + echo ""; + + do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status ); + do_action( "after_plugin_row_$plugin_file", $plugin_file, $plugin_data, $status ); + } +} diff --git a/sources/wp-admin/includes/class-wp-posts-list-table.php b/sources/wp-admin/includes/class-wp-posts-list-table.php new file mode 100644 index 0000000..016a726 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-posts-list-table.php @@ -0,0 +1,1104 @@ + 'posts', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + + $post_type = $this->screen->post_type; + $post_type_object = get_post_type_object( $post_type ); + + if ( !current_user_can( $post_type_object->cap->edit_others_posts ) ) { + $exclude_states = get_post_stati( array( 'show_in_admin_all_list' => false ) ); + $this->user_posts_count = $wpdb->get_var( $wpdb->prepare( " + SELECT COUNT( 1 ) FROM $wpdb->posts + WHERE post_type = %s AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' ) + AND post_author = %d + ", $post_type, get_current_user_id() ) ); + + if ( $this->user_posts_count && empty( $_REQUEST['post_status'] ) && empty( $_REQUEST['all_posts'] ) && empty( $_REQUEST['author'] ) && empty( $_REQUEST['show_sticky'] ) ) + $_GET['author'] = get_current_user_id(); + } + + if ( 'post' == $post_type && $sticky_posts = get_option( 'sticky_posts' ) ) { + $sticky_posts = implode( ', ', array_map( 'absint', (array) $sticky_posts ) ); + $this->sticky_posts_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( 1 ) FROM $wpdb->posts WHERE post_type = %s AND post_status NOT IN ('trash', 'auto-draft') AND ID IN ($sticky_posts)", $post_type ) ); + } + } + + function ajax_user_can() { + return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts ); + } + + function prepare_items() { + global $avail_post_stati, $wp_query, $per_page, $mode; + + $avail_post_stati = wp_edit_posts_query(); + + $this->hierarchical_display = ( is_post_type_hierarchical( $this->screen->post_type ) && 'menu_order title' == $wp_query->query['orderby'] ); + + $total_items = $this->hierarchical_display ? $wp_query->post_count : $wp_query->found_posts; + + $post_type = $this->screen->post_type; + $per_page = $this->get_items_per_page( 'edit_' . $post_type . '_per_page' ); + $per_page = apply_filters( 'edit_posts_per_page', $per_page, $post_type ); + + if ( $this->hierarchical_display ) + $total_pages = ceil( $total_items / $per_page ); + else + $total_pages = $wp_query->max_num_pages; + + $mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode']; + + $this->is_trash = isset( $_REQUEST['post_status'] ) && $_REQUEST['post_status'] == 'trash'; + + $this->set_pagination_args( array( + 'total_items' => $total_items, + 'total_pages' => $total_pages, + 'per_page' => $per_page + ) ); + } + + function has_items() { + return have_posts(); + } + + function no_items() { + if ( isset( $_REQUEST['post_status'] ) && 'trash' == $_REQUEST['post_status'] ) + echo get_post_type_object( $this->screen->post_type )->labels->not_found_in_trash; + else + echo get_post_type_object( $this->screen->post_type )->labels->not_found; + } + + function get_views() { + global $locked_post_status, $avail_post_stati; + + $post_type = $this->screen->post_type; + + if ( !empty($locked_post_status) ) + return array(); + + $status_links = array(); + $num_posts = wp_count_posts( $post_type, 'readable' ); + $class = ''; + $allposts = ''; + + $current_user_id = get_current_user_id(); + + if ( $this->user_posts_count ) { + if ( isset( $_GET['author'] ) && ( $_GET['author'] == $current_user_id ) ) + $class = ' class="current"'; + $status_links['mine'] = "" . sprintf( _nx( 'Mine (%s)', 'Mine (%s)', $this->user_posts_count, 'posts' ), number_format_i18n( $this->user_posts_count ) ) . ''; + $allposts = '&all_posts=1'; + } + + $total_posts = array_sum( (array) $num_posts ); + + // Subtract post types that are not included in the admin all list. + foreach ( get_post_stati( array('show_in_admin_all_list' => false) ) as $state ) + $total_posts -= $num_posts->$state; + + $class = empty( $class ) && empty( $_REQUEST['post_status'] ) && empty( $_REQUEST['show_sticky'] ) ? ' class="current"' : ''; + $status_links['all'] = "" . sprintf( _nx( 'All (%s)', 'All (%s)', $total_posts, 'posts' ), number_format_i18n( $total_posts ) ) . ''; + + foreach ( get_post_stati(array('show_in_admin_status_list' => true), 'objects') as $status ) { + $class = ''; + + $status_name = $status->name; + + if ( !in_array( $status_name, $avail_post_stati ) ) + continue; + + if ( empty( $num_posts->$status_name ) ) + continue; + + if ( isset($_REQUEST['post_status']) && $status_name == $_REQUEST['post_status'] ) + $class = ' class="current"'; + + $status_links[$status_name] = "" . sprintf( translate_nooped_plural( $status->label_count, $num_posts->$status_name ), number_format_i18n( $num_posts->$status_name ) ) . ''; + } + + if ( ! empty( $this->sticky_posts_count ) ) { + $class = ! empty( $_REQUEST['show_sticky'] ) ? ' class="current"' : ''; + + $sticky_link = array( 'sticky' => "" . sprintf( _nx( 'Sticky (%s)', 'Sticky (%s)', $this->sticky_posts_count, 'posts' ), number_format_i18n( $this->sticky_posts_count ) ) . '' ); + + // Sticky comes after Publish, or if not listed, after All. + $split = 1 + array_search( ( isset( $status_links['publish'] ) ? 'publish' : 'all' ), array_keys( $status_links ) ); + $status_links = array_merge( array_slice( $status_links, 0, $split ), $sticky_link, array_slice( $status_links, $split ) ); + } + + return $status_links; + } + + function get_bulk_actions() { + $actions = array(); + + if ( $this->is_trash ) + $actions['untrash'] = __( 'Restore' ); + else + $actions['edit'] = __( 'Edit' ); + + if ( $this->is_trash || !EMPTY_TRASH_DAYS ) + $actions['delete'] = __( 'Delete Permanently' ); + else + $actions['trash'] = __( 'Move to Trash' ); + + return $actions; + } + + function extra_tablenav( $which ) { + global $cat; +?> +
+months_dropdown( $this->screen->post_type ); + + if ( is_object_in_taxonomy( $this->screen->post_type, 'category' ) ) { + $dropdown_options = array( + 'show_option_all' => __( 'View all categories' ), + 'hide_empty' => 0, + 'hierarchical' => 1, + 'show_count' => 0, + 'orderby' => 'name', + 'selected' => $cat + ); + wp_dropdown_categories( $dropdown_options ); + } + do_action( 'restrict_manage_posts' ); + submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); + } + + if ( $this->is_trash && current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts ) ) { + submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); + } +?> +
+screen->post_type ) ) + $this->view_switcher( $mode ); + } + + function get_table_classes() { + return array( 'widefat', 'fixed', is_post_type_hierarchical( $this->screen->post_type ) ? 'pages' : 'posts' ); + } + + function get_columns() { + $post_type = $this->screen->post_type; + + $posts_columns = array(); + + $posts_columns['cb'] = ''; + + /* translators: manage posts column name */ + $posts_columns['title'] = _x( 'Title', 'column name' ); + + if ( post_type_supports( $post_type, 'author' ) ) + $posts_columns['author'] = __( 'Author' ); + + $taxonomies = array(); + + $taxonomies = get_object_taxonomies( $post_type, 'objects' ); + $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); + + $taxonomies = apply_filters( "manage_taxonomies_for_{$post_type}_columns", $taxonomies, $post_type ); + $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' ); + + foreach ( $taxonomies as $taxonomy ) { + if ( 'category' == $taxonomy ) + $column_key = 'categories'; + elseif ( 'post_tag' == $taxonomy ) + $column_key = 'tags'; + else + $column_key = 'taxonomy-' . $taxonomy; + + $posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name; + } + + $post_status = !empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all'; + if ( post_type_supports( $post_type, 'comments' ) && !in_array( $post_status, array( 'pending', 'draft', 'future' ) ) ) + $posts_columns['comments'] = '
'; + + $posts_columns['date'] = __( 'Date' ); + + if ( 'page' == $post_type ) + $posts_columns = apply_filters( 'manage_pages_columns', $posts_columns ); + else + $posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type ); + $posts_columns = apply_filters( "manage_{$post_type}_posts_columns", $posts_columns ); + + return $posts_columns; + } + + function get_sortable_columns() { + return array( + 'title' => 'title', + 'parent' => 'parent', + 'comments' => 'comment_count', + 'date' => array( 'date', true ) + ); + } + + function display_rows( $posts = array(), $level = 0 ) { + global $wp_query, $per_page; + + if ( empty( $posts ) ) + $posts = $wp_query->posts; + + add_filter( 'the_title', 'esc_html' ); + + if ( $this->hierarchical_display ) { + $this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page ); + } else { + $this->_display_rows( $posts, $level ); + } + } + + function _display_rows( $posts, $level = 0 ) { + global $mode; + + // Create array of post IDs. + $post_ids = array(); + + foreach ( $posts as $a_post ) + $post_ids[] = $a_post->ID; + + $this->comment_pending_count = get_pending_comments_num( $post_ids ); + + foreach ( $posts as $post ) + $this->single_row( $post, $level ); + } + + function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) { + global $wpdb; + + $level = 0; + + if ( ! $pages ) { + $pages = get_pages( array( 'sort_column' => 'menu_order' ) ); + + if ( ! $pages ) + return false; + } + + /* + * arrange pages into two parts: top level pages and children_pages + * children_pages is two dimensional array, eg. + * children_pages[10][] contains all sub-pages whose parent is 10. + * It only takes O( N ) to arrange this and it takes O( 1 ) for subsequent lookup operations + * If searching, ignore hierarchy and treat everything as top level + */ + if ( empty( $_REQUEST['s'] ) ) { + + $top_level_pages = array(); + $children_pages = array(); + + foreach ( $pages as $page ) { + + // catch and repair bad pages + if ( $page->post_parent == $page->ID ) { + $page->post_parent = 0; + $wpdb->update( $wpdb->posts, array( 'post_parent' => 0 ), array( 'ID' => $page->ID ) ); + clean_post_cache( $page ); + } + + if ( 0 == $page->post_parent ) + $top_level_pages[] = $page; + else + $children_pages[ $page->post_parent ][] = $page; + } + + $pages = &$top_level_pages; + } + + $count = 0; + $start = ( $pagenum - 1 ) * $per_page; + $end = $start + $per_page; + + foreach ( $pages as $page ) { + if ( $count >= $end ) + break; + + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $page, $level ); + } + + $count++; + + if ( isset( $children_pages ) ) + $this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page ); + } + + // if it is the last pagenum and there are orphaned pages, display them with paging as well + if ( isset( $children_pages ) && $count < $end ){ + foreach ( $children_pages as $orphans ){ + foreach ( $orphans as $op ) { + if ( $count >= $end ) + break; + + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $op, 0 ); + } + + $count++; + } + } + } + } + + /** + * Given a top level page ID, display the nested hierarchy of sub-pages + * together with paging support + * + * @since 3.1.0 (Standalone function exists since 2.6.0) + * + * @param array $children_pages + * @param int $count + * @param int $parent + * @param int $level + * @param int $pagenum + * @param int $per_page + */ + function _page_rows( &$children_pages, &$count, $parent, $level, $pagenum, $per_page ) { + + if ( ! isset( $children_pages[$parent] ) ) + return; + + $start = ( $pagenum - 1 ) * $per_page; + $end = $start + $per_page; + + foreach ( $children_pages[$parent] as $page ) { + + if ( $count >= $end ) + break; + + // If the page starts in a subtree, print the parents. + if ( $count == $start && $page->post_parent > 0 ) { + $my_parents = array(); + $my_parent = $page->post_parent; + while ( $my_parent ) { + $my_parent = get_post( $my_parent ); + $my_parents[] = $my_parent; + if ( !$my_parent->post_parent ) + break; + $my_parent = $my_parent->post_parent; + } + $num_parents = count( $my_parents ); + while ( $my_parent = array_pop( $my_parents ) ) { + echo "\t"; + $this->single_row( $my_parent, $level - $num_parents ); + $num_parents--; + } + } + + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $page, $level ); + } + + $count++; + + $this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page ); + } + + unset( $children_pages[$parent] ); //required in order to keep track of orphans + } + + function single_row( $post, $level = 0 ) { + global $mode; + static $alternate; + + $global_post = get_post(); + $GLOBALS['post'] = $post; + setup_postdata( $post ); + + $edit_link = get_edit_post_link( $post->ID ); + $title = _draft_or_post_title(); + $post_type_object = get_post_type_object( $post->post_type ); + $can_edit_post = current_user_can( 'edit_post', $post->ID ); + + $alternate = 'alternate' == $alternate ? '' : 'alternate'; + $classes = $alternate . ' iedit author-' . ( get_current_user_id() == $post->post_author ? 'self' : 'other' ); + + $lock_holder = wp_check_post_lock( $post->ID ); + if ( $lock_holder ) { + $classes .= ' wp-locked'; + $lock_holder = get_userdata( $lock_holder ); + } + ?> + + get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $class = "class=\"$column_name column-$column_name\""; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = "$class$style"; + + switch ( $column_name ) { + + case 'cb': + ?> + + hierarchical_display ) { + if ( 0 == $level && (int) $post->post_parent > 0 ) { + //sent level 0 by accident, by default, or because we don't know the actual level + $find_main_page = (int) $post->post_parent; + while ( $find_main_page > 0 ) { + $parent = get_post( $find_main_page ); + + if ( is_null( $parent ) ) + break; + + $level++; + $find_main_page = (int) $parent->post_parent; + + if ( !isset( $parent_name ) ) { + /** This filter is documented in wp-includes/post-template.php */ + $parent_name = apply_filters( 'the_title', $parent->post_title, $parent->ID ); + } + } + } + } + + $pad = str_repeat( '— ', $level ); + echo "'; + break; + + case 'date': + if ( '0000-00-00 00:00:00' == $post->post_date ) { + $t_time = $h_time = __( 'Unpublished' ); + $time_diff = 0; + } else { + $t_time = get_the_time( __( 'Y/m/d g:i:s A' ) ); + $m_time = $post->post_date; + $time = get_post_time( 'G', true, $post ); + + $time_diff = time() - $time; + + if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) + $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); + else + $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); + } + + echo ''; + break; + + case 'comments': + ?> + + + + '; + if ( $terms = get_the_terms( $post->ID, $taxonomy ) ) { + $out = array(); + foreach ( $terms as $t ) { + $posts_in_term_qv = array(); + if ( 'post' != $post->post_type ) + $posts_in_term_qv['post_type'] = $post->post_type; + if ( $taxonomy_object->query_var ) { + $posts_in_term_qv[ $taxonomy_object->query_var ] = $t->slug; + } else { + $posts_in_term_qv['taxonomy'] = $taxonomy; + $posts_in_term_qv['term'] = $t->slug; + } + + $out[] = sprintf( '%s', + esc_url( add_query_arg( $posts_in_term_qv, 'edit.php' ) ), + esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) + ); + } + /* translators: used between list items, there is a space after the comma */ + echo join( __( ', ' ), $out ); + } else { + echo '—'; + } + echo ''; + break; + } + ?> + + + + screen; + + $post = get_default_post_to_edit( $screen->post_type ); + $post_type_object = get_post_type_object( $screen->post_type ); + + $taxonomy_names = get_object_taxonomies( $screen->post_type ); + $hierarchical_taxonomies = array(); + $flat_taxonomies = array(); + foreach ( $taxonomy_names as $taxonomy_name ) { + $taxonomy = get_taxonomy( $taxonomy_name ); + + if ( !$taxonomy->show_ui ) + continue; + + if ( $taxonomy->hierarchical ) + $hierarchical_taxonomies[] = $taxonomy; + else + $flat_taxonomies[] = $taxonomy; + } + + $m = ( isset( $mode ) && 'excerpt' == $mode ) ? 'excerpt' : 'list'; + $can_publish = current_user_can( $post_type_object->cap->publish_posts ); + $core_columns = array( 'cb' => true, 'date' => true, 'title' => true, 'categories' => true, 'tags' => true, 'comments' => true, 'author' => true ); + + ?> + +
'; + $this->no_items(); + echo '
'; + echo $this->column_cb( $item ); + echo '"; + echo call_user_func( array( $this, 'column_' . $column_name ), $item ); + echo ""; + echo $this->column_default( $item, $column_name ); + echo "
+ + + + + >ID, array( 80, 60 ), true ) ) { + if ( $this->is_trash || ! $user_can_edit ) { + echo $thumb; + } else { +?> + + + + + + > + is_trash || ! $user_can_edit ) { + echo $att_title; + } else { ?> + + + +

+ID ), $matches ) ) + echo esc_html( strtoupper( $matches[1] ) ); + else + echo strtoupper( str_replace( 'image/', '', get_post_mime_type() ) ); +?> +

+row_actions( $this->_get_row_actions( $post, $att_title ) ); +?> +
>%s', + esc_url( add_query_arg( array( 'author' => get_the_author_meta('ID') ), 'upload.php' ) ), + get_the_author() + ); + ?>>post_excerpt : ''; ?>>> + post_parent ) && $parent_type->show_ui ) { ?> + + , + + >
+ + + +
> +
+ID ); + + $this->comments_bubble( $post->ID, $pending_comments ); +?> +
+
> + ID ); ?> +
+ + + + + + +
$checkbox" . $theme->display('Name') . ""; + echo $this->row_actions( $actions, true ); + echo ""; + if ( $theme->errors() ) { + $pre = $status == 'broken' ? '' : __( 'Broken Theme:' ) . ' '; + echo '

' . $pre . $theme->errors()->get_error_message() . '

'; + } + echo "

" . $theme->display( 'Description' ) . "

+
"; + + $theme_meta = array(); + + if ( $theme->get('Version') ) + $theme_meta[] = sprintf( __( 'Version %s' ), $theme->display('Version') ); + + $theme_meta[] = sprintf( __( 'By %s' ), $theme->display('Author') ); + + if ( $theme->get('ThemeURI') ) + $theme_meta[] = '' . __( 'Visit Theme Site' ) . ''; + + $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status ); + echo implode( ' | ', $theme_meta ); + + echo "
"; + do_action( 'manage_themes_custom_column', $column_name, $stylesheet, $theme ); + echo "
+ + + "; ?> + user_login; ?>user_login, $super_admins ) ) + echo ' - ' . __( 'Super Admin' ); + ?> +
+ ' . __( 'Edit' ) . ''; + + if ( current_user_can( 'delete_user', $user->ID ) && ! in_array( $user->user_login, $super_admins ) ) { + $actions['delete'] = '' . __( 'Delete' ) . ''; + } + + $actions = apply_filters( 'ms_user_row_actions', $actions, $user ); + echo $this->row_actions( $actions ); + ?> +
$user->user_email" . mysql2date( $date, $user->user_registered ) . ""; + if ( is_array( $blogs ) ) { + foreach ( (array) $blogs as $key => $val ) { + if ( !can_edit_network( $val->site_id ) ) + continue; + + $path = ( $val->path == '/' ) ? '' : $val->path; + echo ''; + echo '' . str_replace( '.' . $current_site->domain, '', $val->domain . $path ) . ''; + echo ' '; + $actions = array(); + $actions['edit'] = '' . __( 'Edit' ) . ''; + + $class = ''; + if ( get_blog_status( $val->userblog_id, 'spam' ) == 1 ) + $class .= 'site-spammed '; + if ( get_blog_status( $val->userblog_id, 'mature' ) == 1 ) + $class .= 'site-mature '; + if ( get_blog_status( $val->userblog_id, 'deleted' ) == 1 ) + $class .= 'site-deleted '; + if ( get_blog_status( $val->userblog_id, 'archived' ) == 1 ) + $class .= 'site-archived '; + + $actions['view'] = '' . __( 'View' ) . ''; + + $actions = apply_filters('ms_user_list_site_actions', $actions, $val->userblog_id); + + $i=0; + $action_count = count( $actions ); + foreach ( $actions as $action => $link ) { + ++$i; + ( $i == $action_count ) ? $sep = '' : $sep = ' | '; + echo "$link$sep"; + } + echo '
'; + } + } + ?> +
> + + >> +
+
+
+
>
$checkbox$plugin_name"; + echo $this->row_actions( $actions, true ); + echo " +
$description
+
"; + + $plugin_meta = array(); + if ( !empty( $plugin_data['Version'] ) ) + $plugin_meta[] = sprintf( __( 'Version %s' ), $plugin_data['Version'] ); + if ( !empty( $plugin_data['Author'] ) ) { + $author = $plugin_data['Author']; + if ( !empty( $plugin_data['AuthorURI'] ) ) + $author = '' . $plugin_data['Author'] . ''; + $plugin_meta[] = sprintf( __( 'By %s' ), $author ); + } + if ( ! empty( $plugin_data['PluginURI'] ) ) + $plugin_meta[] = '' . __( 'Visit plugin site' ) . ''; + + $plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status ); + echo implode( ' | ', $plugin_meta ); + + echo "
"; + do_action( 'manage_plugins_custom_column', $column_name, $plugin_file, $plugin_data ); + echo "
+ + + +
+ +
"; + + if ( $format = get_post_format( $post->ID ) ) { + $label = get_post_format_string( $format ); + + echo '' . $label . ": "; + } + + if ( $can_edit_post && $post->post_status != 'trash' ) { + echo '' . $pad . $title . ''; + } else { + echo $pad . $title; + } + _post_states( $post ); + + if ( isset( $parent_name ) ) + echo ' | ' . $post_type_object->labels->parent_item_colon . ' ' . esc_html( $parent_name ); + + echo "\n"; + + if ( $can_edit_post && $post->post_status != 'trash' ) { + if ( $lock_holder ) { + $locked_avatar = get_avatar( $lock_holder->ID, 18 ); + $locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) ); + } else { + $locked_avatar = $locked_text = ''; + } + + echo '
' . $locked_avatar . ' ' . $locked_text . "
\n"; + } + + if ( ! $this->hierarchical_display && 'excerpt' == $mode && current_user_can( 'read_post', $post->ID ) ) + the_excerpt(); + + $actions = array(); + if ( $can_edit_post && 'trash' != $post->post_status ) { + $actions['edit'] = '' . __( 'Edit' ) . ''; + $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; + } + if ( current_user_can( 'delete_post', $post->ID ) ) { + if ( 'trash' == $post->post_status ) + $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore' ) . ""; + elseif ( EMPTY_TRASH_DAYS ) + $actions['trash'] = "" . __( 'Trash' ) . ""; + if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) + $actions['delete'] = "" . __( 'Delete Permanently' ) . ""; + } + if ( $post_type_object->public ) { + if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { + if ( $can_edit_post ) + $actions['view'] = '' . __( 'Preview' ) . ''; + } elseif ( 'trash' != $post->post_status ) { + $actions['view'] = '' . __( 'View' ) . ''; + } + } + + $actions = apply_filters( is_post_type_hierarchical( $post->post_type ) ? 'page_row_actions' : 'post_row_actions', $actions, $post ); + echo $this->row_actions( $actions ); + + get_inline_data( $post ); + echo '
'; + if ( 'excerpt' == $mode ) + echo apply_filters( 'post_date_column_time', $t_time, $post, $column_name, $mode ); + else + echo '' . apply_filters( 'post_date_column_time', $h_time, $post, $column_name, $mode ) . ''; + echo '
'; + if ( 'publish' == $post->post_status ) { + _e( 'Published' ); + } elseif ( 'future' == $post->post_status ) { + if ( $time_diff > 0 ) + echo '' . __( 'Missed schedule' ) . ''; + else + _e( 'Scheduled' ); + } else { + _e( 'Last Modified' ); + } + echo '
>
+ comment_pending_count[$post->ID] ) ? $this->comment_pending_count[$post->ID] : 0; + + $this->comments_bubble( $post->ID, $pending_comments ); + ?> +
>%s', + esc_url( add_query_arg( array( 'post_type' => $post->post_type, 'author' => get_the_author_meta( 'ID' ) ), 'edit.php' )), + get_the_author() + ); + ?>>post_type ) ) + do_action( 'manage_pages_custom_column', $column_name, $post->ID ); + else + do_action( 'manage_posts_custom_column', $column_name, $post->ID ); + do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID ); + ?>
+ + + post_type; + echo $bulk ? " bulk-edit-row bulk-edit-row-$hclass bulk-edit-{$screen->post_type}" : " quick-edit-row quick-edit-row-$hclass inline-edit-{$screen->post_type}"; + ?>" style="display: none"> + +
+ +
+

+ post_type, 'title' ) ) : + if ( $bulk ) : ?> +
+
+
+ + + + + + + + + + + +
+ +
+
+ post_type, 'author' ) ) : + $authors_dropdown = ''; + + if ( is_super_admin() || current_user_can( $post_type_object->cap->edit_others_posts ) ) : + $users_opt = array( + 'hide_if_only_one_author' => false, + 'who' => 'authors', + 'name' => 'post_author', + 'class'=> 'authors', + 'multi' => 1, + 'echo' => 0 + ); + if ( $bulk ) + $users_opt['show_option_none'] = __( '— No Change —' ); + + if ( $authors = wp_dropdown_users( $users_opt ) ) : + $authors_dropdown = ''; + endif; + endif; // authors + ?> + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + labels->name ) ?> + +
    + $taxonomy->name ) ) ?> +
+ + + +
+ + + +
+ + post_type, 'author' ) && $bulk ) + echo $authors_dropdown; + + if ( post_type_supports( $screen->post_type, 'page-attributes' ) ) : + + if ( $post_type_object->hierarchical ) : + ?> + + + + + + + post_type ) : + ?> + + + + + + + + + cap->assign_terms ) ) : ?> + + + + + + + + post_type, 'comments' ) || post_type_supports( $screen->post_type, 'trackbacks' ) ) : + if ( $bulk ) : ?> + +
+ post_type, 'comments' ) ) : ?> + + post_type, 'trackbacks' ) ) : ?> + + +
+ + + +
+ post_type, 'comments' ) ) : ?> + + post_type, 'trackbacks' ) ) : ?> + + +
+ + + +
+ + + post_type && $can_publish && current_user_can( $post_type_object->cap->edit_others_posts ) ) : ?> + + + + + + + + + + + + + +
+ + post_type, 'post-formats' ) ) { + $all_post_formats = get_post_format_strings(); + + ?> + + + +
+ + get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + if ( isset( $core_columns[$column_name] ) ) + continue; + do_action( $bulk ? 'bulk_edit_custom_box' : 'quick_edit_custom_box', $column_name, $screen->post_type ); + } + ?> +

+ + + + + 's' ) ); + } ?> + + + post_type, 'author' ) ) { ?> + + + +
+

+
+ 'tags', + 'singular' => 'tag', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + + $action = $this->screen->action; + $post_type = $this->screen->post_type; + $taxonomy = $this->screen->taxonomy; + + if ( empty( $taxonomy ) ) + $taxonomy = 'post_tag'; + + if ( ! taxonomy_exists( $taxonomy ) ) + wp_die( __( 'Invalid taxonomy' ) ); + + $tax = get_taxonomy( $taxonomy ); + + // @todo Still needed? Maybe just the show_ui part. + if ( empty( $post_type ) || !in_array( $post_type, get_post_types( array( 'show_ui' => true ) ) ) ) + $post_type = 'post'; + + } + + function ajax_user_can() { + return current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->manage_terms ); + } + + function prepare_items() { + $tags_per_page = $this->get_items_per_page( 'edit_' . $this->screen->taxonomy . '_per_page' ); + + if ( 'post_tag' == $this->screen->taxonomy ) { + $tags_per_page = apply_filters( 'edit_tags_per_page', $tags_per_page ); + $tags_per_page = apply_filters( 'tagsperpage', $tags_per_page ); // Old filter + } elseif ( 'category' == $this->screen->taxonomy ) { + $tags_per_page = apply_filters( 'edit_categories_per_page', $tags_per_page ); // Old filter + } + + $search = !empty( $_REQUEST['s'] ) ? trim( wp_unslash( $_REQUEST['s'] ) ) : ''; + + $args = array( + 'search' => $search, + 'page' => $this->get_pagenum(), + 'number' => $tags_per_page, + ); + + if ( !empty( $_REQUEST['orderby'] ) ) + $args['orderby'] = trim( wp_unslash( $_REQUEST['orderby'] ) ); + + if ( !empty( $_REQUEST['order'] ) ) + $args['order'] = trim( wp_unslash( $_REQUEST['order'] ) ); + + $this->callback_args = $args; + + $this->set_pagination_args( array( + 'total_items' => wp_count_terms( $this->screen->taxonomy, compact( 'search' ) ), + 'per_page' => $tags_per_page, + ) ); + } + + function has_items() { + // todo: populate $this->items in prepare_items() + return true; + } + + function get_bulk_actions() { + $actions = array(); + $actions['delete'] = __( 'Delete' ); + + return $actions; + } + + function current_action() { + if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['delete_tags'] ) && ( 'delete' == $_REQUEST['action'] || 'delete' == $_REQUEST['action2'] ) ) + return 'bulk-delete'; + + return parent::current_action(); + } + + function get_columns() { + $columns = array( + 'cb' => '', + 'name' => _x( 'Name', 'term name' ), + 'description' => __( 'Description' ), + 'slug' => __( 'Slug' ), + ); + + if ( 'link_category' == $this->screen->taxonomy ) { + $columns['links'] = __( 'Links' ); + } else { + $post_type_object = get_post_type_object( $this->screen->post_type ); + $columns['posts'] = $post_type_object ? $post_type_object->labels->name : __( 'Posts' ); + } + + return $columns; + } + + function get_sortable_columns() { + return array( + 'name' => 'name', + 'description' => 'description', + 'slug' => 'slug', + 'posts' => 'count', + 'links' => 'count' + ); + } + + function display_rows_or_placeholder() { + $taxonomy = $this->screen->taxonomy; + + $args = wp_parse_args( $this->callback_args, array( + 'page' => 1, + 'number' => 20, + 'search' => '', + 'hide_empty' => 0 + ) ); + + extract( $args, EXTR_SKIP ); + + $args['offset'] = $offset = ( $page - 1 ) * $number; + + // convert it to table rows + $count = 0; + + $terms = array(); + + if ( is_taxonomy_hierarchical( $taxonomy ) && !isset( $orderby ) ) { + // We'll need the full set of terms then. + $args['number'] = $args['offset'] = 0; + } + $terms = get_terms( $taxonomy, $args ); + + if ( empty( $terms ) ) { + list( $columns, $hidden ) = $this->get_column_info(); + echo ''; + $this->no_items(); + echo ''; + return; + } + + if ( is_taxonomy_hierarchical( $taxonomy ) && !isset( $orderby ) ) { + if ( !empty( $search ) ) // Ignore children on searches. + $children = array(); + else + $children = _get_term_hierarchy( $taxonomy ); + + // Some funky recursion to get the job done( Paging & parents mainly ) is contained within, Skip it for non-hierarchical taxonomies for performance sake + $this->_rows( $taxonomy, $terms, $children, $offset, $number, $count ); + } else { + $terms = get_terms( $taxonomy, $args ); + foreach ( $terms as $term ) + $this->single_row( $term ); + $count = $number; // Only displaying a single page. + } + } + + function _rows( $taxonomy, $terms, &$children, $start, $per_page, &$count, $parent = 0, $level = 0 ) { + + $end = $start + $per_page; + + foreach ( $terms as $key => $term ) { + + if ( $count >= $end ) + break; + + if ( $term->parent != $parent && empty( $_REQUEST['s'] ) ) + continue; + + // If the page starts in a subtree, print the parents. + if ( $count == $start && $term->parent > 0 && empty( $_REQUEST['s'] ) ) { + $my_parents = $parent_ids = array(); + $p = $term->parent; + while ( $p ) { + $my_parent = get_term( $p, $taxonomy ); + $my_parents[] = $my_parent; + $p = $my_parent->parent; + if ( in_array( $p, $parent_ids ) ) // Prevent parent loops. + break; + $parent_ids[] = $p; + } + unset( $parent_ids ); + + $num_parents = count( $my_parents ); + while ( $my_parent = array_pop( $my_parents ) ) { + echo "\t"; + $this->single_row( $my_parent, $level - $num_parents ); + $num_parents--; + } + } + + if ( $count >= $start ) { + echo "\t"; + $this->single_row( $term, $level ); + } + + ++$count; + + unset( $terms[$key] ); + + if ( isset( $children[$term->term_id] ) && empty( $_REQUEST['s'] ) ) + $this->_rows( $taxonomy, $terms, $children, $start, $per_page, $count, $term->term_id, $level + 1 ); + } + } + + function single_row( $tag, $level = 0 ) { + static $row_class = ''; + $row_class = ( $row_class == '' ? ' class="alternate"' : '' ); + + $this->level = $level; + + echo ''; + $this->single_row_columns( $tag ); + echo ''; + } + + function column_cb( $tag ) { + $default_term = get_option( 'default_' . $this->screen->taxonomy ); + + if ( current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->delete_terms ) && $tag->term_id != $default_term ) + return '' + . ''; + + return ' '; + } + + function column_name( $tag ) { + $taxonomy = $this->screen->taxonomy; + $tax = get_taxonomy( $taxonomy ); + + $default_term = get_option( 'default_' . $taxonomy ); + + $pad = str_repeat( '— ', max( 0, $this->level ) ); + $name = apply_filters( 'term_name', $pad . ' ' . $tag->name, $tag ); + $qe_data = get_term( $tag->term_id, $taxonomy, OBJECT, 'edit' ); + $edit_link = esc_url( get_edit_term_link( $tag->term_id, $taxonomy, $this->screen->post_type ) ); + + $out = '' . $name . '
'; + + $actions = array(); + if ( current_user_can( $tax->cap->edit_terms ) ) { + $actions['edit'] = '' . __( 'Edit' ) . ''; + $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit' ) . ''; + } + if ( current_user_can( $tax->cap->delete_terms ) && $tag->term_id != $default_term ) + $actions['delete'] = "term_id ) . "'>" . __( 'Delete' ) . ""; + if ( $tax->public ) + $actions['view'] = '' . __( 'View' ) . ''; + + $actions = apply_filters( 'tag_row_actions', $actions, $tag ); + $actions = apply_filters( "{$taxonomy}_row_actions", $actions, $tag ); + + $out .= $this->row_actions( $actions ); + $out .= ''; + + return $out; + } + + function column_description( $tag ) { + return $tag->description; + } + + function column_slug( $tag ) { + return apply_filters( 'editable_slug', $tag->slug ); + } + + function column_posts( $tag ) { + $count = number_format_i18n( $tag->count ); + + $tax = get_taxonomy( $this->screen->taxonomy ); + + $ptype_object = get_post_type_object( $this->screen->post_type ); + if ( ! $ptype_object->show_ui ) + return $count; + + if ( $tax->query_var ) { + $args = array( $tax->query_var => $tag->slug ); + } else { + $args = array( 'taxonomy' => $tax->name, 'term' => $tag->slug ); + } + + if ( 'post' != $this->screen->post_type ) + $args['post_type'] = $this->screen->post_type; + + if ( 'attachment' == $this->screen->post_type ) + return "$count"; + + return "$count"; + } + + function column_links( $tag ) { + $count = number_format_i18n( $tag->count ); + if ( $count ) + $count = "$count"; + return $count; + } + + function column_default( $tag, $column_name ) { + return apply_filters( "manage_{$this->screen->taxonomy}_custom_column", '', $column_name, $tag->term_id ); + } + + /** + * Outputs the hidden row displayed when inline editing + * + * @since 3.1.0 + */ + function inline_edit() { + $tax = get_taxonomy( $this->screen->taxonomy ); + + if ( ! current_user_can( $tax->cap->edit_terms ) ) + return; +?> + +
+ +
+ features = $_REQUEST['features']; + + $paged = $this->get_pagenum(); + + $per_page = 36; + + // These are the tabs which are shown on the page, + $tabs = array(); + $tabs['dashboard'] = __( 'Search' ); + if ( 'search' == $tab ) + $tabs['search'] = __( 'Search Results' ); + $tabs['upload'] = __( 'Upload' ); + $tabs['featured'] = _x( 'Featured','Theme Installer' ); + //$tabs['popular'] = _x( 'Popular','Theme Installer' ); + $tabs['new'] = _x( 'Newest','Theme Installer' ); + $tabs['updated'] = _x( 'Recently Updated','Theme Installer' ); + + $nonmenu_tabs = array( 'theme-information' ); // Valid actions to perform which do not have a Menu item. + + $tabs = apply_filters( 'install_themes_tabs', $tabs ); + $nonmenu_tabs = apply_filters( 'install_themes_nonmenu_tabs', $nonmenu_tabs ); + + // If a non-valid menu tab has been selected, And it's not a non-menu action. + if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs ) ) ) + $tab = key( $tabs ); + + $args = array( 'page' => $paged, 'per_page' => $per_page, 'fields' => $theme_field_defaults ); + + switch ( $tab ) { + case 'search': + $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; + switch ( $type ) { + case 'tag': + $args['tag'] = array_map( 'sanitize_key', $search_terms ); + break; + case 'term': + $args['search'] = $search_string; + break; + case 'author': + $args['author'] = $search_string; + break; + } + + if ( ! empty( $this->features ) ) { + $args['tag'] = $this->features; + $_REQUEST['s'] = implode( ',', $this->features ); + $_REQUEST['type'] = 'tag'; + } + + add_action( 'install_themes_table_header', 'install_theme_search_form', 10, 0 ); + break; + + case 'featured': + //case 'popular': + case 'new': + case 'updated': + $args['browse'] = $tab; + break; + + default: + $args = false; + break; + } + + $args = apply_filters( 'install_themes_table_api_args_' . $tab, $args ); + + if ( ! $args ) + return; + + $api = themes_api( 'query_themes', $args ); + + if ( is_wp_error( $api ) ) + wp_die( $api->get_error_message() . '

' . __( 'Try again' ) . '' ); + + $this->items = $api->themes; + + $this->set_pagination_args( array( + 'total_items' => $api->info['results'], + 'per_page' => $per_page, + 'infinite_scroll' => true, + ) ); + } + + function no_items() { + _e( 'No themes match your request.' ); + } + + function get_views() { + global $tabs, $tab; + + $display_tabs = array(); + foreach ( (array) $tabs as $action => $text ) { + $class = ( $action == $tab ) ? ' class="current"' : ''; + $href = self_admin_url('theme-install.php?tab=' . $action); + $display_tabs['theme-install-'.$action] = "$text"; + } + + return $display_tabs; + } + + function display() { + wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); +?> +

+
+ +
+ pagination( 'top' ); ?> +
+
+ +
+ display_rows_or_placeholder(); ?> +
+ + items; + foreach ( $themes as $theme ) { + ?> +
single_row( $theme ); + ?>
+ theme_installer(); + } + + /* + * Prints a theme from the WordPress.org API. + * + * @param object $theme An object that contains theme data returned by the WordPress.org API. + * + * Example theme data: + * object(stdClass)[59] + * public 'name' => string 'Magazine Basic' + * public 'slug' => string 'magazine-basic' + * public 'version' => string '1.1' + * public 'author' => string 'tinkerpriest' + * public 'preview_url' => string 'http://wp-themes.com/?magazine-basic' + * public 'screenshot_url' => string 'http://wp-themes.com/wp-content/themes/magazine-basic/screenshot.png' + * public 'rating' => float 80 + * public 'num_ratings' => int 1 + * public 'homepage' => string 'http://wordpress.org/themes/magazine-basic' + * public 'description' => string 'A basic magazine style layout with a fully customizable layout through a backend interface. Designed by c.bavota of Tinker Priest Media.' + * public 'download_link' => string 'http://wordpress.org/themes/download/magazine-basic.1.1.zip' + */ + function single_row( $theme ) { + global $themes_allowedtags; + + if ( empty( $theme ) ) + return; + + $name = wp_kses( $theme->name, $themes_allowedtags ); + $author = wp_kses( $theme->author, $themes_allowedtags ); + + $preview_title = sprintf( __('Preview “%s”'), $name ); + $preview_url = add_query_arg( array( + 'tab' => 'theme-information', + 'theme' => $theme->slug, + ) ); + + $actions = array(); + + $install_url = add_query_arg( array( + 'action' => 'install-theme', + 'theme' => $theme->slug, + ), self_admin_url( 'update.php' ) ); + + $update_url = add_query_arg( array( + 'action' => 'upgrade-theme', + 'theme' => $theme->slug, + ), self_admin_url( 'update.php' ) ); + + $status = $this->_get_theme_status( $theme ); + + switch ( $status ) { + default: + case 'install': + $actions[] = '' . __( 'Install Now' ) . ''; + break; + case 'update_available': + $actions[] = '' . __( 'Update' ) . ''; + break; + case 'newer_installed': + case 'latest_installed': + $actions[] = '' . _x( 'Installed', 'theme' ) . ''; + break; + } + + $actions[] = '' . __( 'Preview' ) . ''; + + $actions = apply_filters( 'theme_install_actions', $actions, $theme ); + + ?> + + + + +

+
+ + + + install_theme_info( $theme ); + } + + /* + * Prints the wrapper for the theme installer. + */ + function theme_installer() { + ?> +
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+ install_theme_info( $theme ); ?> +
+
+ +
+
+ name, $themes_allowedtags ); + $author = wp_kses( $theme->author, $themes_allowedtags ); + + $num_ratings = sprintf( _n( '(based on %s rating)', '(based on %s ratings)', $theme->num_ratings ), number_format_i18n( $theme->num_ratings ) ); + + $install_url = add_query_arg( array( + 'action' => 'install-theme', + 'theme' => $theme->slug, + ), self_admin_url( 'update.php' ) ); + + $update_url = add_query_arg( array( + 'action' => 'upgrade-theme', + 'theme' => $theme->slug, + ), self_admin_url( 'update.php' ) ); + + $status = $this->_get_theme_status( $theme ); + + ?> +
slug ) ) . '">' . __( 'Install' ) . ''; + break; + case 'update_available': + echo '' . __( 'Update' ) . ''; + break; + case 'newer_installed': + case 'latest_installed': + echo '' . _x( 'Installed', 'theme' ) . ''; + break; + } ?> +

+ + screenshot_url ) ): ?> + + +
+
+
+
+
+ + version, $themes_allowedtags ); ?> +
+
+ description, $themes_allowedtags ); ?> +
+
+ +
+ Install screen + * @uses $type Global; type of search. + */ + function _js_vars( $extra_args = array() ) { + global $tab, $type; + parent::_js_vars( compact( 'tab', 'type' ) ); + } + + /** + * Check to see if the theme is already installed. + * + * @since 3.4 + * @access private + * + * @param object $theme - A WordPress.org Theme API object. + * @return string Theme status. + */ + private function _get_theme_status( $theme ) { + $status = 'install'; + + $installed_theme = wp_get_theme( $theme->slug ); + if ( $installed_theme->exists() ) { + if ( version_compare( $installed_theme->get('Version'), $theme->version, '=' ) ) + $status = 'latest_installed'; + elseif ( version_compare( $installed_theme->get('Version'), $theme->version, '>' ) ) + $status = 'newer_installed'; + else + $status = 'update_available'; + } + + return $status; + } +} diff --git a/sources/wp-admin/includes/class-wp-themes-list-table.php b/sources/wp-admin/includes/class-wp-themes-list-table.php new file mode 100644 index 0000000..d49d993 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-themes-list-table.php @@ -0,0 +1,264 @@ + true, + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + } + + function ajax_user_can() { + // Do not check edit_theme_options here. AJAX calls for available themes require switch_themes. + return current_user_can( 'switch_themes' ); + } + + function prepare_items() { + $themes = wp_get_themes( array( 'allowed' => true ) ); + + if ( ! empty( $_REQUEST['s'] ) ) + $this->search_terms = array_unique( array_filter( array_map( 'trim', explode( ',', strtolower( wp_unslash( $_REQUEST['s'] ) ) ) ) ) ); + + if ( ! empty( $_REQUEST['features'] ) ) + $this->features = $_REQUEST['features']; + + if ( $this->search_terms || $this->features ) { + foreach ( $themes as $key => $theme ) { + if ( ! $this->search_theme( $theme ) ) + unset( $themes[ $key ] ); + } + } + + unset( $themes[ get_option( 'stylesheet' ) ] ); + WP_Theme::sort_by_name( $themes ); + + $per_page = 36; + $page = $this->get_pagenum(); + + $start = ( $page - 1 ) * $per_page; + + $this->items = array_slice( $themes, $start, $per_page, true ); + + $this->set_pagination_args( array( + 'total_items' => count( $themes ), + 'per_page' => $per_page, + 'infinite_scroll' => true, + ) ); + } + + function no_items() { + if ( $this->search_terms || $this->features ) { + _e( 'No items found.' ); + return; + } + + if ( is_multisite() ) { + if ( current_user_can( 'install_themes' ) && current_user_can( 'manage_network_themes' ) ) { + printf( __( 'You only have one theme enabled for this site right now. Visit the Network Admin to enable or install more themes.' ), network_admin_url( 'site-themes.php?id=' . $GLOBALS['blog_id'] ), network_admin_url( 'theme-install.php' ) ); + + return; + } elseif ( current_user_can( 'manage_network_themes' ) ) { + printf( __( 'You only have one theme enabled for this site right now. Visit the Network Admin to enable more themes.' ), network_admin_url( 'site-themes.php?id=' . $GLOBALS['blog_id'] ) ); + + return; + } + // else, fallthrough. install_themes doesn't help if you can't enable it. + } else { + if ( current_user_can( 'install_themes' ) ) { + printf( __( 'You only have one theme installed right now. Live a little! You can choose from over 1,000 free themes in the WordPress.org Theme Directory at any time: just click on the Install Themes tab above.' ), admin_url( 'theme-install.php' ) ); + + return; + } + } + // Fallthrough. + printf( __( 'Only the current theme is available to you. Contact the %s administrator for information about accessing additional themes.' ), get_site_option( 'site_name' ) ); + } + + function tablenav( $which = 'top' ) { + if ( $this->get_pagination_arg( 'total_pages' ) <= 1 ) + return; + ?> +
+ pagination( $which ); ?> + +
+
+ + tablenav( 'top' ); ?> + +
+ display_rows_or_placeholder(); ?> +
+ + tablenav( 'bottom' ); ?> +has_items() ) { + $this->display_rows(); + } else { + echo '
'; + $this->no_items(); + echo '
'; + } + } + + function display_rows() { + $themes = $this->items; + + foreach ( $themes as $theme ): + ?>
get_template(); + $stylesheet = $theme->get_stylesheet(); + $title = $theme->display('Name'); + $version = $theme->display('Version'); + $author = $theme->display('Author'); + + $activate_link = wp_nonce_url( "themes.php?action=activate&template=" . urlencode( $template ) . "&stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $stylesheet ); + + $preview_link = esc_url( add_query_arg( + array( 'preview' => 1, 'template' => urlencode( $template ), 'stylesheet' => urlencode( $stylesheet ), 'preview_iframe' => true, 'TB_iframe' => 'true' ), + home_url( '/' ) ) ); + + $actions = array(); + $actions['activate'] = '' . __( 'Activate' ) . ''; + + $actions['preview'] = '' . __( 'Preview' ) . ''; + + if ( current_user_can( 'edit_theme_options' ) ) + $actions['preview'] .= '' + . __( 'Live Preview' ) . ''; + + if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) + $actions['delete'] = '' . __( 'Delete' ) . ''; + + $actions = apply_filters( 'theme_action_links', $actions, $theme ); + $actions = apply_filters( "theme_action_links_$stylesheet", $actions, $theme ); + $delete_action = isset( $actions['delete'] ) ? '
' . $actions['delete'] . '
' : ''; + unset( $actions['delete'] ); + + ?> + + + get_screenshot() ) : ?> + + + + + get_screenshot() ) : ?> + + + + +

+
+ + +
+

+

display('Description'); ?>

+ parent() ) { + printf( '

' . __( 'This child theme requires its parent theme, %2$s.' ) . '

', + __( 'http://codex.wordpress.org/Child_Themes' ), + $theme->parent()->display( 'Name' ) ); + } ?> +
+ +
+ features as $word ) { + if ( ! in_array( $word, $theme->get('Tags') ) ) + return false; + } + + // Match all phrases + foreach ( $this->search_terms as $word ) { + if ( in_array( $word, $theme->get('Tags') ) ) + continue; + + foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) { + // Don't mark up; Do translate. + if ( false !== stripos( $theme->display( $header, false, true ), $word ) ) + continue 2; + } + + if ( false !== stripos( $theme->get_stylesheet(), $word ) ) + continue; + + if ( false !== stripos( $theme->get_template(), $word ) ) + continue; + + return false; + } + + return true; + } + + /** + * Send required variables to JavaScript land + * + * @since 3.4 + * @access private + * + * @uses $this->features Array of all feature search terms. + * @uses get_pagenum() + * @uses _pagination_args['total_pages'] + */ + function _js_vars( $extra_args = array() ) { + $search_string = isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : ''; + + $args = array( + 'search' => $search_string, + 'features' => $this->features, + 'paged' => $this->get_pagenum(), + 'total_pages' => ! empty( $this->_pagination_args['total_pages'] ) ? $this->_pagination_args['total_pages'] : 1, + ); + + if ( is_array( $extra_args ) ) + $args = array_merge( $args, $extra_args ); + + printf( "\n", json_encode( $args ) ); + parent::_js_vars(); + } +} diff --git a/sources/wp-admin/includes/class-wp-upgrader-skins.php b/sources/wp-admin/includes/class-wp-upgrader-skins.php new file mode 100644 index 0000000..b8c82c7 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-upgrader-skins.php @@ -0,0 +1,662 @@ + '', 'nonce' => '', 'title' => '', 'context' => false ); + $this->options = wp_parse_args($args, $defaults); + } + + function set_upgrader(&$upgrader) { + if ( is_object($upgrader) ) + $this->upgrader =& $upgrader; + $this->add_strings(); + } + + function add_strings() { + } + + function set_result($result) { + $this->result = $result; + } + + function request_filesystem_credentials($error = false) { + $url = $this->options['url']; + $context = $this->options['context']; + if ( !empty($this->options['nonce']) ) + $url = wp_nonce_url($url, $this->options['nonce']); + return request_filesystem_credentials($url, '', $error, $context); //Possible to bring inline, Leaving as is for now. + } + + function header() { + if ( $this->done_header ) + return; + $this->done_header = true; + echo '
'; + screen_icon(); + echo '

' . $this->options['title'] . '

'; + } + function footer() { + echo '
'; + } + + function error($errors) { + if ( ! $this->done_header ) + $this->header(); + if ( is_string($errors) ) { + $this->feedback($errors); + } elseif ( is_wp_error($errors) && $errors->get_error_code() ) { + foreach ( $errors->get_error_messages() as $message ) { + if ( $errors->get_error_data() && is_string( $errors->get_error_data() ) ) + $this->feedback($message . ' ' . esc_html( $errors->get_error_data() ) ); + else + $this->feedback($message); + } + } + } + + function feedback($string) { + if ( isset( $this->upgrader->strings[$string] ) ) + $string = $this->upgrader->strings[$string]; + + if ( strpos($string, '%') !== false ) { + $args = func_get_args(); + $args = array_splice($args, 1); + if ( $args ) { + $args = array_map( 'strip_tags', $args ); + $args = array_map( 'esc_html', $args ); + $string = vsprintf($string, $args); + } + } + if ( empty($string) ) + return; + show_message($string); + } + function before() {} + function after() {} + +} + +/** + * Plugin Upgrader Skin for WordPress Plugin Upgrades. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Plugin_Upgrader_Skin extends WP_Upgrader_Skin { + var $plugin = ''; + var $plugin_active = false; + var $plugin_network_active = false; + + function __construct($args = array()) { + $defaults = array( 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => __('Update Plugin') ); + $args = wp_parse_args($args, $defaults); + + $this->plugin = $args['plugin']; + + $this->plugin_active = is_plugin_active( $this->plugin ); + $this->plugin_network_active = is_plugin_active_for_network( $this->plugin ); + + parent::__construct($args); + } + + function after() { + $this->plugin = $this->upgrader->plugin_info(); + if ( !empty($this->plugin) && !is_wp_error($this->result) && $this->plugin_active ){ + echo ''; + } + + $update_actions = array( + 'activate_plugin' => '' . __('Activate Plugin') . '', + 'plugins_page' => '' . __('Return to Plugins page') . '' + ); + if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugins' ) ) + unset( $update_actions['activate_plugin'] ); + + $update_actions = apply_filters('update_plugin_complete_actions', $update_actions, $this->plugin); + if ( ! empty($update_actions) ) + $this->feedback(implode(' | ', (array)$update_actions)); + } + + function before() { + if ( $this->upgrader->show_before ) { + echo $this->upgrader->show_before; + $this->upgrader->show_before = ''; + } + } +} + +/** + * Plugin Upgrader Skin for WordPress Plugin Upgrades. + * + * @package WordPress + * @subpackage Upgrader + * @since 3.0.0 + */ +class Bulk_Upgrader_Skin extends WP_Upgrader_Skin { + var $in_loop = false; + var $error = false; + + function __construct($args = array()) { + $defaults = array( 'url' => '', 'nonce' => '' ); + $args = wp_parse_args($args, $defaults); + + parent::__construct($args); + } + + function add_strings() { + $this->upgrader->strings['skin_upgrade_start'] = __('The update process is starting. This process may take a while on some hosts, so please be patient.'); + $this->upgrader->strings['skin_update_failed_error'] = __('An error occurred while updating %1$s: %2$s'); + $this->upgrader->strings['skin_update_failed'] = __('The update of %1$s failed.'); + $this->upgrader->strings['skin_update_successful'] = __('%1$s updated successfully.').' '.__('Show Details').'.'; + $this->upgrader->strings['skin_upgrade_end'] = __('All updates have been completed.'); + } + + function feedback($string) { + if ( isset( $this->upgrader->strings[$string] ) ) + $string = $this->upgrader->strings[$string]; + + if ( strpos($string, '%') !== false ) { + $args = func_get_args(); + $args = array_splice($args, 1); + if ( $args ) { + $args = array_map( 'strip_tags', $args ); + $args = array_map( 'esc_html', $args ); + $string = vsprintf($string, $args); + } + } + if ( empty($string) ) + return; + if ( $this->in_loop ) + echo "$string
\n"; + else + echo "

$string

\n"; + } + + function header() { + // Nothing, This will be displayed within a iframe. + } + + function footer() { + // Nothing, This will be displayed within a iframe. + } + function error($error) { + if ( is_string($error) && isset( $this->upgrader->strings[$error] ) ) + $this->error = $this->upgrader->strings[$error]; + + if ( is_wp_error($error) ) { + foreach ( $error->get_error_messages() as $emessage ) { + if ( $error->get_error_data() && is_string( $error->get_error_data() ) ) + $messages[] = $emessage . ' ' . esc_html( $error->get_error_data() ); + else + $messages[] = $emessage; + } + $this->error = implode(', ', $messages); + } + echo ''; + } + + function bulk_header() { + $this->feedback('skin_upgrade_start'); + } + + function bulk_footer() { + $this->feedback('skin_upgrade_end'); + } + + function before($title = '') { + $this->in_loop = true; + printf( '

' . $this->upgrader->strings['skin_before_update_header'] . '

', $title, $this->upgrader->update_current, $this->upgrader->update_count); + echo ''; + echo '

'; + $this->flush_output(); + } + + function after($title = '') { + echo '

'; + if ( $this->error || ! $this->result ) { + if ( $this->error ) + echo '

' . sprintf($this->upgrader->strings['skin_update_failed_error'], $title, $this->error) . '

'; + else + echo '

' . sprintf($this->upgrader->strings['skin_update_failed'], $title) . '

'; + + echo ''; + } + if ( $this->result && ! is_wp_error( $this->result ) ) { + if ( ! $this->error ) + echo '

' . sprintf($this->upgrader->strings['skin_update_successful'], $title, 'jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').toggle();jQuery(\'span\', this).toggle(); return false;') . '

'; + echo ''; + } + + $this->reset(); + $this->flush_output(); + } + + function reset() { + $this->in_loop = false; + $this->error = false; + } + + function flush_output() { + wp_ob_end_flush_all(); + flush(); + } +} + +class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin { + var $plugin_info = array(); // Plugin_Upgrader::bulk() will fill this in. + + function __construct($args = array()) { + parent::__construct($args); + } + + function add_strings() { + parent::add_strings(); + $this->upgrader->strings['skin_before_update_header'] = __('Updating Plugin %1$s (%2$d/%3$d)'); + } + + function before($title = '') { + parent::before($this->plugin_info['Title']); + } + + function after($title = '') { + parent::after($this->plugin_info['Title']); + } + function bulk_footer() { + parent::bulk_footer(); + $update_actions = array( + 'plugins_page' => '' . __('Return to Plugins page') . '', + 'updates_page' => '' . __('Return to WordPress Updates') . '' + ); + if ( ! current_user_can( 'activate_plugins' ) ) + unset( $update_actions['plugins_page'] ); + + $update_actions = apply_filters('update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info); + if ( ! empty($update_actions) ) + $this->feedback(implode(' | ', (array)$update_actions)); + } +} + +class Bulk_Theme_Upgrader_Skin extends Bulk_Upgrader_Skin { + var $theme_info = array(); // Theme_Upgrader::bulk() will fill this in. + + function __construct($args = array()) { + parent::__construct($args); + } + + function add_strings() { + parent::add_strings(); + $this->upgrader->strings['skin_before_update_header'] = __('Updating Theme %1$s (%2$d/%3$d)'); + } + + function before($title = '') { + parent::before( $this->theme_info->display('Name') ); + } + + function after($title = '') { + parent::after( $this->theme_info->display('Name') ); + } + + function bulk_footer() { + parent::bulk_footer(); + $update_actions = array( + 'themes_page' => '' . __('Return to Themes page') . '', + 'updates_page' => '' . __('Return to WordPress Updates') . '' + ); + if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) + unset( $update_actions['themes_page'] ); + + $update_actions = apply_filters('update_bulk_theme_complete_actions', $update_actions, $this->theme_info ); + if ( ! empty($update_actions) ) + $this->feedback(implode(' | ', (array)$update_actions)); + } +} + +/** + * Plugin Installer Skin for WordPress Plugin Installer. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Plugin_Installer_Skin extends WP_Upgrader_Skin { + var $api; + var $type; + + function __construct($args = array()) { + $defaults = array( 'type' => 'web', 'url' => '', 'plugin' => '', 'nonce' => '', 'title' => '' ); + $args = wp_parse_args($args, $defaults); + + $this->type = $args['type']; + $this->api = isset($args['api']) ? $args['api'] : array(); + + parent::__construct($args); + } + + function before() { + if ( !empty($this->api) ) + $this->upgrader->strings['process_success'] = sprintf( __('Successfully installed the plugin %s %s.'), $this->api->name, $this->api->version); + } + + function after() { + + $plugin_file = $this->upgrader->plugin_info(); + + $install_actions = array(); + + $from = isset($_GET['from']) ? wp_unslash( $_GET['from'] ) : 'plugins'; + + if ( 'import' == $from ) + $install_actions['activate_plugin'] = '' . __('Activate Plugin & Run Importer') . ''; + else + $install_actions['activate_plugin'] = '' . __('Activate Plugin') . ''; + + if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) { + $install_actions['network_activate'] = '' . __('Network Activate') . ''; + unset( $install_actions['activate_plugin'] ); + } + + if ( 'import' == $from ) + $install_actions['importers_page'] = '' . __('Return to Importers') . ''; + else if ( $this->type == 'web' ) + $install_actions['plugins_page'] = '' . __('Return to Plugin Installer') . ''; + else + $install_actions['plugins_page'] = '' . __('Return to Plugins page') . ''; + + if ( ! $this->result || is_wp_error($this->result) ) { + unset( $install_actions['activate_plugin'], $install_actions['network_activate'] ); + } elseif ( ! current_user_can( 'activate_plugins' ) ) { + unset( $install_actions['activate_plugin'] ); + } + + $install_actions = apply_filters('install_plugin_complete_actions', $install_actions, $this->api, $plugin_file); + if ( ! empty($install_actions) ) + $this->feedback(implode(' | ', (array)$install_actions)); + } +} + +/** + * Theme Installer Skin for the WordPress Theme Installer. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Theme_Installer_Skin extends WP_Upgrader_Skin { + var $api; + var $type; + + function __construct($args = array()) { + $defaults = array( 'type' => 'web', 'url' => '', 'theme' => '', 'nonce' => '', 'title' => '' ); + $args = wp_parse_args($args, $defaults); + + $this->type = $args['type']; + $this->api = isset($args['api']) ? $args['api'] : array(); + + parent::__construct($args); + } + + function before() { + if ( !empty($this->api) ) + $this->upgrader->strings['process_success'] = sprintf( $this->upgrader->strings['process_success_specific'], $this->api->name, $this->api->version); + } + + function after() { + if ( empty($this->upgrader->result['destination_name']) ) + return; + + $theme_info = $this->upgrader->theme_info(); + if ( empty( $theme_info ) ) + return; + + $name = $theme_info->display('Name'); + $stylesheet = $this->upgrader->result['destination_name']; + $template = $theme_info->get_template(); + + $preview_link = add_query_arg( array( + 'preview' => 1, + 'template' => urlencode( $template ), + 'stylesheet' => urlencode( $stylesheet ), + ), trailingslashit( home_url() ) ); + + $activate_link = add_query_arg( array( + 'action' => 'activate', + 'template' => urlencode( $template ), + 'stylesheet' => urlencode( $stylesheet ), + ), admin_url('themes.php') ); + $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet ); + + $install_actions = array(); + $install_actions['preview'] = '' . __('Preview') . ''; + $install_actions['preview'] .= '' . __('Live Preview') . ''; + $install_actions['activate'] = '' . __('Activate') . ''; + + if ( is_network_admin() && current_user_can( 'manage_network_themes' ) ) + $install_actions['network_enable'] = '' . __( 'Network Enable' ) . ''; + + if ( $this->type == 'web' ) + $install_actions['themes_page'] = '' . __('Return to Theme Installer') . ''; + elseif ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) ) + $install_actions['themes_page'] = '' . __('Return to Themes page') . ''; + + if ( ! $this->result || is_wp_error($this->result) || is_network_admin() || ! current_user_can( 'switch_themes' ) ) + unset( $install_actions['activate'], $install_actions['preview'] ); + + $install_actions = apply_filters('install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info); + if ( ! empty($install_actions) ) + $this->feedback(implode(' | ', (array)$install_actions)); + } +} + +/** + * Theme Upgrader Skin for WordPress Theme Upgrades. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Theme_Upgrader_Skin extends WP_Upgrader_Skin { + var $theme = ''; + + function __construct($args = array()) { + $defaults = array( 'url' => '', 'theme' => '', 'nonce' => '', 'title' => __('Update Theme') ); + $args = wp_parse_args($args, $defaults); + + $this->theme = $args['theme']; + + parent::__construct($args); + } + + function after() { + + $update_actions = array(); + if ( ! empty( $this->upgrader->result['destination_name'] ) && $theme_info = $this->upgrader->theme_info() ) { + $name = $theme_info->display('Name'); + $stylesheet = $this->upgrader->result['destination_name']; + $template = $theme_info->get_template(); + + $preview_link = add_query_arg( array( + 'preview' => 1, + 'template' => urlencode( $template ), + 'stylesheet' => urlencode( $stylesheet ), + ), trailingslashit( home_url() ) ); + + $activate_link = add_query_arg( array( + 'action' => 'activate', + 'template' => urlencode( $template ), + 'stylesheet' => urlencode( $stylesheet ), + ), admin_url('themes.php') ); + $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet ); + + if ( get_stylesheet() == $stylesheet ) { + if ( current_user_can( 'edit_theme_options' ) ) + $update_actions['preview'] = '' . __('Customize') . ''; + } elseif ( current_user_can( 'switch_themes' ) ) { + $update_actions['preview'] = '' . __('Preview') . ''; + $update_actions['preview'] .= '' . __('Live Preview') . ''; + $update_actions['activate'] = '' . __('Activate') . ''; + } + + if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() ) + unset( $update_actions['preview'], $update_actions['activate'] ); + } + + $update_actions['themes_page'] = '' . __('Return to Themes page') . ''; + + $update_actions = apply_filters('update_theme_complete_actions', $update_actions, $this->theme); + if ( ! empty($update_actions) ) + $this->feedback(implode(' | ', (array)$update_actions)); + } +} + +/** + * Translation Upgrader Skin for WordPress Translation Upgrades. + * + * @package WordPress + * @subpackage Upgrader + * @since 3.7.0 + */ +class Language_Pack_Upgrader_Skin extends WP_Upgrader_Skin { + var $language_update = null; + var $done_header = false; + var $display_footer_actions = true; + + function __construct( $args = array() ) { + $defaults = array( 'url' => '', 'nonce' => '', 'title' => __( 'Update Translations' ), 'skip_header_footer' => false ); + $args = wp_parse_args( $args, $defaults ); + if ( $args['skip_header_footer'] ) { + $this->done_header = true; + $this->display_footer_actions = false; + } + parent::__construct( $args ); + } + + function before() { + $name = $this->upgrader->get_name_for_update( $this->language_update ); + + echo '
'; + + printf( '

' . __( 'Updating translations for %1$s (%2$s)…' ) . '

', $name, $this->language_update->language ); + } + + function error( $error ) { + echo '
'; + parent::error( $error ); + echo '
'; + } + + function after() { + echo '
'; + } + + function bulk_footer() { + $update_actions = array(); + $update_actions['updates_page'] = '' . __( 'Return to WordPress Updates' ) . ''; + $update_actions = apply_filters( 'update_translations_complete_actions', $update_actions ); + + if ( $update_actions && $this->display_footer_actions ) + $this->feedback( implode( ' | ', $update_actions ) ); + + parent::footer(); + } +} + +/** + * Upgrader Skin for Automatic WordPress Upgrades + * + * This skin is designed to be used when no output is intended, all output + * is captured and stored for the caller to process and log/email/discard. + * + * @package WordPress + * @subpackage Upgrader + * @since 3.7.0 + */ +class Automatic_Upgrader_Skin extends WP_Upgrader_Skin { + protected $messages = array(); + + function request_filesystem_credentials( $error = false, $context = '' ) { + if ( $context ) + $this->options['context'] = $context; + // TODO: fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version + // This will output a credentials form in event of failure, We don't want that, so just hide with a buffer + ob_start(); + $result = parent::request_filesystem_credentials( $error ); + ob_end_clean(); + return $result; + } + + function get_upgrade_messages() { + return $this->messages; + } + + function feedback( $data ) { + if ( is_wp_error( $data ) ) + $string = $data->get_error_message(); + else if ( is_array( $data ) ) + return; + else + $string = $data; + + if ( ! empty( $this->upgrader->strings[ $string ] ) ) + $string = $this->upgrader->strings[ $string ]; + + if ( strpos( $string, '%' ) !== false ) { + $args = func_get_args(); + $args = array_splice( $args, 1 ); + if ( ! empty( $args ) ) + $string = vsprintf( $string, $args ); + } + + $string = trim( $string ); + + // Only allow basic HTML in the messages, as it'll be used in emails/logs rather than direct browser output. + $string = wp_kses( $string, array( + 'a' => array( + 'href' => true + ), + 'br' => true, + 'em' => true, + 'strong' => true, + ) ); + + if ( empty( $string ) ) + return; + + $this->messages[] = $string; + } + + function header() { + ob_start(); + } + + function footer() { + $output = ob_get_contents(); + if ( ! empty( $output ) ) + $this->feedback( $output ); + ob_end_clean(); + } + + function bulk_header() {} + function bulk_footer() {} + function before() {} + function after() {} +} diff --git a/sources/wp-admin/includes/class-wp-upgrader.php b/sources/wp-admin/includes/class-wp-upgrader.php new file mode 100644 index 0000000..90b9658 --- /dev/null +++ b/sources/wp-admin/includes/class-wp-upgrader.php @@ -0,0 +1,2401 @@ +skin = new WP_Upgrader_Skin(); + else + $this->skin = $skin; + } + + function init() { + $this->skin->set_upgrader($this); + $this->generic_strings(); + } + + function generic_strings() { + $this->strings['bad_request'] = __('Invalid Data provided.'); + $this->strings['fs_unavailable'] = __('Could not access filesystem.'); + $this->strings['fs_error'] = __('Filesystem error.'); + $this->strings['fs_no_root_dir'] = __('Unable to locate WordPress Root directory.'); + $this->strings['fs_no_content_dir'] = __('Unable to locate WordPress Content directory (wp-content).'); + $this->strings['fs_no_plugins_dir'] = __('Unable to locate WordPress Plugin directory.'); + $this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress Theme directory.'); + /* translators: %s: directory name */ + $this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).'); + + $this->strings['download_failed'] = __('Download failed.'); + $this->strings['installing_package'] = __('Installing the latest version…'); + $this->strings['no_files'] = __('The package contains no files.'); + $this->strings['folder_exists'] = __('Destination folder already exists.'); + $this->strings['mkdir_failed'] = __('Could not create directory.'); + $this->strings['incompatible_archive'] = __('The package could not be installed.'); + + $this->strings['maintenance_start'] = __('Enabling Maintenance mode…'); + $this->strings['maintenance_end'] = __('Disabling Maintenance mode…'); + } + + function fs_connect( $directories = array() ) { + global $wp_filesystem; + + if ( false === ($credentials = $this->skin->request_filesystem_credentials()) ) + return false; + + if ( ! WP_Filesystem($credentials) ) { + $error = true; + if ( is_object($wp_filesystem) && $wp_filesystem->errors->get_error_code() ) + $error = $wp_filesystem->errors; + $this->skin->request_filesystem_credentials($error); //Failed to connect, Error and request again + return false; + } + + if ( ! is_object($wp_filesystem) ) + return new WP_Error('fs_unavailable', $this->strings['fs_unavailable'] ); + + if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) + return new WP_Error('fs_error', $this->strings['fs_error'], $wp_filesystem->errors); + + foreach ( (array)$directories as $dir ) { + switch ( $dir ) { + case ABSPATH: + if ( ! $wp_filesystem->abspath() ) + return new WP_Error('fs_no_root_dir', $this->strings['fs_no_root_dir']); + break; + case WP_CONTENT_DIR: + if ( ! $wp_filesystem->wp_content_dir() ) + return new WP_Error('fs_no_content_dir', $this->strings['fs_no_content_dir']); + break; + case WP_PLUGIN_DIR: + if ( ! $wp_filesystem->wp_plugins_dir() ) + return new WP_Error('fs_no_plugins_dir', $this->strings['fs_no_plugins_dir']); + break; + case get_theme_root(): + if ( ! $wp_filesystem->wp_themes_dir() ) + return new WP_Error('fs_no_themes_dir', $this->strings['fs_no_themes_dir']); + break; + default: + if ( ! $wp_filesystem->find_folder($dir) ) + return new WP_Error( 'fs_no_folder', sprintf( $this->strings['fs_no_folder'], esc_html( basename( $dir ) ) ) ); + break; + } + } + return true; + } //end fs_connect(); + + function download_package($package) { + + /** + * Filter whether to return the package. + * + * @since 3.7.0 + * + * @param bool $reply Whether to bail without returning the package. Default is false. + * @param string $package The package file name. + * @param object $this The WP_Upgrader instance. + */ + $reply = apply_filters( 'upgrader_pre_download', false, $package, $this ); + if ( false !== $reply ) + return $reply; + + if ( ! preg_match('!^(http|https|ftp)://!i', $package) && file_exists($package) ) //Local file or remote? + return $package; //must be a local file.. + + if ( empty($package) ) + return new WP_Error('no_package', $this->strings['no_package']); + + $this->skin->feedback('downloading_package', $package); + + $download_file = download_url($package); + + if ( is_wp_error($download_file) ) + return new WP_Error('download_failed', $this->strings['download_failed'], $download_file->get_error_message()); + + return $download_file; + } + + function unpack_package($package, $delete_package = true) { + global $wp_filesystem; + + $this->skin->feedback('unpack_package'); + + $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/'; + + //Clean up contents of upgrade directory beforehand. + $upgrade_files = $wp_filesystem->dirlist($upgrade_folder); + if ( !empty($upgrade_files) ) { + foreach ( $upgrade_files as $file ) + $wp_filesystem->delete($upgrade_folder . $file['name'], true); + } + + //We need a working directory + $working_dir = $upgrade_folder . basename($package, '.zip'); + + // Clean up working directory + if ( $wp_filesystem->is_dir($working_dir) ) + $wp_filesystem->delete($working_dir, true); + + // Unzip package to working directory + $result = unzip_file( $package, $working_dir ); + + // Once extracted, delete the package if required. + if ( $delete_package ) + unlink($package); + + if ( is_wp_error($result) ) { + $wp_filesystem->delete($working_dir, true); + if ( 'incompatible_archive' == $result->get_error_code() ) { + return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() ); + } + return $result; + } + + return $working_dir; + } + + function install_package( $args = array() ) { + global $wp_filesystem, $wp_theme_directories; + + $defaults = array( + 'source' => '', // Please always pass this + 'destination' => '', // and this + 'clear_destination' => false, + 'clear_working' => false, + 'abort_if_destination_exists' => true, + 'hook_extra' => array() + ); + + $args = wp_parse_args($args, $defaults); + extract($args); + + @set_time_limit( 300 ); + + if ( empty($source) || empty($destination) ) + return new WP_Error('bad_request', $this->strings['bad_request']); + + $this->skin->feedback('installing_package'); + + $res = apply_filters('upgrader_pre_install', true, $hook_extra); + if ( is_wp_error($res) ) + return $res; + + //Retain the Original source and destinations + $remote_source = $source; + $local_destination = $destination; + + $source_files = array_keys( $wp_filesystem->dirlist($remote_source) ); + $remote_destination = $wp_filesystem->find_folder($local_destination); + + //Locate which directory to copy to the new folder, This is based on the actual folder holding the files. + if ( 1 == count($source_files) && $wp_filesystem->is_dir( trailingslashit($source) . $source_files[0] . '/') ) //Only one folder? Then we want its contents. + $source = trailingslashit($source) . trailingslashit($source_files[0]); + elseif ( count($source_files) == 0 ) + return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files? + else //It's only a single file, the upgrader will use the foldername of this file as the destination folder. foldername is based on zip filename. + $source = trailingslashit($source); + + //Hook ability to change the source file location.. + $source = apply_filters('upgrader_source_selection', $source, $remote_source, $this); + if ( is_wp_error($source) ) + return $source; + + //Has the source location changed? If so, we need a new source_files list. + if ( $source !== $remote_source ) + $source_files = array_keys( $wp_filesystem->dirlist($source) ); + + // Protection against deleting files in any important base directories. + // Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the destination directory (WP_PLUGIN_DIR / wp-content/themes) + // intending to copy the directory into the directory, whilst they pass the source as the actual files to copy. + $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' ); + if ( is_array( $wp_theme_directories ) ) + $protected_directories = array_merge( $protected_directories, $wp_theme_directories ); + if ( in_array( $destination, $protected_directories ) ) { + $remote_destination = trailingslashit($remote_destination) . trailingslashit(basename($source)); + $destination = trailingslashit($destination) . trailingslashit(basename($source)); + } + + if ( $clear_destination ) { + //We're going to clear the destination if there's something there + $this->skin->feedback('remove_old'); + $removed = true; + if ( $wp_filesystem->exists($remote_destination) ) + $removed = $wp_filesystem->delete($remote_destination, true); + $removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $hook_extra); + + if ( is_wp_error($removed) ) + return $removed; + else if ( ! $removed ) + return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']); + } elseif ( $abort_if_destination_exists && $wp_filesystem->exists($remote_destination) ) { + //If we're not clearing the destination folder and something exists there already, Bail. + //But first check to see if there are actually any files in the folder. + $_files = $wp_filesystem->dirlist($remote_destination); + if ( ! empty($_files) ) { + $wp_filesystem->delete($remote_source, true); //Clear out the source files. + return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination ); + } + } + + //Create destination if needed + if ( !$wp_filesystem->exists($remote_destination) ) + if ( !$wp_filesystem->mkdir($remote_destination, FS_CHMOD_DIR) ) + return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination ); + + // Copy new version of item into place. + $result = copy_dir($source, $remote_destination); + if ( is_wp_error($result) ) { + if ( $clear_working ) + $wp_filesystem->delete($remote_source, true); + return $result; + } + + //Clear the Working folder? + if ( $clear_working ) + $wp_filesystem->delete($remote_source, true); + + $destination_name = basename( str_replace($local_destination, '', $destination) ); + if ( '.' == $destination_name ) + $destination_name = ''; + + $this->result = compact('local_source', 'source', 'source_name', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination', 'delete_source_dir'); + + $res = apply_filters('upgrader_post_install', true, $hook_extra, $this->result); + if ( is_wp_error($res) ) { + $this->result = $res; + return $res; + } + + //Bombard the calling function will all the info which we've just used. + return $this->result; + } + + function run($options) { + + $defaults = array( + 'package' => '', // Please always pass this. + 'destination' => '', // And this + 'clear_destination' => false, + 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please + 'clear_working' => true, + 'is_multi' => false, + 'hook_extra' => array() // Pass any extra $hook_extra args here, this will be passed to any hooked filters. + ); + + $options = wp_parse_args($options, $defaults); + extract($options); + + if ( ! $is_multi ) // call $this->header separately if running multiple times + $this->skin->header(); + + // Connect to the Filesystem first. + $res = $this->fs_connect( array(WP_CONTENT_DIR, $destination) ); + // Mainly for non-connected filesystem. + if ( ! $res ) { + if ( ! $is_multi ) + $this->skin->footer(); + return false; + } + + $this->skin->before(); + + if ( is_wp_error($res) ) { + $this->skin->error($res); + $this->skin->after(); + if ( ! $is_multi ) + $this->skin->footer(); + return $res; + } + + //Download the package (Note, This just returns the filename of the file if the package is a local file) + $download = $this->download_package( $package ); + if ( is_wp_error($download) ) { + $this->skin->error($download); + $this->skin->after(); + if ( ! $is_multi ) + $this->skin->footer(); + return $download; + } + + $delete_package = ($download != $package); // Do not delete a "local" file + + //Unzips the file into a temporary directory + $working_dir = $this->unpack_package( $download, $delete_package ); + if ( is_wp_error($working_dir) ) { + $this->skin->error($working_dir); + $this->skin->after(); + if ( ! $is_multi ) + $this->skin->footer(); + return $working_dir; + } + + //With the given options, this installs it to the destination directory. + $result = $this->install_package( array( + 'source' => $working_dir, + 'destination' => $destination, + 'clear_destination' => $clear_destination, + 'abort_if_destination_exists' => $abort_if_destination_exists, + 'clear_working' => $clear_working, + 'hook_extra' => $hook_extra + ) ); + + $this->skin->set_result($result); + if ( is_wp_error($result) ) { + $this->skin->error($result); + $this->skin->feedback('process_failed'); + } else { + //Install Succeeded + $this->skin->feedback('process_success'); + } + + $this->skin->after(); + + if ( ! $is_multi ) { + do_action( 'upgrader_process_complete', $this, $hook_extra ); + $this->skin->footer(); + } + + return $result; + } + + function maintenance_mode($enable = false) { + global $wp_filesystem; + $file = $wp_filesystem->abspath() . '.maintenance'; + if ( $enable ) { + $this->skin->feedback('maintenance_start'); + // Create maintenance file to signal that we are upgrading + $maintenance_string = ''; + $wp_filesystem->delete($file); + $wp_filesystem->put_contents($file, $maintenance_string, FS_CHMOD_FILE); + } else if ( !$enable && $wp_filesystem->exists($file) ) { + $this->skin->feedback('maintenance_end'); + $wp_filesystem->delete($file); + } + } + +} + +/** + * Plugin Upgrader class for WordPress Plugins, It is designed to upgrade/install plugins from a local zip, remote zip URL, or uploaded zip file. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Plugin_Upgrader extends WP_Upgrader { + + var $result; + var $bulk = false; + var $show_before = ''; + + function upgrade_strings() { + $this->strings['up_to_date'] = __('The plugin is at the latest version.'); + $this->strings['no_package'] = __('Update package not available.'); + $this->strings['downloading_package'] = __('Downloading update from %s…'); + $this->strings['unpack_package'] = __('Unpacking the update…'); + $this->strings['remove_old'] = __('Removing the old version of the plugin…'); + $this->strings['remove_old_failed'] = __('Could not remove the old plugin.'); + $this->strings['process_failed'] = __('Plugin update failed.'); + $this->strings['process_success'] = __('Plugin updated successfully.'); + } + + function install_strings() { + $this->strings['no_package'] = __('Install package not available.'); + $this->strings['downloading_package'] = __('Downloading install package from %s…'); + $this->strings['unpack_package'] = __('Unpacking the package…'); + $this->strings['installing_package'] = __('Installing the plugin…'); + $this->strings['no_files'] = __('The plugin contains no files.'); + $this->strings['process_failed'] = __('Plugin install failed.'); + $this->strings['process_success'] = __('Plugin installed successfully.'); + } + + function install( $package, $args = array() ) { + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->install_strings(); + + add_filter('upgrader_source_selection', array($this, 'check_package') ); + + $this->run( array( + 'package' => $package, + 'destination' => WP_PLUGIN_DIR, + 'clear_destination' => false, // Do not overwrite files. + 'clear_working' => true, + 'hook_extra' => array( + 'type' => 'plugin', + 'action' => 'install', + ) + ) ); + + remove_filter('upgrader_source_selection', array($this, 'check_package') ); + + if ( ! $this->result || is_wp_error($this->result) ) + return $this->result; + + // Force refresh of plugin update information + wp_clean_plugins_cache( $parsed_args['clear_update_cache'] ); + + return true; + } + + function upgrade( $plugin, $args = array() ) { + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->upgrade_strings(); + + $current = get_site_transient( 'update_plugins' ); + if ( !isset( $current->response[ $plugin ] ) ) { + $this->skin->before(); + $this->skin->set_result(false); + $this->skin->error('up_to_date'); + $this->skin->after(); + return false; + } + + // Get the URL to the zip file + $r = $current->response[ $plugin ]; + + add_filter('upgrader_pre_install', array($this, 'deactivate_plugin_before_upgrade'), 10, 2); + add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); + //'source_selection' => array($this, 'source_selection'), //there's a trac ticket to move up the directory for zip's which are made a bit differently, useful for non-.org plugins. + + $this->run( array( + 'package' => $r->package, + 'destination' => WP_PLUGIN_DIR, + 'clear_destination' => true, + 'clear_working' => true, + 'hook_extra' => array( + 'plugin' => $plugin, + 'type' => 'plugin', + 'action' => 'update', + ), + ) ); + + // Cleanup our hooks, in case something else does a upgrade on this connection. + remove_filter('upgrader_pre_install', array($this, 'deactivate_plugin_before_upgrade')); + remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); + + if ( ! $this->result || is_wp_error($this->result) ) + return $this->result; + + // Force refresh of plugin update information + wp_clean_plugins_cache( $parsed_args['clear_update_cache'] ); + + return true; + } + + function bulk_upgrade( $plugins, $args = array() ) { + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->bulk = true; + $this->upgrade_strings(); + + $current = get_site_transient( 'update_plugins' ); + + add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4); + + $this->skin->header(); + + // Connect to the Filesystem first. + $res = $this->fs_connect( array(WP_CONTENT_DIR, WP_PLUGIN_DIR) ); + if ( ! $res ) { + $this->skin->footer(); + return false; + } + + $this->skin->bulk_header(); + + // Only start maintenance mode if: + // - running Multisite and there are one or more plugins specified, OR + // - a plugin with an update available is currently active. + // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible. + $maintenance = ( is_multisite() && ! empty( $plugins ) ); + foreach ( $plugins as $plugin ) + $maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin] ) ); + if ( $maintenance ) + $this->maintenance_mode(true); + + $results = array(); + + $this->update_count = count($plugins); + $this->update_current = 0; + foreach ( $plugins as $plugin ) { + $this->update_current++; + $this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true); + + if ( !isset( $current->response[ $plugin ] ) ) { + $this->skin->set_result(true); + $this->skin->before(); + $this->skin->feedback('up_to_date'); + $this->skin->after(); + $results[$plugin] = true; + continue; + } + + // Get the URL to the zip file + $r = $current->response[ $plugin ]; + + $this->skin->plugin_active = is_plugin_active($plugin); + + $result = $this->run( array( + 'package' => $r->package, + 'destination' => WP_PLUGIN_DIR, + 'clear_destination' => true, + 'clear_working' => true, + 'is_multi' => true, + 'hook_extra' => array( + 'plugin' => $plugin + ) + ) ); + + $results[$plugin] = $this->result; + + // Prevent credentials auth screen from displaying multiple times + if ( false === $result ) + break; + } //end foreach $plugins + + $this->maintenance_mode(false); + + do_action( 'upgrader_process_complete', $this, array( + 'action' => 'update', + 'type' => 'plugin', + 'bulk' => true, + 'plugins' => $plugins, + ) ); + + $this->skin->bulk_footer(); + + $this->skin->footer(); + + // Cleanup our hooks, in case something else does a upgrade on this connection. + remove_filter('upgrader_clear_destination', array($this, 'delete_old_plugin')); + + // Force refresh of plugin update information + wp_clean_plugins_cache( $parsed_args['clear_update_cache'] ); + + return $results; + } + + function check_package($source) { + global $wp_filesystem; + + if ( is_wp_error($source) ) + return $source; + + $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source); + if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, lets not prevent installation. + return $source; + + // Check the folder contains at least 1 valid plugin. + $plugins_found = false; + foreach ( glob( $working_directory . '*.php' ) as $file ) { + $info = get_plugin_data($file, false, false); + if ( !empty( $info['Name'] ) ) { + $plugins_found = true; + break; + } + } + + if ( ! $plugins_found ) + return new WP_Error( 'incompatible_archive_no_plugins', $this->strings['incompatible_archive'], __( 'No valid plugins were found.' ) ); + + return $source; + } + + //return plugin info. + function plugin_info() { + if ( ! is_array($this->result) ) + return false; + if ( empty($this->result['destination_name']) ) + return false; + + $plugin = get_plugins('/' . $this->result['destination_name']); //Ensure to pass with leading slash + if ( empty($plugin) ) + return false; + + $pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list + + return $this->result['destination_name'] . '/' . $pluginfiles[0]; + } + + //Hooked to pre_install + function deactivate_plugin_before_upgrade($return, $plugin) { + + if ( is_wp_error($return) ) //Bypass. + return $return; + + // When in cron (background updates) don't deactivate the plugin, as we require a browser to reactivate it + if ( defined( 'DOING_CRON' ) && DOING_CRON ) + return $return; + + $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : ''; + if ( empty($plugin) ) + return new WP_Error('bad_request', $this->strings['bad_request']); + + if ( is_plugin_active($plugin) ) { + //Deactivate the plugin silently, Prevent deactivation hooks from running. + deactivate_plugins($plugin, true); + } + } + + //Hooked to upgrade_clear_destination + function delete_old_plugin($removed, $local_destination, $remote_destination, $plugin) { + global $wp_filesystem; + + if ( is_wp_error($removed) ) + return $removed; //Pass errors through. + + $plugin = isset($plugin['plugin']) ? $plugin['plugin'] : ''; + if ( empty($plugin) ) + return new WP_Error('bad_request', $this->strings['bad_request']); + + $plugins_dir = $wp_filesystem->wp_plugins_dir(); + $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin) ); + + if ( ! $wp_filesystem->exists($this_plugin_dir) ) //If it's already vanished. + return $removed; + + // If plugin is in its own directory, recursively delete the directory. + if ( strpos($plugin, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory separator AND that it's not the root plugin folder + $deleted = $wp_filesystem->delete($this_plugin_dir, true); + else + $deleted = $wp_filesystem->delete($plugins_dir . $plugin); + + if ( ! $deleted ) + return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']); + + return true; + } +} + +/** + * Theme Upgrader class for WordPress Themes, It is designed to upgrade/install themes from a local zip, remote zip URL, or uploaded zip file. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Theme_Upgrader extends WP_Upgrader { + + var $result; + var $bulk = false; + + function upgrade_strings() { + $this->strings['up_to_date'] = __('The theme is at the latest version.'); + $this->strings['no_package'] = __('Update package not available.'); + $this->strings['downloading_package'] = __('Downloading update from %s…'); + $this->strings['unpack_package'] = __('Unpacking the update…'); + $this->strings['remove_old'] = __('Removing the old version of the theme…'); + $this->strings['remove_old_failed'] = __('Could not remove the old theme.'); + $this->strings['process_failed'] = __('Theme update failed.'); + $this->strings['process_success'] = __('Theme updated successfully.'); + } + + function install_strings() { + $this->strings['no_package'] = __('Install package not available.'); + $this->strings['downloading_package'] = __('Downloading install package from %s…'); + $this->strings['unpack_package'] = __('Unpacking the package…'); + $this->strings['installing_package'] = __('Installing the theme…'); + $this->strings['no_files'] = __('The theme contains no files.'); + $this->strings['process_failed'] = __('Theme install failed.'); + $this->strings['process_success'] = __('Theme installed successfully.'); + /* translators: 1: theme name, 2: version */ + $this->strings['process_success_specific'] = __('Successfully installed the theme %1$s %2$s.'); + $this->strings['parent_theme_search'] = __('This theme requires a parent theme. Checking if it is installed…'); + /* translators: 1: theme name, 2: version */ + $this->strings['parent_theme_prepare_install'] = __('Preparing to install %1$s %2$s…'); + /* translators: 1: theme name, 2: version */ + $this->strings['parent_theme_currently_installed'] = __('The parent theme, %1$s %2$s, is currently installed.'); + /* translators: 1: theme name, 2: version */ + $this->strings['parent_theme_install_success'] = __('Successfully installed the parent theme, %1$s %2$s.'); + $this->strings['parent_theme_not_found'] = __('The parent theme could not be found. You will need to install the parent theme, %s, before you can use this child theme.'); + } + + function check_parent_theme_filter($install_result, $hook_extra, $child_result) { + // Check to see if we need to install a parent theme + $theme_info = $this->theme_info(); + + if ( ! $theme_info->parent() ) + return $install_result; + + $this->skin->feedback( 'parent_theme_search' ); + + if ( ! $theme_info->parent()->errors() ) { + $this->skin->feedback( 'parent_theme_currently_installed', $theme_info->parent()->display('Name'), $theme_info->parent()->display('Version') ); + // We already have the theme, fall through. + return $install_result; + } + + // We don't have the parent theme, lets install it + $api = themes_api('theme_information', array('slug' => $theme_info->get('Template'), 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth. + + if ( ! $api || is_wp_error($api) ) { + $this->skin->feedback( 'parent_theme_not_found', $theme_info->get('Template') ); + // Don't show activate or preview actions after install + add_filter('install_theme_complete_actions', array($this, 'hide_activate_preview_actions') ); + return $install_result; + } + + // Backup required data we're going to override: + $child_api = $this->skin->api; + $child_success_message = $this->strings['process_success']; + + // Override them + $this->skin->api = $api; + $this->strings['process_success_specific'] = $this->strings['parent_theme_install_success'];//, $api->name, $api->version); + + $this->skin->feedback('parent_theme_prepare_install', $api->name, $api->version); + + add_filter('install_theme_complete_actions', '__return_false', 999); // Don't show any actions after installing the theme. + + // Install the parent theme + $parent_result = $this->run( array( + 'package' => $api->download_link, + 'destination' => get_theme_root(), + 'clear_destination' => false, //Do not overwrite files. + 'clear_working' => true + ) ); + + if ( is_wp_error($parent_result) ) + add_filter('install_theme_complete_actions', array($this, 'hide_activate_preview_actions') ); + + // Start cleaning up after the parents installation + remove_filter('install_theme_complete_actions', '__return_false', 999); + + // Reset child's result and data + $this->result = $child_result; + $this->skin->api = $child_api; + $this->strings['process_success'] = $child_success_message; + + return $install_result; + } + + function hide_activate_preview_actions($actions) { + unset($actions['activate'], $actions['preview']); + return $actions; + } + + function install( $package, $args = array() ) { + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->install_strings(); + + add_filter('upgrader_source_selection', array($this, 'check_package') ); + add_filter('upgrader_post_install', array($this, 'check_parent_theme_filter'), 10, 3); + + $this->run( array( + 'package' => $package, + 'destination' => get_theme_root(), + 'clear_destination' => false, //Do not overwrite files. + 'clear_working' => true, + 'hook_extra' => array( + 'type' => 'theme', + 'action' => 'install', + ), + ) ); + + remove_filter('upgrader_source_selection', array($this, 'check_package') ); + remove_filter('upgrader_post_install', array($this, 'check_parent_theme_filter')); + + if ( ! $this->result || is_wp_error($this->result) ) + return $this->result; + + // Refresh the Theme Update information + wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); + + return true; + } + + function upgrade( $theme, $args = array() ) { + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->upgrade_strings(); + + // Is an update available? + $current = get_site_transient( 'update_themes' ); + if ( !isset( $current->response[ $theme ] ) ) { + $this->skin->before(); + $this->skin->set_result(false); + $this->skin->error('up_to_date'); + $this->skin->after(); + return false; + } + + $r = $current->response[ $theme ]; + + add_filter('upgrader_pre_install', array($this, 'current_before'), 10, 2); + add_filter('upgrader_post_install', array($this, 'current_after'), 10, 2); + add_filter('upgrader_clear_destination', array($this, 'delete_old_theme'), 10, 4); + + $this->run( array( + 'package' => $r['package'], + 'destination' => get_theme_root( $theme ), + 'clear_destination' => true, + 'clear_working' => true, + 'hook_extra' => array( + 'theme' => $theme, + 'type' => 'theme', + 'action' => 'update', + ), + ) ); + + remove_filter('upgrader_pre_install', array($this, 'current_before')); + remove_filter('upgrader_post_install', array($this, 'current_after')); + remove_filter('upgrader_clear_destination', array($this, 'delete_old_theme')); + + if ( ! $this->result || is_wp_error($this->result) ) + return $this->result; + + wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); + + return true; + } + + function bulk_upgrade( $themes, $args = array() ) { + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->bulk = true; + $this->upgrade_strings(); + + $current = get_site_transient( 'update_themes' ); + + add_filter('upgrader_pre_install', array($this, 'current_before'), 10, 2); + add_filter('upgrader_post_install', array($this, 'current_after'), 10, 2); + add_filter('upgrader_clear_destination', array($this, 'delete_old_theme'), 10, 4); + + $this->skin->header(); + + // Connect to the Filesystem first. + $res = $this->fs_connect( array(WP_CONTENT_DIR) ); + if ( ! $res ) { + $this->skin->footer(); + return false; + } + + $this->skin->bulk_header(); + + // Only start maintenance mode if: + // - running Multisite and there are one or more themes specified, OR + // - a theme with an update available is currently in use. + // @TODO: For multisite, maintenance mode should only kick in for individual sites if at all possible. + $maintenance = ( is_multisite() && ! empty( $themes ) ); + foreach ( $themes as $theme ) + $maintenance = $maintenance || $theme == get_stylesheet() || $theme == get_template(); + if ( $maintenance ) + $this->maintenance_mode(true); + + $results = array(); + + $this->update_count = count($themes); + $this->update_current = 0; + foreach ( $themes as $theme ) { + $this->update_current++; + + $this->skin->theme_info = $this->theme_info($theme); + + if ( !isset( $current->response[ $theme ] ) ) { + $this->skin->set_result(true); + $this->skin->before(); + $this->skin->feedback('up_to_date'); + $this->skin->after(); + $results[$theme] = true; + continue; + } + + // Get the URL to the zip file + $r = $current->response[ $theme ]; + + $result = $this->run( array( + 'package' => $r['package'], + 'destination' => get_theme_root( $theme ), + 'clear_destination' => true, + 'clear_working' => true, + 'hook_extra' => array( + 'theme' => $theme + ), + ) ); + + $results[$theme] = $this->result; + + // Prevent credentials auth screen from displaying multiple times + if ( false === $result ) + break; + } //end foreach $plugins + + $this->maintenance_mode(false); + + do_action( 'upgrader_process_complete', $this, array( + 'action' => 'update', + 'type' => 'plugin', + 'bulk' => true, + 'themes' => $themes, + ) ); + + $this->skin->bulk_footer(); + + $this->skin->footer(); + + // Cleanup our hooks, in case something else does a upgrade on this connection. + remove_filter('upgrader_pre_install', array($this, 'current_before')); + remove_filter('upgrader_post_install', array($this, 'current_after')); + remove_filter('upgrader_clear_destination', array($this, 'delete_old_theme')); + + // Refresh the Theme Update information + wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); + + return $results; + } + + function check_package($source) { + global $wp_filesystem; + + if ( is_wp_error($source) ) + return $source; + + // Check the folder contains a valid theme + $working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit(WP_CONTENT_DIR), $source); + if ( ! is_dir($working_directory) ) // Sanity check, if the above fails, lets not prevent installation. + return $source; + + // A proper archive should have a style.css file in the single subdirectory + if ( ! file_exists( $working_directory . 'style.css' ) ) + return new WP_Error( 'incompatible_archive_theme_no_style', $this->strings['incompatible_archive'], __( 'The theme is missing the style.css stylesheet.' ) ); + + $info = get_file_data( $working_directory . 'style.css', array( 'Name' => 'Theme Name', 'Template' => 'Template' ) ); + + if ( empty( $info['Name'] ) ) + return new WP_Error( 'incompatible_archive_theme_no_name', $this->strings['incompatible_archive'], __( "The style.css stylesheet doesn't contain a valid theme header." ) ); + + // If it's not a child theme, it must have at least an index.php to be legit. + if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) ) + return new WP_Error( 'incompatible_archive_theme_no_index', $this->strings['incompatible_archive'], __( 'The theme is missing the index.php file.' ) ); + + return $source; + } + + function current_before($return, $theme) { + + if ( is_wp_error($return) ) + return $return; + + $theme = isset($theme['theme']) ? $theme['theme'] : ''; + + if ( $theme != get_stylesheet() ) //If not current + return $return; + //Change to maintenance mode now. + if ( ! $this->bulk ) + $this->maintenance_mode(true); + + return $return; + } + + function current_after($return, $theme) { + if ( is_wp_error($return) ) + return $return; + + $theme = isset($theme['theme']) ? $theme['theme'] : ''; + + if ( $theme != get_stylesheet() ) // If not current + return $return; + + // Ensure stylesheet name hasn't changed after the upgrade: + if ( $theme == get_stylesheet() && $theme != $this->result['destination_name'] ) { + wp_clean_themes_cache(); + $stylesheet = $this->result['destination_name']; + switch_theme( $stylesheet ); + } + + //Time to remove maintenance mode + if ( ! $this->bulk ) + $this->maintenance_mode(false); + return $return; + } + + function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) { + global $wp_filesystem; + + if ( is_wp_error( $removed ) ) + return $removed; // Pass errors through. + + if ( ! isset( $theme['theme'] ) ) + return $removed; + + $theme = $theme['theme']; + $themes_dir = trailingslashit( $wp_filesystem->wp_themes_dir( $theme ) ); + if ( $wp_filesystem->exists( $themes_dir . $theme ) ) { + if ( ! $wp_filesystem->delete( $themes_dir . $theme, true ) ) + return false; + } + + return true; + } + + function theme_info($theme = null) { + + if ( empty($theme) ) { + if ( !empty($this->result['destination_name']) ) + $theme = $this->result['destination_name']; + else + return false; + } + return wp_get_theme( $theme ); + } + +} + +add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 ); + +/** + * Language pack upgrader, for updating translations of plugins, themes, and core. + * + * @package WordPress + * @subpackage Upgrader + * @since 3.7.0 + */ +class Language_Pack_Upgrader extends WP_Upgrader { + + var $result; + var $bulk = true; + + static function async_upgrade( $upgrader = false ) { + // Avoid recursion. + if ( $upgrader && $upgrader instanceof Language_Pack_Upgrader ) + return; + + // Nothing to do? + $language_updates = wp_get_translation_updates(); + if ( ! $language_updates ) + return; + + $skin = new Language_Pack_Upgrader_Skin( array( + 'skip_header_footer' => true, + ) ); + + $lp_upgrader = new Language_Pack_Upgrader( $skin ); + $lp_upgrader->upgrade(); + } + + function upgrade_strings() { + $this->strings['starting_upgrade'] = __( 'Some of your translations need updating. Sit tight for a few more seconds while we update them as well.' ); + $this->strings['up_to_date'] = __( 'The translation is up to date.' ); // We need to silently skip this case + $this->strings['no_package'] = __( 'Update package not available.' ); + $this->strings['downloading_package'] = __( 'Downloading translation from %s…' ); + $this->strings['unpack_package'] = __( 'Unpacking the update…' ); + $this->strings['process_failed'] = __( 'Translation update failed.' ); + $this->strings['process_success'] = __( 'Translation updated successfully.' ); + } + + function upgrade( $update = false, $args = array() ) { + if ( $update ) + $update = array( $update ); + $results = $this->bulk_upgrade( $update, $args ); + return $results[0]; + } + + function bulk_upgrade( $language_updates = array(), $args = array() ) { + global $wp_filesystem; + + $defaults = array( + 'clear_update_cache' => true, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->upgrade_strings(); + + if ( ! $language_updates ) + $language_updates = wp_get_translation_updates(); + + if ( empty( $language_updates ) ) { + $this->skin->header(); + $this->skin->before(); + $this->skin->set_result( true ); + $this->skin->feedback( 'up_to_date' ); + $this->skin->after(); + $this->skin->bulk_footer(); + $this->skin->footer(); + return true; + } + + if ( 'upgrader_process_complete' == current_filter() ) + $this->skin->feedback( 'starting_upgrade' ); + + add_filter( 'upgrader_source_selection', array( &$this, 'check_package' ), 10, 3 ); + + $this->skin->header(); + + // Connect to the Filesystem first. + $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_LANG_DIR ) ); + if ( ! $res ) { + $this->skin->footer(); + return false; + } + + $results = array(); + + $this->update_count = count( $language_updates ); + $this->update_current = 0; + + // The filesystem's mkdir() is not recursive. Make sure WP_LANG_DIR exists, + // as we then may need to create a /plugins or /themes directory inside of it. + $remote_destination = $wp_filesystem->find_folder( WP_LANG_DIR ); + if ( ! $wp_filesystem->exists( $remote_destination ) ) + if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) + return new WP_Error( 'mkdir_failed_lang_dir', $this->strings['mkdir_failed'], $remote_destination ); + + foreach ( $language_updates as $language_update ) { + + $this->skin->language_update = $language_update; + + $destination = WP_LANG_DIR; + if ( 'plugin' == $language_update->type ) + $destination .= '/plugins'; + elseif ( 'theme' == $language_update->type ) + $destination .= '/themes'; + + $this->update_current++; + + $options = array( + 'package' => $language_update->package, + 'destination' => $destination, + 'clear_destination' => false, + 'abort_if_destination_exists' => false, // We expect the destination to exist. + 'clear_working' => true, + 'is_multi' => true, + 'hook_extra' => array( + 'language_update_type' => $language_update->type, + 'language_update' => $language_update, + ) + ); + + $result = $this->run( $options ); + + $results[] = $this->result; + + // Prevent credentials auth screen from displaying multiple times. + if ( false === $result ) + break; + } + + $this->skin->bulk_footer(); + + $this->skin->footer(); + + // Clean up our hooks, in case something else does an upgrade on this connection. + remove_filter( 'upgrader_source_selection', array( &$this, 'check_package' ), 10, 2 ); + + if ( $parsed_args['clear_update_cache'] ) { + wp_clean_themes_cache( true ); + wp_clean_plugins_cache( true ); + delete_site_transient( 'update_core' ); + } + + return $results; + } + + function check_package( $source, $remote_source ) { + global $wp_filesystem; + + if ( is_wp_error( $source ) ) + return $source; + + // Check that the folder contains a valid language. + $files = $wp_filesystem->dirlist( $remote_source ); + + // Check to see if a .po and .mo exist in the folder. + $po = $mo = false; + foreach ( (array) $files as $file => $filedata ) { + if ( '.po' == substr( $file, -3 ) ) + $po = true; + elseif ( '.mo' == substr( $file, -3 ) ) + $mo = true; + } + + if ( ! $mo || ! $po ) + return new WP_Error( 'incompatible_archive_pomo', $this->strings['incompatible_archive'], + __( 'The language pack is missing either the .po or .mo files.' ) ); + + return $source; + } + + function get_name_for_update( $update ) { + switch ( $update->type ) { + case 'core': + return 'WordPress'; // Not translated + break; + case 'theme': + $theme = wp_get_theme( $update->slug ); + if ( $theme->exists() ) + return $theme->Get( 'Name' ); + break; + case 'plugin': + $plugin_data = get_plugins( '/' . $update->slug ); + $plugin_data = array_shift( $plugin_data ); + if ( $plugin_data ) + return $plugin_data['Name']; + break; + } + return ''; + } + +} + +/** + * Core Upgrader class for WordPress. It allows for WordPress to upgrade itself in combination with the wp-admin/includes/update-core.php file + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class Core_Upgrader extends WP_Upgrader { + + function upgrade_strings() { + $this->strings['up_to_date'] = __('WordPress is at the latest version.'); + $this->strings['no_package'] = __('Update package not available.'); + $this->strings['downloading_package'] = __('Downloading update from %s…'); + $this->strings['unpack_package'] = __('Unpacking the update…'); + $this->strings['copy_failed'] = __('Could not copy files.'); + $this->strings['copy_failed_space'] = __('Could not copy files. You may have run out of disk space.' ); + $this->strings['start_rollback'] = __( 'Attempting to roll back to previous version.' ); + $this->strings['rollback_was_required'] = __( 'Due to an error during updating, WordPress has rolled back to your previous version.' ); + } + + function upgrade( $current, $args = array() ) { + global $wp_filesystem, $wp_version; + + $start_time = time(); + + $defaults = array( + 'pre_check_md5' => true, + 'attempt_rollback' => false, + 'do_rollback' => false, + ); + $parsed_args = wp_parse_args( $args, $defaults ); + + $this->init(); + $this->upgrade_strings(); + + // Is an update available? + if ( !isset( $current->response ) || $current->response == 'latest' ) + return new WP_Error('up_to_date', $this->strings['up_to_date']); + + $res = $this->fs_connect( array(ABSPATH, WP_CONTENT_DIR) ); + if ( is_wp_error($res) ) + return $res; + + $wp_dir = trailingslashit($wp_filesystem->abspath()); + + $partial = true; + if ( $parsed_args['do_rollback'] ) + $partial = false; + elseif ( $parsed_args['pre_check_md5'] && ! $this->check_files() ) + $partial = false; + + // If partial update is returned from the API, use that, unless we're doing a reinstall. + // If we cross the new_bundled version number, then use the new_bundled zip. + // Don't though if the constant is set to skip bundled items. + // If the API returns a no_content zip, go with it. Finally, default to the full zip. + if ( $parsed_args['do_rollback'] && $current->packages->rollback ) + $to_download = 'rollback'; + elseif ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version && $partial ) + $to_download = 'partial'; + elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' ) + && ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) ) + $to_download = 'new_bundled'; + elseif ( $current->packages->no_content ) + $to_download = 'no_content'; + else + $to_download = 'full'; + + $download = $this->download_package( $current->packages->$to_download ); + if ( is_wp_error($download) ) + return $download; + + $working_dir = $this->unpack_package( $download ); + if ( is_wp_error($working_dir) ) + return $working_dir; + + // Copy update-core.php from the new version into place. + if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) { + $wp_filesystem->delete($working_dir, true); + return new WP_Error( 'copy_failed_for_update_core_file', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), 'wp-admin/includes/update-core.php' ); + } + $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE); + + require_once( ABSPATH . 'wp-admin/includes/update-core.php' ); + + if ( ! function_exists( 'update_core' ) ) + return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] ); + + $result = update_core( $working_dir, $wp_dir ); + + // In the event of an issue, we may be able to roll back. + if ( $parsed_args['attempt_rollback'] && $current->packages->rollback && ! $parsed_args['do_rollback'] ) { + $try_rollback = false; + if ( is_wp_error( $result ) ) { + $error_code = $result->get_error_code(); + // Not all errors are equal. These codes are critical: copy_failed__copy_dir, + // mkdir_failed__copy_dir, copy_failed__copy_dir_retry, and disk_full. + // do_rollback allows for update_core() to trigger a rollback if needed. + if ( false !== strpos( $error_code, 'do_rollback' ) ) + $try_rollback = true; + elseif ( false !== strpos( $error_code, '__copy_dir' ) ) + $try_rollback = true; + elseif ( 'disk_full' === $error_code ) + $try_rollback = true; + } + + if ( $try_rollback ) { + apply_filters( 'update_feedback', $result ); + apply_filters( 'update_feedback', $this->strings['start_rollback'] ); + + $rollback_result = $this->upgrade( $current, array_merge( $parsed_args, array( 'do_rollback' => true ) ) ); + + $original_result = $result; + $result = new WP_Error( 'rollback_was_required', $this->strings['rollback_was_required'], (object) array( 'update' => $original_result, 'rollback' => $rollback_result ) ); + } + } + + do_action( 'upgrader_process_complete', $this, array( 'action' => 'update', 'type' => 'core' ) ); + + // Clear the current updates + delete_site_transient( 'update_core' ); + + if ( ! $parsed_args['do_rollback'] ) { + $stats = array( + 'update_type' => $current->response, + 'success' => true, + 'fs_method' => $wp_filesystem->method, + 'fs_method_forced' => defined( 'FS_METHOD' ) || has_filter( 'filesystem_method' ), + 'time_taken' => time() - $start_time, + 'attempted' => $current->version, + ); + + if ( is_wp_error( $result ) ) { + $stats['success'] = false; + // Did a rollback occur? + if ( ! empty( $try_rollback ) ) { + $stats['error_code'] = $original_result->get_error_code(); + $stats['error_data'] = $original_result->get_error_data(); + // Was the rollback successful? If not, collect its error too. + $stats['rollback'] = ! is_wp_error( $rollback_result ); + if ( is_wp_error( $rollback_result ) ) { + $stats['rollback_code'] = $rollback_result->get_error_code(); + $stats['rollback_data'] = $rollback_result->get_error_data(); + } + } else { + $stats['error_code'] = $result->get_error_code(); + $stats['error_data'] = $result->get_error_data(); + } + } + + wp_version_check( $stats ); + } + + return $result; + } + + // Determines if this WordPress Core version should update to $offered_ver or not + static function should_update_to_version( $offered_ver /* x.y.z */ ) { + include ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z + + $current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version ), 0, 2 ) ); // x.y + $new_branch = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y + $current_is_development_version = (bool) strpos( $wp_version, '-' ); + + // Defaults: + $upgrade_dev = true; + $upgrade_minor = true; + $upgrade_major = false; + + // WP_AUTO_UPDATE_CORE = true (all), 'minor', false. + if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) { + if ( false === WP_AUTO_UPDATE_CORE ) { + // Defaults to turned off, unless a filter allows it + $upgrade_dev = $upgrade_minor = $upgrade_major = false; + } elseif ( true === WP_AUTO_UPDATE_CORE ) { + // ALL updates for core + $upgrade_dev = $upgrade_minor = $upgrade_major = true; + } elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) { + // Only minor updates for core + $upgrade_dev = $upgrade_major = false; + $upgrade_minor = true; + } + } + + // 1: If we're already on that version, not much point in updating? + if ( $offered_ver == $wp_version ) + return false; + + // 2: If we're running a newer version, that's a nope + if ( version_compare( $wp_version, $offered_ver, '>' ) ) + return false; + + $failure_data = get_site_option( 'auto_core_update_failed' ); + if ( $failure_data ) { + // If this was a critical update failure, cannot update. + if ( ! empty( $failure_data['critical'] ) ) + return false; + + // Don't claim we can update on update-core.php if we have a non-critical failure logged. + if ( $wp_version == $failure_data['current'] && false !== strpos( $offered_ver, '.1.next.minor' ) ) + return false; + + // Cannot update if we're retrying the same A to B update that caused a non-critical failure. + // Some non-critical failures do allow retries, like download_failed. + // 3.7.1 => 3.7.2 resulted in files_not_writable, if we are still on 3.7.1 and still trying to update to 3.7.2. + if ( empty( $failure_data['retry'] ) && $wp_version == $failure_data['current'] && $offered_ver == $failure_data['attempted'] ) + return false; + } + + // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2 + if ( $current_is_development_version ) { + if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) ) + return false; + // else fall through to minor + major branches below + } + + // 4: Minor In-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4) + if ( $current_branch == $new_branch ) + return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor ); + + // 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1) + if ( version_compare( $new_branch, $current_branch, '>' ) ) + return apply_filters( 'allow_major_auto_core_updates', $upgrade_major ); + + // If we're not sure, we don't want it + return false; + } + + function check_files() { + global $wp_version, $wp_local_package; + + $checksums = get_core_checksums( $wp_version, isset( $wp_local_package ) ? $wp_local_package : 'en_US' ); + + if ( ! is_array( $checksums ) ) + return false; + + foreach ( $checksums as $file => $checksum ) { + // Skip files which get updated + if ( 'wp-content' == substr( $file, 0, 10 ) ) + continue; + if ( ! file_exists( ABSPATH . $file ) || md5_file( ABSPATH . $file ) !== $checksum ) + return false; + } + + return true; + } +} + +/** + * Upgrade Skin helper for File uploads. This class handles the upload process and passes it as if it's a local file to the Upgrade/Installer functions. + * + * @package WordPress + * @subpackage Upgrader + * @since 2.8.0 + */ +class File_Upload_Upgrader { + var $package; + var $filename; + var $id = 0; + + function __construct($form, $urlholder) { + + if ( empty($_FILES[$form]['name']) && empty($_GET[$urlholder]) ) + wp_die(__('Please select a file')); + + //Handle a newly uploaded file, Else assume it's already been uploaded + if ( ! empty($_FILES) ) { + $overrides = array( 'test_form' => false, 'test_type' => false ); + $file = wp_handle_upload( $_FILES[$form], $overrides ); + + if ( isset( $file['error'] ) ) + wp_die( $file['error'] ); + + $this->filename = $_FILES[$form]['name']; + $this->package = $file['file']; + + // Construct the object array + $object = array( + 'post_title' => $this->filename, + 'post_content' => $file['url'], + 'post_mime_type' => $file['type'], + 'guid' => $file['url'], + 'context' => 'upgrader', + 'post_status' => 'private' + ); + + // Save the data + $this->id = wp_insert_attachment( $object, $file['file'] ); + + // schedule a cleanup for 2 hours from now in case of failed install + wp_schedule_single_event( time() + 7200, 'upgrader_scheduled_cleanup', array( $this->id ) ); + + } elseif ( is_numeric( $_GET[$urlholder] ) ) { + // Numeric Package = previously uploaded file, see above. + $this->id = (int) $_GET[$urlholder]; + $attachment = get_post( $this->id ); + if ( empty($attachment) ) + wp_die(__('Please select a file')); + + $this->filename = $attachment->post_title; + $this->package = get_attached_file( $attachment->ID ); + } else { + // Else, It's set to something, Back compat for plugins using the old (pre-3.3) File_Uploader handler. + if ( ! ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) ) + wp_die( $uploads['error'] ); + + $this->filename = $_GET[$urlholder]; + $this->package = $uploads['basedir'] . '/' . $this->filename; + } + } + + function cleanup() { + if ( $this->id ) + wp_delete_attachment( $this->id ); + + elseif ( file_exists( $this->package ) ) + return @unlink( $this->package ); + + return true; + } +} + +/** + * The WordPress automatic background updater. + * + * @package WordPress + * @subpackage Upgrader + * @since 3.7.0 + */ +class WP_Automatic_Updater { + + /** + * Tracks update results during processing. + * + * @var array + */ + protected $update_results = array(); + + /** + * Whether the entire automatic updater is disabled. + * + * @since 3.7.0 + */ + public function is_disabled() { + // Background updates are disabled if you don't want file changes. + if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) + return true; + + if ( defined( 'WP_INSTALLING' ) ) + return true; + + // More fine grained control can be done through the WP_AUTO_UPDATE_CORE constant and filters. + $disabled = defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED; + + /** + * Filter whether to entirely disable background updates. + * + * There are more fine-grained filters and controls for selective disabling. + * This filter parallels the AUTOMATIC_UPDATER_DISABLED constant in name. + * + * This also disables update notification emails. That may change in the future. + * + * @since 3.7.0 + * @param bool $disabled Whether the updater should be disabled. + */ + return apply_filters( 'automatic_updater_disabled', $disabled ); + } + + /** + * Check for version control checkouts. + * + * Checks for Subversion, Git, Mercurial, and Bazaar. It recursively looks up the + * filesystem to the top of the drive, erring on the side of detecting a VCS + * checkout somewhere. + * + * ABSPATH is always checked in addition to whatever $context is (which may be the + * wp-content directory, for example). The underlying assumption is that if you are + * using version control *anywhere*, then you should be making decisions for + * how things get updated. + * + * @since 3.7.0 + * + * @param string $context The filesystem path to check, in addition to ABSPATH. + */ + public function is_vcs_checkout( $context ) { + $context_dirs = array( untrailingslashit( $context ) ); + if ( $context !== ABSPATH ) + $context_dirs[] = untrailingslashit( ABSPATH ); + + $vcs_dirs = array( '.svn', '.git', '.hg', '.bzr' ); + $check_dirs = array(); + + foreach ( $context_dirs as $context_dir ) { + // Walk up from $context_dir to the root. + do { + $check_dirs[] = $context_dir; + + // Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here. + if ( $context_dir == dirname( $context_dir ) ) + break; + + // Continue one level at a time. + } while ( $context_dir = dirname( $context_dir ) ); + } + + $check_dirs = array_unique( $check_dirs ); + + // Search all directories we've found for evidence of version control. + foreach ( $vcs_dirs as $vcs_dir ) { + foreach ( $check_dirs as $check_dir ) { + if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) + break 2; + } + } + + /** + * Filter whether the automatic updater should consider a filesystem location to be potentially + * managed by a version control system. + * + * @since 3.7.0 + * + * @param bool $checkout Whether a VCS checkout was discovered at $context or ABSPATH, or anywhere higher. + * @param string $context The filesystem context (a path) against which filesystem status should be checked. + */ + return apply_filters( 'automatic_updates_is_vcs_checkout', $checkout, $context ); + } + + /** + * Tests to see if we can and should update a specific item. + * + * @since 3.7.0 + * + * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'. + * @param object $item The update offer. + * @param string $context The filesystem context (a path) against which filesystem access and status + * should be checked. + */ + public function should_update( $type, $item, $context ) { + // Used to see if WP_Filesystem is set up to allow unattended updates. + $skin = new Automatic_Upgrader_Skin; + + if ( $this->is_disabled() ) + return false; + + // If we can't do an auto core update, we may still be able to email the user. + if ( ! $skin->request_filesystem_credentials( false, $context ) || $this->is_vcs_checkout( $context ) ) { + if ( 'core' == $type ) + $this->send_core_update_notification_email( $item ); + return false; + } + + // Next up, is this an item we can update? + if ( 'core' == $type ) + $update = Core_Upgrader::should_update_to_version( $item->current ); + else + $update = ! empty( $item->autoupdate ); + + /** + * Filter whether to automatically update core, a plugin, a theme, or a language. + * + * The dynamic portion of the hook name, $type, refers to the type of update + * being checked. Can be 'core', 'theme', 'plugin', or 'translation'. + * + * Generally speaking, plugins, themes, and major core versions are not updated by default, + * while translations and minor and development versions for core are updated by default. + * + * See the filters allow_dev_auto_core_updates, allow_minor_auto_core_updates, and + * allow_major_auto_core_updates more straightforward filters to adjust core updates. + * + * @since 3.7.0 + * + * @param bool $update Whether to update. + * @param object $item The update offer. + */ + $update = apply_filters( 'auto_update_' . $type, $update, $item ); + + if ( ! $update ) { + if ( 'core' == $type ) + $this->send_core_update_notification_email( $item ); + return false; + } + + // If it's a core update, are we actually compatible with its requirements? + if ( 'core' == $type ) { + global $wpdb; + + $php_compat = version_compare( phpversion(), $item->php_version, '>=' ); + if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) + $mysql_compat = true; + else + $mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' ); + + if ( ! $php_compat || ! $mysql_compat ) + return false; + } + + return true; + } + + /** + * Notifies an administrator of a core update. + * + * @since 3.7.0 + * + * @param object $item The update offer. + */ + protected function send_core_update_notification_email( $item ) { + $notify = true; + $notified = get_site_option( 'auto_core_update_notified' ); + + // Don't notify if we've already notified the same email address of the same version. + if ( $notified && $notified['email'] == get_site_option( 'admin_email' ) && $notified['version'] == $item->current ) + return false; + + // See if we need to notify users of a core update. + $notify = ! empty( $item->notify_email ); + + /** + * Whether to notify the site administrator of a new core update. + * + * By default, administrators are notified when the update offer received from WordPress.org + * sets a particular flag. This allows for discretion in if and when to notify. + * + * This filter only fires once per release -- if the same email address was already + * notified of the same new version, we won't repeatedly email the administrator. + * + * This filter is also used on about.php to check if a plugin has disabled these notifications. + * + * @since 3.7.0 + * + * @param bool $notify Whether the site administrator is notified. + * @param object $item The update offer. + */ + if ( ! apply_filters( 'send_core_update_notification_email', $notify, $item ) ) + return false; + + $this->send_email( 'manual', $item ); + return true; + } + + /** + * Update an item, if appropriate. + * + * @since 3.7.0 + * + * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'. + * @param object $item The update offer. + */ + public function update( $type, $item ) { + $skin = new Automatic_Upgrader_Skin; + + switch ( $type ) { + case 'core': + // The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter. + add_filter( 'update_feedback', array( $skin, 'feedback' ) ); + $upgrader = new Core_Upgrader( $skin ); + $context = ABSPATH; + break; + case 'plugin': + $upgrader = new Plugin_Upgrader( $skin ); + $context = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR + break; + case 'theme': + $upgrader = new Theme_Upgrader( $skin ); + $context = get_theme_root( $item ); + break; + case 'translation': + $upgrader = new Language_Pack_Upgrader( $skin ); + $context = WP_CONTENT_DIR; // WP_LANG_DIR; + break; + } + + // Determine whether we can and should perform this update. + if ( ! $this->should_update( $type, $item, $context ) ) + return false; + + switch ( $type ) { + case 'core': + $skin->feedback( __( 'Updating to WordPress %s' ), $item->version ); + $item_name = sprintf( __( 'WordPress %s' ), $item->version ); + break; + case 'theme': + $theme = wp_get_theme( $item ); + $item_name = $theme->Get( 'Name' ); + $skin->feedback( __( 'Updating theme: %s' ), $item_name ); + break; + case 'plugin': + $plugin_data = get_plugin_data( $context . '/' . $item ); + $item_name = $plugin_data['Name']; + $skin->feedback( __( 'Updating plugin: %s' ), $item_name ); + break; + case 'translation': + $language_item_name = $upgrader->get_name_for_update( $item ); + $item_name = sprintf( __( 'Translations for %s' ), $language_item_name ); + $skin->feedback( sprintf( __( 'Updating translations for %1$s (%2$s)…' ), $language_item_name, $item->language ) ); + break; + } + + // Boom, This sites about to get a whole new splash of paint! + $upgrade_result = $upgrader->upgrade( $item, array( + 'clear_update_cache' => false, + 'pre_check_md5' => false, /* always use partial builds if possible for core updates */ + 'attempt_rollback' => true, /* only available for core updates */ + ) ); + + // Core doesn't output this, so lets append it so we don't get confused + if ( 'core' == $type ) { + if ( is_wp_error( $upgrade_result ) ) { + $skin->error( __( 'Installation Failed' ), $upgrade_result ); + } else { + $skin->feedback( __( 'WordPress updated successfully' ) ); + } + } + + $this->update_results[ $type ][] = (object) array( + 'item' => $item, + 'result' => $upgrade_result, + 'name' => $item_name, + 'messages' => $skin->get_upgrade_messages() + ); + + return $upgrade_result; + } + + /** + * Kicks off the background update process, looping through all pending updates. + * + * @since 3.7.0 + */ + public function run() { + global $wpdb, $wp_version; + + if ( $this->is_disabled() ) + return; + + if ( ! is_main_network() || ! is_main_site() ) + return; + + $lock_name = 'auto_updater.lock'; + + // Try to lock + $lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_name, time() ) ); + + if ( ! $lock_result ) { + $lock_result = get_option( $lock_name ); + + // If we couldn't create a lock, and there isn't a lock, bail + if ( ! $lock_result ) + return; + + // Check to see if the lock is still valid + if ( $lock_result > ( time() - HOUR_IN_SECONDS ) ) + return; + } + + // Update the lock, as by this point we've definately got a lock, just need to fire the actions + update_option( $lock_name, time() ); + + // Don't automatically run these thins, as we'll handle it ourselves + remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 ); + remove_action( 'upgrader_process_complete', 'wp_version_check' ); + remove_action( 'upgrader_process_complete', 'wp_update_plugins' ); + remove_action( 'upgrader_process_complete', 'wp_update_themes' ); + + // Next, Plugins + wp_update_plugins(); // Check for Plugin updates + $plugin_updates = get_site_transient( 'update_plugins' ); + if ( $plugin_updates && !empty( $plugin_updates->response ) ) { + foreach ( array_keys( $plugin_updates->response ) as $plugin ) { + $this->update( 'plugin', $plugin ); + } + // Force refresh of plugin update information + wp_clean_plugins_cache(); + } + + // Next, those themes we all love + wp_update_themes(); // Check for Theme updates + $theme_updates = get_site_transient( 'update_themes' ); + if ( $theme_updates && !empty( $theme_updates->response ) ) { + foreach ( array_keys( $theme_updates->response ) as $theme ) { + $this->update( 'theme', $theme ); + } + // Force refresh of theme update information + wp_clean_themes_cache(); + } + + // Next, Process any core update + wp_version_check(); // Check for Core updates + $core_update = find_core_auto_update(); + + if ( $core_update ) + $this->update( 'core', $core_update ); + + // Clean up, and check for any pending translations + // (Core_Upgrader checks for core updates) + wp_update_themes(); // Check for Theme updates + wp_update_plugins(); // Check for Plugin updates + + // Finally, Process any new translations + $language_updates = wp_get_translation_updates(); + if ( $language_updates ) { + foreach ( $language_updates as $update ) { + $this->update( 'translation', $update ); + } + + // Clear existing caches + wp_clean_plugins_cache(); + wp_clean_themes_cache(); + delete_site_transient( 'update_core' ); + + wp_version_check(); // check for Core updates + wp_update_themes(); // Check for Theme updates + wp_update_plugins(); // Check for Plugin updates + } + + // Send debugging email to all development installs. + if ( ! empty( $this->update_results ) ) { + $development_version = false !== strpos( $wp_version, '-' ); + /** + * Filter whether to send a debugging email for each automatic background update. + * + * @since 3.7.0 + * @param bool $development_version By default, emails are sent if the install is a development version. + * Return false to avoid the email. + */ + if ( apply_filters( 'automatic_updates_send_debug_email', $development_version ) ) + $this->send_debug_email(); + + if ( ! empty( $this->update_results['core'] ) ) + $this->after_core_update( $this->update_results['core'][0] ); + } + + // Clear the lock + delete_option( $lock_name ); + } + + /** + * If we tried to perform a core update, check if we should send an email, + * and if we need to avoid processing future updates. + * + * @param object $update_result The result of the core update. Includes the update offer and result. + */ + protected function after_core_update( $update_result ) { + global $wp_version; + + $core_update = $update_result->item; + $result = $update_result->result; + + if ( ! is_wp_error( $result ) ) { + $this->send_email( 'success', $core_update ); + return; + } + + $error_code = $result->get_error_code(); + + // Any of these WP_Error codes are critical failures, as in they occurred after we started to copy core files. + // We should not try to perform a background update again until there is a successful one-click update performed by the user. + $critical = false; + if ( $error_code === 'disk_full' || false !== strpos( $error_code, '__copy_dir' ) ) { + $critical = true; + } elseif ( $error_code === 'rollback_was_required' && is_wp_error( $result->get_error_data()->rollback ) ) { + // A rollback is only critical if it failed too. + $critical = true; + $rollback_result = $result->get_error_data()->rollback; + } elseif ( false !== strpos( $error_code, 'do_rollback' ) ) { + $critical = true; + } + + if ( $critical ) { + $critical_data = array( + 'attempted' => $core_update->current, + 'current' => $wp_version, + 'error_code' => $error_code, + 'error_data' => $result->get_error_data(), + 'timestamp' => time(), + 'critical' => true, + ); + if ( isset( $rollback_result ) ) { + $critical_data['rollback_code'] = $rollback_result->get_error_code(); + $critical_data['rollback_data'] = $rollback_result->get_error_data(); + } + update_site_option( 'auto_core_update_failed', $critical_data ); + $this->send_email( 'critical', $core_update, $result ); + return; + } + + /* + * Any other WP_Error code (like download_failed or files_not_writable) occurs before + * we tried to copy over core files. Thus, the failures are early and graceful. + * + * We should avoid trying to perform a background update again for the same version. + * But we can try again if another version is released. + * + * For certain 'transient' failures, like download_failed, we should allow retries. + * In fact, let's schedule a special update for an hour from now. (It's possible + * the issue could actually be on WordPress.org's side.) If that one fails, then email. + */ + $send = true; + $transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro' ); + if ( in_array( $error_code, $transient_failures ) && ! get_site_option( 'auto_core_update_failed' ) ) { + wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_maybe_auto_update' ); + $send = false; + } + + $n = get_site_option( 'auto_core_update_notified' ); + // Don't notify if we've already notified the same email address of the same version of the same notification type. + if ( $n && 'fail' == $n['type'] && $n['email'] == get_site_option( 'admin_email' ) && $n['version'] == $core_update->current ) + $send = false; + + update_site_option( 'auto_core_update_failed', array( + 'attempted' => $core_update->current, + 'current' => $wp_version, + 'error_code' => $error_code, + 'error_data' => $result->get_error_data(), + 'timestamp' => time(), + 'retry' => in_array( $error_code, $transient_failures ), + ) ); + + if ( $send ) + $this->send_email( 'fail', $core_update, $result ); + } + + /** + * Sends an email upon the completion or failure of a background core update. + * + * @since 3.7.0 + * + * @param string $type The type of email to send. Can be one of 'success', 'fail', 'manual', 'critical'. + * @param object $core_update The update offer that was attempted. + * @param mixed $result Optional. The result for the core update. Can be WP_Error. + */ + protected function send_email( $type, $core_update, $result = null ) { + update_site_option( 'auto_core_update_notified', array( + 'type' => $type, + 'email' => get_site_option( 'admin_email' ), + 'version' => $core_update->current, + 'timestamp' => time(), + ) ); + + $next_user_core_update = get_preferred_from_update_core(); + // If the update transient is empty, use the update we just performed + if ( ! $next_user_core_update ) + $next_user_core_update = $core_update; + $newer_version_available = ( 'upgrade' == $next_user_core_update->response && version_compare( $next_user_core_update->version, $core_update->version, '>' ) ); + + /** + * Filter whether to send an email following an automatic background core update. + * + * @since 3.7.0 + * + * @param bool $send Whether to send the email. Default true. + * @param string $type The type of email to send. Can be one of 'success', 'fail', 'critical'. + * @param object $core_update The update offer that was attempted. + * @param mixed $result The result for the core update. Can be WP_Error. + */ + if ( 'manual' !== $type && ! apply_filters( 'auto_core_update_send_email', true, $type, $core_update, $result ) ) + return; + + switch ( $type ) { + case 'success' : // We updated. + /* translators: 1: Site name, 2: WordPress version number. */ + $subject = __( '[%1$s] Your site has updated to WordPress %2$s' ); + break; + + case 'fail' : // We tried to update but couldn't. + case 'manual' : // We can't update (and made no attempt). + /* translators: 1: Site name, 2: WordPress version number. */ + $subject = __( '[%1$s] WordPress %2$s is available. Please update!' ); + break; + + case 'critical' : // We tried to update, started to copy files, then things went wrong. + /* translators: 1: Site name. */ + $subject = __( '[%1$s] URGENT: Your site may be down due to a failed update' ); + break; + + default : + return; + } + + // If the auto update is not to the latest version, say that the current version of WP is available instead. + $version = 'success' === $type ? $core_update->current : $next_user_core_update->current; + $subject = sprintf( $subject, wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $version ); + + $body = ''; + + switch ( $type ) { + case 'success' : + $body .= sprintf( __( 'Howdy! Your site at %1$s has been updated automatically to WordPress %2$s.' ), home_url(), $core_update->current ); + $body .= "\n\n"; + if ( ! $newer_version_available ) + $body .= __( 'No further action is needed on your part.' ) . ' '; + + // Can only reference the About screen if their update was successful. + list( $about_version ) = explode( '-', $core_update->current, 2 ); + $body .= sprintf( __( "For more on version %s, see the About WordPress screen:" ), $about_version ); + $body .= "\n" . admin_url( 'about.php' ); + + if ( $newer_version_available ) { + $body .= "\n\n" . sprintf( __( 'WordPress %s is also now available.' ), $next_user_core_update->current ) . ' '; + $body .= __( 'Updating is easy and only takes a few moments:' ); + $body .= "\n" . network_admin_url( 'update-core.php' ); + } + + break; + + case 'fail' : + case 'manual' : + $body .= sprintf( __( 'Please update your site at %1$s to WordPress %2$s.' ), home_url(), $next_user_core_update->current ); + + $body .= "\n\n"; + + // Don't show this message if there is a newer version available. + // Potential for confusion, and also not useful for them to know at this point. + if ( 'fail' == $type && ! $newer_version_available ) + $body .= __( 'We tried but were unable to update your site automatically.' ) . ' '; + + $body .= __( 'Updating is easy and only takes a few moments:' ); + $body .= "\n" . network_admin_url( 'update-core.php' ); + break; + + case 'critical' : + if ( $newer_version_available ) + $body .= sprintf( __( 'Your site at %1$s experienced a critical failure while trying to update WordPress to version %2$s.' ), home_url(), $core_update->current ); + else + $body .= sprintf( __( 'Your site at %1$s experienced a critical failure while trying to update to the latest version of WordPress, %2$s.' ), home_url(), $core_update->current ); + + $body .= "\n\n" . __( "This means your site may be offline or broken. Don't panic; this can be fixed." ); + + $body .= "\n\n" . __( "Please check out your site now. It's possible that everything is working. If it says you need to update, you should do so:" ); + $body .= "\n" . network_admin_url( 'update-core.php' ); + break; + } + + // Updates are important! + if ( $type != 'success' || $newer_version_available ) + $body .= "\n\n" . __( 'Keeping your site updated is important for security. It also makes the internet a safer place for you and your readers.' ); + + // Add a note about the support forums to all emails. + $body .= "\n\n" . __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' ); + $body .= "\n" . __( 'http://wordpress.org/support/' ); + + // If things are successful and we're now on the latest, mention plugins and themes if any are out of date. + if ( $type == 'success' && ! $newer_version_available && ( get_plugin_updates() || get_theme_updates() ) ) { + $body .= "\n\n" . __( 'You also have some plugins or themes with updates available. Update them now:' ); + $body .= "\n" . network_admin_url(); + } + + $body .= "\n\n" . __( 'The WordPress Team' ) . "\n"; + + if ( 'critical' == $type && is_wp_error( $result ) ) { + $body .= "\n***\n\n"; + $body .= sprintf( __( 'Your site was running version %s.' ), $GLOBALS['wp_version'] ); + $body .= ' ' . __( 'We have some data that describes the error your site encountered.' ); + $body .= ' ' . __( 'Your hosting company, support forum volunteers, or a friendly developer may be able to use this information to help you:' ); + + // If we had a rollback and we're still critical, then the rollback failed too. + // Loop through all errors (the main WP_Error, the update result, the rollback result) for code, data, etc. + if ( 'rollback_was_required' == $result->get_error_code() ) + $errors = array( $result, $result->get_error_data()->update, $result->get_error_data()->rollback ); + else + $errors = array( $result ); + + foreach ( $errors as $error ) { + if ( ! is_wp_error( $error ) ) + continue; + $error_code = $error->get_error_code(); + $body .= "\n\n" . sprintf( __( "Error code: %s" ), $error_code ); + if ( 'rollback_was_required' == $error_code ) + continue; + if ( $error->get_error_message() ) + $body .= "\n" . $error->get_error_message(); + $error_data = $error->get_error_data(); + if ( $error_data ) + $body .= "\n" . implode( ', ', (array) $error_data ); + } + $body .= "\n"; + } + + $to = get_site_option( 'admin_email' ); + $headers = ''; + + $email = compact( 'to', 'subject', 'body', 'headers' ); + /** + * Filter the email sent following an automatic background core update. + * + * @since 3.7.0 + * + * @param array $email { + * Array of email arguments that will be passed to wp_mail(). + * + * @type string $to The email recipient. An array of emails can be returned, as handled by wp_mail(). + * @type string $subject The email's subject. + * @type string $body The email message body. + * @type string $headers Any email headers, defaults to no headers. + * } + * @param string $type The type of email being sent. Can be one of 'success', 'fail', 'manual', 'critical'. + * @param object $core_update The update offer that was attempted. + * @param mixed $result The result for the core update. Can be WP_Error. + */ + $email = apply_filters( 'auto_core_update_email', $email, $type, $core_update, $result ); + + wp_mail( $email['to'], $email['subject'], $email['body'], $email['headers'] ); + } + + /** + * Prepares and sends an email of a full log of background update results, useful for debugging and geekery. + * + * @since 3.7.0 + */ + protected function send_debug_email() { + $update_count = 0; + foreach ( $this->update_results as $type => $updates ) + $update_count += count( $updates ); + + $body = array(); + $failures = 0; + + $body[] = 'WordPress site: ' . network_home_url( '/' ); + + // Core + if ( isset( $this->update_results['core'] ) ) { + $result = $this->update_results['core'][0]; + if ( $result->result && ! is_wp_error( $result->result ) ) { + $body[] = sprintf( 'SUCCESS: WordPress was successfully updated to %s', $result->name ); + } else { + $body[] = sprintf( 'FAILED: WordPress failed to update to %s', $result->name ); + $failures++; + } + $body[] = ''; + } + + // Plugins, Themes, Translations + foreach ( array( 'plugin', 'theme', 'translation' ) as $type ) { + if ( ! isset( $this->update_results[ $type ] ) ) + continue; + $success_items = wp_list_filter( $this->update_results[ $type ], array( 'result' => true ) ); + if ( $success_items ) { + $body[] = "The following {$type}s were successfully updated:"; + foreach ( wp_list_pluck( $success_items, 'name' ) as $name ) + $body[] = ' * SUCCESS: ' . $name; + } + if ( $success_items != $this->update_results[ $type ] ) { + // Failed updates + $body[] = "The following {$type}s failed to update:"; + foreach ( $this->update_results[ $type ] as $item ) { + if ( ! $item->result || is_wp_error( $item->result ) ) { + $body[] = ' * FAILED: ' . $item->name; + $failures++; + } + } + } + $body[] = ''; + } + + if ( $failures ) { + $body[] = ''; + $body[] = 'BETA TESTING?'; + $body[] = '============='; + $body[] = ''; + $body[] = 'This debugging email is sent when you are using a development version of WordPress.'; + $body[] = ''; + $body[] = 'If you think these failures might be due to a bug in WordPress, could you report it?'; + $body[] = ' * Open a thread in the support forums: http://wordpress.org/support/forum/alphabeta'; + $body[] = " * Or, if you're comfortable writing a bug report: http://core.trac.wordpress.org/"; + $body[] = ''; + $body[] = 'Thanks! -- The WordPress Team'; + $body[] = ''; + $subject = sprintf( '[%s] There were failures during background updates', get_bloginfo( 'name' ) ); + } else { + $subject = sprintf( '[%s] Background updates have finished', get_bloginfo( 'name' ) ); + } + + $body[] = 'UPDATE LOG'; + $body[] = '=========='; + $body[] = ''; + + foreach ( array( 'core', 'plugin', 'theme', 'translation' ) as $type ) { + if ( ! isset( $this->update_results[ $type ] ) ) + continue; + foreach ( $this->update_results[ $type ] as $update ) { + $body[] = $update->name; + $body[] = str_repeat( '-', strlen( $update->name ) ); + foreach ( $update->messages as $message ) + $body[] = " " . html_entity_decode( str_replace( '…', '...', $message ) ); + if ( is_wp_error( $update->result ) ) { + $results = array( 'update' => $update->result ); + // If we rolled back, we want to know an error that occurred then too. + if ( 'rollback_was_required' === $update->result->get_error_code() ) + $results = (array) $update->result->get_error_data(); + foreach ( $results as $result_type => $result ) { + if ( ! is_wp_error( $result ) ) + continue; + $body[] = ' ' . ( 'rollback' === $result_type ? 'Rollback ' : '' ) . 'Error: [' . $result->get_error_code() . '] ' . $result->get_error_message(); + if ( $result->get_error_data() ) + $body[] = ' ' . implode( ', ', (array) $result->get_error_data() ); + } + } + $body[] = ''; + } + } + + //echo "

\n$subject\n

\n"; + //echo "
\n" . implode( "\n", $body ) . "\n
"; + + wp_mail( get_site_option( 'admin_email' ), $subject, implode( "\n", $body ) ); + } +} diff --git a/sources/wp-admin/includes/class-wp-users-list-table.php b/sources/wp-admin/includes/class-wp-users-list-table.php new file mode 100644 index 0000000..48c9c0c --- /dev/null +++ b/sources/wp-admin/includes/class-wp-users-list-table.php @@ -0,0 +1,324 @@ + 'user', + 'plural' => 'users', + 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, + ) ); + + $this->is_site_users = 'site-users-network' == $this->screen->id; + + if ( $this->is_site_users ) + $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; + } + + function ajax_user_can() { + if ( $this->is_site_users ) + return current_user_can( 'manage_sites' ); + else + return current_user_can( 'list_users' ); + } + + function prepare_items() { + global $role, $usersearch; + + $usersearch = isset( $_REQUEST['s'] ) ? trim( $_REQUEST['s'] ) : ''; + + $role = isset( $_REQUEST['role'] ) ? $_REQUEST['role'] : ''; + + $per_page = ( $this->is_site_users ) ? 'site_users_network_per_page' : 'users_per_page'; + $users_per_page = $this->get_items_per_page( $per_page ); + + $paged = $this->get_pagenum(); + + $args = array( + 'number' => $users_per_page, + 'offset' => ( $paged-1 ) * $users_per_page, + 'role' => $role, + 'search' => $usersearch, + 'fields' => 'all_with_meta' + ); + + if ( '' !== $args['search'] ) + $args['search'] = '*' . $args['search'] . '*'; + + if ( $this->is_site_users ) + $args['blog_id'] = $this->site_id; + + if ( isset( $_REQUEST['orderby'] ) ) + $args['orderby'] = $_REQUEST['orderby']; + + if ( isset( $_REQUEST['order'] ) ) + $args['order'] = $_REQUEST['order']; + + // Query the user IDs for this page + $wp_user_search = new WP_User_Query( $args ); + + $this->items = $wp_user_search->get_results(); + + $this->set_pagination_args( array( + 'total_items' => $wp_user_search->get_total(), + 'per_page' => $users_per_page, + ) ); + } + + function no_items() { + _e( 'No matching users were found.' ); + } + + function get_views() { + global $wp_roles, $role; + + if ( $this->is_site_users ) { + $url = 'site-users.php?id=' . $this->site_id; + switch_to_blog( $this->site_id ); + $users_of_blog = count_users(); + restore_current_blog(); + } else { + $url = 'users.php'; + $users_of_blog = count_users(); + } + $total_users = $users_of_blog['total_users']; + $avail_roles =& $users_of_blog['avail_roles']; + unset($users_of_blog); + + $current_role = false; + $class = empty($role) ? ' class="current"' : ''; + $role_links = array(); + $role_links['all'] = "" . sprintf( _nx( 'All (%s)', 'All (%s)', $total_users, 'users' ), number_format_i18n( $total_users ) ) . ''; + foreach ( $wp_roles->get_names() as $this_role => $name ) { + if ( !isset($avail_roles[$this_role]) ) + continue; + + $class = ''; + + if ( $this_role == $role ) { + $current_role = $role; + $class = ' class="current"'; + } + + $name = translate_user_role( $name ); + /* translators: User role name with count */ + $name = sprintf( __('%1$s (%2$s)'), $name, number_format_i18n( $avail_roles[$this_role] ) ); + $role_links[$this_role] = "$name"; + } + + return $role_links; + } + + function get_bulk_actions() { + $actions = array(); + + if ( is_multisite() ) { + if ( current_user_can( 'remove_users' ) ) + $actions['remove'] = __( 'Remove' ); + } else { + if ( current_user_can( 'delete_users' ) ) + $actions['delete'] = __( 'Delete' ); + } + + return $actions; + } + + function extra_tablenav( $which ) { + if ( 'top' != $which ) + return; + ?> +
+ + + + '; + } + + function current_action() { + if ( isset($_REQUEST['changeit']) && !empty($_REQUEST['new_role']) ) + return 'promote'; + + return parent::current_action(); + } + + function get_columns() { + $c = array( + 'cb' => '', + 'username' => __( 'Username' ), + 'name' => __( 'Name' ), + 'email' => __( 'E-mail' ), + 'role' => __( 'Role' ), + 'posts' => __( 'Posts' ) + ); + + if ( $this->is_site_users ) + unset( $c['posts'] ); + + return $c; + } + + function get_sortable_columns() { + $c = array( + 'username' => 'login', + 'name' => 'name', + 'email' => 'email', + ); + + if ( $this->is_site_users ) + unset( $c['posts'] ); + + return $c; + } + + function display_rows() { + // Query the post counts for this page + if ( ! $this->is_site_users ) + $post_counts = count_many_users_posts( array_keys( $this->items ) ); + + $editable_roles = array_keys( get_editable_roles() ); + + $style = ''; + foreach ( $this->items as $userid => $user_object ) { + if ( count( $user_object->roles ) <= 1 ) { + $role = reset( $user_object->roles ); + } elseif ( $roles = array_intersect( array_values( $user_object->roles ), $editable_roles ) ) { + $role = reset( $roles ); + } else { + $role = reset( $user_object->roles ); + } + + if ( is_multisite() && empty( $user_object->allcaps ) ) + continue; + + $style = ( ' class="alternate"' == $style ) ? '' : ' class="alternate"'; + echo "\n\t" . $this->single_row( $user_object, $style, $role, isset( $post_counts ) ? $post_counts[ $userid ] : 0 ); + } + } + + /** + * Generate HTML for a single row on the users.php admin panel. + * + * @since 2.1.0 + * + * @param object $user_object + * @param string $style Optional. Attributes added to the TR element. Must be sanitized. + * @param string $role Key for the $wp_roles array. + * @param int $numposts Optional. Post count to display for this user. Defaults to zero, as in, a new user has made zero posts. + * @return string + */ + function single_row( $user_object, $style = '', $role = '', $numposts = 0 ) { + global $wp_roles; + + if ( !( is_object( $user_object ) && is_a( $user_object, 'WP_User' ) ) ) + $user_object = get_userdata( (int) $user_object ); + $user_object->filter = 'display'; + $email = $user_object->user_email; + + if ( $this->is_site_users ) + $url = "site-users.php?id={$this->site_id}&"; + else + $url = 'users.php?'; + + $checkbox = ''; + // Check if the user for this row is editable + if ( current_user_can( 'list_users' ) ) { + // Set up the user editing link + $edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user_object->ID ) ) ); + + // Set up the hover actions for this user + $actions = array(); + + if ( current_user_can( 'edit_user', $user_object->ID ) ) { + $edit = "$user_object->user_login
"; + $actions['edit'] = '' . __( 'Edit' ) . ''; + } else { + $edit = "$user_object->user_login
"; + } + + if ( !is_multisite() && get_current_user_id() != $user_object->ID && current_user_can( 'delete_user', $user_object->ID ) ) + $actions['delete'] = "" . __( 'Delete' ) . ""; + if ( is_multisite() && get_current_user_id() != $user_object->ID && current_user_can( 'remove_user', $user_object->ID ) ) + $actions['remove'] = "" . __( 'Remove' ) . ""; + $actions = apply_filters( 'user_row_actions', $actions, $user_object ); + $edit .= $this->row_actions( $actions ); + + // Set up the checkbox ( because the user is editable, otherwise it's empty ) + $checkbox = '' + . ""; + + } else { + $edit = '' . $user_object->user_login . ''; + } + $role_name = isset( $wp_roles->role_names[$role] ) ? translate_user_role( $wp_roles->role_names[$role] ) : __( 'None' ); + $avatar = get_avatar( $user_object->ID, 32 ); + + $r = ""; + + list( $columns, $hidden ) = $this->get_column_info(); + + foreach ( $columns as $column_name => $column_display_name ) { + $class = "class=\"$column_name column-$column_name\""; + + $style = ''; + if ( in_array( $column_name, $hidden ) ) + $style = ' style="display:none;"'; + + $attributes = "$class$style"; + + switch ( $column_name ) { + case 'cb': + $r .= "$checkbox"; + break; + case 'username': + $r .= "$avatar $edit"; + break; + case 'name': + $r .= "$user_object->first_name $user_object->last_name"; + break; + case 'email': + $r .= "$email"; + break; + case 'role': + $r .= "$role_name"; + break; + case 'posts': + $attributes = 'class="posts column-posts num"' . $style; + $r .= ""; + if ( $numposts > 0 ) { + $r .= ""; + $r .= $numposts; + $r .= ''; + } else { + $r .= 0; + } + $r .= ""; + break; + default: + $r .= ""; + $r .= apply_filters( 'manage_users_custom_column', '', $column_name, $user_object->ID ); + $r .= ""; + } + } + $r .= ''; + + return $r; + } +} diff --git a/sources/wp-admin/includes/comment.php b/sources/wp-admin/includes/comment.php new file mode 100644 index 0000000..a74eeaa --- /dev/null +++ b/sources/wp-admin/includes/comment.php @@ -0,0 +1,171 @@ +get_var( $wpdb->prepare("SELECT comment_post_ID FROM $wpdb->comments + WHERE comment_author = %s AND comment_date = %s", $comment_author, $comment_date) ); +} + +/** + * Update a comment with values provided in $_POST. + * + * @since 2.0.0 + */ +function edit_comment() { + + if ( ! current_user_can( 'edit_comment', (int) $_POST['comment_ID'] ) ) + wp_die ( __( 'You are not allowed to edit comments on this post.' ) ); + + if ( isset( $_POST['newcomment_author'] ) ) + $_POST['comment_author'] = $_POST['newcomment_author']; + if ( isset( $_POST['newcomment_author_email'] ) ) + $_POST['comment_author_email'] = $_POST['newcomment_author_email']; + if ( isset( $_POST['newcomment_author_url'] ) ) + $_POST['comment_author_url'] = $_POST['newcomment_author_url']; + if ( isset( $_POST['comment_status'] ) ) + $_POST['comment_approved'] = $_POST['comment_status']; + if ( isset( $_POST['content'] ) ) + $_POST['comment_content'] = $_POST['content']; + if ( isset( $_POST['comment_ID'] ) ) + $_POST['comment_ID'] = (int) $_POST['comment_ID']; + + foreach ( array ('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) { + if ( !empty( $_POST['hidden_' . $timeunit] ) && $_POST['hidden_' . $timeunit] != $_POST[$timeunit] ) { + $_POST['edit_date'] = '1'; + break; + } + } + + if ( !empty ( $_POST['edit_date'] ) ) { + $aa = $_POST['aa']; + $mm = $_POST['mm']; + $jj = $_POST['jj']; + $hh = $_POST['hh']; + $mn = $_POST['mn']; + $ss = $_POST['ss']; + $jj = ($jj > 31 ) ? 31 : $jj; + $hh = ($hh > 23 ) ? $hh -24 : $hh; + $mn = ($mn > 59 ) ? $mn -60 : $mn; + $ss = ($ss > 59 ) ? $ss -60 : $ss; + $_POST['comment_date'] = "$aa-$mm-$jj $hh:$mn:$ss"; + } + + wp_update_comment( $_POST ); +} + +/** + * Returns a comment object based on comment ID. + * + * @since 2.0.0 + * + * @param int $id ID of comment to retrieve. + * @return bool|object Comment if found. False on failure. + */ +function get_comment_to_edit( $id ) { + if ( !$comment = get_comment($id) ) + return false; + + $comment->comment_ID = (int) $comment->comment_ID; + $comment->comment_post_ID = (int) $comment->comment_post_ID; + + $comment->comment_content = format_to_edit( $comment->comment_content ); + /** + * Filter the comment content before editing. + * + * @since 2.0.0 + * + * @param string $comment->comment_content Comment content. + */ + $comment->comment_content = apply_filters( 'comment_edit_pre', $comment->comment_content ); + + $comment->comment_author = format_to_edit( $comment->comment_author ); + $comment->comment_author_email = format_to_edit( $comment->comment_author_email ); + $comment->comment_author_url = format_to_edit( $comment->comment_author_url ); + $comment->comment_author_url = esc_url($comment->comment_author_url); + + return $comment; +} + +/** + * Get the number of pending comments on a post or posts + * + * @since 2.3.0 + * @uses $wpdb + * + * @param int|array $post_id Either a single Post ID or an array of Post IDs + * @return int|array Either a single Posts pending comments as an int or an array of ints keyed on the Post IDs + */ +function get_pending_comments_num( $post_id ) { + global $wpdb; + + $single = false; + if ( !is_array($post_id) ) { + $post_id_array = (array) $post_id; + $single = true; + } else { + $post_id_array = $post_id; + } + $post_id_array = array_map('intval', $post_id_array); + $post_id_in = "'" . implode("', '", $post_id_array) . "'"; + + $pending = $wpdb->get_results( "SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM $wpdb->comments WHERE comment_post_ID IN ( $post_id_in ) AND comment_approved = '0' GROUP BY comment_post_ID", ARRAY_A ); + + if ( $single ) { + if ( empty($pending) ) + return 0; + else + return absint($pending[0]['num_comments']); + } + + $pending_keyed = array(); + + // Default to zero pending for all posts in request + foreach ( $post_id_array as $id ) + $pending_keyed[$id] = 0; + + if ( !empty($pending) ) + foreach ( $pending as $pend ) + $pending_keyed[$pend['comment_post_ID']] = absint($pend['num_comments']); + + return $pending_keyed; +} + +/** + * Add avatars to relevant places in admin, or try to. + * + * @since 2.5.0 + * @uses $comment + * + * @param string $name User name. + * @return string Avatar with Admin name. + */ +function floated_admin_avatar( $name ) { + global $comment; + $avatar = get_avatar( $comment, 32, 'mystery' ); + return "$avatar $name"; +} + +function enqueue_comment_hotkeys_js() { + if ( 'true' == get_user_option( 'comment_shortcuts' ) ) + wp_enqueue_script( 'jquery-table-hotkeys' ); +} diff --git a/sources/wp-admin/includes/continents-cities.php b/sources/wp-admin/includes/continents-cities.php new file mode 100644 index 0000000..0ebc4f3 --- /dev/null +++ b/sources/wp-admin/includes/continents-cities.php @@ -0,0 +1,493 @@ + 5, + ); + } + $recent_comments_title = __( 'Recent Comments' ); + wp_add_dashboard_widget( 'dashboard_recent_comments', $recent_comments_title, 'wp_dashboard_recent_comments', 'wp_dashboard_recent_comments_control' ); + } + + // Incoming Links Widget + if ( is_blog_admin() && current_user_can('publish_posts') ) { + if ( !isset( $widget_options['dashboard_incoming_links'] ) || !isset( $widget_options['dashboard_incoming_links']['home'] ) || $widget_options['dashboard_incoming_links']['home'] != get_option('home') ) { + $update = true; + $num_items = isset($widget_options['dashboard_incoming_links']['items']) ? $widget_options['dashboard_incoming_links']['items'] : 10; + $widget_options['dashboard_incoming_links'] = array( + 'home' => get_option('home'), + 'link' => apply_filters( 'dashboard_incoming_links_link', 'http://blogsearch.google.com/blogsearch?scoring=d&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ), + 'url' => isset($widget_options['dashboard_incoming_links']['url']) ? apply_filters( 'dashboard_incoming_links_feed', $widget_options['dashboard_incoming_links']['url'] ) : apply_filters( 'dashboard_incoming_links_feed', 'http://blogsearch.google.com/blogsearch_feeds?scoring=d&ie=utf-8&num=' . $num_items . '&output=rss&partner=wordpress&q=link:' . trailingslashit( get_option('home') ) ), + 'items' => $num_items, + 'show_date' => isset($widget_options['dashboard_incoming_links']['show_date']) ? $widget_options['dashboard_incoming_links']['show_date'] : false + ); + } + wp_add_dashboard_widget( 'dashboard_incoming_links', __( 'Incoming Links' ), 'wp_dashboard_incoming_links', 'wp_dashboard_incoming_links_control' ); + } + + // WP Plugins Widget + if ( ( ! is_multisite() && is_blog_admin() && current_user_can( 'install_plugins' ) ) || ( is_network_admin() && current_user_can( 'manage_network_plugins' ) && current_user_can( 'install_plugins' ) ) ) + wp_add_dashboard_widget( 'dashboard_plugins', __( 'Plugins' ), 'wp_dashboard_plugins' ); + + // QuickPress Widget + if ( is_blog_admin() && current_user_can('edit_posts') ) + wp_add_dashboard_widget( 'dashboard_quick_press', __( 'QuickPress' ), 'wp_dashboard_quick_press' ); + + // Recent Drafts + if ( is_blog_admin() && current_user_can('edit_posts') ) + wp_add_dashboard_widget( 'dashboard_recent_drafts', __('Recent Drafts'), 'wp_dashboard_recent_drafts' ); + + // Primary feed (Dev Blog) Widget + if ( !isset( $widget_options['dashboard_primary'] ) ) { + $update = true; + $widget_options['dashboard_primary'] = array( + 'link' => apply_filters( 'dashboard_primary_link', __( 'http://wordpress.org/news/' ) ), + 'url' => apply_filters( 'dashboard_primary_feed', __( 'http://wordpress.org/news/feed/' ) ), + 'title' => apply_filters( 'dashboard_primary_title', __( 'WordPress Blog' ) ), + 'items' => 2, + 'show_summary' => 1, + 'show_author' => 0, + 'show_date' => 1, + ); + } + wp_add_dashboard_widget( 'dashboard_primary', $widget_options['dashboard_primary']['title'], 'wp_dashboard_primary', 'wp_dashboard_primary_control' ); + + // Secondary Feed (Planet) Widget + if ( !isset( $widget_options['dashboard_secondary'] ) ) { + $update = true; + $widget_options['dashboard_secondary'] = array( + 'link' => apply_filters( 'dashboard_secondary_link', __( 'http://planet.wordpress.org/' ) ), + 'url' => apply_filters( 'dashboard_secondary_feed', __( 'http://planet.wordpress.org/feed/' ) ), + 'title' => apply_filters( 'dashboard_secondary_title', __( 'Other WordPress News' ) ), + 'items' => 5, + 'show_summary' => 0, + 'show_author' => 0, + 'show_date' => 0, + ); + } + wp_add_dashboard_widget( 'dashboard_secondary', $widget_options['dashboard_secondary']['title'], 'wp_dashboard_secondary', 'wp_dashboard_secondary_control' ); + + // Hook to register new widgets + // Filter widget order + if ( is_network_admin() ) { + do_action( 'wp_network_dashboard_setup' ); + $dashboard_widgets = apply_filters( 'wp_network_dashboard_widgets', array() ); + } elseif ( is_user_admin() ) { + do_action( 'wp_user_dashboard_setup' ); + $dashboard_widgets = apply_filters( 'wp_user_dashboard_widgets', array() ); + } else { + do_action( 'wp_dashboard_setup' ); + $dashboard_widgets = apply_filters( 'wp_dashboard_widgets', array() ); + } + + foreach ( $dashboard_widgets as $widget_id ) { + $name = empty( $wp_registered_widgets[$widget_id]['all_link'] ) ? $wp_registered_widgets[$widget_id]['name'] : $wp_registered_widgets[$widget_id]['name'] . " " . __('View all') . ''; + wp_add_dashboard_widget( $widget_id, $name, $wp_registered_widgets[$widget_id]['callback'], $wp_registered_widget_controls[$widget_id]['callback'] ); + } + + if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget_id']) ) { + check_admin_referer( 'edit-dashboard-widget_' . $_POST['widget_id'], 'dashboard-widget-nonce' ); + ob_start(); // hack - but the same hack wp-admin/widgets.php uses + wp_dashboard_trigger_widget_control( $_POST['widget_id'] ); + ob_end_clean(); + wp_redirect( remove_query_arg( 'edit' ) ); + exit; + } + + if ( $update ) + update_option( 'dashboard_widget_options', $widget_options ); + + /** This action is documented in wp-admin/edit-form-advanced.php */ + do_action('do_meta_boxes', $screen->id, 'normal', ''); + /** This action is documented in wp-admin/edit-form-advanced.php */ + do_action('do_meta_boxes', $screen->id, 'side', ''); +} + +function wp_add_dashboard_widget( $widget_id, $widget_name, $callback, $control_callback = null, $callback_args = null ) { + $screen = get_current_screen(); + global $wp_dashboard_control_callbacks; + + if ( $control_callback && current_user_can( 'edit_dashboard' ) && is_callable( $control_callback ) ) { + $wp_dashboard_control_callbacks[$widget_id] = $control_callback; + if ( isset( $_GET['edit'] ) && $widget_id == $_GET['edit'] ) { + list($url) = explode( '#', add_query_arg( 'edit', false ), 2 ); + $widget_name .= ' ' . __( 'Cancel' ) . ''; + $callback = '_wp_dashboard_control_callback'; + } else { + list($url) = explode( '#', add_query_arg( 'edit', $widget_id ), 2 ); + $widget_name .= ' ' . __( 'Configure' ) . ''; + } + } + + if ( is_blog_admin () ) + $side_widgets = array('dashboard_quick_press', 'dashboard_recent_drafts', 'dashboard_primary', 'dashboard_secondary'); + else if (is_network_admin() ) + $side_widgets = array('dashboard_primary', 'dashboard_secondary'); + else + $side_widgets = array(); + + $location = 'normal'; + if ( in_array($widget_id, $side_widgets) ) + $location = 'side'; + + $priority = 'core'; + if ( 'dashboard_browser_nag' === $widget_id ) + $priority = 'high'; + + add_meta_box( $widget_id, $widget_name, $callback, $screen, $location, $priority, $callback_args ); +} + +function _wp_dashboard_control_callback( $dashboard, $meta_box ) { + echo '
'; + wp_dashboard_trigger_widget_control( $meta_box['id'] ); + wp_nonce_field( 'edit-dashboard-widget_' . $meta_box['id'], 'dashboard-widget-nonce' ); + echo ''; + submit_button( __('Submit') ); + echo '
'; +} + +/** + * Displays the dashboard. + * + * @since 2.5.0 + */ +function wp_dashboard() { + $screen = get_current_screen(); + $class = 'columns-' . get_current_screen()->get_columns(); + +?> +
+
+ id, 'normal', '' ); ?> +
+
+ id, 'side', '' ); ?> +
+
+ id, 'column3', '' ); ?> +
+
+ id, 'column4', '' ); ?> +
+
+ +'; + echo "\n\t".'

' . __('Content') . '

'."\n\t".''; + echo "\n\t".''; + + // Posts + $num = number_format_i18n( $num_posts->publish ); + $text = _n( 'Post', 'Posts', intval($num_posts->publish) ); + if ( current_user_can( 'edit_posts' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ''; + /* TODO: Show status breakdown on hover + if ( $can_edit_pages && !empty($num_pages->publish) ) { // how many pages is not exposed in feeds. Don't show if !current_user_can + $post_type_texts[] = ''.sprintf( _n( '%s page', '%s pages', $num_pages->publish ), number_format_i18n( $num_pages->publish ) ).''; + } + if ( $can_edit_posts && !empty($num_posts->draft) ) { + $post_type_texts[] = ''.sprintf( _n( '%s draft', '%s drafts', $num_posts->draft ), number_format_i18n( $num_posts->draft ) ).''; + } + if ( $can_edit_posts && !empty($num_posts->future) ) { + $post_type_texts[] = ''.sprintf( _n( '%s scheduled post', '%s scheduled posts', $num_posts->future ), number_format_i18n( $num_posts->future ) ).''; + } + if ( current_user_can('publish_posts') && !empty($num_posts->pending) ) { + $pending_text = sprintf( _n( 'There is %2$s post pending your review.', 'There are %2$s posts pending your review.', $num_posts->pending ), 'edit.php?post_status=pending', number_format_i18n( $num_posts->pending ) ); + } else { + $pending_text = ''; + } + */ + + // Pages + $num = number_format_i18n( $num_pages->publish ); + $text = _n( 'Page', 'Pages', $num_pages->publish ); + if ( current_user_can( 'edit_pages' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ''; + + // Categories + $num = number_format_i18n( $num_cats ); + $text = _n( 'Category', 'Categories', $num_cats ); + if ( current_user_can( 'manage_categories' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ''; + + // Tags + $num = number_format_i18n( $num_tags ); + $text = _n( 'Tag', 'Tags', $num_tags ); + if ( current_user_can( 'manage_categories' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ""; + do_action('right_now_content_table_end'); + echo "\n\t
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
\n\t
"; + + echo "\n\t".'
'; + echo "\n\t".'

' . __('Discussion') . '

'."\n\t".''; + echo "\n\t".''; + + // Total Comments + $num = '' . number_format_i18n($num_comm->total_comments) . ''; + $text = _n( 'Comment', 'Comments', $num_comm->total_comments ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = '' . $num . ''; + $text = '' . $text . ''; + } + echo ''; + echo ''; + + echo ''; + + // Approved Comments + $num = '' . number_format_i18n($num_comm->approved) . ''; + $text = _nx( 'Approved', 'Approved', $num_comm->approved, 'Right Now' ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo "\n\t"; + + // Pending Comments + $num = '' . number_format_i18n($num_comm->moderated) . ''; + $text = _n( 'Pending', 'Pending', $num_comm->moderated ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo "\n\t"; + + // Spam Comments + $num = number_format_i18n($num_comm->spam); + $text = _nx( 'Spam', 'Spam', $num_comm->spam, 'comment' ); + if ( current_user_can( 'moderate_comments' ) ) { + $num = "$num"; + $text = "$text"; + } + echo ''; + echo ''; + + echo ""; + do_action('right_now_table_end'); + do_action('right_now_discussion_table_end'); + echo "\n\t
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
' . $num . '' . $text . '
\n\t
"; + + echo "\n\t".'
'; + $theme = wp_get_theme(); + + echo "\n\t

"; + + if ( $theme->errors() ) { + if ( ! is_multisite() || is_super_admin() ) + echo '' . sprintf( __( 'ERROR: %s' ), $theme->errors()->get_error_message() ) . ''; + } elseif ( ! empty($wp_registered_sidebars) ) { + $sidebars_widgets = wp_get_sidebars_widgets(); + $num_widgets = 0; + foreach ( (array) $sidebars_widgets as $k => $v ) { + if ( 'wp_inactive_widgets' == $k || 'orphaned_widgets' == substr( $k, 0, 16 ) ) + continue; + if ( is_array($v) ) + $num_widgets = $num_widgets + count($v); + } + $num = number_format_i18n( $num_widgets ); + + $switch_themes = $theme->display('Name'); + if ( current_user_can( 'switch_themes') ) + $switch_themes = '' . $switch_themes . ''; + if ( current_user_can( 'edit_theme_options' ) ) { + printf(_n('Theme %1$s with %2$s Widget', 'Theme %1$s with %2$s Widgets', $num_widgets), $switch_themes, $num); + } else { + printf(_n('Theme %1$s with %2$s Widget', 'Theme %1$s with %2$s Widgets', $num_widgets), $switch_themes, $num); + } + } else { + if ( current_user_can( 'switch_themes' ) ) + printf( __('Theme %1$s'), $theme->display('Name') ); + else + printf( __('Theme %1$s'), $theme->display('Name') ); + } + echo '

'; + + // Check if search engines are asked not to index this site. + if ( !is_network_admin() && !is_user_admin() && current_user_can('manage_options') && '1' != get_option('blog_public') ) { + $title = apply_filters('privacy_on_link_title', __('Your site is asking search engines not to index its content') ); + $content = apply_filters('privacy_on_link_text', __('Search Engines Discouraged') ); + + echo "

$content

"; + } + + update_right_now_message(); + + echo "\n\t".'
'; + do_action( 'rightnow_end' ); + do_action( 'activity_box_end' ); +} + +function wp_network_dashboard_right_now() { + $actions = array(); + if ( current_user_can('create_sites') ) + $actions['create-site'] = '' . __( 'Create a New Site' ) . ''; + if ( current_user_can('create_users') ) + $actions['create-user'] = '' . __( 'Create a New User' ) . ''; + + $c_users = get_user_count(); + $c_blogs = get_blog_count(); + + $user_text = sprintf( _n( '%s user', '%s users', $c_users ), number_format_i18n( $c_users ) ); + $blog_text = sprintf( _n( '%s site', '%s sites', $c_blogs ), number_format_i18n( $c_blogs ) ); + + $sentence = sprintf( __( 'You have %1$s and %2$s.' ), $blog_text, $user_text ); + + if ( $actions ) { + echo '
    '; + foreach ( $actions as $class => $action ) { + $actions[ $class ] = "\t
  • $action"; + } + echo implode( " |
  • \n", $actions ) . "\n"; + echo '
'; + } +?> +
+ +

+ + +
+

+ + 'submit_users' ) ); ?> +

+
+ +
+

+ + 'submit_sites' ) ); ?> +

+
+

' . __( 'Post published. View post | Edit post' ) . '

' . __('Documentation on Import') . '

yCaqh*`q zI$4%C3CWUUamB5+PAfNpf-m8oPqp_>eInEsm7Pg&)-qj{O}V-5JpbevSiq5K7v!B~ zuz0uma&+^WsA5$2lq3^N>B`qin(wGjsqG&VsCf81D{UR`TC=Vs9NK}7mIq1NrH@`I aS`10{xfgpUWytult&Qc5!|>S(P#`t4I3W|qYGnXi8026g`h-@SfGLu5*0&? z8jTAy(n4D>JOoA5NTDbQEwn{?OL?@ty>mRny|+rRWv+4MB!BL79^d@uoMDIo0ObmC z3DM@219{J8;AeCGEi~wkhviW-@SKJL%H%R0U6vA86F|_ZWq>ld+z4JX5hl(9_`kit zLz38`Ax?!G5`Kx3zH?`UsY(b9m(T*aa67_J?HlIA->upSVh z-^&1&ZGdaS^Vl!LgEUdYC64M8lt-8>2VuAv_z(FMh+j$A7p%n~II4k6S6hK=SFfMb zfFqVTu4j;`3cv966aouGs060JiM;}F-brTaVwnqtA*zVuY7uUfp^^$H9HEuy@}^pO z^%sXy5GupMDG){uQI~zdyOWebd2R!y;j|z+74tZHBzypI-lca|trV((`K~s>b_@_q zMf2Fb68896+NU?5L?P4}M_l)ShL50&sAS@7)Zn)eWu=FJ@9h&jJW&C3juxpKl?t3e z+$aevuEy~aGTSnb_mi>u^hH|yxSKkQv<6+q5y!QSxHgpy8g#3e-v$48JOfm@{zItY zR$5p_o%l7^@4RnZJ1&bAs-+uI6qx&{ucg?7{UQ;#TDVrR)8vl2EWc;62P_SFL#thC z{|;)pozpa8Dh~p--sZg?9NQ(%$x;YK7b;^-x&T0cHn;6HSnlLm#N0CE)TGbWoAf(4 zst$b?C-<%Gm;CTs>wUQ2BhS+>6&BGR$=xPnO-3lNFav(y^onTzPc7h^0ePLR>q>~` zI%3!u?)J{c!g=2B1(vorHwKvVX-r4-e|*N;%&I;NQ3wU10t1U~FzV8IjBpE6p)gVwVop8}X5fFw^t$kzhv5_B?pCk{wpYF3zO8@`>07*qoM6N<$f`wzX Ap#T5? literal 0 HcmV?d00001 diff --git a/sources/wp-admin/images/stars.png b/sources/wp-admin/images/stars.png new file mode 100644 index 0000000000000000000000000000000000000000..c01ada13ee9a58afc51489ea80a53dca6dbe7eaa GIT binary patch literal 924 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

', esc_url( $view ), $edit ); + else + printf( '

' . __( 'Post submitted. Preview post | Edit post' ) . '

', esc_url( add_query_arg( 'preview', 1, $view ) ), $edit ); + } else { + printf( '

' . __( 'Draft saved. Preview post | Edit post' ) . '

', esc_url( add_query_arg( 'preview', 1, $view ) ), $edit ); + $drafts_query = new WP_Query( array( + 'post_type' => 'post', + 'post_status' => 'draft', + 'author' => $GLOBALS['current_user']->ID, + 'posts_per_page' => 1, + 'orderby' => 'modified', + 'order' => 'DESC' + ) ); + + if ( $drafts_query->posts ) + $drafts =& $drafts_query->posts; + } + printf('

' . __('You can also try %s, easy blogging from anywhere on the Web.') . '

', '' . __('Press This') . '' ); + $_REQUEST = array(); // hack for get_default_post_to_edit() + } + + /* Check if a new auto-draft (= no new post_ID) is needed or if the old can be used */ + $last_post_id = (int) get_user_option( 'dashboard_quick_press_last_post_id' ); // Get the last post_ID + if ( $last_post_id ) { + $post = get_post( $last_post_id ); + if ( empty( $post ) || $post->post_status != 'auto-draft' ) { // auto-draft doesn't exists anymore + $post = get_default_post_to_edit('post', true); + update_user_option( get_current_user_id(), 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID + } else { + $post->post_title = ''; // Remove the auto draft title + } + } else { + $post = get_default_post_to_edit( 'post' , true); + $user_id = get_current_user_id(); + // Don't create an option if this is a super admin who does not belong to this site. + if ( ! ( is_super_admin( $user_id ) && ! in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user_id ) ) ) ) ) + update_user_option( $user_id, 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID + } + + $post_ID = (int) $post->ID; + + $media_settings = array( + 'id' => $post->ID, + 'nonce' => wp_create_nonce( 'update-post_' . $post->ID ), + ); + + if ( current_theme_supports( 'post-thumbnails', $post->post_type ) && post_type_supports( $post->post_type, 'thumbnail' ) ) { + $featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true ); + $media_settings['featuredImageId'] = $featured_image_id ? $featured_image_id : -1; + } +?> + +
+
+ + +
+ + +
+ +
+ + +
+ + +
+ + + +
+ + +
+ +

+ + + + + + + + + 'save-post' ) ); ?> + +
+

+ +
+ + 'post', + 'post_status' => 'draft', + 'author' => $GLOBALS['current_user']->ID, + 'posts_per_page' => 5, + 'orderby' => 'modified', + 'order' => 'DESC' + ) ); + $drafts =& $drafts_query->posts; + } + + if ( $drafts && is_array( $drafts ) ) { + $list = array(); + foreach ( $drafts as $draft ) { + $url = get_edit_post_link( $draft->ID ); + $title = _draft_or_post_title( $draft->ID ); + $item = "

" . esc_html($title) . " " . get_the_time( get_option( 'date_format' ), $draft ) . '

'; + if ( $the_content = wp_trim_words( $draft->post_content, 10 ) ) + $item .= '

' . $the_content . '

'; + $list[] = $item; + } +?> +
    +
  • \n
  • ", $list ); ?>
  • +
+

+ $total_items * 5, 'offset' => 0 ); + if ( ! current_user_can( 'edit_posts' ) ) + $comments_query['status'] = 'approve'; + + while ( count( $comments ) < $total_items && $possible = get_comments( $comments_query ) ) { + foreach ( $possible as $comment ) { + if ( ! current_user_can( 'read_post', $comment->comment_post_ID ) ) + continue; + $comments[] = $comment; + if ( count( $comments ) == $total_items ) + break 2; + } + $comments_query['offset'] += $comments_query['number']; + $comments_query['number'] = $total_items * 10; + } + + if ( $comments ) { + echo '
'; + foreach ( $comments as $comment ) + _wp_dashboard_recent_comments_row( $comment ); + echo '
'; + + if ( current_user_can('edit_posts') ) + _get_list_table('WP_Comments_List_Table')->views(); + + wp_comment_reply( -1, false, 'dashboard', false ); + wp_comment_trashnotice(); + } else { + echo '

' . __( 'No comments yet.' ) . '

'; + } +} + +function _wp_dashboard_recent_comments_row( &$comment, $show_date = true ) { + $GLOBALS['comment'] =& $comment; + + $comment_post_url = get_edit_post_link( $comment->comment_post_ID ); + $comment_post_title = strip_tags(get_the_title( $comment->comment_post_ID )); + $comment_post_link = "$comment_post_title"; + $comment_link = '#'; + + $actions_string = ''; + if ( current_user_can( 'edit_comment', $comment->comment_ID ) ) { + // preorder it: Approve | Reply | Edit | Spam | Trash + $actions = array( + 'approve' => '', 'unapprove' => '', + 'reply' => '', + 'edit' => '', + 'spam' => '', + 'trash' => '', 'delete' => '' + ); + + $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); + $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); + + $approve_url = esc_url( "comment.php?action=approvecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$approve_nonce" ); + $unapprove_url = esc_url( "comment.php?action=unapprovecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$approve_nonce" ); + $spam_url = esc_url( "comment.php?action=spamcomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" ); + $trash_url = esc_url( "comment.php?action=trashcomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" ); + $delete_url = esc_url( "comment.php?action=deletecomment&p=$comment->comment_post_ID&c=$comment->comment_ID&$del_nonce" ); + + $actions['approve'] = "" . __( 'Approve' ) . ''; + $actions['unapprove'] = "" . __( 'Unapprove' ) . ''; + $actions['edit'] = "". __('Edit') . ''; + $actions['reply'] = '' . __('Reply') . ''; + $actions['spam'] = "" . /* translators: mark as spam link */ _x( 'Spam', 'verb' ) . ''; + if ( !EMPTY_TRASH_DAYS ) + $actions['delete'] = "" . __('Delete Permanently') . ''; + else + $actions['trash'] = "" . _x('Trash', 'verb') . ''; + + $actions = apply_filters( 'comment_row_actions', array_filter($actions), $comment ); + + $i = 0; + foreach ( $actions as $action => $link ) { + ++$i; + ( ( ('approve' == $action || 'unapprove' == $action) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | '; + + // Reply and quickedit need a hide-if-no-js span + if ( 'reply' == $action || 'quickedit' == $action ) + $action .= ' hide-if-no-js'; + + $actions_string .= "$sep$link"; + } + } + +?> + +
comment_ID) ) ); ?>> + comment_type || 'comment' == $comment->comment_type ) : ?> + + + +
+

+ ' . get_comment_author_link() . '', $comment_post_link.' '.$comment_link, ' ' . __( '[Pending]' ) . '' ); ?> +

+ + comment_type ) : + case 'pingback' : + $type = __( 'Pingback' ); + break; + case 'trackback' : + $type = __( 'Trackback' ); + break; + default : + $type = ucwords( $comment->comment_type ); + endswitch; + $type = esc_html( $type ); + ?> +
+ +

$type", $comment_post_link." ".$comment_link ); ?>

+

+ + +

+

+
+
+'; + echo '

'; +} + +function wp_dashboard_incoming_links() { + wp_dashboard_cached_rss_widget( 'dashboard_incoming_links', 'wp_dashboard_incoming_links_output' ); +} + +/** + * Display incoming links dashboard widget content. + * + * @since 2.5.0 + */ +function wp_dashboard_incoming_links_output() { + $widgets = get_option( 'dashboard_widget_options' ); + @extract( @$widgets['dashboard_incoming_links'], EXTR_SKIP ); + $rss = fetch_feed( $url ); + + if ( is_wp_error($rss) ) { + if ( is_admin() || current_user_can('manage_options') ) { + echo '

'; + printf(__('RSS Error: %s'), $rss->get_error_message()); + echo '

'; + } + return; + } + + if ( !$rss->get_item_quantity() ) { + echo '

' . __('This dashboard widget queries Google Blog Search so that when another blog links to your site it will show up here. It has found no incoming links… yet. It’s okay — there is no rush.') . "

\n"; + $rss->__destruct(); + unset($rss); + return; + } + + echo "
    \n"; + + if ( !isset($items) ) + $items = 10; + + foreach ( $rss->get_items(0, $items) as $item ) { + $publisher = ''; + $site_link = ''; + $link = ''; + $content = ''; + $date = ''; + $link = esc_url( strip_tags( $item->get_link() ) ); + + $author = $item->get_author(); + if ( $author ) { + $site_link = esc_url( strip_tags( $author->get_link() ) ); + + if ( !$publisher = esc_html( strip_tags( $author->get_name() ) ) ) + $publisher = __( 'Somebody' ); + } else { + $publisher = __( 'Somebody' ); + } + if ( $site_link ) + $publisher = "$publisher"; + else + $publisher = "$publisher"; + + $content = $item->get_content(); + $content = wp_html_excerpt( $content, 50, ' …' ); + + if ( $link ) + /* translators: incoming links feed, %1$s is other person, %3$s is content */ + $text = __( '%1$s linked here saying, "%3$s"' ); + else + /* translators: incoming links feed, %1$s is other person, %3$s is content */ + $text = __( '%1$s linked here saying, "%3$s"' ); + + if ( !empty( $show_date ) ) { + if ( $link ) + /* translators: incoming links feed, %1$s is other person, %3$s is content, %4$s is the date */ + $text = __( '%1$s linked here saying, "%3$s" on %4$s' ); + else + /* translators: incoming links feed, %1$s is other person, %3$s is content, %4$s is the date */ + $text = __( '%1$s linked here saying, "%3$s" on %4$s' ); + $date = esc_html( strip_tags( $item->get_date() ) ); + $date = strtotime( $date ); + $date = gmdate( get_option( 'date_format' ), $date ); + } + + echo "\t
  • " . sprintf( $text, $publisher, $link, $content, $date ) . "
  • \n"; + } + + echo "
\n"; + $rss->__destruct(); + unset($rss); +} + +function wp_dashboard_incoming_links_control() { + wp_dashboard_rss_control( 'dashboard_incoming_links', array( 'title' => false, 'show_summary' => false, 'show_author' => false ) ); +} + +function wp_dashboard_primary() { + wp_dashboard_cached_rss_widget( 'dashboard_primary', 'wp_dashboard_rss_output' ); +} + +function wp_dashboard_primary_control() { + wp_dashboard_rss_control( 'dashboard_primary' ); +} + +/** + * Display primary dashboard RSS widget feed. + * + * @since 2.5.0 + * + * @param string $widget_id + */ +function wp_dashboard_rss_output( $widget_id ) { + $widgets = get_option( 'dashboard_widget_options' ); + echo '
'; + wp_widget_rss_output( $widgets[$widget_id] ); + echo "
"; +} + +function wp_dashboard_secondary() { + wp_dashboard_cached_rss_widget( 'dashboard_secondary', 'wp_dashboard_secondary_output' ); +} + +function wp_dashboard_secondary_control() { + wp_dashboard_rss_control( 'dashboard_secondary' ); +} + +/** + * Display secondary dashboard RSS widget feed. + * + * @since 2.5.0 + * + * @return unknown + */ +function wp_dashboard_secondary_output() { + $widgets = get_option( 'dashboard_widget_options' ); + @extract( @$widgets['dashboard_secondary'], EXTR_SKIP ); + $rss = @fetch_feed( $url ); + + if ( is_wp_error($rss) ) { + if ( is_admin() || current_user_can('manage_options') ) { + echo '

'; + printf(__('RSS Error: %s'), $rss->get_error_message()); + echo '

'; + } + } elseif ( !$rss->get_item_quantity() ) { + $rss->__destruct(); + unset($rss); + return false; + } else { + echo '
'; + wp_widget_rss_output( $rss, $widgets['dashboard_secondary'] ); + echo '
'; + $rss->__destruct(); + unset($rss); + } +} + +function wp_dashboard_plugins() { + wp_dashboard_cached_rss_widget( 'dashboard_plugins', 'wp_dashboard_plugins_output', array( + 'http://wordpress.org/plugins/rss/browse/popular/', + 'http://wordpress.org/plugins/rss/browse/new/' + ) ); +} + +/** + * Display plugins most popular, newest plugins, and recently updated widget text. + * + * @since 2.5.0 + */ +function wp_dashboard_plugins_output() { + $popular = fetch_feed( 'http://wordpress.org/plugins/rss/browse/popular/' ); + $new = fetch_feed( 'http://wordpress.org/plugins/rss/browse/new/' ); + + if ( false === $plugin_slugs = get_transient( 'plugin_slugs' ) ) { + $plugin_slugs = array_keys( get_plugins() ); + set_transient( 'plugin_slugs', $plugin_slugs, DAY_IN_SECONDS ); + } + + foreach ( array( 'popular' => __('Most Popular'), 'new' => __('Newest Plugins') ) as $feed => $label ) { + if ( is_wp_error($$feed) || !$$feed->get_item_quantity() ) + continue; + + $items = $$feed->get_items(0, 5); + + // Pick a random, non-installed plugin + while ( true ) { + // Abort this foreach loop iteration if there's no plugins left of this type + if ( 0 == count($items) ) + continue 2; + + $item_key = array_rand($items); + $item = $items[$item_key]; + + list($link, $frag) = explode( '#', $item->get_link() ); + + $link = esc_url($link); + if ( preg_match( '|/([^/]+?)/?$|', $link, $matches ) ) + $slug = $matches[1]; + else { + unset( $items[$item_key] ); + continue; + } + + // Is this random plugin's slug already installed? If so, try again. + reset( $plugin_slugs ); + foreach ( $plugin_slugs as $plugin_slug ) { + if ( $slug == substr( $plugin_slug, 0, strlen( $slug ) ) ) { + unset( $items[$item_key] ); + continue 2; + } + } + + // If we get to this point, then the random plugin isn't installed and we can stop the while(). + break; + } + + // Eliminate some common badly formed plugin descriptions + while ( ( null !== $item_key = array_rand($items) ) && false !== strpos( $items[$item_key]->get_description(), 'Plugin Name:' ) ) + unset($items[$item_key]); + + if ( !isset($items[$item_key]) ) + continue; + + $title = esc_html( $item->get_title() ); + + $description = esc_html( strip_tags(@html_entity_decode($item->get_description(), ENT_QUOTES, get_option('blog_charset'))) ); + + $ilink = wp_nonce_url('plugin-install.php?tab=plugin-information&plugin=' . $slug, 'install-plugin_' . $slug) . + '&TB_iframe=true&width=600&height=800'; + + echo "

$label

\n"; + echo "
$title
 (" . __( 'Install' ) . ")\n"; + echo "

$description

\n"; + + $$feed->__destruct(); + unset($$feed); + } +} + +/** + * Checks to see if all of the feed url in $check_urls are cached. + * + * If $check_urls is empty, look for the rss feed url found in the dashboard + * widget options of $widget_id. If cached, call $callback, a function that + * echoes out output for this widget. If not cache, echo a "Loading..." stub + * which is later replaced by AJAX call (see top of /wp-admin/index.php) + * + * @since 2.5.0 + * + * @param string $widget_id + * @param callback $callback + * @param array $check_urls RSS feeds + * @return bool False on failure. True on success. + */ +function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array() ) { + $loading = '

' . __( 'Loading…' ) . '

' . __( 'This widget requires JavaScript.' ) . '

'; + $doing_ajax = ( defined('DOING_AJAX') && DOING_AJAX ); + + if ( empty($check_urls) ) { + $widgets = get_option( 'dashboard_widget_options' ); + if ( empty($widgets[$widget_id]['url']) && ! $doing_ajax ) { + echo $loading; + return false; + } + $check_urls = array( $widgets[$widget_id]['url'] ); + } + + $cache_key = 'dash_' . md5( $widget_id ); + if ( false !== ( $output = get_transient( $cache_key ) ) ) { + echo $output; + return true; + } + + if ( ! $doing_ajax ) { + echo $loading; + return false; + } + + if ( $callback && is_callable( $callback ) ) { + $args = array_slice( func_get_args(), 2 ); + array_unshift( $args, $widget_id ); + ob_start(); + call_user_func_array( $callback, $args ); + set_transient( $cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS ); // Default lifetime in cache of 12 hours (same as the feeds) + } + + return true; +} + +/* Dashboard Widgets Controls */ + +// Calls widget_control callback +/** + * Calls widget control callback. + * + * @since 2.5.0 + * + * @param int $widget_control_id Registered Widget ID. + */ +function wp_dashboard_trigger_widget_control( $widget_control_id = false ) { + global $wp_dashboard_control_callbacks; + + if ( is_scalar($widget_control_id) && $widget_control_id && isset($wp_dashboard_control_callbacks[$widget_control_id]) && is_callable($wp_dashboard_control_callbacks[$widget_control_id]) ) { + call_user_func( $wp_dashboard_control_callbacks[$widget_control_id], '', array( 'id' => $widget_control_id, 'callback' => $wp_dashboard_control_callbacks[$widget_control_id] ) ); + } +} + +/** + * The RSS dashboard widget control. + * + * Sets up $args to be used as input to wp_widget_rss_form(). Handles POST data + * from RSS-type widgets. + * + * @since 2.5.0 + * + * @param string $widget_id + * @param array $form_inputs + */ +function wp_dashboard_rss_control( $widget_id, $form_inputs = array() ) { + if ( !$widget_options = get_option( 'dashboard_widget_options' ) ) + $widget_options = array(); + + if ( !isset($widget_options[$widget_id]) ) + $widget_options[$widget_id] = array(); + + $number = 1; // Hack to use wp_widget_rss_form() + $widget_options[$widget_id]['number'] = $number; + + if ( 'POST' == $_SERVER['REQUEST_METHOD'] && isset($_POST['widget-rss'][$number]) ) { + $_POST['widget-rss'][$number] = wp_unslash( $_POST['widget-rss'][$number] ); + $widget_options[$widget_id] = wp_widget_rss_process( $_POST['widget-rss'][$number] ); + $widget_options[$widget_id]['number'] = $number; + // title is optional. If black, fill it if possible + if ( !$widget_options[$widget_id]['title'] && isset($_POST['widget-rss'][$number]['title']) ) { + $rss = fetch_feed($widget_options[$widget_id]['url']); + if ( is_wp_error($rss) ) { + $widget_options[$widget_id]['title'] = htmlentities(__('Unknown Feed')); + } else { + $widget_options[$widget_id]['title'] = htmlentities(strip_tags($rss->get_title())); + $rss->__destruct(); + unset($rss); + } + } + update_option( 'dashboard_widget_options', $widget_options ); + $cache_key = 'dash_' . md5( $widget_id ); + delete_transient( $cache_key ); + } + + wp_widget_rss_form( $widget_options[$widget_id], $form_inputs ); +} + +/** + * Display file upload quota on dashboard. + * + * Runs on the activity_box_end hook in wp_dashboard_right_now(). + * + * @since 3.0.0 + * + * @return bool True if not multisite, user can't upload files, or the space check option is disabled. +*/ +function wp_dashboard_quota() { + if ( !is_multisite() || !current_user_can('upload_files') || get_site_option( 'upload_space_check_disabled' ) ) + return true; + + $quota = get_space_allowed(); + $used = get_space_used(); + + if ( $used > $quota ) + $percentused = '100'; + else + $percentused = ( $used / $quota ) * 100; + $used_color = ( $percentused >= 70 ) ? ' spam' : ''; + $used = round( $used, 2 ); + $percentused = number_format( $percentused ); + + ?> +

+
+ + + + + +
%2$sMB' ), esc_url( admin_url( 'upload.php' ) ), number_format_i18n( $quota ) ); ?>
+
+
+ + + + + +
%2$sMB (%3$s%%)' ), esc_url( admin_url( 'upload.php' ) ), number_format_i18n( $used, 2 ), $percentused ); ?>
+
+
+ %s. Using an outdated browser makes your computer unsafe. For the best WordPress experience, please update your browser." ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ) ); + } else { + $msg = sprintf( __( "It looks like you're using an old version of %s. For the best WordPress experience, please update your browser." ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ) ); + } + + $browser_nag_class = ''; + if ( !empty( $response['img_src'] ) ) { + $img_src = ( is_ssl() && ! empty( $response['img_src_ssl'] ) )? $response['img_src_ssl'] : $response['img_src']; + + $notice .= '
'; + $browser_nag_class = ' has-browser-icon'; + } + $notice .= "

{$msg}

"; + + $browsehappy = 'http://browsehappy.com/'; + $locale = get_locale(); + if ( 'en_US' !== $locale ) + $browsehappy = add_query_arg( 'locale', $locale, $browsehappy ); + + $notice .= '

' . sprintf( __( 'Update %2$s or learn how to browse happy' ), esc_attr( $response['update_url'] ), esc_html( $response['name'] ), esc_url( $browsehappy ) ) . '

'; + $notice .= '

' . __( 'Dismiss' ) . '

'; + $notice .= '
'; + } + + echo apply_filters( 'browse-happy-notice', $notice, $response ); +} + +function dashboard_browser_nag_class( $classes ) { + $response = wp_check_browser_version(); + + if ( $response && $response['insecure'] ) + $classes[] = 'browser-insecure'; + + return $classes; +} + +/** + * Check if the user needs a browser update + * + * @since 3.2.0 + * + * @return array|bool False on failure, array of browser data on success. + */ +function wp_check_browser_version() { + if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) + return false; + + $key = md5( $_SERVER['HTTP_USER_AGENT'] ); + + if ( false === ($response = get_site_transient('browser_' . $key) ) ) { + global $wp_version; + + $options = array( + 'body' => array( 'useragent' => $_SERVER['HTTP_USER_AGENT'] ), + 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url() + ); + + $response = wp_remote_post( 'http://api.wordpress.org/core/browse-happy/1.1/', $options ); + + if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) + return false; + + /** + * Response should be an array with: + * 'name' - string - A user friendly browser name + * 'version' - string - The most recent version of the browser + * 'current_version' - string - The version of the browser the user is using + * 'upgrade' - boolean - Whether the browser needs an upgrade + * 'insecure' - boolean - Whether the browser is deemed insecure + * 'upgrade_url' - string - The url to visit to upgrade + * 'img_src' - string - An image representing the browser + * 'img_src_ssl' - string - An image (over SSL) representing the browser + */ + $response = json_decode( wp_remote_retrieve_body( $response ), true ); + + if ( ! is_array( $response ) ) + return false; + + set_site_transient( 'browser_' . $key, $response, WEEK_IN_SECONDS ); + } + + return $response; +} + +/** + * Empty function usable by plugins to output empty dashboard widget (to be populated later by JS). + */ +function wp_dashboard_empty() {} + +/** + * Displays a welcome panel to introduce users to WordPress. + * + * @since 3.3.0 + */ +function wp_welcome_panel() { + ?> +
+

+

+
+
+

+ + + true ) ) ) > 1 ) ) : ?> +

change your theme completely' ), admin_url( 'themes.php' ) ); ?>

+ +
+
+

+
    + +
  • ' . __( 'Edit your front page' ) . '', get_edit_post_link( get_option( 'page_on_front' ) ) ); ?>
  • +
  • ' . __( 'Add additional pages' ) . '', admin_url( 'post-new.php?post_type=page' ) ); ?>
  • + +
  • ' . __( 'Edit your front page' ) . '', get_edit_post_link( get_option( 'page_on_front' ) ) ); ?>
  • +
  • ' . __( 'Add additional pages' ) . '', admin_url( 'post-new.php?post_type=page' ) ); ?>
  • +
  • ' . __( 'Add a blog post' ) . '', admin_url( 'post-new.php' ) ); ?>
  • + +
  • ' . __( 'Write your first blog post' ) . '', admin_url( 'post-new.php' ) ); ?>
  • +
  • ' . __( 'Add an About page' ) . '', admin_url( 'post-new.php?post_type=page' ) ); ?>
  • + +
  • ' . __( 'View your site' ) . '', home_url( '/' ) ); ?>
  • +
+
+
+

+
', admin_url( 'widgets.php' ), admin_url( 'nav-menus.php' ) ); ?> +
  • ' . __( 'Turn comments on or off' ) . '', admin_url( 'options-discussion.php' ) ); ?>
  • +
  • ' . __( 'Learn more about getting started' ) . '', __( 'http://codex.wordpress.org/First_Steps_With_WordPress' ) ); ?>
  • + +
    +
    +
    + 0) ); + + if ( $categories ) { + foreach ( $categories as $category ) { + if ( $currentcat != $category->term_id && $parent == $category->parent) { + $pad = str_repeat( '– ', $level ); + $category->name = esc_html( $category->name ); + echo "\n\t"; + wp_dropdown_cats( $currentcat, $currentparent, $category->term_id, $level +1, $categories ); + } + } + } else { + return false; + } +} + +/** + * Register a setting and its sanitization callback + * + * @since 2.7.0 + * @deprecated 3.0.0 + * @deprecated Use register_setting() + * @see register_setting() + * + * @param string $option_group A settings group name. Should correspond to a whitelisted option key name. + * Default whitelisted option key names include "general," "discussion," and "reading," among others. + * @param string $option_name The name of an option to sanitize and save. + * @param unknown_type $sanitize_callback A callback function that sanitizes the option's value. + * @return unknown + */ +function add_option_update_handler( $option_group, $option_name, $sanitize_callback = '' ) { + _deprecated_function( __FUNCTION__, '3.0', 'register_setting()' ); + return register_setting( $option_group, $option_name, $sanitize_callback ); +} + +/** + * Unregister a setting + * + * @since 2.7.0 + * @deprecated 3.0.0 + * @deprecated Use unregister_setting() + * @see unregister_setting() + * + * @param unknown_type $option_group + * @param unknown_type $option_name + * @param unknown_type $sanitize_callback + * @return unknown + */ +function remove_option_update_handler( $option_group, $option_name, $sanitize_callback = '' ) { + _deprecated_function( __FUNCTION__, '3.0', 'unregister_setting()' ); + return unregister_setting( $option_group, $option_name, $sanitize_callback ); +} + +/** + * Determines the language to use for CodePress syntax highlighting. + * + * @since 2.8.0 + * @deprecated 3.0.0 + * + * @param string $filename +**/ +function codepress_get_lang( $filename ) { + _deprecated_function( __FUNCTION__, '3.0' ); + return; +} + +/** + * Adds Javascript required to make CodePress work on the theme/plugin editors. + * + * @since 2.8.0 + * @deprecated 3.0.0 +**/ +function codepress_footer_js() { + _deprecated_function( __FUNCTION__, '3.0' ); + return; +} + +/** + * Determine whether to use CodePress. + * + * @since 2.8.0 + * @deprecated 3.0.0 +**/ +function use_codepress() { + _deprecated_function( __FUNCTION__, '3.0' ); + return; +} + +/** + * @deprecated 3.1.0 + * + * @return array List of user IDs. + */ +function get_author_user_ids() { + _deprecated_function( __FUNCTION__, '3.1', 'get_users()' ); + + global $wpdb; + if ( !is_multisite() ) + $level_key = $wpdb->get_blog_prefix() . 'user_level'; + else + $level_key = $wpdb->get_blog_prefix() . 'capabilities'; // wpmu site admins don't have user_levels + + return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value != '0'", $level_key) ); +} + +/** + * @deprecated 3.1.0 + * + * @param int $user_id User ID. + * @return array|bool List of editable authors. False if no editable users. + */ +function get_editable_authors( $user_id ) { + _deprecated_function( __FUNCTION__, '3.1', 'get_users()' ); + + global $wpdb; + + $editable = get_editable_user_ids( $user_id ); + + if ( !$editable ) { + return false; + } else { + $editable = join(',', $editable); + $authors = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($editable) ORDER BY display_name" ); + } + + return apply_filters('get_editable_authors', $authors); +} + +/** + * @deprecated 3.1.0 + * + * @param int $user_id User ID. + * @param bool $exclude_zeros Optional, default is true. Whether to exclude zeros. + * @return unknown + */ +function get_editable_user_ids( $user_id, $exclude_zeros = true, $post_type = 'post' ) { + _deprecated_function( __FUNCTION__, '3.1', 'get_users()' ); + + global $wpdb; + + if ( ! $user = get_userdata( $user_id ) ) + return array(); + $post_type_obj = get_post_type_object($post_type); + + if ( ! $user->has_cap($post_type_obj->cap->edit_others_posts) ) { + if ( $user->has_cap($post_type_obj->cap->edit_posts) || ! $exclude_zeros ) + return array($user->ID); + else + return array(); + } + + if ( !is_multisite() ) + $level_key = $wpdb->get_blog_prefix() . 'user_level'; + else + $level_key = $wpdb->get_blog_prefix() . 'capabilities'; // wpmu site admins don't have user_levels + + $query = $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s", $level_key); + if ( $exclude_zeros ) + $query .= " AND meta_value != '0'"; + + return $wpdb->get_col( $query ); +} + +/** + * @deprecated 3.1.0 + */ +function get_nonauthor_user_ids() { + _deprecated_function( __FUNCTION__, '3.1', 'get_users()' ); + + global $wpdb; + + if ( !is_multisite() ) + $level_key = $wpdb->get_blog_prefix() . 'user_level'; + else + $level_key = $wpdb->get_blog_prefix() . 'capabilities'; // wpmu site admins don't have user_levels + + return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value = '0'", $level_key) ); +} + +if ( !class_exists('WP_User_Search') ) : +/** + * WordPress User Search class. + * + * @since 2.1.0 + * @deprecated 3.1.0 + */ +class WP_User_Search { + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var unknown_type + */ + var $results; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var unknown_type + */ + var $search_term; + + /** + * Page number. + * + * @since 2.1.0 + * @access private + * @var int + */ + var $page; + + /** + * Role name that users have. + * + * @since 2.5.0 + * @access private + * @var string + */ + var $role; + + /** + * Raw page number. + * + * @since 2.1.0 + * @access private + * @var int|bool + */ + var $raw_page; + + /** + * Amount of users to display per page. + * + * @since 2.1.0 + * @access public + * @var int + */ + var $users_per_page = 50; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var unknown_type + */ + var $first_user; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var int + */ + var $last_user; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var string + */ + var $query_limit; + + /** + * {@internal Missing Description}} + * + * @since 3.0.0 + * @access private + * @var string + */ + var $query_orderby; + + /** + * {@internal Missing Description}} + * + * @since 3.0.0 + * @access private + * @var string + */ + var $query_from; + + /** + * {@internal Missing Description}} + * + * @since 3.0.0 + * @access private + * @var string + */ + var $query_where; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var int + */ + var $total_users_for_query = 0; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var bool + */ + var $too_many_total_users = false; + + /** + * {@internal Missing Description}} + * + * @since 2.1.0 + * @access private + * @var unknown_type + */ + var $search_errors; + + /** + * {@internal Missing Description}} + * + * @since 2.7.0 + * @access private + * @var unknown_type + */ + var $paging_text; + + /** + * PHP4 Constructor - Sets up the object properties. + * + * @since 2.1.0 + * + * @param string $search_term Search terms string. + * @param int $page Optional. Page ID. + * @param string $role Role name. + * @return WP_User_Search + */ + function WP_User_Search ($search_term = '', $page = '', $role = '') { + _deprecated_function( __FUNCTION__, '3.1', 'WP_User_Query' ); + + $this->search_term = wp_unslash( $search_term ); + $this->raw_page = ( '' == $page ) ? false : (int) $page; + $this->page = (int) ( '' == $page ) ? 1 : $page; + $this->role = $role; + + $this->prepare_query(); + $this->query(); + $this->do_paging(); + } + + /** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * @access public + */ + function prepare_query() { + global $wpdb; + $this->first_user = ($this->page - 1) * $this->users_per_page; + + $this->query_limit = $wpdb->prepare(" LIMIT %d, %d", $this->first_user, $this->users_per_page); + $this->query_orderby = ' ORDER BY user_login'; + + $search_sql = ''; + if ( $this->search_term ) { + $searches = array(); + $search_sql = 'AND ('; + foreach ( array('user_login', 'user_nicename', 'user_email', 'user_url', 'display_name') as $col ) + $searches[] = $wpdb->prepare( $col . ' LIKE %s', '%' . like_escape($this->search_term) . '%' ); + $search_sql .= implode(' OR ', $searches); + $search_sql .= ')'; + } + + $this->query_from = " FROM $wpdb->users"; + $this->query_where = " WHERE 1=1 $search_sql"; + + if ( $this->role ) { + $this->query_from .= " INNER JOIN $wpdb->usermeta ON $wpdb->users.ID = $wpdb->usermeta.user_id"; + $this->query_where .= $wpdb->prepare(" AND $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%'); + } elseif ( is_multisite() ) { + $level_key = $wpdb->prefix . 'capabilities'; // wpmu site admins don't have user_levels + $this->query_from .= ", $wpdb->usermeta"; + $this->query_where .= " AND $wpdb->users.ID = $wpdb->usermeta.user_id AND meta_key = '{$level_key}'"; + } + + do_action_ref_array( 'pre_user_search', array( &$this ) ); + } + + /** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * @access public + */ + function query() { + global $wpdb; + + $this->results = $wpdb->get_col("SELECT DISTINCT($wpdb->users.ID)" . $this->query_from . $this->query_where . $this->query_orderby . $this->query_limit); + + if ( $this->results ) + $this->total_users_for_query = $wpdb->get_var("SELECT COUNT(DISTINCT($wpdb->users.ID))" . $this->query_from . $this->query_where); // no limit + else + $this->search_errors = new WP_Error('no_matching_users_found', __('No matching users were found!')); + } + + /** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * @access public + */ + function prepare_vars_for_template_usage() {} + + /** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * @access public + */ + function do_paging() { + if ( $this->total_users_for_query > $this->users_per_page ) { // have to page the results + $args = array(); + if( ! empty($this->search_term) ) + $args['usersearch'] = urlencode($this->search_term); + if( ! empty($this->role) ) + $args['role'] = urlencode($this->role); + + $this->paging_text = paginate_links( array( + 'total' => ceil($this->total_users_for_query / $this->users_per_page), + 'current' => $this->page, + 'base' => 'users.php?%_%', + 'format' => 'userspage=%#%', + 'add_args' => $args + ) ); + if ( $this->paging_text ) { + $this->paging_text = sprintf( '' . __( 'Displaying %s–%s of %s' ) . '%s', + number_format_i18n( ( $this->page - 1 ) * $this->users_per_page + 1 ), + number_format_i18n( min( $this->page * $this->users_per_page, $this->total_users_for_query ) ), + number_format_i18n( $this->total_users_for_query ), + $this->paging_text + ); + } + } + } + + /** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * @access public + * + * @return unknown + */ + function get_results() { + return (array) $this->results; + } + + /** + * Displaying paging text. + * + * @see do_paging() Builds paging text. + * + * @since 2.1.0 + * @access public + */ + function page_links() { + echo $this->paging_text; + } + + /** + * Whether paging is enabled. + * + * @see do_paging() Builds paging text. + * + * @since 2.1.0 + * @access public + * + * @return bool + */ + function results_are_paged() { + if ( $this->paging_text ) + return true; + return false; + } + + /** + * Whether there are search terms. + * + * @since 2.1.0 + * @access public + * + * @return bool + */ + function is_search() { + if ( $this->search_term ) + return true; + return false; + } +} +endif; + +/** + * Retrieve editable posts from other users. + * + * @deprecated 3.1.0 + * + * @param int $user_id User ID to not retrieve posts from. + * @param string $type Optional, defaults to 'any'. Post type to retrieve, can be 'draft' or 'pending'. + * @return array List of posts from others. + */ +function get_others_unpublished_posts($user_id, $type='any') { + _deprecated_function( __FUNCTION__, '3.1' ); + + global $wpdb; + + $editable = get_editable_user_ids( $user_id ); + + if ( in_array($type, array('draft', 'pending')) ) + $type_sql = " post_status = '$type' "; + else + $type_sql = " ( post_status = 'draft' OR post_status = 'pending' ) "; + + $dir = ( 'pending' == $type ) ? 'ASC' : 'DESC'; + + if ( !$editable ) { + $other_unpubs = ''; + } else { + $editable = join(',', $editable); + $other_unpubs = $wpdb->get_results( $wpdb->prepare("SELECT ID, post_title, post_author FROM $wpdb->posts WHERE post_type = 'post' AND $type_sql AND post_author IN ($editable) AND post_author != %d ORDER BY post_modified $dir", $user_id) ); + } + + return apply_filters('get_others_drafts', $other_unpubs); +} + +/** + * Retrieve drafts from other users. + * + * @deprecated 3.1.0 + * + * @param int $user_id User ID. + * @return array List of drafts from other users. + */ +function get_others_drafts($user_id) { + _deprecated_function( __FUNCTION__, '3.1' ); + + return get_others_unpublished_posts($user_id, 'draft'); +} + +/** + * Retrieve pending review posts from other users. + * + * @deprecated 3.1.0 + * + * @param int $user_id User ID. + * @return array List of posts with pending review post type from other users. + */ +function get_others_pending($user_id) { + _deprecated_function( __FUNCTION__, '3.1' ); + + return get_others_unpublished_posts($user_id, 'pending'); +} + +/** + * Output the QuickPress dashboard widget. + * + * @since 3.0.0 + * @deprecated 3.2.0 + * @deprecated Use wp_dashboard_quick_press() + * @see wp_dashboard_quick_press() + */ +function wp_dashboard_quick_press_output() { + _deprecated_function( __FUNCTION__, '3.2', 'wp_dashboard_quick_press()' ); + wp_dashboard_quick_press(); +} + +/** + * @since 2.7.0 + * @deprecated 3.3.0 + * @deprecated Use wp_editor() + * @see wp_editor() + */ +function wp_tiny_mce( $teeny = false, $settings = false ) { + _deprecated_function( __FUNCTION__, '3.3', 'wp_editor()' ); + + static $num = 1; + + if ( ! class_exists('_WP_Editors' ) ) + require_once( ABSPATH . WPINC . '/class-wp-editor.php' ); + + $editor_id = 'content' . $num++; + + $set = array( + 'teeny' => $teeny, + 'tinymce' => $settings ? $settings : true, + 'quicktags' => false + ); + + $set = _WP_Editors::parse_settings($editor_id, $set); + _WP_Editors::editor_settings($editor_id, $set); +} + +/** + * @deprecated 3.3.0 + * @deprecated Use wp_editor() + * @see wp_editor() + */ +function wp_preload_dialogs() { + _deprecated_function( __FUNCTION__, '3.3', 'wp_editor()' ); +} + +/** + * @deprecated 3.3.0 + * @deprecated Use wp_editor() + * @see wp_editor() + */ +function wp_print_editor_js() { + _deprecated_function( __FUNCTION__, '3.3', 'wp_editor()' ); +} + +/** + * @deprecated 3.3.0 + * @deprecated Use wp_editor() + * @see wp_editor() + */ +function wp_quicktags() { + _deprecated_function( __FUNCTION__, '3.3', 'wp_editor()' ); +} + +/** + * Returns the screen layout options. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * @deprecated Use $current_screen->render_screen_layout() + * @see WP_Screen::render_screen_layout() + */ +function screen_layout( $screen ) { + _deprecated_function( __FUNCTION__, '3.3', '$current_screen->render_screen_layout()' ); + + $current_screen = get_current_screen(); + + if ( ! $current_screen ) + return ''; + + ob_start(); + $current_screen->render_screen_layout(); + return ob_get_clean(); +} + +/** + * Returns the screen's per-page options. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * @deprecated Use $current_screen->render_per_page_options() + * @see WP_Screen::render_per_page_options() + */ +function screen_options( $screen ) { + _deprecated_function( __FUNCTION__, '3.3', '$current_screen->render_per_page_options()' ); + + $current_screen = get_current_screen(); + + if ( ! $current_screen ) + return ''; + + ob_start(); + $current_screen->render_per_page_options(); + return ob_get_clean(); +} + +/** + * Renders the screen's help. + * + * @since 2.7.0 + * @deprecated 3.3.0 + * @deprecated Use $current_screen->render_screen_meta() + * @see WP_Screen::render_screen_meta() + */ +function screen_meta( $screen ) { + $current_screen = get_current_screen(); + $current_screen->render_screen_meta(); +} + +/** + * Favorite actions were deprecated in version 3.2. Use the admin bar instead. + * + * @since 2.7.0 + * @deprecated 3.2.0 + */ +function favorite_actions() { + _deprecated_function( __FUNCTION__, '3.2', 'WP_Admin_Bar' ); +} + +function media_upload_image() { + __deprecated_function( __FUNCTION__, '3.3', 'wp_media_upload_handler()' ); + return wp_media_upload_handler(); +} + +function media_upload_audio() { + __deprecated_function( __FUNCTION__, '3.3', 'wp_media_upload_handler()' ); + return wp_media_upload_handler(); +} + +function media_upload_video() { + __deprecated_function( __FUNCTION__, '3.3', 'wp_media_upload_handler()' ); + return wp_media_upload_handler(); +} + +function media_upload_file() { + __deprecated_function( __FUNCTION__, '3.3', 'wp_media_upload_handler()' ); + return wp_media_upload_handler(); +} + +function type_url_form_image() { + __deprecated_function( __FUNCTION__, '3.3', "wp_media_insert_url_form('image')" ); + return wp_media_insert_url_form( 'image' ); +} + +function type_url_form_audio() { + __deprecated_function( __FUNCTION__, '3.3', "wp_media_insert_url_form('audio')" ); + return wp_media_insert_url_form( 'audio' ); +} + +function type_url_form_video() { + __deprecated_function( __FUNCTION__, '3.3', "wp_media_insert_url_form('video')" ); + return wp_media_insert_url_form( 'video' ); +} + +function type_url_form_file() { + __deprecated_function( __FUNCTION__, '3.3', "wp_media_insert_url_form('file')" ); + return wp_media_insert_url_form( 'file' ); +} + +/** + * Add contextual help text for a page. + * + * Creates an 'Overview' help tab. + * + * @since 2.7.0 + * @deprecated 3.3.0 + * @deprecated Use get_current_screen()->add_help_tab() + * @see WP_Screen + * + * @param string $screen The handle for the screen to add help to. This is usually the hook name returned by the add_*_page() functions. + * @param string $help The content of an 'Overview' help tab. + */ +function add_contextual_help( $screen, $help ) { + _deprecated_function( __FUNCTION__, '3.3', 'get_current_screen()->add_help_tab()' ); + + if ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + WP_Screen::add_old_compat_help( $screen, $help ); +} + +/** + * Get the allowed themes for the current blog. + * + * @since 3.0.0 + * @deprecated 3.4.0 + * @deprecated Use wp_get_themes() + * @see wp_get_themes() + * + * @return array $themes Array of allowed themes. + */ +function get_allowed_themes() { + _deprecated_function( __FUNCTION__, '3.4', "wp_get_themes( array( 'allowed' => true ) )" ); + + $themes = wp_get_themes( array( 'allowed' => true ) ); + + $wp_themes = array(); + foreach ( $themes as $theme ) { + $wp_themes[ $theme->get('Name') ] = $theme; + } + + return $wp_themes; +} + +/** + * {@internal Missing Short Description}} + * + * @since 1.5.0 + * @deprecated 3.4.0 + * + * @return unknown + */ +function get_broken_themes() { + _deprecated_function( __FUNCTION__, '3.4', "wp_get_themes( array( 'errors' => true )" ); + + $themes = wp_get_themes( array( 'errors' => true ) ); + $broken = array(); + foreach ( $themes as $theme ) { + $name = $theme->get('Name'); + $broken[ $name ] = array( + 'Name' => $name, + 'Title' => $name, + 'Description' => $theme->errors()->get_error_message(), + ); + } + return $broken; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.0.0 + * @deprecated 3.4.0 + * + * @return unknown + */ +function current_theme_info() { + _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme()' ); + + return wp_get_theme(); +} + +/** + * This was once used to display an 'Insert into Post' button. Now it is deprecated and stubbed. + * + * @deprecated 3.5.0 + */ +function _insert_into_post_button( $type ) { + _deprecated_function( __FUNCTION__, '3.5' ); +} + +/** + * This was once used to display a media button. Now it is deprecated and stubbed. + * + * @deprecated 3.5.0 + */ +function _media_button($title, $icon, $type, $id) { + _deprecated_function( __FUNCTION__, '3.5' ); +} + +/** + * Get an existing post and format it for editing. + * + * @since 2.0.0 + * @deprecated 3.5.0 + * + * @param int $id + * @return object + */ +function get_post_to_edit( $id ) { + _deprecated_function( __FUNCTION__, '3.5', 'get_post()' ); + + return get_post( $id, OBJECT, 'edit' ); +} + +/** + * Get the default page information to use. + * + * @since 2.5.0 + * @deprecated 3.5.0 + * @deprecated Use get_default_post_to_edit() + * + * @return WP_Post Post object containing all the default post data as attributes + */ +function get_default_page_to_edit() { + _deprecated_function( __FUNCTION__, '3.5', "get_default_post_to_edit( 'page' )" ); + + $page = get_default_post_to_edit(); + $page->post_type = 'page'; + return $page; +} + +/** + * This was once used to create a thumbnail from an Image given a maximum side size. + * + * @since 1.2.0 + * @deprecated 3.5.0 + * @deprecated Use image_resize() + * @see image_resize() + * + * @param mixed $file Filename of the original image, Or attachment id. + * @param int $max_side Maximum length of a single side for the thumbnail. + * @param mixed $deprecated Never used. + * @return string Thumbnail path on success, Error string on failure. + */ +function wp_create_thumbnail( $file, $max_side, $deprecated = '' ) { + _deprecated_function( __FUNCTION__, '3.5', 'image_resize()' ); + return apply_filters( 'wp_create_thumbnail', image_resize( $file, $max_side, $max_side ) ); +} + +/** + * This was once used to display a metabox for the nav menu theme locations. + * + * Deprecated in favor of a 'Manage Locations' tab added to nav menus management screen. + * + * @since 3.0.0 + * @deprecated 3.6.0 + */ +function wp_nav_menu_locations_meta_box() { + _deprecated_function( __FUNCTION__, '3.6' ); +} + +/** + * This was once used to kick-off the Core Updater. + * + * Deprecated in favor of instantating a Core_Upgrader instance directly, + * and calling the 'upgrade' method. + * + * @since 2.7.0 + * @deprecated 3.7.0 + */ +function wp_update_core($current, $feedback = '') { + _deprecated_function( __FUNCTION__, '3.7', 'new Core_Upgrader();' ); + + if ( !empty($feedback) ) + add_filter('update_feedback', $feedback); + + include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + $upgrader = new Core_Upgrader(); + return $upgrader->upgrade($current); + +} + +/** + * This was once used to kick-off the Plugin Updater. + * + * Deprecated in favor of instantating a Plugin_Upgrader instance directly, + * and calling the 'upgrade' method. + * Unused since 2.8.0. + * + * @since 2.5.0 + * @deprecated 3.7.0 + */ +function wp_update_plugin($plugin, $feedback = '') { + _deprecated_function( __FUNCTION__, '3.7', 'new Plugin_Upgrader();' ); + + if ( !empty($feedback) ) + add_filter('update_feedback', $feedback); + + include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + $upgrader = new Plugin_Upgrader(); + return $upgrader->upgrade($plugin); +} + +/** + * This was once used to kick-off the Plugin Updater. + * + * Deprecated in favor of instantating a Plugin_Upgrader instance directly, + * and calling the 'upgrade' method. + * Unused since 2.8.0. + * + * @since 2.7.0 + * @deprecated 3.7.0 + */ +function wp_update_theme($theme, $feedback = '') { + _deprecated_function( __FUNCTION__, '3.7', 'new Theme_Upgrader();' ); + + if ( !empty($feedback) ) + add_filter('update_feedback', $feedback); + + include ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + $upgrader = new Theme_Upgrader(); + return $upgrader->upgrade($theme); +} + +/** + * This was once used to display attachment links. Now it is deprecated and stubbed. + * + * {@internal Missing Short Description}} + * + * @since 2.0.0 + * @deprecated 3.7.0 + * + * @param unknown_type $id + * @return unknown + */ +function the_attachment_links( $id = false ) { + _deprecated_function( __FUNCTION__, '3.7' ); +} diff --git a/sources/wp-admin/includes/export.php b/sources/wp-admin/includes/export.php new file mode 100644 index 0000000..91d88a1 --- /dev/null +++ b/sources/wp-admin/includes/export.php @@ -0,0 +1,437 @@ + 'all', 'author' => false, 'category' => false, + 'start_date' => false, 'end_date' => false, 'status' => false, + ); + $args = wp_parse_args( $args, $defaults ); + + do_action( 'export_wp' ); + + $sitename = sanitize_key( get_bloginfo( 'name' ) ); + if ( ! empty($sitename) ) $sitename .= '.'; + $filename = $sitename . 'wordpress.' . date( 'Y-m-d' ) . '.xml'; + + header( 'Content-Description: File Transfer' ); + header( 'Content-Disposition: attachment; filename=' . $filename ); + header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true ); + + if ( 'all' != $args['content'] && post_type_exists( $args['content'] ) ) { + $ptype = get_post_type_object( $args['content'] ); + if ( ! $ptype->can_export ) + $args['content'] = 'post'; + + $where = $wpdb->prepare( "{$wpdb->posts}.post_type = %s", $args['content'] ); + } else { + $post_types = get_post_types( array( 'can_export' => true ) ); + $esses = array_fill( 0, count($post_types), '%s' ); + $where = $wpdb->prepare( "{$wpdb->posts}.post_type IN (" . implode( ',', $esses ) . ')', $post_types ); + } + + if ( $args['status'] && ( 'post' == $args['content'] || 'page' == $args['content'] ) ) + $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_status = %s", $args['status'] ); + else + $where .= " AND {$wpdb->posts}.post_status != 'auto-draft'"; + + $join = ''; + if ( $args['category'] && 'post' == $args['content'] ) { + if ( $term = term_exists( $args['category'], 'category' ) ) { + $join = "INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)"; + $where .= $wpdb->prepare( " AND {$wpdb->term_relationships}.term_taxonomy_id = %d", $term['term_taxonomy_id'] ); + } + } + + if ( 'post' == $args['content'] || 'page' == $args['content'] ) { + if ( $args['author'] ) + $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_author = %d", $args['author'] ); + + if ( $args['start_date'] ) + $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_date >= %s", date( 'Y-m-d', strtotime($args['start_date']) ) ); + + if ( $args['end_date'] ) + $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_date < %s", date( 'Y-m-d', strtotime('+1 month', strtotime($args['end_date'])) ) ); + } + + // grab a snapshot of post IDs, just in case it changes during the export + $post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} $join WHERE $where" ); + + // get the requested terms ready, empty unless posts filtered by category or all content + $cats = $tags = $terms = array(); + if ( isset( $term ) && $term ) { + $cat = get_term( $term['term_id'], 'category' ); + $cats = array( $cat->term_id => $cat ); + unset( $term, $cat ); + } else if ( 'all' == $args['content'] ) { + $categories = (array) get_categories( array( 'get' => 'all' ) ); + $tags = (array) get_tags( array( 'get' => 'all' ) ); + + $custom_taxonomies = get_taxonomies( array( '_builtin' => false ) ); + $custom_terms = (array) get_terms( $custom_taxonomies, array( 'get' => 'all' ) ); + + // put categories in order with no child going before its parent + while ( $cat = array_shift( $categories ) ) { + if ( $cat->parent == 0 || isset( $cats[$cat->parent] ) ) + $cats[$cat->term_id] = $cat; + else + $categories[] = $cat; + } + + // put terms in order with no child going before its parent + while ( $t = array_shift( $custom_terms ) ) { + if ( $t->parent == 0 || isset( $terms[$t->parent] ) ) + $terms[$t->term_id] = $t; + else + $custom_terms[] = $t; + } + + unset( $categories, $custom_taxonomies, $custom_terms ); + } + + /** + * Wrap given string in XML CDATA tag. + * + * @since 2.1.0 + * + * @param string $str String to wrap in XML CDATA tag. + * @return string + */ + function wxr_cdata( $str ) { + if ( seems_utf8( $str ) == false ) + $str = utf8_encode( $str ); + + // $str = ent2ncr(esc_html($str)); + $str = '', ']]]]>', $str ) . ']]>'; + + return $str; + } + + /** + * Return the URL of the site + * + * @since 2.5.0 + * + * @return string Site URL. + */ + function wxr_site_url() { + // ms: the base url + if ( is_multisite() ) + return network_home_url(); + // wp: the blog url + else + return get_bloginfo_rss( 'url' ); + } + + /** + * Output a cat_name XML tag from a given category object + * + * @since 2.1.0 + * + * @param object $category Category Object + */ + function wxr_cat_name( $category ) { + if ( empty( $category->name ) ) + return; + + echo '' . wxr_cdata( $category->name ) . ''; + } + + /** + * Output a category_description XML tag from a given category object + * + * @since 2.1.0 + * + * @param object $category Category Object + */ + function wxr_category_description( $category ) { + if ( empty( $category->description ) ) + return; + + echo '' . wxr_cdata( $category->description ) . ''; + } + + /** + * Output a tag_name XML tag from a given tag object + * + * @since 2.3.0 + * + * @param object $tag Tag Object + */ + function wxr_tag_name( $tag ) { + if ( empty( $tag->name ) ) + return; + + echo '' . wxr_cdata( $tag->name ) . ''; + } + + /** + * Output a tag_description XML tag from a given tag object + * + * @since 2.3.0 + * + * @param object $tag Tag Object + */ + function wxr_tag_description( $tag ) { + if ( empty( $tag->description ) ) + return; + + echo '' . wxr_cdata( $tag->description ) . ''; + } + + /** + * Output a term_name XML tag from a given term object + * + * @since 2.9.0 + * + * @param object $term Term Object + */ + function wxr_term_name( $term ) { + if ( empty( $term->name ) ) + return; + + echo '' . wxr_cdata( $term->name ) . ''; + } + + /** + * Output a term_description XML tag from a given term object + * + * @since 2.9.0 + * + * @param object $term Term Object + */ + function wxr_term_description( $term ) { + if ( empty( $term->description ) ) + return; + + echo '' . wxr_cdata( $term->description ) . ''; + } + + /** + * Output list of authors with posts + * + * @since 3.1.0 + */ + function wxr_authors_list() { + global $wpdb; + + $authors = array(); + $results = $wpdb->get_results( "SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft'" ); + foreach ( (array) $results as $result ) + $authors[] = get_userdata( $result->post_author ); + + $authors = array_filter( $authors ); + + foreach ( $authors as $author ) { + echo "\t"; + echo '' . $author->ID . ''; + echo '' . $author->user_login . ''; + echo '' . $author->user_email . ''; + echo '' . wxr_cdata( $author->display_name ) . ''; + echo '' . wxr_cdata( $author->user_firstname ) . ''; + echo '' . wxr_cdata( $author->user_lastname ) . ''; + echo "\n"; + } + } + + /** + * Ouput all navigation menu terms + * + * @since 3.1.0 + */ + function wxr_nav_menu_terms() { + $nav_menus = wp_get_nav_menus(); + if ( empty( $nav_menus ) || ! is_array( $nav_menus ) ) + return; + + foreach ( $nav_menus as $menu ) { + echo "\t{$menu->term_id}nav_menu{$menu->slug}"; + wxr_term_name( $menu ); + echo "\n"; + } + } + + /** + * Output list of taxonomy terms, in XML tag format, associated with a post + * + * @since 2.3.0 + */ + function wxr_post_taxonomy() { + $post = get_post(); + + $taxonomies = get_object_taxonomies( $post->post_type ); + if ( empty( $taxonomies ) ) + return; + $terms = wp_get_object_terms( $post->ID, $taxonomies ); + + foreach ( (array) $terms as $term ) { + echo "\t\ttaxonomy}\" nicename=\"{$term->slug}\">" . wxr_cdata( $term->name ) . "\n"; + } + } + + function wxr_filter_postmeta( $return_me, $meta_key ) { + if ( '_edit_lock' == $meta_key ) + $return_me = true; + return $return_me; + } + add_filter( 'wxr_export_skip_postmeta', 'wxr_filter_postmeta', 10, 2 ); + + echo '\n"; + + ?> + + + + + + + + + + + + + + + + + + + + + + <?php bloginfo_rss( 'name' ); ?> + + + + + + + + + + + + term_id ?>slug; ?>parent ? $cats[$c->parent]->slug : ''; ?> + + + term_id ?>slug; ?> + + + term_id ?>taxonomy; ?>slug; ?>parent ? $terms[$t->parent]->slug : ''; ?> + + + + + +in_the_loop = true; // Fake being in the loop. + + // fetch 20 posts at a time rather than loading the entire table into memory + while ( $next_posts = array_splice( $post_ids, 0, 20 ) ) { + $where = 'WHERE ID IN (' . join( ',', $next_posts ) . ')'; + $posts = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} $where" ); + + // Begin Loop + foreach ( $posts as $post ) { + setup_postdata( $post ); + $is_sticky = is_sticky( $post->ID ) ? 1 : 0; +?> + + + <?php echo apply_filters( 'the_title_rss', $post->post_title ); ?> + + + + + + post_content ) ); ?> + post_excerpt ) ); ?> + ID; ?> + post_date; ?> + post_date_gmt; ?> + comment_status; ?> + ping_status; ?> + post_name; ?> + post_status; ?> + post_parent; ?> + menu_order; ?> + post_type; ?> + post_password; ?> + +post_type == 'attachment' ) : ?> + ID ); ?> + + +get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID ) ); + foreach ( $postmeta as $meta ) : + if ( apply_filters( 'wxr_export_skip_postmeta', false, $meta->meta_key, $meta ) ) + continue; + ?> + + meta_key; ?> + meta_value ); ?> + + +get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID ) ); + foreach ( $comments as $c ) : ?> + + comment_ID; ?> + comment_author ); ?> + comment_author_email; ?> + comment_author_url ); ?> + comment_author_IP; ?> + comment_date; ?> + comment_date_gmt; ?> + comment_content ) ?> + comment_approved; ?> + comment_type; ?> + comment_parent; ?> + user_id; ?> +get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $c->comment_ID ) ); + foreach ( $c_meta as $meta ) : ?> + + meta_key; ?> + meta_value ); ?> + + + + + + + + + __( 'Main Index Template' ), + 'style.css' => __( 'Stylesheet' ), + 'editor-style.css' => __( 'Visual Editor Stylesheet' ), + 'editor-style-rtl.css' => __( 'Visual Editor RTL Stylesheet' ), + 'rtl.css' => __( 'RTL Stylesheet' ), + 'comments.php' => __( 'Comments' ), + 'comments-popup.php' => __( 'Popup Comments' ), + 'footer.php' => __( 'Footer' ), + 'header.php' => __( 'Header' ), + 'sidebar.php' => __( 'Sidebar' ), + 'archive.php' => __( 'Archives' ), + 'author.php' => __( 'Author Template' ), + 'tag.php' => __( 'Tag Template' ), + 'category.php' => __( 'Category Template' ), + 'page.php' => __( 'Page Template' ), + 'search.php' => __( 'Search Results' ), + 'searchform.php' => __( 'Search Form' ), + 'single.php' => __( 'Single Post' ), + '404.php' => __( '404 Template' ), + 'link.php' => __( 'Links Template' ), + 'functions.php' => __( 'Theme Functions' ), + 'attachment.php' => __( 'Attachment Template' ), + 'image.php' => __('Image Attachment Template'), + 'video.php' => __('Video Attachment Template'), + 'audio.php' => __('Audio Attachment Template'), + 'application.php' => __('Application Attachment Template'), + 'my-hacks.php' => __( 'my-hacks.php (legacy hacks support)' ), + '.htaccess' => __( '.htaccess (for rewrite rules )' ), + // Deprecated files + 'wp-layout.css' => __( 'Stylesheet' ), + 'wp-comments.php' => __( 'Comments Template' ), + 'wp-comments-popup.php' => __( 'Popup Comments Template' ), +); + +/** + * Get the description for standard WordPress theme files and other various standard + * WordPress files + * + * @since 1.5.0 + * + * @uses _cleanup_header_comment + * @uses $wp_file_descriptions + * @param string $file Filesystem path or filename + * @return string Description of file from $wp_file_descriptions or basename of $file if description doesn't exist + */ +function get_file_description( $file ) { + global $wp_file_descriptions; + + if ( isset( $wp_file_descriptions[basename( $file )] ) ) { + return $wp_file_descriptions[basename( $file )]; + } + elseif ( file_exists( $file ) && is_file( $file ) ) { + $template_data = implode( '', file( $file ) ); + if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name )) + return sprintf( __( '%s Page Template' ), _cleanup_header_comment($name[1]) ); + } + + return trim( basename( $file ) ); +} + +/** + * Get the absolute filesystem path to the root of the WordPress installation + * + * @since 1.5.0 + * + * @uses get_option + * @return string Full filesystem path to the root of the WordPress installation + */ +function get_home_path() { + $home = get_option( 'home' ); + $siteurl = get_option( 'siteurl' ); + if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) { + $wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */ + $pos = strripos( str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] ), trailingslashit( $wp_path_rel_to_home ) ); + $home_path = substr( $_SERVER['SCRIPT_FILENAME'], 0, $pos ); + $home_path = trailingslashit( $home_path ); + } else { + $home_path = ABSPATH; + } + + return str_replace( '\\', '/', $home_path ); +} + +/** + * Returns a listing of all files in the specified folder and all subdirectories up to 100 levels deep. + * The depth of the recursiveness can be controlled by the $levels param. + * + * @since 2.6.0 + * + * @param string $folder Full path to folder + * @param int $levels (optional) Levels of folders to follow, Default: 100 (PHP Loop limit). + * @return bool|array False on failure, Else array of files + */ +function list_files( $folder = '', $levels = 100 ) { + if ( empty($folder) ) + return false; + + if ( ! $levels ) + return false; + + $files = array(); + if ( $dir = @opendir( $folder ) ) { + while (($file = readdir( $dir ) ) !== false ) { + if ( in_array($file, array('.', '..') ) ) + continue; + if ( is_dir( $folder . '/' . $file ) ) { + $files2 = list_files( $folder . '/' . $file, $levels - 1); + if ( $files2 ) + $files = array_merge($files, $files2 ); + else + $files[] = $folder . '/' . $file . '/'; + } else { + $files[] = $folder . '/' . $file; + } + } + } + @closedir( $dir ); + return $files; +} + +/** + * Returns a filename of a Temporary unique file. + * Please note that the calling function must unlink() this itself. + * + * The filename is based off the passed parameter or defaults to the current unix timestamp, + * while the directory can either be passed as well, or by leaving it blank, default to a writable temporary directory. + * + * @since 2.6.0 + * + * @param string $filename (optional) Filename to base the Unique file off + * @param string $dir (optional) Directory to store the file in + * @return string a writable filename + */ +function wp_tempnam($filename = '', $dir = '') { + if ( empty($dir) ) + $dir = get_temp_dir(); + $filename = basename($filename); + if ( empty($filename) ) + $filename = time(); + + $filename = preg_replace('|\..*$|', '.tmp', $filename); + $filename = $dir . wp_unique_filename($dir, $filename); + touch($filename); + return $filename; +} + +/** + * Make sure that the file that was requested to edit, is allowed to be edited + * + * Function will die if if you are not allowed to edit the file + * + * @since 1.5.0 + * + * @uses wp_die + * @uses validate_file + * @param string $file file the users is attempting to edit + * @param array $allowed_files Array of allowed files to edit, $file must match an entry exactly + * @return null + */ +function validate_file_to_edit( $file, $allowed_files = '' ) { + $code = validate_file( $file, $allowed_files ); + + if (!$code ) + return $file; + + switch ( $code ) { + case 1 : + wp_die( __('Sorry, can’t edit files with “..” in the name. If you are trying to edit a file in your WordPress home directory, you can just type the name of the file in.' )); + + //case 2 : + // wp_die( __('Sorry, can’t call files with their real path.' )); + + case 3 : + wp_die( __('Sorry, that file cannot be edited.' )); + } +} + +/** + * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type, + * and moving the file to the appropriate directory within the uploads directory. + * + * @since 2.0 + * + * @uses wp_handle_upload_error + * @uses apply_filters + * @uses is_multisite + * @uses wp_check_filetype_and_ext + * @uses current_user_can + * @uses wp_upload_dir + * @uses wp_unique_filename + * @uses delete_transient + * @param array $file Reference to a single element of $_FILES. Call the function once for each uploaded file. + * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ). + * @param string $time Optional. Time formatted in 'yyyy/mm'. + * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). + */ +function wp_handle_upload( &$file, $overrides = false, $time = null ) { + // The default error handler. + if ( ! function_exists( 'wp_handle_upload_error' ) ) { + function wp_handle_upload_error( &$file, $message ) { + return array( 'error'=>$message ); + } + } + + $file = apply_filters( 'wp_handle_upload_prefilter', $file ); + + // You may define your own function and pass the name in $overrides['upload_error_handler'] + $upload_error_handler = 'wp_handle_upload_error'; + + // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully. + if ( isset( $file['error'] ) && !is_numeric( $file['error'] ) && $file['error'] ) + return $upload_error_handler( $file, $file['error'] ); + + // You may define your own function and pass the name in $overrides['unique_filename_callback'] + $unique_filename_callback = null; + + // $_POST['action'] must be set and its value must equal $overrides['action'] or this: + $action = 'wp_handle_upload'; + + // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. + $upload_error_strings = array( false, + __( "The uploaded file exceeds the upload_max_filesize directive in php.ini." ), + __( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." ), + __( "The uploaded file was only partially uploaded." ), + __( "No file was uploaded." ), + '', + __( "Missing a temporary folder." ), + __( "Failed to write file to disk." ), + __( "File upload stopped by extension." )); + + // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false; + $test_form = true; + $test_size = true; + $test_upload = true; + + // If you override this, you must provide $ext and $type!!!! + $test_type = true; + $mimes = false; + + // Install user overrides. Did we mention that this voids your warranty? + if ( is_array( $overrides ) ) + extract( $overrides, EXTR_OVERWRITE ); + + // A correct form post will pass this test. + if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) ) + return call_user_func($upload_error_handler, $file, __( 'Invalid form submission.' )); + + // A successful upload will pass this test. It makes no sense to override this one. + if ( $file['error'] > 0 ) + return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']] ); + + // A non-empty file will pass this test. + if ( $test_size && !($file['size'] > 0 ) ) { + if ( is_multisite() ) + $error_msg = __( 'File is empty. Please upload something more substantial.' ); + else + $error_msg = __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.' ); + return call_user_func($upload_error_handler, $file, $error_msg); + } + + // A properly uploaded file will pass this test. There should be no reason to override this one. + if ( $test_upload && ! @ is_uploaded_file( $file['tmp_name'] ) ) + return call_user_func($upload_error_handler, $file, __( 'Specified file failed upload test.' )); + + // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. + if ( $test_type ) { + $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes ); + + extract( $wp_filetype ); + + // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect + if ( $proper_filename ) + $file['name'] = $proper_filename; + + if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) + return call_user_func($upload_error_handler, $file, __( 'Sorry, this file type is not permitted for security reasons.' )); + + if ( !$ext ) + $ext = ltrim(strrchr($file['name'], '.'), '.'); + + if ( !$type ) + $type = $file['type']; + } else { + $type = ''; + } + + // A writable uploads dir will pass this test. Again, there's no point overriding this one. + if ( ! ( ( $uploads = wp_upload_dir($time) ) && false === $uploads['error'] ) ) + return call_user_func($upload_error_handler, $file, $uploads['error'] ); + + $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); + + // Move the file to the uploads dir + $new_file = $uploads['path'] . "/$filename"; + if ( false === @ move_uploaded_file( $file['tmp_name'], $new_file ) ) { + if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) + $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; + else + $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; + + return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $error_path ) ); + } + + // Set correct file permissions + $stat = stat( dirname( $new_file )); + $perms = $stat['mode'] & 0000666; + @ chmod( $new_file, $perms ); + + // Compute the URL + $url = $uploads['url'] . "/$filename"; + + if ( is_multisite() ) + delete_transient( 'dirsize_cache' ); + + return apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ), 'upload' ); +} + +/** + * Handle sideloads, which is the process of retrieving a media item from another server instead of + * a traditional media upload. This process involves sanitizing the filename, checking extensions + * for mime type, and moving the file to the appropriate directory within the uploads directory. + * + * @since 2.6.0 + * + * @uses wp_handle_upload_error + * @uses apply_filters + * @uses wp_check_filetype_and_ext + * @uses current_user_can + * @uses wp_upload_dir + * @uses wp_unique_filename + * @param array $file an array similar to that of a PHP $_FILES POST array + * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ). + * @param string $time Optional. Time formatted in 'yyyy/mm'. + * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). + */ +function wp_handle_sideload( &$file, $overrides = false, $time = null ) { + // The default error handler. + if (! function_exists( 'wp_handle_upload_error' ) ) { + function wp_handle_upload_error( &$file, $message ) { + return array( 'error'=>$message ); + } + } + + // You may define your own function and pass the name in $overrides['upload_error_handler'] + $upload_error_handler = 'wp_handle_upload_error'; + + // You may define your own function and pass the name in $overrides['unique_filename_callback'] + $unique_filename_callback = null; + + // $_POST['action'] must be set and its value must equal $overrides['action'] or this: + $action = 'wp_handle_sideload'; + + // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. + $upload_error_strings = array( false, + __( "The uploaded file exceeds the upload_max_filesize directive in php.ini." ), + __( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." ), + __( "The uploaded file was only partially uploaded." ), + __( "No file was uploaded." ), + '', + __( "Missing a temporary folder." ), + __( "Failed to write file to disk." ), + __( "File upload stopped by extension." )); + + // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false; + $test_form = true; + $test_size = true; + + // If you override this, you must provide $ext and $type!!!! + $test_type = true; + $mimes = false; + + // Install user overrides. Did we mention that this voids your warranty? + if ( is_array( $overrides ) ) + extract( $overrides, EXTR_OVERWRITE ); + + // A correct form post will pass this test. + if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) ) + return $upload_error_handler( $file, __( 'Invalid form submission.' )); + + // A successful upload will pass this test. It makes no sense to override this one. + if ( ! empty( $file['error'] ) ) + return $upload_error_handler( $file, $upload_error_strings[$file['error']] ); + + // A non-empty file will pass this test. + if ( $test_size && !(filesize($file['tmp_name']) > 0 ) ) + return $upload_error_handler( $file, __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini.' )); + + // A properly uploaded file will pass this test. There should be no reason to override this one. + if (! @ is_file( $file['tmp_name'] ) ) + return $upload_error_handler( $file, __( 'Specified file does not exist.' )); + + // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. + if ( $test_type ) { + $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes ); + + extract( $wp_filetype ); + + // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect + if ( $proper_filename ) + $file['name'] = $proper_filename; + + if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) + return $upload_error_handler( $file, __( 'Sorry, this file type is not permitted for security reasons.' )); + + if ( !$ext ) + $ext = ltrim(strrchr($file['name'], '.'), '.'); + + if ( !$type ) + $type = $file['type']; + } + + // A writable uploads dir will pass this test. Again, there's no point overriding this one. + if ( ! ( ( $uploads = wp_upload_dir( $time ) ) && false === $uploads['error'] ) ) + return $upload_error_handler( $file, $uploads['error'] ); + + $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); + + // Strip the query strings. + $filename = str_replace('?','-', $filename); + $filename = str_replace('&','-', $filename); + + // Move the file to the uploads dir + $new_file = $uploads['path'] . "/$filename"; + if ( false === @ rename( $file['tmp_name'], $new_file ) ) { + if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) + $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; + else + $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; + return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $error_path ) ); + } + + // Set correct file permissions + $stat = stat( dirname( $new_file )); + $perms = $stat['mode'] & 0000666; + @ chmod( $new_file, $perms ); + + // Compute the URL + $url = $uploads['url'] . "/$filename"; + + $return = apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ), 'sideload' ); + + return $return; +} + +/** + * Downloads a url to a local temporary file using the WordPress HTTP Class. + * Please note, That the calling function must unlink() the file. + * + * @since 2.5.0 + * + * @param string $url the URL of the file to download + * @param int $timeout The timeout for the request to download the file default 300 seconds + * @return mixed WP_Error on failure, string Filename on success. + */ +function download_url( $url, $timeout = 300 ) { + //WARNING: The file is not automatically deleted, The script must unlink() the file. + if ( ! $url ) + return new WP_Error('http_no_url', __('Invalid URL Provided.')); + + $tmpfname = wp_tempnam($url); + if ( ! $tmpfname ) + return new WP_Error('http_no_file', __('Could not create Temporary file.')); + + $response = wp_safe_remote_get( $url, array( 'timeout' => $timeout, 'stream' => true, 'filename' => $tmpfname ) ); + + if ( is_wp_error( $response ) ) { + unlink( $tmpfname ); + return $response; + } + + if ( 200 != wp_remote_retrieve_response_code( $response ) ){ + unlink( $tmpfname ); + return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ) ); + } + + $content_md5 = wp_remote_retrieve_header( $response, 'content-md5' ); + if ( $content_md5 ) { + $md5_check = verify_file_md5( $tmpfname, $content_md5 ); + if ( is_wp_error( $md5_check ) ) { + unlink( $tmpfname ); + return $md5_check; + } + } + + return $tmpfname; +} + +/** + * Calculates and compares the MD5 of a file to it's expected value. + * + * @since 3.7.0 + * + * @param string $filename The filename to check the MD5 of. + * @param string $expected_md5 The expected MD5 of the file, either a base64 encoded raw md5, or a hex-encoded md5 + * @return bool|object WP_Error on failure, true on success, false when the MD5 format is unknown/unexpected + */ +function verify_file_md5( $filename, $expected_md5 ) { + if ( 32 == strlen( $expected_md5 ) ) + $expected_raw_md5 = pack( 'H*', $expected_md5 ); + elseif ( 24 == strlen( $expected_md5 ) ) + $expected_raw_md5 = base64_decode( $expected_md5 ); + else + return false; // unknown format + + $file_md5 = md5_file( $filename, true ); + + if ( $file_md5 === $expected_raw_md5 ) + return true; + + return new WP_Error( 'md5_mismatch', sprintf( __( 'The checksum of the file (%1$s) does not match the expected checksum value (%2$s).' ), bin2hex( $file_md5 ), bin2hex( $expected_raw_md5 ) ) ); +} + +/** + * Unzips a specified ZIP file to a location on the Filesystem via the WordPress Filesystem Abstraction. + * Assumes that WP_Filesystem() has already been called and set up. Does not extract a root-level __MACOSX directory, if present. + * + * Attempts to increase the PHP Memory limit to 256M before uncompressing, + * However, The most memory required shouldn't be much larger than the Archive itself. + * + * @since 2.5.0 + * + * @param string $file Full path and filename of zip archive + * @param string $to Full path on the filesystem to extract archive to + * @return mixed WP_Error on failure, True on success + */ +function unzip_file($file, $to) { + global $wp_filesystem; + + if ( ! $wp_filesystem || !is_object($wp_filesystem) ) + return new WP_Error('fs_unavailable', __('Could not access filesystem.')); + + // Unzip can use a lot of memory, but not this much hopefully + @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + + $needed_dirs = array(); + $to = trailingslashit($to); + + // Determine any parent dir's needed (of the upgrade directory) + if ( ! $wp_filesystem->is_dir($to) ) { //Only do parents if no children exist + $path = preg_split('![/\\\]!', untrailingslashit($to)); + for ( $i = count($path); $i >= 0; $i-- ) { + if ( empty($path[$i]) ) + continue; + + $dir = implode('/', array_slice($path, 0, $i+1) ); + if ( preg_match('!^[a-z]:$!i', $dir) ) // Skip it if it looks like a Windows Drive letter. + continue; + + if ( ! $wp_filesystem->is_dir($dir) ) + $needed_dirs[] = $dir; + else + break; // A folder exists, therefor, we dont need the check the levels below this + } + } + + if ( class_exists('ZipArchive') && apply_filters('unzip_file_use_ziparchive', true ) ) { + $result = _unzip_file_ziparchive($file, $to, $needed_dirs); + if ( true === $result ) { + return $result; + } elseif ( is_wp_error($result) ) { + if ( 'incompatible_archive' != $result->get_error_code() ) + return $result; + } + } + // Fall through to PclZip if ZipArchive is not available, or encountered an error opening the file. + return _unzip_file_pclzip($file, $to, $needed_dirs); +} + +/** + * This function should not be called directly, use unzip_file instead. Attempts to unzip an archive using the ZipArchive class. + * Assumes that WP_Filesystem() has already been called and set up. + * + * @since 3.0.0 + * @see unzip_file + * @access private + * + * @param string $file Full path and filename of zip archive + * @param string $to Full path on the filesystem to extract archive to + * @param array $needed_dirs A partial list of required folders needed to be created. + * @return mixed WP_Error on failure, True on success + */ +function _unzip_file_ziparchive($file, $to, $needed_dirs = array() ) { + global $wp_filesystem; + + $z = new ZipArchive(); + + $zopen = $z->open( $file, ZIPARCHIVE::CHECKCONS ); + if ( true !== $zopen ) + return new WP_Error( 'incompatible_archive', __( 'Incompatible Archive.' ), array( 'ziparchive_error' => $zopen ) ); + + $uncompressed_size = 0; + + for ( $i = 0; $i < $z->numFiles; $i++ ) { + if ( ! $info = $z->statIndex($i) ) + return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) ); + + if ( '__MACOSX/' === substr($info['name'], 0, 9) ) // Skip the OS X-created __MACOSX directory + continue; + + $uncompressed_size += $info['size']; + + if ( '/' == substr($info['name'], -1) ) // directory + $needed_dirs[] = $to . untrailingslashit($info['name']); + else + $needed_dirs[] = $to . untrailingslashit(dirname($info['name'])); + } + + /* + * disk_free_space() could return false. Assume that any falsey value is an error. + * A disk that has zero free bytes has bigger problems. + * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. + */ + if ( defined( 'DOING_CRON' ) && DOING_CRON ) { + $available_space = @disk_free_space( WP_CONTENT_DIR ); + if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) + return new WP_Error( 'disk_full_unzip_file', __( 'Could not copy files. You may have run out of disk space.' ), compact( 'uncompressed_size', 'available_space' ) ); + } + + $needed_dirs = array_unique($needed_dirs); + foreach ( $needed_dirs as $dir ) { + // Check the parent folders of the folders all exist within the creation array. + if ( untrailingslashit($to) == $dir ) // Skip over the working directory, We know this exists (or will exist) + continue; + if ( strpos($dir, $to) === false ) // If the directory is not within the working directory, Skip it + continue; + + $parent_folder = dirname($dir); + while ( !empty($parent_folder) && untrailingslashit($to) != $parent_folder && !in_array($parent_folder, $needed_dirs) ) { + $needed_dirs[] = $parent_folder; + $parent_folder = dirname($parent_folder); + } + } + asort($needed_dirs); + + // Create those directories if need be: + foreach ( $needed_dirs as $_dir ) { + if ( ! $wp_filesystem->mkdir($_dir, FS_CHMOD_DIR) && ! $wp_filesystem->is_dir($_dir) ) // Only check to see if the Dir exists upon creation failure. Less I/O this way. + return new WP_Error( 'mkdir_failed_ziparchive', __( 'Could not create directory.' ), substr( $_dir, strlen( $to ) ) ); + } + unset($needed_dirs); + + for ( $i = 0; $i < $z->numFiles; $i++ ) { + if ( ! $info = $z->statIndex($i) ) + return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) ); + + if ( '/' == substr($info['name'], -1) ) // directory + continue; + + if ( '__MACOSX/' === substr($info['name'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files + continue; + + $contents = $z->getFromIndex($i); + if ( false === $contents ) + return new WP_Error( 'extract_failed_ziparchive', __( 'Could not extract file from archive.' ), $info['name'] ); + + if ( ! $wp_filesystem->put_contents( $to . $info['name'], $contents, FS_CHMOD_FILE) ) + return new WP_Error( 'copy_failed_ziparchive', __( 'Could not copy file.' ), $info['name'] ); + } + + $z->close(); + + return true; +} + +/** + * This function should not be called directly, use unzip_file instead. Attempts to unzip an archive using the PclZip library. + * Assumes that WP_Filesystem() has already been called and set up. + * + * @since 3.0.0 + * @see unzip_file + * @access private + * + * @param string $file Full path and filename of zip archive + * @param string $to Full path on the filesystem to extract archive to + * @param array $needed_dirs A partial list of required folders needed to be created. + * @return mixed WP_Error on failure, True on success + */ +function _unzip_file_pclzip($file, $to, $needed_dirs = array()) { + global $wp_filesystem; + + mbstring_binary_safe_encoding(); + + require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php'); + + $archive = new PclZip($file); + + $archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING); + + reset_mbstring_encoding(); + + // Is the archive valid? + if ( !is_array($archive_files) ) + return new WP_Error('incompatible_archive', __('Incompatible Archive.'), $archive->errorInfo(true)); + + if ( 0 == count($archive_files) ) + return new WP_Error( 'empty_archive_pclzip', __( 'Empty archive.' ) ); + + $uncompressed_size = 0; + + // Determine any children directories needed (From within the archive) + foreach ( $archive_files as $file ) { + if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Skip the OS X-created __MACOSX directory + continue; + + $uncompressed_size += $file['size']; + + $needed_dirs[] = $to . untrailingslashit( $file['folder'] ? $file['filename'] : dirname($file['filename']) ); + } + + /* + * disk_free_space() could return false. Assume that any falsey value is an error. + * A disk that has zero free bytes has bigger problems. + * Require we have enough space to unzip the file and copy its contents, with a 10% buffer. + */ + if ( defined( 'DOING_CRON' ) && DOING_CRON ) { + $available_space = @disk_free_space( WP_CONTENT_DIR ); + if ( $available_space && ( $uncompressed_size * 2.1 ) > $available_space ) + return new WP_Error( 'disk_full_unzip_file', __( 'Could not copy files. You may have run out of disk space.' ), compact( 'uncompressed_size', 'available_space' ) ); + } + + $needed_dirs = array_unique($needed_dirs); + foreach ( $needed_dirs as $dir ) { + // Check the parent folders of the folders all exist within the creation array. + if ( untrailingslashit($to) == $dir ) // Skip over the working directory, We know this exists (or will exist) + continue; + if ( strpos($dir, $to) === false ) // If the directory is not within the working directory, Skip it + continue; + + $parent_folder = dirname($dir); + while ( !empty($parent_folder) && untrailingslashit($to) != $parent_folder && !in_array($parent_folder, $needed_dirs) ) { + $needed_dirs[] = $parent_folder; + $parent_folder = dirname($parent_folder); + } + } + asort($needed_dirs); + + // Create those directories if need be: + foreach ( $needed_dirs as $_dir ) { + // Only check to see if the dir exists upon creation failure. Less I/O this way. + if ( ! $wp_filesystem->mkdir( $_dir, FS_CHMOD_DIR ) && ! $wp_filesystem->is_dir( $_dir ) ) + return new WP_Error( 'mkdir_failed_pclzip', __( 'Could not create directory.' ), substr( $_dir, strlen( $to ) ) ); + } + unset($needed_dirs); + + // Extract the files from the zip + foreach ( $archive_files as $file ) { + if ( $file['folder'] ) + continue; + + if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files + continue; + + if ( ! $wp_filesystem->put_contents( $to . $file['filename'], $file['content'], FS_CHMOD_FILE) ) + return new WP_Error( 'copy_failed_pclzip', __( 'Could not copy file.' ), $file['filename'] ); + } + return true; +} + +/** + * Copies a directory from one location to another via the WordPress Filesystem Abstraction. + * Assumes that WP_Filesystem() has already been called and setup. + * + * @since 2.5.0 + * + * @param string $from source directory + * @param string $to destination directory + * @param array $skip_list a list of files/folders to skip copying + * @return mixed WP_Error on failure, True on success. + */ +function copy_dir($from, $to, $skip_list = array() ) { + global $wp_filesystem; + + $dirlist = $wp_filesystem->dirlist($from); + + $from = trailingslashit($from); + $to = trailingslashit($to); + + foreach ( (array) $dirlist as $filename => $fileinfo ) { + if ( in_array( $filename, $skip_list ) ) + continue; + + if ( 'f' == $fileinfo['type'] ) { + if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) { + // If copy failed, chmod file to 0644 and try again. + $wp_filesystem->chmod( $to . $filename, FS_CHMOD_FILE ); + if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) + return new WP_Error( 'copy_failed_copy_dir', __( 'Could not copy file.' ), $to . $filename ); + } + } elseif ( 'd' == $fileinfo['type'] ) { + if ( !$wp_filesystem->is_dir($to . $filename) ) { + if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) ) + return new WP_Error( 'mkdir_failed_copy_dir', __( 'Could not create directory.' ), $to . $filename ); + } + + // generate the $sub_skip_list for the subdirectory as a sub-set of the existing $skip_list + $sub_skip_list = array(); + foreach ( $skip_list as $skip_item ) { + if ( 0 === strpos( $skip_item, $filename . '/' ) ) + $sub_skip_list[] = preg_replace( '!^' . preg_quote( $filename, '!' ) . '/!i', '', $skip_item ); + } + + $result = copy_dir($from . $filename, $to . $filename, $sub_skip_list); + if ( is_wp_error($result) ) + return $result; + } + } + return true; +} + +/** + * Initialises and connects the WordPress Filesystem Abstraction classes. + * This function will include the chosen transport and attempt connecting. + * + * Plugins may add extra transports, And force WordPress to use them by returning the filename via the 'filesystem_method_file' filter. + * + * @since 2.5.0 + * + * @param array $args (optional) Connection args, These are passed directly to the WP_Filesystem_*() classes. + * @param string $context (optional) Context for get_filesystem_method(), See function declaration for more information. + * @return boolean false on failure, true on success + */ +function WP_Filesystem( $args = false, $context = false ) { + global $wp_filesystem; + + require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'); + + $method = get_filesystem_method($args, $context); + + if ( ! $method ) + return false; + + if ( ! class_exists("WP_Filesystem_$method") ) { + $abstraction_file = apply_filters('filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method); + if ( ! file_exists($abstraction_file) ) + return; + + require_once($abstraction_file); + } + $method = "WP_Filesystem_$method"; + + $wp_filesystem = new $method($args); + + //Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default. + if ( ! defined('FS_CONNECT_TIMEOUT') ) + define('FS_CONNECT_TIMEOUT', 30); + if ( ! defined('FS_TIMEOUT') ) + define('FS_TIMEOUT', 30); + + if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) + return false; + + if ( !$wp_filesystem->connect() ) + return false; //There was an error connecting to the server. + + // Set the permission constants if not already set. + if ( ! defined('FS_CHMOD_DIR') ) + define('FS_CHMOD_DIR', ( fileperms( ABSPATH ) & 0777 | 0755 ) ); + if ( ! defined('FS_CHMOD_FILE') ) + define('FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) ); + + return true; +} + +/** + * Determines which Filesystem Method to use. + * The priority of the Transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets (Via Sockets class, or fsockopen()) + * + * Note that the return value of this function can be overridden in 2 ways + * - By defining FS_METHOD in your wp-config.php file + * - By using the filesystem_method filter + * Valid values for these are: 'direct', 'ssh', 'ftpext' or 'ftpsockets' + * Plugins may also define a custom transport handler, See the WP_Filesystem function for more information. + * + * @since 2.5.0 + * + * @param array $args Connection details. + * @param string $context Full path to the directory that is tested for being writable. + * @return string The transport to use, see description for valid return values. + */ +function get_filesystem_method($args = array(), $context = false) { + $method = defined('FS_METHOD') ? FS_METHOD : false; //Please ensure that this is either 'direct', 'ssh', 'ftpext' or 'ftpsockets' + + if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){ + if ( !$context ) + $context = WP_CONTENT_DIR; + + // If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it. + if ( WP_LANG_DIR == $context && ! is_dir( $context ) ) + $context = dirname( $context ); + + $context = trailingslashit($context); + $temp_file_name = $context . 'temp-write-test-' . time(); + $temp_handle = @fopen($temp_file_name, 'w'); + if ( $temp_handle ) { + if ( getmyuid() == @fileowner($temp_file_name) ) + $method = 'direct'; + @fclose($temp_handle); + @unlink($temp_file_name); + } + } + + if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; + if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; + if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread + return apply_filters('filesystem_method', $method, $args); +} + +/** + * Displays a form to the user to request for their FTP/SSH details in order to connect to the filesystem. + * All chosen/entered details are saved, Excluding the Password. + * + * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) to specify an alternate FTP/SSH port. + * + * Plugins may override this form by returning true|false via the request_filesystem_credentials filter. + * + * @since 2.5.0 + * + * @param string $form_post the URL to post the form to + * @param string $type the chosen Filesystem method in use + * @param boolean $error if the current request has failed to connect + * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() + * @param string $extra_fields Extra POST fields which should be checked for to be included in the post. + * @return boolean False on failure. True on success. + */ +function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null) { + $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields ); + if ( '' !== $req_cred ) + return $req_cred; + + if ( empty($type) ) + $type = get_filesystem_method(array(), $context); + + if ( 'direct' == $type ) + return true; + + if ( is_null( $extra_fields ) ) + $extra_fields = array( 'version', 'locale' ); + + $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => '')); + + // If defined, set it to that, Else, If POST'd, set it to that, If not, Set it to whatever it previously was(saved details in option) + $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? wp_unslash( $_POST['hostname'] ) : $credentials['hostname']); + $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? wp_unslash( $_POST['username'] ) : $credentials['username']); + $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? wp_unslash( $_POST['password'] ) : ''); + + // Check to see if we are setting the public/private keys for ssh + $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? wp_unslash( $_POST['public_key'] ) : ''); + $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? wp_unslash( $_POST['private_key'] ) : ''); + + //sanitize the hostname, Some people might pass in odd-data: + $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off + + if ( strpos($credentials['hostname'], ':') ) { + list( $credentials['hostname'], $credentials['port'] ) = explode(':', $credentials['hostname'], 2); + if ( ! is_numeric($credentials['port']) ) + unset($credentials['port']); + } else { + unset($credentials['port']); + } + + if ( (defined('FTP_SSH') && FTP_SSH) || (defined('FS_METHOD') && 'ssh' == FS_METHOD) ) + $credentials['connection_type'] = 'ssh'; + else if ( (defined('FTP_SSL') && FTP_SSL) && 'ftpext' == $type ) //Only the FTP Extension understands SSL + $credentials['connection_type'] = 'ftps'; + else if ( !empty($_POST['connection_type']) ) + $credentials['connection_type'] = wp_unslash( $_POST['connection_type'] ); + else if ( !isset($credentials['connection_type']) ) //All else fails (And it's not defaulted to something else saved), Default to FTP + $credentials['connection_type'] = 'ftp'; + + if ( ! $error && + ( + ( !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) || + ( 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']) ) + ) ) { + $stored_credentials = $credentials; + if ( !empty($stored_credentials['port']) ) //save port as part of hostname to simplify above code. + $stored_credentials['hostname'] .= ':' . $stored_credentials['port']; + + unset($stored_credentials['password'], $stored_credentials['port'], $stored_credentials['private_key'], $stored_credentials['public_key']); + update_option('ftp_credentials', $stored_credentials); + return $credentials; + } + $hostname = ''; + $username = ''; + $password = ''; + $connection_type = ''; + if ( !empty($credentials) ) + extract($credentials, EXTR_OVERWRITE); + if ( $error ) { + $error_string = __('ERROR: There was an error connecting to the server, Please verify the settings are correct.'); + if ( is_wp_error($error) ) + $error_string = esc_html( $error->get_error_message() ); + echo '

    ' . $error_string . '

    '; + } + + $types = array(); + if ( extension_loaded('ftp') || extension_loaded('sockets') || function_exists('fsockopen') ) + $types[ 'ftp' ] = __('FTP'); + if ( extension_loaded('ftp') ) //Only this supports FTPS + $types[ 'ftps' ] = __('FTPS (SSL)'); + if ( extension_loaded('ssh2') && function_exists('stream_get_contents') ) + $types[ 'ssh' ] = __('SSH2'); + + $types = apply_filters('fs_ftp_connection_types', $types, $credentials, $type, $error, $context); + +?> + +
    +
    +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    " size="40" />
    size="40" />
    size="40" />
    +
    +
    +
    + +

    size="40" />
    size="40" /> +
    +
    + $text ) : ?> + + +
    +
    + +'; +} +submit_button( __( 'Proceed' ), 'button', 'upgrade' ); +?> +
    +
    + 400 ? 400 / $big : 1; + + $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true ); + $can_restore = false; + if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) + $can_restore = $backup_sizes['full-orig']['file'] != basename( $meta['file'] ); + + if ( $msg ) { + if ( isset($msg->error) ) + $note = "

    $msg->error

    "; + elseif ( isset($msg->msg) ) + $note = "

    $msg->msg

    "; + } + + ?> +
    + + + + + +
    +
    +
    , this)" class="imgedit-crop disabled" title="">
    get_post_mime_type( $post_id ), 'methods' => array( 'rotate' ) ) ) ) { ?> +
    , this)" title="">
    +
    , this)" title="">
    + +
    +
    + + +
    , this)" class="imgedit-flipv" title="">
    +
    , this)" class="imgedit-fliph" title="">
    + +
    , this)" class="imgedit-undo disabled" title="">
    +
    , this)" class="imgedit-redo disabled" title="">
    +
    +
    + + + + + + + + + +
    + +
    + +
    + + )" disabled="disabled" class="button-primary imgedit-submit-btn" value="" /> +
    +
    +
    +
    + +
    +

    + +

    + +
    + × + ! + , 'scale')" class="button-primary" value="" /> +
    +
    +
    + + + +
    + +
    +

    +
    + , 'restore')" class="button-primary" value="" /> +
    +
    +
    + + + +
    + +
    +
    + + +
    +

    + +


    +

    + +


    +

    +
    +
    + +

    + + + + : + + +

    + +

    + + + + : + + +

    +
    + + + +
    +
    + + +

    +
    + +

    +
    +

    + +

    +
    + + + + + + +

    +
    + + + +
    +
    + + +
    +stream( $mime_type ) ) ) + return false; + + return true; + } else { + _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) ); + + $image = apply_filters('image_save_pre', $image, $post_id); + + switch ( $mime_type ) { + case 'image/jpeg': + header( 'Content-Type: image/jpeg' ); + return imagejpeg( $image, null, 90 ); + case 'image/png': + header( 'Content-Type: image/png' ); + return imagepng( $image ); + case 'image/gif': + header( 'Content-Type: image/gif' ); + return imagegif( $image ); + default: + return false; + } + } +} + +/** + * Saves Image to File + * + * @param string $filename + * @param WP_Image_Editor $image + * @param string $mime_type + * @param int $post_id + * @return boolean + */ +function wp_save_image_file( $filename, $image, $mime_type, $post_id ) { + if ( $image instanceof WP_Image_Editor ) { + $image = apply_filters('image_editor_save_pre', $image, $post_id); + $saved = apply_filters('wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id); + + if ( null !== $saved ) + return $saved; + + return $image->save( $filename, $mime_type ); + } else { + _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) ); + + $image = apply_filters('image_save_pre', $image, $post_id); + $saved = apply_filters('wp_save_image_file', null, $filename, $image, $mime_type, $post_id); + + if ( null !== $saved ) + return $saved; + + switch ( $mime_type ) { + case 'image/jpeg': + return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) ); + case 'image/png': + return imagepng( $image, $filename ); + case 'image/gif': + return imagegif( $image, $filename ); + default: + return false; + } + } +} + +function _image_get_preview_ratio($w, $h) { + $max = max($w, $h); + return $max > 400 ? (400 / $max) : 1; +} + +// @TODO: Returns GD resource, but is NOT public +function _rotate_image_resource($img, $angle) { + _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::rotate' ) ); + if ( function_exists('imagerotate') ) { + $rotated = imagerotate($img, $angle, 0); + if ( is_resource($rotated) ) { + imagedestroy($img); + $img = $rotated; + } + } + return $img; +} + +/** + * @TODO: Only used within image_edit_apply_changes + * and receives/returns GD Resource. + * Consider removal. + * + * @param GD_Resource $img + * @param boolean $horz + * @param boolean $vert + * @return GD_Resource + */ +function _flip_image_resource($img, $horz, $vert) { + _deprecated_function( __FUNCTION__, '3.5', __( 'Use WP_Image_Editor::flip' ) ); + $w = imagesx($img); + $h = imagesy($img); + $dst = wp_imagecreatetruecolor($w, $h); + if ( is_resource($dst) ) { + $sx = $vert ? ($w - 1) : 0; + $sy = $horz ? ($h - 1) : 0; + $sw = $vert ? -$w : $w; + $sh = $horz ? -$h : $h; + + if ( imagecopyresampled($dst, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh) ) { + imagedestroy($img); + $img = $dst; + } + } + return $img; +} + +/** + * @TODO: Only used within image_edit_apply_changes + * and receives/returns GD Resource. + * Consider removal. + * + * @param GD_Resource $img + * @param float $x + * @param float $y + * @param float $w + * @param float $h + * @return GD_Resource + */ +function _crop_image_resource($img, $x, $y, $w, $h) { + $dst = wp_imagecreatetruecolor($w, $h); + if ( is_resource($dst) ) { + if ( imagecopy($dst, $img, 0, 0, $x, $y, $w, $h) ) { + imagedestroy($img); + $img = $dst; + } + } + return $img; +} + +/** + * Performs group of changes on Editor specified. + * + * @param WP_Image_Editor $image + * @param type $changes + * @return WP_Image_Editor + */ +function image_edit_apply_changes( $image, $changes ) { + if ( is_resource( $image ) ) + _deprecated_argument( __FUNCTION__, '3.5', __( '$image needs to be an WP_Image_Editor object' ) ); + + if ( !is_array($changes) ) + return $image; + + // expand change operations + foreach ( $changes as $key => $obj ) { + if ( isset($obj->r) ) { + $obj->type = 'rotate'; + $obj->angle = $obj->r; + unset($obj->r); + } elseif ( isset($obj->f) ) { + $obj->type = 'flip'; + $obj->axis = $obj->f; + unset($obj->f); + } elseif ( isset($obj->c) ) { + $obj->type = 'crop'; + $obj->sel = $obj->c; + unset($obj->c); + } + $changes[$key] = $obj; + } + + // combine operations + if ( count($changes) > 1 ) { + $filtered = array($changes[0]); + for ( $i = 0, $j = 1; $j < count($changes); $j++ ) { + $combined = false; + if ( $filtered[$i]->type == $changes[$j]->type ) { + switch ( $filtered[$i]->type ) { + case 'rotate': + $filtered[$i]->angle += $changes[$j]->angle; + $combined = true; + break; + case 'flip': + $filtered[$i]->axis ^= $changes[$j]->axis; + $combined = true; + break; + } + } + if ( !$combined ) + $filtered[++$i] = $changes[$j]; + } + $changes = $filtered; + unset($filtered); + } + + // image resource before applying the changes + if ( $image instanceof WP_Image_Editor ) + $image = apply_filters('wp_image_editor_before_change', $image, $changes); + elseif ( is_resource( $image ) ) + $image = apply_filters('image_edit_before_change', $image, $changes); + + foreach ( $changes as $operation ) { + switch ( $operation->type ) { + case 'rotate': + if ( $operation->angle != 0 ) { + if ( $image instanceof WP_Image_Editor ) + $image->rotate( $operation->angle ); + else + $image = _rotate_image_resource( $image, $operation->angle ); + } + break; + case 'flip': + if ( $operation->axis != 0 ) + if ( $image instanceof WP_Image_Editor ) + $image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + else + $image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 ); + break; + case 'crop': + $sel = $operation->sel; + + if ( $image instanceof WP_Image_Editor ) { + $size = $image->get_size(); + $w = $size['width']; + $h = $size['height']; + + $scale = 1 / _image_get_preview_ratio( $w, $h ); // discard preview scaling + $image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale ); + } else { + $scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // discard preview scaling + $image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale ); + } + break; + } + } + + return $image; +} + + +/** + * Streams image in post to browser, along with enqueued changes + * in $_REQUEST['history'] + * + * @param int $post_id + * @return boolean + */ +function stream_preview_image( $post_id ) { + $post = get_post( $post_id ); + @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + + $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) ); + + if ( is_wp_error( $img ) ) + return false; + + $changes = !empty($_REQUEST['history']) ? json_decode( wp_unslash($_REQUEST['history']) ) : null; + if ( $changes ) + $img = image_edit_apply_changes( $img, $changes ); + + // scale the image + $size = $img->get_size(); + $w = $size['width']; + $h = $size['height']; + + $ratio = _image_get_preview_ratio( $w, $h ); + $w2 = max ( 1, $w * $ratio ); + $h2 = max ( 1, $h * $ratio ); + + if ( is_wp_error( $img->resize( $w2, $h2 ) ) ) + return false; + + return wp_stream_image( $img, $post->post_mime_type, $post_id ); +} + +function wp_restore_image($post_id) { + $meta = wp_get_attachment_metadata($post_id); + $file = get_attached_file($post_id); + $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true ); + $restored = false; + $msg = new stdClass; + + if ( !is_array($backup_sizes) ) { + $msg->error = __('Cannot load image metadata.'); + return $msg; + } + + $parts = pathinfo($file); + $suffix = time() . rand(100, 999); + $default_sizes = get_intermediate_image_sizes(); + + if ( isset($backup_sizes['full-orig']) && is_array($backup_sizes['full-orig']) ) { + $data = $backup_sizes['full-orig']; + + if ( $parts['basename'] != $data['file'] ) { + if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) { + // delete only if it's edited image + if ( preg_match('/-e[0-9]{13}\./', $parts['basename']) ) { + /** This filter is documented in wp-admin/custom-header.php */ + $delpath = apply_filters('wp_delete_file', $file); + @unlink($delpath); + } + } elseif ( isset( $meta['width'], $meta['height'] ) ) { + $backup_sizes["full-$suffix"] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $parts['basename']); + } + } + + $restored_file = path_join($parts['dirname'], $data['file']); + $restored = update_attached_file($post_id, $restored_file); + + $meta['file'] = _wp_relative_upload_path( $restored_file ); + $meta['width'] = $data['width']; + $meta['height'] = $data['height']; + } + + foreach ( $default_sizes as $default_size ) { + if ( isset($backup_sizes["$default_size-orig"]) ) { + $data = $backup_sizes["$default_size-orig"]; + if ( isset($meta['sizes'][$default_size]) && $meta['sizes'][$default_size]['file'] != $data['file'] ) { + if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE ) { + // delete only if it's edited image + if ( preg_match('/-e[0-9]{13}-/', $meta['sizes'][$default_size]['file']) ) { + /** This filter is documented in wp-admin/custom-header.php */ + $delpath = apply_filters( 'wp_delete_file', path_join($parts['dirname'], $meta['sizes'][$default_size]['file']) ); + @unlink($delpath); + } + } else { + $backup_sizes["$default_size-{$suffix}"] = $meta['sizes'][$default_size]; + } + } + + $meta['sizes'][$default_size] = $data; + } else { + unset($meta['sizes'][$default_size]); + } + } + + if ( !wp_update_attachment_metadata($post_id, $meta) || !update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes) ) { + $msg->error = __('Cannot save image metadata.'); + return $msg; + } + + if ( !$restored ) + $msg->error = __('Image metadata is inconsistent.'); + else + $msg->msg = __('Image restored successfully.'); + + return $msg; +} + +/** + * Saves image to post along with enqueued changes + * in $_REQUEST['history'] + * + * @param int $post_id + * @return \stdClass + */ +function wp_save_image( $post_id ) { + $return = new stdClass; + $success = $delete = $scaled = $nocrop = false; + $post = get_post( $post_id ); + + $img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) ); + if ( is_wp_error( $img ) ) { + $return->error = esc_js( __('Unable to create new image.') ); + return $return; + } + + $fwidth = !empty($_REQUEST['fwidth']) ? intval($_REQUEST['fwidth']) : 0; + $fheight = !empty($_REQUEST['fheight']) ? intval($_REQUEST['fheight']) : 0; + $target = !empty($_REQUEST['target']) ? preg_replace('/[^a-z0-9_-]+/i', '', $_REQUEST['target']) : ''; + $scale = !empty($_REQUEST['do']) && 'scale' == $_REQUEST['do']; + + if ( $scale && $fwidth > 0 && $fheight > 0 ) { + $size = $img->get_size(); + $sX = $size['width']; + $sY = $size['height']; + + // check if it has roughly the same w / h ratio + $diff = round($sX / $sY, 2) - round($fwidth / $fheight, 2); + if ( -0.1 < $diff && $diff < 0.1 ) { + // scale the full size image + if ( $img->resize( $fwidth, $fheight ) ) + $scaled = true; + } + + if ( !$scaled ) { + $return->error = esc_js( __('Error while saving the scaled image. Please reload the page and try again.') ); + return $return; + } + } elseif ( !empty($_REQUEST['history']) ) { + $changes = json_decode( wp_unslash($_REQUEST['history']) ); + if ( $changes ) + $img = image_edit_apply_changes($img, $changes); + } else { + $return->error = esc_js( __('Nothing to save, the image has not changed.') ); + return $return; + } + + $meta = wp_get_attachment_metadata($post_id); + $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true ); + + if ( !is_array($meta) ) { + $return->error = esc_js( __('Image data does not exist. Please re-upload the image.') ); + return $return; + } + + if ( !is_array($backup_sizes) ) + $backup_sizes = array(); + + // generate new filename + $path = get_attached_file($post_id); + $path_parts = pathinfo( $path ); + $filename = $path_parts['filename']; + $suffix = time() . rand(100, 999); + + if ( defined('IMAGE_EDIT_OVERWRITE') && IMAGE_EDIT_OVERWRITE && + isset($backup_sizes['full-orig']) && $backup_sizes['full-orig']['file'] != $path_parts['basename'] ) { + + if ( 'thumbnail' == $target ) + $new_path = "{$path_parts['dirname']}/{$filename}-temp.{$path_parts['extension']}"; + else + $new_path = $path; + } else { + while( true ) { + $filename = preg_replace( '/-e([0-9]+)$/', '', $filename ); + $filename .= "-e{$suffix}"; + $new_filename = "{$filename}.{$path_parts['extension']}"; + $new_path = "{$path_parts['dirname']}/$new_filename"; + if ( file_exists($new_path) ) + $suffix++; + else + break; + } + } + + // save the full-size file, also needed to create sub-sizes + if ( !wp_save_image_file($new_path, $img, $post->post_mime_type, $post_id) ) { + $return->error = esc_js( __('Unable to save the image.') ); + return $return; + } + + if ( 'nothumb' == $target || 'all' == $target || 'full' == $target || $scaled ) { + $tag = false; + if ( isset($backup_sizes['full-orig']) ) { + if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] != $path_parts['basename'] ) + $tag = "full-$suffix"; + } else { + $tag = 'full-orig'; + } + + if ( $tag ) + $backup_sizes[$tag] = array('width' => $meta['width'], 'height' => $meta['height'], 'file' => $path_parts['basename']); + + $success = update_attached_file( $post_id, $new_path ); + + $meta['file'] = _wp_relative_upload_path( $new_path ); + + $size = $img->get_size(); + $meta['width'] = $size['width']; + $meta['height'] = $size['height']; + + if ( $success && ('nothumb' == $target || 'all' == $target) ) { + $sizes = get_intermediate_image_sizes(); + if ( 'nothumb' == $target ) + $sizes = array_diff( $sizes, array('thumbnail') ); + } + + $return->fw = $meta['width']; + $return->fh = $meta['height']; + } elseif ( 'thumbnail' == $target ) { + $sizes = array( 'thumbnail' ); + $success = $delete = $nocrop = true; + } + + if ( isset( $sizes ) ) { + $_sizes = array(); + + foreach ( $sizes as $size ) { + $tag = false; + if ( isset( $meta['sizes'][$size] ) ) { + if ( isset($backup_sizes["$size-orig"]) ) { + if ( ( !defined('IMAGE_EDIT_OVERWRITE') || !IMAGE_EDIT_OVERWRITE ) && $backup_sizes["$size-orig"]['file'] != $meta['sizes'][$size]['file'] ) + $tag = "$size-$suffix"; + } else { + $tag = "$size-orig"; + } + + if ( $tag ) + $backup_sizes[$tag] = $meta['sizes'][$size]; + } + + $crop = $nocrop ? false : get_option("{$size}_crop"); + $_sizes[ $size ] = array( 'width' => get_option("{$size}_size_w"), 'height' => get_option("{$size}_size_h"), 'crop' => $crop ); + } + + $meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) ); + } + + unset( $img ); + + if ( $success ) { + wp_update_attachment_metadata( $post_id, $meta ); + update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes); + + if ( $target == 'thumbnail' || $target == 'all' || $target == 'full' ) { + // Check if it's an image edit from attachment edit screen + if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' == $_REQUEST['context'] ) { + $thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true ); + $return->thumbnail = $thumb_url[0]; + } else { + $file_url = wp_get_attachment_url($post_id); + if ( $thumb = $meta['sizes']['thumbnail'] ) + $return->thumbnail = path_join( dirname($file_url), $thumb['file'] ); + else + $return->thumbnail = "$file_url?w=128&h=128"; + } + } + } else { + $delete = true; + } + + if ( $delete ) { + /** This filter is documented in wp-admin/custom-header.php */ + $delpath = apply_filters('wp_delete_file', $new_path); + @unlink( $delpath ); + } + + $return->msg = esc_js( __('Image saved') ); + return $return; +} diff --git a/sources/wp-admin/includes/image.php b/sources/wp-admin/includes/image.php new file mode 100644 index 0000000..f2e636b --- /dev/null +++ b/sources/wp-admin/includes/image.php @@ -0,0 +1,450 @@ +crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs ); + if ( is_wp_error( $src ) ) + return $src; + + if ( ! $dst_file ) + $dst_file = str_replace( basename( $src_file ), 'cropped-' . basename( $src_file ), $src_file ); + + // The directory containing the original file may no longer exist when + // using a replication plugin. + wp_mkdir_p( dirname( $dst_file ) ); + + $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) ); + + $result = $editor->save( $dst_file ); + if ( is_wp_error( $result ) ) + return $result; + + return $dst_file; +} + +/** + * Generate post thumbnail attachment meta data. + * + * @since 2.1.0 + * + * @param int $attachment_id Attachment Id to process. + * @param string $file Filepath of the Attached image. + * @return mixed Metadata for attachment. + */ +function wp_generate_attachment_metadata( $attachment_id, $file ) { + $attachment = get_post( $attachment_id ); + + $metadata = array(); + $support = false; + if ( preg_match('!^image/!', get_post_mime_type( $attachment )) && file_is_displayable_image($file) ) { + $imagesize = getimagesize( $file ); + $metadata['width'] = $imagesize[0]; + $metadata['height'] = $imagesize[1]; + + // Make the file path relative to the upload dir + $metadata['file'] = _wp_relative_upload_path($file); + + // make thumbnails and other intermediate sizes + global $_wp_additional_image_sizes; + + $sizes = array(); + foreach ( get_intermediate_image_sizes() as $s ) { + $sizes[$s] = array( 'width' => '', 'height' => '', 'crop' => false ); + if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) + $sizes[$s]['width'] = intval( $_wp_additional_image_sizes[$s]['width'] ); // For theme-added sizes + else + $sizes[$s]['width'] = get_option( "{$s}_size_w" ); // For default sizes set in options + if ( isset( $_wp_additional_image_sizes[$s]['height'] ) ) + $sizes[$s]['height'] = intval( $_wp_additional_image_sizes[$s]['height'] ); // For theme-added sizes + else + $sizes[$s]['height'] = get_option( "{$s}_size_h" ); // For default sizes set in options + if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) ) + $sizes[$s]['crop'] = intval( $_wp_additional_image_sizes[$s]['crop'] ); // For theme-added sizes + else + $sizes[$s]['crop'] = get_option( "{$s}_crop" ); // For default sizes set in options + } + + $sizes = apply_filters( 'intermediate_image_sizes_advanced', $sizes ); + + if ( $sizes ) { + $editor = wp_get_image_editor( $file ); + + if ( ! is_wp_error( $editor ) ) + $metadata['sizes'] = $editor->multi_resize( $sizes ); + } else { + $metadata['sizes'] = array(); + } + + // fetch additional metadata from exif/iptc + $image_meta = wp_read_image_metadata( $file ); + if ( $image_meta ) + $metadata['image_meta'] = $image_meta; + + } elseif ( preg_match( '#^video/#', get_post_mime_type( $attachment ) ) ) { + $metadata = wp_read_video_metadata( $file ); + $support = current_theme_supports( 'post-thumbnails', 'attachment:video' ) && post_type_supports( 'attachment:video', 'thumbnail' ); + } elseif ( preg_match( '#^audio/#', get_post_mime_type( $attachment ) ) ) { + $metadata = wp_read_audio_metadata( $file ); + $support = current_theme_supports( 'post-thumbnails', 'attachment:audio' ) && post_type_supports( 'attachment:audio', 'thumbnail' ); + } + + if ( $support && ! empty( $metadata['image']['data'] ) ) { + $ext = '.jpg'; + switch ( $metadata['image']['mime'] ) { + case 'image/gif': + $ext = '.gif'; + break; + case 'image/png': + $ext = '.png'; + break; + } + $basename = str_replace( '.', '-', basename( $file ) ) . '-image' . $ext; + $uploaded = wp_upload_bits( $basename, '', $metadata['image']['data'] ); + if ( false === $uploaded['error'] ) { + $attachment = array( + 'post_mime_type' => $metadata['image']['mime'], + 'post_type' => 'attachment', + 'post_content' => '', + ); + $sub_attachment_id = wp_insert_attachment( $attachment, $uploaded['file'] ); + $attach_data = wp_generate_attachment_metadata( $sub_attachment_id, $uploaded['file'] ); + wp_update_attachment_metadata( $sub_attachment_id, $attach_data ); + update_post_meta( $attachment_id, '_thumbnail_id', $sub_attachment_id ); + } + } + // remove the blob of binary data from the array + unset( $metadata['image']['data'] ); + + return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id ); +} + +/** + * Convert a fraction string to a decimal. + * + * @since 2.5.0 + * + * @param string $str + * @return int|float + */ +function wp_exif_frac2dec($str) { + @list( $n, $d ) = explode( '/', $str ); + if ( !empty($d) ) + return $n / $d; + return $str; +} + +/** + * Convert the exif date format to a unix timestamp. + * + * @since 2.5.0 + * + * @param string $str + * @return int + */ +function wp_exif_date2ts($str) { + @list( $date, $time ) = explode( ' ', trim($str) ); + @list( $y, $m, $d ) = explode( ':', $date ); + + return strtotime( "{$y}-{$m}-{$d} {$time}" ); +} + +/** + * Get extended image metadata, exif or iptc as available. + * + * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso + * created_timestamp, focal_length, shutter_speed, and title. + * + * The IPTC metadata that is retrieved is APP13, credit, byline, created date + * and time, caption, copyright, and title. Also includes FNumber, Model, + * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime. + * + * @todo Try other exif libraries if available. + * @since 2.5.0 + * + * @param string $file + * @return bool|array False on failure. Image metadata array on success. + */ +function wp_read_image_metadata( $file ) { + if ( ! file_exists( $file ) ) + return false; + + list( , , $sourceImageType ) = getimagesize( $file ); + + // exif contains a bunch of data we'll probably never need formatted in ways + // that are difficult to use. We'll normalize it and just extract the fields + // that are likely to be useful. Fractions and numbers are converted to + // floats, dates to unix timestamps, and everything else to strings. + $meta = array( + 'aperture' => 0, + 'credit' => '', + 'camera' => '', + 'caption' => '', + 'created_timestamp' => 0, + 'copyright' => '', + 'focal_length' => 0, + 'iso' => 0, + 'shutter_speed' => 0, + 'title' => '', + ); + + // read iptc first, since it might contain data not available in exif such + // as caption, description etc + if ( is_callable( 'iptcparse' ) ) { + getimagesize( $file, $info ); + + if ( ! empty( $info['APP13'] ) ) { + $iptc = iptcparse( $info['APP13'] ); + + // headline, "A brief synopsis of the caption." + if ( ! empty( $iptc['2#105'][0] ) ) + $meta['title'] = trim( $iptc['2#105'][0] ); + // title, "Many use the Title field to store the filename of the image, though the field may be used in many ways." + elseif ( ! empty( $iptc['2#005'][0] ) ) + $meta['title'] = trim( $iptc['2#005'][0] ); + + if ( ! empty( $iptc['2#120'][0] ) ) { // description / legacy caption + $caption = trim( $iptc['2#120'][0] ); + if ( empty( $meta['title'] ) ) { + // Assume the title is stored in 2:120 if it's short. + if ( strlen( $caption ) < 80 ) + $meta['title'] = $caption; + else + $meta['caption'] = $caption; + } elseif ( $caption != $meta['title'] ) { + $meta['caption'] = $caption; + } + } + + if ( ! empty( $iptc['2#110'][0] ) ) // credit + $meta['credit'] = trim( $iptc['2#110'][0] ); + elseif ( ! empty( $iptc['2#080'][0] ) ) // creator / legacy byline + $meta['credit'] = trim( $iptc['2#080'][0] ); + + if ( ! empty( $iptc['2#055'][0] ) and ! empty( $iptc['2#060'][0] ) ) // created date and time + $meta['created_timestamp'] = strtotime( $iptc['2#055'][0] . ' ' . $iptc['2#060'][0] ); + + if ( ! empty( $iptc['2#116'][0] ) ) // copyright + $meta['copyright'] = trim( $iptc['2#116'][0] ); + } + } + + // fetch additional info from exif if available + if ( is_callable( 'exif_read_data' ) && in_array( $sourceImageType, apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) ) ) ) { + $exif = @exif_read_data( $file ); + + if ( !empty( $exif['Title'] ) ) + $meta['title'] = trim( $exif['Title'] ); + + if ( ! empty( $exif['ImageDescription'] ) ) { + if ( empty( $meta['title'] ) && strlen( $exif['ImageDescription'] ) < 80 ) { + // Assume the title is stored in ImageDescription + $meta['title'] = trim( $exif['ImageDescription'] ); + if ( ! empty( $exif['COMPUTED']['UserComment'] ) && trim( $exif['COMPUTED']['UserComment'] ) != $meta['title'] ) + $meta['caption'] = trim( $exif['COMPUTED']['UserComment'] ); + } elseif ( trim( $exif['ImageDescription'] ) != $meta['title'] ) { + $meta['caption'] = trim( $exif['ImageDescription'] ); + } + } elseif ( ! empty( $exif['Comments'] ) && trim( $exif['Comments'] ) != $meta['title'] ) { + $meta['caption'] = trim( $exif['Comments'] ); + } + + if ( ! empty( $exif['Artist'] ) ) + $meta['credit'] = trim( $exif['Artist'] ); + elseif ( ! empty($exif['Author'] ) ) + $meta['credit'] = trim( $exif['Author'] ); + + if ( ! empty( $exif['Copyright'] ) ) + $meta['copyright'] = trim( $exif['Copyright'] ); + if ( ! empty($exif['FNumber'] ) ) + $meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 ); + if ( ! empty($exif['Model'] ) ) + $meta['camera'] = trim( $exif['Model'] ); + if ( ! empty($exif['DateTimeDigitized'] ) ) + $meta['created_timestamp'] = wp_exif_date2ts($exif['DateTimeDigitized'] ); + if ( ! empty($exif['FocalLength'] ) ) + $meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] ); + if ( ! empty($exif['ISOSpeedRatings'] ) ) { + $meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings']; + $meta['iso'] = trim( $meta['iso'] ); + } + if ( ! empty($exif['ExposureTime'] ) ) + $meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] ); + } + + foreach ( array( 'title', 'caption', 'credit', 'copyright', 'camera', 'iso' ) as $key ) { + if ( $meta[ $key ] && ! seems_utf8( $meta[ $key ] ) ) + $meta[ $key ] = utf8_encode( $meta[ $key ] ); + } + + return apply_filters( 'wp_read_image_metadata', $meta, $file, $sourceImageType ); + +} + +/** + * Validate that file is an image. + * + * @since 2.5.0 + * + * @param string $path File path to test if valid image. + * @return bool True if valid image, false if not valid image. + */ +function file_is_valid_image($path) { + $size = @getimagesize($path); + return !empty($size); +} + +/** + * Validate that file is suitable for displaying within a web page. + * + * @since 2.5.0 + * @uses apply_filters() Calls 'file_is_displayable_image' on $result and $path. + * + * @param string $path File path to test. + * @return bool True if suitable, false if not suitable. + */ +function file_is_displayable_image($path) { + $info = @getimagesize($path); + if ( empty($info) ) + $result = false; + elseif ( !in_array($info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG)) ) // only gif, jpeg and png images can reliably be displayed + $result = false; + else + $result = true; + + return apply_filters('file_is_displayable_image', $result, $path); +} + +/** + * Load an image resource for editing. + * + * @since 2.9.0 + * + * @param string $attachment_id Attachment ID. + * @param string $mime_type Image mime type. + * @param string $size Optional. Image size, defaults to 'full'. + * @return resource|false The resulting image resource on success, false on failure. + */ +function load_image_to_edit( $attachment_id, $mime_type, $size = 'full' ) { + $filepath = _load_image_to_edit_path( $attachment_id, $size ); + if ( empty( $filepath ) ) + return false; + + switch ( $mime_type ) { + case 'image/jpeg': + $image = imagecreatefromjpeg($filepath); + break; + case 'image/png': + $image = imagecreatefrompng($filepath); + break; + case 'image/gif': + $image = imagecreatefromgif($filepath); + break; + default: + $image = false; + break; + } + if ( is_resource($image) ) { + $image = apply_filters('load_image_to_edit', $image, $attachment_id, $size); + if ( function_exists('imagealphablending') && function_exists('imagesavealpha') ) { + imagealphablending($image, false); + imagesavealpha($image, true); + } + } + return $image; +} + +/** + * Retrieve the path or url of an attachment's attached file. + * + * If the attached file is not present on the local filesystem (usually due to replication plugins), + * then the url of the file is returned if url fopen is supported. + * + * @since 3.4.0 + * @access private + * + * @param string $attachment_id Attachment ID. + * @param string $size Optional. Image size, defaults to 'full'. + * @return string|false File path or url on success, false on failure. + */ +function _load_image_to_edit_path( $attachment_id, $size = 'full' ) { + $filepath = get_attached_file( $attachment_id ); + + if ( $filepath && file_exists( $filepath ) ) { + if ( 'full' != $size && ( $data = image_get_intermediate_size( $attachment_id, $size ) ) ) { + $filepath = apply_filters( 'load_image_to_edit_filesystempath', path_join( dirname( $filepath ), $data['file'] ), $attachment_id, $size ); + } + } elseif ( function_exists( 'fopen' ) && function_exists( 'ini_get' ) && true == ini_get( 'allow_url_fopen' ) ) { + $filepath = apply_filters( 'load_image_to_edit_attachmenturl', wp_get_attachment_url( $attachment_id ), $attachment_id, $size ); + } + + return apply_filters( 'load_image_to_edit_path', $filepath, $attachment_id, $size ); +} + +/** + * Copy an existing image file. + * + * @since 3.4.0 + * @access private + * + * @param string $attachment_id Attachment ID. + * @return string|false New file path on success, false on failure. + */ +function _copy_image_file( $attachment_id ) { + $dst_file = $src_file = get_attached_file( $attachment_id ); + if ( ! file_exists( $src_file ) ) + $src_file = _load_image_to_edit_path( $attachment_id ); + + if ( $src_file ) { + $dst_file = str_replace( basename( $dst_file ), 'copy-' . basename( $dst_file ), $dst_file ); + $dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), basename( $dst_file ) ); + + // The directory containing the original file may no longer exist when + // using a replication plugin. + wp_mkdir_p( dirname( $dst_file ) ); + + if ( ! @copy( $src_file, $dst_file ) ) + $dst_file = false; + } else { + $dst_file = false; + } + + return $dst_file; +} diff --git a/sources/wp-admin/includes/import.php b/sources/wp-admin/includes/import.php new file mode 100644 index 0000000..590a54f --- /dev/null +++ b/sources/wp-admin/includes/import.php @@ -0,0 +1,186 @@ + false, 'test_type' => false ); + $_FILES['import']['name'] .= '.txt'; + $file = wp_handle_upload( $_FILES['import'], $overrides ); + + if ( isset( $file['error'] ) ) + return $file; + + $url = $file['url']; + $type = $file['type']; + $file = $file['file']; + $filename = basename( $file ); + + // Construct the object array + $object = array( 'post_title' => $filename, + 'post_content' => $url, + 'post_mime_type' => $type, + 'guid' => $url, + 'context' => 'import', + 'post_status' => 'private' + ); + + // Save the data + $id = wp_insert_attachment( $object, $file ); + + // schedule a cleanup for one day from now in case of failed import or missing wp_import_cleanup() call + wp_schedule_single_event( time() + DAY_IN_SECONDS, 'importer_scheduled_cleanup', array( $id ) ); + + return array( 'file' => $file, 'id' => $id ); +} + +/** + * Returns a list from WordPress.org of popular importer plugins. + * + * @since 3.5.0 + * + * @return array Importers with metadata for each. + */ +function wp_get_popular_importers() { + include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version + + $locale = get_locale(); + $popular_importers = get_site_transient( 'popular_importers_' . $locale ); + + if ( ! $popular_importers ) { + $url = add_query_arg( 'locale', get_locale(), 'http://api.wordpress.org/core/importers/1.1/' ); + $options = array( 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url() ); + $response = wp_remote_get( $url, $options ); + $popular_importers = json_decode( wp_remote_retrieve_body( $response ), true ); + + if ( is_array( $popular_importers ) ) + set_site_transient( 'popular_importers_' . $locale, $popular_importers, 2 * DAY_IN_SECONDS ); + else + $popular_importers = false; + } + + if ( is_array( $popular_importers ) ) { + // If the data was received as translated, return it as-is. + if ( $popular_importers['translated'] ) + return $popular_importers['importers']; + + foreach ( $popular_importers['importers'] as &$importer ) { + $importer['description'] = translate( $importer['description'] ); + if ( $importer['name'] != 'WordPress' ) + $importer['name'] = translate( $importer['name'] ); + } + return $popular_importers['importers']; + } + + return array( + // slug => name, description, plugin slug, and register_importer() slug + 'blogger' => array( + 'name' => __( 'Blogger' ), + 'description' => __( 'Install the Blogger importer to import posts, comments, and users from a Blogger blog.' ), + 'plugin-slug' => 'blogger-importer', + 'importer-id' => 'blogger', + ), + 'wpcat2tag' => array( + 'name' => __( 'Categories and Tags Converter' ), + 'description' => __( 'Install the category/tag converter to convert existing categories to tags or tags to categories, selectively.' ), + 'plugin-slug' => 'wpcat2tag-importer', + 'importer-id' => 'wp-cat2tag', + ), + 'livejournal' => array( + 'name' => __( 'LiveJournal' ), + 'description' => __( 'Install the LiveJournal importer to import posts from LiveJournal using their API.' ), + 'plugin-slug' => 'livejournal-importer', + 'importer-id' => 'livejournal', + ), + 'movabletype' => array( + 'name' => __( 'Movable Type and TypePad' ), + 'description' => __( 'Install the Movable Type importer to import posts and comments from a Movable Type or TypePad blog.' ), + 'plugin-slug' => 'movabletype-importer', + 'importer-id' => 'mt', + ), + 'opml' => array( + 'name' => __( 'Blogroll' ), + 'description' => __( 'Install the blogroll importer to import links in OPML format.' ), + 'plugin-slug' => 'opml-importer', + 'importer-id' => 'opml', + ), + 'rss' => array( + 'name' => __( 'RSS' ), + 'description' => __( 'Install the RSS importer to import posts from an RSS feed.' ), + 'plugin-slug' => 'rss-importer', + 'importer-id' => 'rss', + ), + 'tumblr' => array( + 'name' => __( 'Tumblr' ), + 'description' => __( 'Install the Tumblr importer to import posts & media from Tumblr using their API.' ), + 'plugin-slug' => 'tumblr-importer', + 'importer-id' => 'tumblr', + ), + 'wordpress' => array( + 'name' => 'WordPress', + 'description' => __( 'Install the WordPress importer to import posts, pages, comments, custom fields, categories, and tags from a WordPress export file.' ), + 'plugin-slug' => 'wordpress-importer', + 'importer-id' => 'wordpress', + ), + ); +} diff --git a/sources/wp-admin/includes/list-table.php b/sources/wp-admin/includes/list-table.php new file mode 100644 index 0000000..2403ec8 --- /dev/null +++ b/sources/wp-admin/includes/list-table.php @@ -0,0 +1,113 @@ + 'posts', + 'WP_Media_List_Table' => 'media', + 'WP_Terms_List_Table' => 'terms', + 'WP_Users_List_Table' => 'users', + 'WP_Comments_List_Table' => 'comments', + 'WP_Post_Comments_List_Table' => 'comments', + 'WP_Links_List_Table' => 'links', + 'WP_Plugin_Install_List_Table' => 'plugin-install', + 'WP_Themes_List_Table' => 'themes', + 'WP_Theme_Install_List_Table' => array( 'themes', 'theme-install' ), + 'WP_Plugins_List_Table' => 'plugins', + // Network Admin + 'WP_MS_Sites_List_Table' => 'ms-sites', + 'WP_MS_Users_List_Table' => 'ms-users', + 'WP_MS_Themes_List_Table' => 'ms-themes', + ); + + if ( isset( $core_classes[ $class ] ) ) { + foreach ( (array) $core_classes[ $class ] as $required ) + require_once( ABSPATH . 'wp-admin/includes/class-wp-' . $required . '-list-table.php' ); + + if ( isset( $args['screen'] ) ) + $args['screen'] = convert_to_screen( $args['screen'] ); + elseif ( isset( $GLOBALS['hook_suffix'] ) ) + $args['screen'] = get_current_screen(); + else + $args['screen'] = null; + + return new $class( $args ); + } + + return false; +} + +/** + * Register column headers for a particular screen. + * + * @since 2.7.0 + * + * @param string $screen The handle for the screen to add help to. This is usually the hook name returned by the add_*_page() functions. + * @param array $columns An array of columns with column IDs as the keys and translated column names as the values + * @see get_column_headers(), print_column_headers(), get_hidden_columns() + */ +function register_column_headers($screen, $columns) { + $wp_list_table = new _WP_List_Table_Compat($screen, $columns); +} + +/** + * Prints column headers for a particular screen. + * + * @since 2.7.0 + */ +function print_column_headers($screen, $id = true) { + $wp_list_table = new _WP_List_Table_Compat($screen); + + $wp_list_table->print_column_headers($id); +} + +/** + * Helper class to be used only by back compat functions + * + * @since 3.1.0 + */ +class _WP_List_Table_Compat extends WP_List_Table { + var $_screen; + var $_columns; + + function _WP_List_Table_Compat( $screen, $columns = array() ) { + if ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + $this->_screen = $screen; + + if ( !empty( $columns ) ) { + $this->_columns = $columns; + add_filter( 'manage_' . $screen->id . '_columns', array( $this, 'get_columns' ), 0 ); + } + } + + function get_column_info() { + $columns = get_column_headers( $this->_screen ); + $hidden = get_hidden_columns( $this->_screen ); + $sortable = array(); + + return array( $columns, $hidden, $sortable ); + } + + function get_columns() { + return $this->_columns; + } +} diff --git a/sources/wp-admin/includes/media.php b/sources/wp-admin/includes/media.php new file mode 100644 index 0000000..e2f78d6 --- /dev/null +++ b/sources/wp-admin/includes/media.php @@ -0,0 +1,2708 @@ + __('From Computer'), // handler action suffix => tab text + 'type_url' => __('From URL'), + 'gallery' => __('Gallery'), + 'library' => __('Media Library') + ); + + return apply_filters('media_upload_tabs', $_default_tabs); +} + +/** + * Adds the gallery tab back to the tabs array if post has image attachments + * + * @since 2.5.0 + * + * @param array $tabs + * @return array $tabs with gallery if post has image attachment + */ +function update_gallery_tab($tabs) { + global $wpdb; + + if ( !isset($_REQUEST['post_id']) ) { + unset($tabs['gallery']); + return $tabs; + } + + $post_id = intval($_REQUEST['post_id']); + + if ( $post_id ) + $attachments = intval( $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent = %d", $post_id ) ) ); + + if ( empty($attachments) ) { + unset($tabs['gallery']); + return $tabs; + } + + $tabs['gallery'] = sprintf(__('Gallery (%s)'), "$attachments"); + + return $tabs; +} +add_filter('media_upload_tabs', 'update_gallery_tab'); + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + */ +function the_media_upload_tabs() { + global $redir_tab; + $tabs = media_upload_tabs(); + $default = 'type'; + + if ( !empty($tabs) ) { + echo "
      \n"; + if ( isset($redir_tab) && array_key_exists($redir_tab, $tabs) ) + $current = $redir_tab; + elseif ( isset($_GET['tab']) && array_key_exists($_GET['tab'], $tabs) ) + $current = $_GET['tab']; + else + $current = apply_filters('media_upload_default_tab', $default); + + foreach ( $tabs as $callback => $text ) { + $class = ''; + + if ( $current == $callback ) + $class = " class='current'"; + + $href = add_query_arg(array('tab' => $callback, 's' => false, 'paged' => false, 'post_mime_type' => false, 'm' => false)); + $link = "$text"; + echo "\t
    • $link
    • \n"; + } + echo "
    \n"; + } +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param integer $id image attachment id + * @param string $caption image caption + * @param string $alt image alt attribute + * @param string $title image title attribute + * @param string $align image css alignment property + * @param string $url image src url + * @param string|bool $rel image rel attribute + * @param string $size image size (thumbnail, medium, large, full or added with add_image_size() ) + * @return string the html to insert into editor + */ +function get_image_send_to_editor($id, $caption, $title, $align, $url='', $rel = false, $size='medium', $alt = '') { + + $html = get_image_tag($id, $alt, '', $align, $size); + + $rel = $rel ? ' rel="attachment wp-att-' . esc_attr($id).'"' : ''; + + if ( $url ) + $html = '$html"; + + $html = apply_filters( 'image_send_to_editor', $html, $id, $caption, $title, $align, $url, $size, $alt ); + + return $html; +} + +/** + * Adds image shortcode with caption to editor + * + * @since 2.6.0 + * + * @param string $html + * @param integer $id + * @param string $caption image caption + * @param string $alt image alt attribute + * @param string $title image title attribute + * @param string $align image css alignment property + * @param string $url image src url + * @param string $size image size (thumbnail, medium, large, full or added with add_image_size() ) + * @return string + */ +function image_add_caption( $html, $id, $caption, $title, $align, $url, $size, $alt = '' ) { + + if ( empty($caption) || apply_filters( 'disable_captions', '' ) ) + return $html; + + $id = ( 0 < (int) $id ) ? 'attachment_' . $id : ''; + + if ( ! preg_match( '/width=["\']([0-9]+)/', $html, $matches ) ) + return $html; + + $width = $matches[1]; + + $caption = str_replace( array("\r\n", "\r"), "\n", $caption); + $caption = preg_replace_callback( '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', '_cleanup_image_add_caption', $caption ); + // convert any remaining line breaks to
    + $caption = preg_replace( '/[ \n\t]*\n[ \t]*/', '
    ', $caption ); + + $html = preg_replace( '/(class=["\'][^\'"]*)align(none|left|right|center)\s?/', '$1', $html ); + if ( empty($align) ) + $align = 'none'; + + $shcode = '[caption id="' . $id . '" align="align' . $align . '" width="' . $width . '"]' . $html . ' ' . $caption . '[/caption]'; + + return apply_filters( 'image_add_caption_shortcode', $shcode, $html ); +} +add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 ); + +/** + * Private preg_replace callback used in image_add_caption() + * + * @access private + * @since 3.4.0 + */ +function _cleanup_image_add_caption( $matches ) { + // remove any line breaks from inside the tags + return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] ); +} + +/** + * Adds image html to editor + * + * @since 2.5.0 + * + * @param string $html + */ +function media_send_to_editor($html) { +?> + + false )) { + + $time = current_time('mysql'); + if ( $post = get_post($post_id) ) { + if ( substr( $post->post_date, 0, 4 ) > 0 ) + $time = $post->post_date; + } + + $name = $_FILES[$file_id]['name']; + $file = wp_handle_upload($_FILES[$file_id], $overrides, $time); + + if ( isset($file['error']) ) + return new WP_Error( 'upload_error', $file['error'] ); + + $name_parts = pathinfo($name); + $name = trim( substr( $name, 0, -(1 + strlen($name_parts['extension'])) ) ); + + $url = $file['url']; + $type = $file['type']; + $file = $file['file']; + $title = $name; + $content = ''; + + if ( preg_match( '#^audio#', $type ) ) { + $meta = wp_read_audio_metadata( $file ); + + if ( ! empty( $meta['title'] ) ) + $title = $meta['title']; + + $content = ''; + + if ( ! empty( $title ) ) { + + if ( ! empty( $meta['album'] ) && ! empty( $meta['artist'] ) ) { + /* translators: 1: audio track title, 2: album title, 3: artist name */ + $content .= sprintf( __( '"%1$s" from %2$s by %3$s.' ), $title, $meta['album'], $meta['artist'] ); + } else if ( ! empty( $meta['album'] ) ) { + /* translators: 1: audio track title, 2: album title */ + $content .= sprintf( __( '"%1$s" from %2$s.' ), $title, $meta['album'] ); + } else if ( ! empty( $meta['artist'] ) ) { + /* translators: 1: audio track title, 2: artist name */ + $content .= sprintf( __( '"%1$s" by %2$s.' ), $title, $meta['artist'] ); + } else { + $content .= sprintf( __( '"%s".' ), $title ); + } + + } else if ( ! empty( $meta['album'] ) ) { + + if ( ! empty( $meta['artist'] ) ) { + /* translators: 1: audio album title, 2: artist name */ + $content .= sprintf( __( '%1$s by %2$s.' ), $meta['album'], $meta['artist'] ); + } else { + $content .= $meta['album'] . '.'; + } + + } else if ( ! empty( $meta['artist'] ) ) { + + $content .= $meta['artist'] . '.'; + + } + + if ( ! empty( $meta['year'] ) ) + $content .= ' ' . sprintf( __( 'Released: %d.' ), $meta['year'] ); + + if ( ! empty( $meta['track_number'] ) ) { + $track_number = explode( '/', $meta['track_number'] ); + if ( isset( $track_number[1] ) ) + $content .= ' ' . sprintf( __( 'Track %1$s of %2$s.' ), number_format_i18n( $track_number[0] ), number_format_i18n( $track_number[1] ) ); + else + $content .= ' ' . sprintf( __( 'Track %1$s.' ), number_format_i18n( $track_number[0] ) ); + } + + if ( ! empty( $meta['genre'] ) ) + $content .= ' ' . sprintf( __( 'Genre: %s.' ), $meta['genre'] ); + + // use image exif/iptc data for title and caption defaults if possible + } elseif ( $image_meta = @wp_read_image_metadata( $file ) ) { + if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) + $title = $image_meta['title']; + if ( trim( $image_meta['caption'] ) ) + $content = $image_meta['caption']; + } + + // Construct the attachment array + $attachment = array_merge( array( + 'post_mime_type' => $type, + 'guid' => $url, + 'post_parent' => $post_id, + 'post_title' => $title, + 'post_content' => $content, + ), $post_data ); + + // This should never be set as it would then overwrite an existing attachment. + if ( isset( $attachment['ID'] ) ) + unset( $attachment['ID'] ); + + // Save the data + $id = wp_insert_attachment($attachment, $file, $post_id); + if ( !is_wp_error($id) ) { + wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) ); + } + + return $id; + +} + +/** + * This handles a sideloaded file in the same way as an uploaded file is handled by {@link media_handle_upload()} + * + * @since 2.6.0 + * + * @param array $file_array Array similar to a {@link $_FILES} upload array + * @param int $post_id The post ID the media is associated with + * @param string $desc Description of the sideloaded file + * @param array $post_data allows you to overwrite some of the attachment + * @return int|object The ID of the attachment or a WP_Error on failure + */ +function media_handle_sideload($file_array, $post_id, $desc = null, $post_data = array()) { + $overrides = array('test_form'=>false); + + $time = current_time( 'mysql' ); + if ( $post = get_post( $post_id ) ) { + if ( substr( $post->post_date, 0, 4 ) > 0 ) + $time = $post->post_date; + } + + $file = wp_handle_sideload( $file_array, $overrides, $time ); + if ( isset($file['error']) ) + return new WP_Error( 'upload_error', $file['error'] ); + + $url = $file['url']; + $type = $file['type']; + $file = $file['file']; + $title = preg_replace('/\.[^.]+$/', '', basename($file)); + $content = ''; + + // use image exif/iptc data for title and caption defaults if possible + if ( $image_meta = @wp_read_image_metadata($file) ) { + if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) + $title = $image_meta['title']; + if ( trim( $image_meta['caption'] ) ) + $content = $image_meta['caption']; + } + + if ( isset( $desc ) ) + $title = $desc; + + // Construct the attachment array + $attachment = array_merge( array( + 'post_mime_type' => $type, + 'guid' => $url, + 'post_parent' => $post_id, + 'post_title' => $title, + 'post_content' => $content, + ), $post_data ); + + // This should never be set as it would then overwrite an existing attachment. + if ( isset( $attachment['ID'] ) ) + unset( $attachment['ID'] ); + + // Save the attachment metadata + $id = wp_insert_attachment($attachment, $file, $post_id); + if ( !is_wp_error($id) ) + wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) ); + + return $id; +} + +/** + * Adds the iframe to display content for the media upload page + * + * @since 2.5.0 + * + * @param array $content_func + */ +function wp_iframe($content_func /* ... */) { + _wp_admin_html_begin(); +?> +<?php bloginfo('name') ?> › <?php _e('Uploads'); ?> — <?php _e('WordPress'); ?> + + + + + class="wp-core-ui no-js"> + + + + + + $post + ) ); + + $img = ' '; + + echo '' . $img . __( 'Add Media' ) . ''; + + // Don't use this filter. Want to add a button? Use the media_buttons action. + $legacy_filter = apply_filters('media_buttons_context', ''); // deprecated + + if ( $legacy_filter ) { + // #WP22559. Close if a plugin started by closing to open their own tag. + if ( 0 === stripos( trim( $legacy_filter ), '' ) ) + $legacy_filter .= ''; + echo $legacy_filter; + } +} +add_action( 'media_buttons', 'media_buttons' ); + +function get_upload_iframe_src( $type = null, $post_id = null, $tab = null ) { + global $post_ID; + + if ( empty( $post_id ) ) + $post_id = $post_ID; + + $upload_iframe_src = add_query_arg( 'post_id', (int) $post_id, admin_url('media-upload.php') ); + + if ( $type && 'media' != $type ) + $upload_iframe_src = add_query_arg('type', $type, $upload_iframe_src); + + if ( ! empty( $tab ) ) + $upload_iframe_src = add_query_arg('tab', $tab, $upload_iframe_src); + + $upload_iframe_src = apply_filters($type . '_upload_iframe_src', $upload_iframe_src); + + return add_query_arg('TB_iframe', true, $upload_iframe_src); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @return mixed void|object WP_Error on failure + */ +function media_upload_form_handler() { + check_admin_referer('media-form'); + + $errors = null; + + if ( isset($_POST['send']) ) { + $keys = array_keys($_POST['send']); + $send_id = (int) array_shift($keys); + } + + if ( !empty($_POST['attachments']) ) foreach ( $_POST['attachments'] as $attachment_id => $attachment ) { + $post = $_post = get_post($attachment_id, ARRAY_A); + + if ( !current_user_can( 'edit_post', $attachment_id ) ) + continue; + + if ( isset($attachment['post_content']) ) + $post['post_content'] = $attachment['post_content']; + if ( isset($attachment['post_title']) ) + $post['post_title'] = $attachment['post_title']; + if ( isset($attachment['post_excerpt']) ) + $post['post_excerpt'] = $attachment['post_excerpt']; + if ( isset($attachment['menu_order']) ) + $post['menu_order'] = $attachment['menu_order']; + + if ( isset($send_id) && $attachment_id == $send_id ) { + if ( isset($attachment['post_parent']) ) + $post['post_parent'] = $attachment['post_parent']; + } + + $post = apply_filters('attachment_fields_to_save', $post, $attachment); + + if ( isset($attachment['image_alt']) ) { + $image_alt = wp_unslash( $attachment['image_alt'] ); + if ( $image_alt != get_post_meta($attachment_id, '_wp_attachment_image_alt', true) ) { + $image_alt = wp_strip_all_tags( $image_alt, true ); + // update_meta expects slashed + update_post_meta( $attachment_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) ); + } + } + + if ( isset($post['errors']) ) { + $errors[$attachment_id] = $post['errors']; + unset($post['errors']); + } + + if ( $post != $_post ) + wp_update_post($post); + + foreach ( get_attachment_taxonomies($post) as $t ) { + if ( isset($attachment[$t]) ) + wp_set_object_terms($attachment_id, array_map('trim', preg_split('/,+/', $attachment[$t])), $t, false); + } + } + + if ( isset($_POST['insert-gallery']) || isset($_POST['update-gallery']) ) { ?> + + $html"; + } + + $html = apply_filters('media_send_to_editor', $html, $send_id, $attachment); + return media_send_to_editor($html); + } + + return $errors; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @return mixed + */ +function wp_media_upload_handler() { + $errors = array(); + $id = 0; + + if ( isset($_POST['html-upload']) && !empty($_FILES) ) { + check_admin_referer('media-form'); + // Upload File button was clicked + $id = media_handle_upload('async-upload', $_REQUEST['post_id']); + unset($_FILES); + if ( is_wp_error($id) ) { + $errors['upload_error'] = $id; + $id = false; + } + } + + if ( !empty($_POST['insertonlybutton']) ) { + $src = $_POST['src']; + if ( !empty($src) && !strpos($src, '://') ) + $src = "http://$src"; + + if ( isset( $_POST['media_type'] ) && 'image' != $_POST['media_type'] ) { + $title = esc_html( wp_unslash( $_POST['title'] ) ); + if ( empty( $title ) ) + $title = esc_html( basename( $src ) ); + + if ( $title && $src ) + $html = "$title"; + + $type = 'file'; + if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) ) + && ( 'audio' == $ext_type || 'video' == $ext_type ) ) + $type = $ext_type; + + $html = apply_filters( $type . '_send_to_editor_url', $html, esc_url_raw( $src ), $title ); + } else { + $align = ''; + $alt = esc_attr( wp_unslash( $_POST['alt'] ) ); + if ( isset($_POST['align']) ) { + $align = esc_attr( wp_unslash( $_POST['align'] ) ); + $class = " class='align$align'"; + } + if ( !empty($src) ) + $html = "$alt"; + + $html = apply_filters( 'image_send_to_editor_url', $html, esc_url_raw( $src ), $alt, $align ); + } + + return media_send_to_editor($html); + } + + if ( !empty($_POST) ) { + $return = media_upload_form_handler(); + + if ( is_string($return) ) + return $return; + if ( is_array($return) ) + $errors = $return; + } + + if ( isset($_POST['save']) ) { + $errors['upload_notice'] = __('Saved.'); + return media_upload_gallery(); + } + + if ( isset($_GET['tab']) && $_GET['tab'] == 'type_url' ) { + $type = 'image'; + if ( isset( $_GET['type'] ) && in_array( $_GET['type'], array( 'video', 'audio', 'file' ) ) ) + $type = $_GET['type']; + return wp_iframe( 'media_upload_type_url_form', $type, $errors, $id ); + } + + return wp_iframe( 'media_upload_type_form', 'image', $errors, $id ); +} + +/** + * Download an image from the specified URL and attach it to a post. + * + * @since 2.6.0 + * + * @param string $file The URL of the image to download + * @param int $post_id The post ID the media is to be associated with + * @param string $desc Optional. Description of the image + * @return string|WP_Error Populated HTML img tag on success + */ +function media_sideload_image($file, $post_id, $desc = null) { + if ( ! empty($file) ) { + // Download file to temp location + $tmp = download_url( $file ); + + // Set variables for storage + // fix file filename for query strings + preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches ); + $file_array['name'] = basename($matches[0]); + $file_array['tmp_name'] = $tmp; + + // If error storing temporarily, unlink + if ( is_wp_error( $tmp ) ) { + @unlink($file_array['tmp_name']); + $file_array['tmp_name'] = ''; + } + + // do the validation and storage stuff + $id = media_handle_sideload( $file_array, $post_id, $desc ); + // If error storing permanently, unlink + if ( is_wp_error($id) ) { + @unlink($file_array['tmp_name']); + return $id; + } + + $src = wp_get_attachment_url( $id ); + } + + // Finally check to make sure the file has been saved, then return the html + if ( ! empty($src) ) { + $alt = isset($desc) ? esc_attr($desc) : ''; + $html = "$alt"; + return $html; + } +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @return unknown + */ +function media_upload_gallery() { + $errors = array(); + + if ( !empty($_POST) ) { + $return = media_upload_form_handler(); + + if ( is_string($return) ) + return $return; + if ( is_array($return) ) + $errors = $return; + } + + wp_enqueue_script('admin-gallery'); + return wp_iframe( 'media_upload_gallery_form', $errors ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @return unknown + */ +function media_upload_library() { + $errors = array(); + if ( !empty($_POST) ) { + $return = media_upload_form_handler(); + + if ( is_string($return) ) + return $return; + if ( is_array($return) ) + $errors = $return; + } + + return wp_iframe( 'media_upload_library_form', $errors ); +} + +/** + * Retrieve HTML for the image alignment radio buttons with the specified one checked. + * + * @since 2.7.0 + * + * @param object $post + * @param string $checked + * @return string + */ +function image_align_input_fields( $post, $checked = '' ) { + + if ( empty($checked) ) + $checked = get_user_setting('align', 'none'); + + $alignments = array('none' => __('None'), 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right')); + if ( !array_key_exists( (string) $checked, $alignments ) ) + $checked = 'none'; + + $out = array(); + foreach ( $alignments as $name => $label ) { + $name = esc_attr($name); + $out[] = ""; + } + return join("\n", $out); +} + +/** + * Retrieve HTML for the size radio buttons with the specified one checked. + * + * @since 2.7.0 + * + * @param object $post + * @param bool|string $check + * @return array + */ +function image_size_input_fields( $post, $check = '' ) { + + // get a list of the actual pixel dimensions of each possible intermediate version of this image + $size_names = apply_filters( 'image_size_names_choose', array('thumbnail' => __('Thumbnail'), 'medium' => __('Medium'), 'large' => __('Large'), 'full' => __('Full Size')) ); + + if ( empty($check) ) + $check = get_user_setting('imgsize', 'medium'); + + foreach ( $size_names as $size => $label ) { + $downsize = image_downsize($post->ID, $size); + $checked = ''; + + // is this size selectable? + $enabled = ( $downsize[3] || 'full' == $size ); + $css_id = "image-size-{$size}-{$post->ID}"; + // if this size is the default but that's not available, don't select it + if ( $size == $check ) { + if ( $enabled ) + $checked = " checked='checked'"; + else + $check = ''; + } elseif ( !$check && $enabled && 'thumbnail' != $size ) { + // if $check is not enabled, default to the first available size that's bigger than a thumbnail + $check = $size; + $checked = " checked='checked'"; + } + + $html = "
    "; + + $html .= ""; + // only show the dimensions if that choice is available + if ( $enabled ) + $html .= " "; + + $html .= '
    '; + + $out[] = $html; + } + + return array( + 'label' => __('Size'), + 'input' => 'html', + 'html' => join("\n", $out), + ); +} + +/** + * Retrieve HTML for the Link URL buttons with the default link type as specified. + * + * @since 2.7.0 + * + * @param object $post + * @param string $url_type + * @return string + */ +function image_link_input_fields($post, $url_type = '') { + + $file = wp_get_attachment_url($post->ID); + $link = get_attachment_link($post->ID); + + if ( empty($url_type) ) + $url_type = get_user_setting('urlbutton', 'post'); + + $url = ''; + if ( $url_type == 'file' ) + $url = $file; + elseif ( $url_type == 'post' ) + $url = $link; + + return " +
    + + + +"; +} + +function wp_caption_input_textarea($edit_post) { + // post data is already escaped + $name = "attachments[{$edit_post->ID}][post_excerpt]"; + + return ''; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param array $form_fields + * @param object $post + * @return array + */ +function image_attachment_fields_to_edit($form_fields, $post) { + return $form_fields; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param array $form_fields + * @param object $post {@internal $post not used}} + * @return array + */ +function media_single_attachment_fields_to_edit( $form_fields, $post ) { + unset($form_fields['url'], $form_fields['align'], $form_fields['image-size']); + return $form_fields; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.8.0 + * + * @param array $form_fields + * @param object $post {@internal $post not used}} + * @return array + */ +function media_post_single_attachment_fields_to_edit( $form_fields, $post ) { + unset($form_fields['image_url']); + return $form_fields; +} + +/** + * Filters input from media_upload_form_handler() and assigns a default + * post_title from the file name if none supplied. + * + * Illustrates the use of the attachment_fields_to_save filter + * which can be used to add default values to any field before saving to DB. + * + * @since 2.5.0 + * + * @param object $post + * @param array $attachment {@internal $attachment not used}} + * @return array + */ +function image_attachment_fields_to_save( $post, $attachment ) { + if ( substr( $post['post_mime_type'], 0, 5 ) == 'image' ) { + if ( strlen( trim( $post['post_title'] ) ) == 0 ) { + $attachment_url = ( isset( $post['attachment_url'] ) ) ? $post['attachment_url'] : $post['guid']; + $post['post_title'] = preg_replace( '/\.\w+$/', '', wp_basename( $attachment_url ) ); + $post['errors']['post_title']['errors'][] = __( 'Empty Title filled from filename.' ); + } + } + + return $post; +} + +add_filter( 'attachment_fields_to_save', 'image_attachment_fields_to_save', 10, 2 ); + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param string $html + * @param integer $attachment_id + * @param array $attachment + * @return array + */ +function image_media_send_to_editor($html, $attachment_id, $attachment) { + $post = get_post($attachment_id); + if ( substr($post->post_mime_type, 0, 5) == 'image' ) { + $url = $attachment['url']; + $align = !empty($attachment['align']) ? $attachment['align'] : 'none'; + $size = !empty($attachment['image-size']) ? $attachment['image-size'] : 'medium'; + $alt = !empty($attachment['image_alt']) ? $attachment['image_alt'] : ''; + $rel = ( $url == get_attachment_link($attachment_id) ); + + return get_image_send_to_editor($attachment_id, $attachment['post_excerpt'], $attachment['post_title'], $align, $url, $rel, $size, $alt); + } + + return $html; +} + +add_filter('media_send_to_editor', 'image_media_send_to_editor', 10, 3); + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param object $post + * @param array $errors + * @return array + */ +function get_attachment_fields_to_edit($post, $errors = null) { + if ( is_int($post) ) + $post = get_post($post); + if ( is_array($post) ) + $post = new WP_Post( (object) $post ); + + $image_url = wp_get_attachment_url($post->ID); + + $edit_post = sanitize_post($post, 'edit'); + + $form_fields = array( + 'post_title' => array( + 'label' => __('Title'), + 'value' => $edit_post->post_title + ), + 'image_alt' => array(), + 'post_excerpt' => array( + 'label' => __('Caption'), + 'input' => 'html', + 'html' => wp_caption_input_textarea($edit_post) + ), + 'post_content' => array( + 'label' => __('Description'), + 'value' => $edit_post->post_content, + 'input' => 'textarea' + ), + 'url' => array( + 'label' => __('Link URL'), + 'input' => 'html', + 'html' => image_link_input_fields($post, get_option('image_default_link_type')), + 'helps' => __('Enter a link URL or click above for presets.') + ), + 'menu_order' => array( + 'label' => __('Order'), + 'value' => $edit_post->menu_order + ), + 'image_url' => array( + 'label' => __('File URL'), + 'input' => 'html', + 'html' => "
    ", + 'value' => wp_get_attachment_url($post->ID), + 'helps' => __('Location of the uploaded file.') + ) + ); + + foreach ( get_attachment_taxonomies($post) as $taxonomy ) { + $t = (array) get_taxonomy($taxonomy); + if ( ! $t['public'] || ! $t['show_ui'] ) + continue; + if ( empty($t['label']) ) + $t['label'] = $taxonomy; + if ( empty($t['args']) ) + $t['args'] = array(); + + $terms = get_object_term_cache($post->ID, $taxonomy); + if ( false === $terms ) + $terms = wp_get_object_terms($post->ID, $taxonomy, $t['args']); + + $values = array(); + + foreach ( $terms as $term ) + $values[] = $term->slug; + $t['value'] = join(', ', $values); + + $form_fields[$taxonomy] = $t; + } + + // Merge default fields with their errors, so any key passed with the error (e.g. 'error', 'helps', 'value') will replace the default + // The recursive merge is easily traversed with array casting: foreach( (array) $things as $thing ) + $form_fields = array_merge_recursive($form_fields, (array) $errors); + + // This was formerly in image_attachment_fields_to_edit(). + if ( substr($post->post_mime_type, 0, 5) == 'image' ) { + $alt = get_post_meta($post->ID, '_wp_attachment_image_alt', true); + if ( empty($alt) ) + $alt = ''; + + $form_fields['post_title']['required'] = true; + + $form_fields['image_alt'] = array( + 'value' => $alt, + 'label' => __('Alternative Text'), + 'helps' => __('Alt text for the image, e.g. “The Mona Lisa”') + ); + + $form_fields['align'] = array( + 'label' => __('Alignment'), + 'input' => 'html', + 'html' => image_align_input_fields($post, get_option('image_default_align')), + ); + + $form_fields['image-size'] = image_size_input_fields( $post, get_option('image_default_size', 'medium') ); + + } else { + unset( $form_fields['image_alt'] ); + } + + $form_fields = apply_filters('attachment_fields_to_edit', $form_fields, $post); + + return $form_fields; +} + +/** + * Retrieve HTML for media items of post gallery. + * + * The HTML markup retrieved will be created for the progress of SWF Upload + * component. Will also create link for showing and hiding the form to modify + * the image attachment. + * + * @since 2.5.0 + * + * @param int $post_id Optional. Post ID. + * @param array $errors Errors for attachment, if any. + * @return string + */ +function get_media_items( $post_id, $errors ) { + $attachments = array(); + if ( $post_id ) { + $post = get_post($post_id); + if ( $post && $post->post_type == 'attachment' ) + $attachments = array($post->ID => $post); + else + $attachments = get_children( array( 'post_parent' => $post_id, 'post_type' => 'attachment', 'orderby' => 'menu_order ASC, ID', 'order' => 'DESC') ); + } else { + if ( is_array($GLOBALS['wp_the_query']->posts) ) + foreach ( $GLOBALS['wp_the_query']->posts as $attachment ) + $attachments[$attachment->ID] = $attachment; + } + + $output = ''; + foreach ( (array) $attachments as $id => $attachment ) { + if ( $attachment->post_status == 'trash' ) + continue; + if ( $item = get_media_item( $id, array( 'errors' => isset($errors[$id]) ? $errors[$id] : null) ) ) + $output .= "\n
    $item\n
    "; + } + + return $output; +} + +/** + * Retrieve HTML form for modifying the image attachment. + * + * @since 2.5.0 + * + * @param int $attachment_id Attachment ID for modification. + * @param string|array $args Optional. Override defaults. + * @return string HTML form for attachment. + */ +function get_media_item( $attachment_id, $args = null ) { + global $redir_tab; + + if ( ( $attachment_id = intval( $attachment_id ) ) && $thumb_url = wp_get_attachment_image_src( $attachment_id, 'thumbnail', true ) ) + $thumb_url = $thumb_url[0]; + else + $thumb_url = false; + + $post = get_post( $attachment_id ); + $current_post_id = !empty( $_GET['post_id'] ) ? (int) $_GET['post_id'] : 0; + + $default_args = array( 'errors' => null, 'send' => $current_post_id ? post_type_supports( get_post_type( $current_post_id ), 'editor' ) : true, 'delete' => true, 'toggle' => true, 'show_title' => true ); + $args = wp_parse_args( $args, $default_args ); + $args = apply_filters( 'get_media_item_args', $args ); + extract( $args, EXTR_SKIP ); + + $toggle_on = __( 'Show' ); + $toggle_off = __( 'Hide' ); + + $filename = esc_html( wp_basename( $post->guid ) ); + $title = esc_attr( $post->post_title ); + + if ( $_tags = get_the_tags( $attachment_id ) ) { + foreach ( $_tags as $tag ) + $tags[] = $tag->name; + $tags = esc_attr( join( ', ', $tags ) ); + } + + $post_mime_types = get_post_mime_types(); + $keys = array_keys( wp_match_mime_types( array_keys( $post_mime_types ), $post->post_mime_type ) ); + $type = array_shift( $keys ); + $type_html = ""; + + $form_fields = get_attachment_fields_to_edit( $post, $errors ); + + if ( $toggle ) { + $class = empty( $errors ) ? 'startclosed' : 'startopen'; + $toggle_links = " + $toggle_on + $toggle_off"; + } else { + $class = ''; + $toggle_links = ''; + } + + $display_title = ( !empty( $title ) ) ? $title : $filename; // $title shouldn't ever be empty, but just in case + $display_title = $show_title ? "
    " . wp_html_excerpt( $display_title, 60, '…' ) . "
    " : ''; + + $gallery = ( ( isset( $_REQUEST['tab'] ) && 'gallery' == $_REQUEST['tab'] ) || ( isset( $redir_tab ) && 'gallery' == $redir_tab ) ); + $order = ''; + + foreach ( $form_fields as $key => $val ) { + if ( 'menu_order' == $key ) { + if ( $gallery ) + $order = ""; + else + $order = ""; + + unset( $form_fields['menu_order'] ); + break; + } + } + + $media_dims = ''; + $meta = wp_get_attachment_metadata( $post->ID ); + if ( isset( $meta['width'], $meta['height'] ) ) + $media_dims .= "{$meta['width']} × {$meta['height']} "; + $media_dims = apply_filters( 'media_meta', $media_dims, $post ); + + $image_edit_button = ''; + if ( wp_attachment_is_image( $post->ID ) && wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) { + $nonce = wp_create_nonce( "image_editor-$post->ID" ); + $image_edit_button = " "; + } + + $attachment_url = get_permalink( $attachment_id ); + + $item = " + $type_html + $toggle_links + $order + $display_title + + + + + \n"; + + $item .= " + + + + \n"; + + $defaults = array( + 'input' => 'text', + 'required' => false, + 'value' => '', + 'extra_rows' => array(), + ); + + if ( $send ) + $send = get_submit_button( __( 'Insert into Post' ), 'button', "send[$attachment_id]", false ); + if ( $delete && current_user_can( 'delete_post', $attachment_id ) ) { + if ( !EMPTY_TRASH_DAYS ) { + $delete = "" . __( 'Delete Permanently' ) . ''; + } elseif ( !MEDIA_TRASH ) { + $delete = "" . __( 'Delete' ) . " + "; + } else { + $delete = "" . __( 'Move to Trash' ) . " + "; + } + } else { + $delete = ''; + } + + $thumbnail = ''; + $calling_post_id = 0; + if ( isset( $_GET['post_id'] ) ) + $calling_post_id = absint( $_GET['post_id'] ); + elseif ( isset( $_POST ) && count( $_POST ) ) // Like for async-upload where $_GET['post_id'] isn't set + $calling_post_id = $post->post_parent; + if ( 'image' == $type && $calling_post_id && current_theme_supports( 'post-thumbnails', get_post_type( $calling_post_id ) ) + && post_type_supports( get_post_type( $calling_post_id ), 'thumbnail' ) && get_post_thumbnail_id( $calling_post_id ) != $attachment_id ) { + $ajax_nonce = wp_create_nonce( "set_post_thumbnail-$calling_post_id" ); + $thumbnail = "" . esc_html__( "Use as featured image" ) . ""; + } + + if ( ( $send || $thumbnail || $delete ) && !isset( $form_fields['buttons'] ) ) + $form_fields['buttons'] = array( 'tr' => "\t\t\n" ); + + $hidden_fields = array(); + + foreach ( $form_fields as $id => $field ) { + if ( $id[0] == '_' ) + continue; + + if ( !empty( $field['tr'] ) ) { + $item .= $field['tr']; + continue; + } + + $field = array_merge( $defaults, $field ); + $name = "attachments[$attachment_id][$id]"; + + if ( $field['input'] == 'hidden' ) { + $hidden_fields[$name] = $field['value']; + continue; + } + + $required = $field['required'] ? '*' : ''; + $aria_required = $field['required'] ? " aria-required='true' " : ''; + $class = $id; + $class .= $field['required'] ? ' form-required' : ''; + + $item .= "\t\t\n\t\t\t\n\t\t\t\n\t\t\n"; + + $extra_rows = array(); + + if ( !empty( $field['errors'] ) ) + foreach ( array_unique( (array) $field['errors'] ) as $error ) + $extra_rows['error'][] = $error; + + if ( !empty( $field['extra_rows'] ) ) + foreach ( $field['extra_rows'] as $class => $rows ) + foreach ( (array) $rows as $html ) + $extra_rows[$class][] = $html; + + foreach ( $extra_rows as $class => $rows ) + foreach ( $rows as $html ) + $item .= "\t\t\n"; + } + + if ( !empty( $form_fields['_final'] ) ) + $item .= "\t\t\n"; + $item .= "\t\n"; + $item .= "\t
    +

    +

    $image_edit_button

    +
    +

    " . __('File name:') . " $filename

    +

    " . __('File type:') . " $post->post_mime_type

    +

    " . __('Upload date:') . " " . mysql2date( get_option('date_format'), $post->post_date ). '

    '; + if ( !empty( $media_dims ) ) + $item .= "

    " . __('Dimensions:') . " $media_dims

    \n"; + + $item .= "
    $send $thumbnail $delete
    "; + if ( !empty( $field[ $field['input'] ] ) ) + $item .= $field[ $field['input'] ]; + elseif ( $field['input'] == 'textarea' ) { + if ( 'post_content' == $id && user_can_richedit() ) { + // sanitize_post() skips the post_content when user_can_richedit + $field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES ); + } + // post_excerpt is already escaped by sanitize_post() in get_attachment_fields_to_edit() + $item .= "'; + } else { + $item .= ""; + } + if ( !empty( $field['helps'] ) ) + $item .= "

    " . join( "

    \n

    ", array_unique( (array) $field['helps'] ) ) . '

    '; + $item .= "
    $html
    {$form_fields['_final']}
    \n"; + + foreach ( $hidden_fields as $name => $value ) + $item .= "\t\n"; + + if ( $post->post_parent < 1 && isset( $_REQUEST['post_id'] ) ) { + $parent = (int) $_REQUEST['post_id']; + $parent_name = "attachments[$attachment_id][post_parent]"; + $item .= "\t\n"; + } + + return $item; +} + +function get_compat_media_markup( $attachment_id, $args = null ) { + $post = get_post( $attachment_id ); + + $default_args = array( + 'errors' => null, + 'in_modal' => false, + ); + + $user_can_edit = current_user_can( 'edit_post', $attachment_id ); + + $args = wp_parse_args( $args, $default_args ); + $args = apply_filters( 'get_media_item_args', $args ); + + $form_fields = array(); + + if ( $args['in_modal'] ) { + foreach ( get_attachment_taxonomies($post) as $taxonomy ) { + $t = (array) get_taxonomy($taxonomy); + if ( ! $t['public'] || ! $t['show_ui'] ) + continue; + if ( empty($t['label']) ) + $t['label'] = $taxonomy; + if ( empty($t['args']) ) + $t['args'] = array(); + + $terms = get_object_term_cache($post->ID, $taxonomy); + if ( false === $terms ) + $terms = wp_get_object_terms($post->ID, $taxonomy, $t['args']); + + $values = array(); + + foreach ( $terms as $term ) + $values[] = $term->slug; + $t['value'] = join(', ', $values); + $t['taxonomy'] = true; + + $form_fields[$taxonomy] = $t; + } + } + + // Merge default fields with their errors, so any key passed with the error (e.g. 'error', 'helps', 'value') will replace the default + // The recursive merge is easily traversed with array casting: foreach( (array) $things as $thing ) + $form_fields = array_merge_recursive($form_fields, (array) $args['errors'] ); + + $form_fields = apply_filters( 'attachment_fields_to_edit', $form_fields, $post ); + + unset( $form_fields['image-size'], $form_fields['align'], $form_fields['image_alt'], + $form_fields['post_title'], $form_fields['post_excerpt'], $form_fields['post_content'], + $form_fields['url'], $form_fields['menu_order'], $form_fields['image_url'] ); + + $media_meta = apply_filters( 'media_meta', '', $post ); + + $defaults = array( + 'input' => 'text', + 'required' => false, + 'value' => '', + 'extra_rows' => array(), + 'show_in_edit' => true, + 'show_in_modal' => true, + ); + + $hidden_fields = array(); + + $item = ''; + foreach ( $form_fields as $id => $field ) { + if ( $id[0] == '_' ) + continue; + + $name = "attachments[$attachment_id][$id]"; + $id_attr = "attachments-$attachment_id-$id"; + + if ( !empty( $field['tr'] ) ) { + $item .= $field['tr']; + continue; + } + + $field = array_merge( $defaults, $field ); + + if ( ( ! $field['show_in_edit'] && ! $args['in_modal'] ) || ( ! $field['show_in_modal'] && $args['in_modal'] ) ) + continue; + + if ( $field['input'] == 'hidden' ) { + $hidden_fields[$name] = $field['value']; + continue; + } + + $readonly = ! $user_can_edit && ! empty( $field['taxonomy'] ) ? " readonly='readonly' " : ''; + $required = $field['required'] ? '*' : ''; + $aria_required = $field['required'] ? " aria-required='true' " : ''; + $class = 'compat-field-' . $id; + $class .= $field['required'] ? ' form-required' : ''; + + $item .= "\t\t"; + $item .= "\t\t\t"; + $item .= "\n\t\t\t"; + + if ( !empty( $field[ $field['input'] ] ) ) + $item .= $field[ $field['input'] ]; + elseif ( $field['input'] == 'textarea' ) { + if ( 'post_content' == $id && user_can_richedit() ) { + // sanitize_post() skips the post_content when user_can_richedit + $field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES ); + } + $item .= "'; + } else { + $item .= ""; + } + if ( !empty( $field['helps'] ) ) + $item .= "

    " . join( "

    \n

    ", array_unique( (array) $field['helps'] ) ) . '

    '; + $item .= "\n\t\t\n"; + + $extra_rows = array(); + + if ( !empty( $field['errors'] ) ) + foreach ( array_unique( (array) $field['errors'] ) as $error ) + $extra_rows['error'][] = $error; + + if ( !empty( $field['extra_rows'] ) ) + foreach ( $field['extra_rows'] as $class => $rows ) + foreach ( (array) $rows as $html ) + $extra_rows[$class][] = $html; + + foreach ( $extra_rows as $class => $rows ) + foreach ( $rows as $html ) + $item .= "\t\t$html\n"; + } + + if ( !empty( $form_fields['_final'] ) ) + $item .= "\t\t{$form_fields['_final']}\n"; + if ( $item ) + $item = '' . $item . '
    '; + + foreach ( $hidden_fields as $hidden_field => $value ) { + $item .= '' . "\n"; + } + + if ( $item ) + $item = '' . $item; + + return array( + 'item' => $item, + 'meta' => $media_meta, + ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + */ +function media_upload_header() { + $post_id = isset( $_REQUEST['post_id'] ) ? intval( $_REQUEST['post_id'] ) : 0; + echo '\n"; + if ( empty( $_GET['chromeless'] ) ) { + echo '
    '; + the_media_upload_tabs(); + echo '
    '; + } +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param unknown_type $errors + */ +function media_upload_form( $errors = null ) { + global $type, $tab, $is_IE, $is_opera; + + if ( ! _device_can_upload() ) { + echo '

    ' . sprintf( __('The web browser on your device cannot be used to upload files. You may be able to use the native app for your device instead.'), 'http://wordpress.org/mobile/' ) . '

    '; + return; + } + + $upload_action_url = admin_url('async-upload.php'); + $post_id = isset($_REQUEST['post_id']) ? intval($_REQUEST['post_id']) : 0; + $_type = isset($type) ? $type : ''; + $_tab = isset($tab) ? $tab : ''; + + $upload_size_unit = $max_upload_size = wp_max_upload_size(); + $sizes = array( 'KB', 'MB', 'GB' ); + + for ( $u = -1; $upload_size_unit > 1024 && $u < count( $sizes ) - 1; $u++ ) { + $upload_size_unit /= 1024; + } + + if ( $u < 0 ) { + $upload_size_unit = 0; + $u = 0; + } else { + $upload_size_unit = (int) $upload_size_unit; + } +?> + +
    +
    get_error_message(); + +?>
    + $post_id, + "_wpnonce" => wp_create_nonce('media-form'), + "type" => $_type, + "tab" => $_tab, + "short" => "1", +); + +$post_params = apply_filters( 'upload_post_params', $post_params ); // hook change! old name: 'swfupload_post_params' + +$plupload_init = array( + 'runtimes' => 'html5,silverlight,flash,html4', + 'browse_button' => 'plupload-browse-button', + 'container' => 'plupload-upload-ui', + 'drop_element' => 'drag-drop-area', + 'file_data_name' => 'async-upload', + 'multiple_queues' => true, + 'max_file_size' => $max_upload_size . 'b', + 'url' => $upload_action_url, + 'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'), + 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'), + 'filters' => array( array('title' => __( 'Allowed Files' ), 'extensions' => '*') ), + 'multipart' => true, + 'urlstream_upload' => true, + 'multipart_params' => $post_params +); + +// Multi-file uploading doesn't currently work in iOS Safari, +// single-file allows the built-in camera to be used as source for images +if ( wp_is_mobile() ) + $plupload_init['multi_selection'] = false; + +$plupload_init = apply_filters( 'plupload_init', $plupload_init ); + +?> + + + +
    + +
    +
    +

    +

    +

    +
    +
    + +
    + +
    + +

    + + + + +

    +
    + +
    + + + 100 * 1024 * 1024 ) { ?> + + + +
    + + + + +

    + + + + +
    '.esc_html($id->get_error_message()).'
    '; + exit; + } +} +?> + +

    + +

    + + + +
    + + + +

    + + + +
    +
    + +
    +
    +
    + + + +
    + + + + + + + | + | + +
    + + + +
    + + + + + + + + +
      + $reals ) + foreach ( $reals as $real ) + if ( isset($num_posts[$_type]) ) + $num_posts[$_type] += $_num_posts[$real]; + else + $num_posts[$_type] = $_num_posts[$real]; +// If available type specified by media button clicked, filter by that type +if ( empty($_GET['post_mime_type']) && !empty($num_posts[$type]) ) { + $_GET['post_mime_type'] = $type; + list($post_mime_types, $avail_post_mime_types) = wp_edit_attachments_query(); +} +if ( empty($_GET['post_mime_type']) || $_GET['post_mime_type'] == 'all' ) + $class = ' class="current"'; +else + $class = ''; +$type_links[] = "
    • 'all', 'paged'=>false, 'm'=>false))) . "'$class>".__('All Types').""; +foreach ( $post_mime_types as $mime_type => $label ) { + $class = ''; + + if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) ) + continue; + + if ( isset($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) ) + $class = ' class="current"'; + + $type_links[] = "
    • $mime_type, 'paged'=>false))) . "'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), "" . number_format_i18n( $num_posts[$mime_type] ) . '') . ''; +} +echo implode(' |
    • ', apply_filters( 'media_upload_mime_type_links', $type_links ) ) . ''; +unset($type_links); +?> +
    + +
    + + add_query_arg( 'paged', '%#%' ), + 'format' => '', + 'prev_text' => __('«'), + 'next_text' => __('»'), + 'total' => ceil($wp_query->found_posts / 10), + 'current' => $_GET['paged'] +)); + +if ( $page_links ) + echo "
    $page_links
    "; +?> + +
    +posts WHERE post_type = 'attachment' ORDER BY post_date DESC"; + +$arc_result = $wpdb->get_results( $arc_query ); + +$month_count = count($arc_result); +$selected_month = isset( $_GET['m'] ) ? $_GET['m'] : 0; + +if ( $month_count && !( 1 == $month_count && 0 == $arc_result[0]->mmonth ) ) { ?> + + + + + +
    + +
    +
    +
    + +
    + + + + + + +
    + + +
    +

    + + +

    +
    + + + + + + +'; + } else { + $caption = ''; + } + + $default_align = get_option('image_default_align'); + if ( empty($default_align) ) + $default_align = 'none'; + + if ( 'image' == $default_view ) { + $view = 'image-only'; + $table_class = ''; + } else { + $view = $table_class = 'not-image'; + } + + return ' +

       

    + + + + + + + + + + + + + + + + + + ' . $caption . ' + + + + + + + + + + + + + + + + + +
    + + * +
    + + * +

    ' . __('Link text, e.g. “Ransom Demands (PDF)”') . '

    + + +

    ' . __('Alt text for the image, e.g. “The Mona Lisa”') . '

    + + + + + + + + +
    + +
    + + + +

    ' . __('Enter a link URL or click above for presets.') . '

    + +
    + ' . get_submit_button( __( 'Insert into Post' ), 'button', 'insertonlybutton', false ) . ' +
    +'; + +} + +/** + * Displays the multi-file uploader message. + * + * @since 2.6.0 + */ +function media_upload_flash_bypass() { + $browser_uploader = admin_url( 'media-new.php?browser-uploader' ); + + if ( $post = get_post() ) + $browser_uploader .= '&post_id=' . intval( $post->ID ); + elseif ( ! empty( $GLOBALS['post_ID'] ) ) + $browser_uploader .= '&post_id=' . intval( $GLOBALS['post_ID'] ); + + ?> +

    + browser uploader instead.' ), $browser_uploader, '_blank' ); ?> +

    + +

    + Switch to the multi-file uploader.'); ?> +

    + '; + $end = ''; + } +?> +

    +' . sprintf( __( 'Sorry, you have used all of your storage quota of %s MB.' ), get_space_allowed() ) . '

    '; +} + +/** + * Displays the image and editor in the post editor + * + * @since 3.5.0 + */ +function edit_form_image_editor( $post ) { + $open = isset( $_GET['image-editor'] ); + if ( $open ) + require_once ABSPATH . 'wp-admin/includes/image-edit.php'; + + $thumb_url = false; + if ( $attachment_id = intval( $post->ID ) ) + $thumb_url = wp_get_attachment_image_src( $attachment_id, array( 900, 450 ), true ); + + $filename = esc_html( basename( $post->guid ) ); + $title = esc_attr( $post->post_title ); + $alt_text = get_post_meta( $post->ID, '_wp_attachment_image_alt', true ); + + $att_url = wp_get_attachment_url( $post->ID ); ?> +
    + ID ) ) : + $image_edit_button = ''; + if ( wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) { + $nonce = wp_create_nonce( "image_editor-$post->ID" ); + $image_edit_button = " "; + } + ?> + +
    + + class="wp_attachment_image" id="media-head-"> +

    +

    +
    + class="image-editor" id="image-editor-"> + + + post_mime_type, 'audio/' ) ): + + echo wp_audio_shortcode( array( 'src' => $att_url ) ); + + elseif ( $attachment_id && 0 === strpos( $post->post_mime_type, 'video/' ) ): + + $meta = wp_get_attachment_metadata( $attachment_id ); + $w = ! empty( $meta['width'] ) ? min( $meta['width'], 600 ) : 0; + $h = 0; + if ( ! empty( $meta['height'] ) ) + $h = $meta['height']; + if ( $h && $w < $meta['width'] ) + $h = round( ( $meta['height'] * $w ) / $meta['width'] ); + + $attr = array( 'src' => $att_url ); + + if ( ! empty( $meta['width' ] ) ) + $attr['width'] = $w; + + if ( ! empty( $meta['height'] ) ) + $attr['height'] = $h; + + echo wp_video_shortcode( $attr ); + + endif; ?> + +
    +

    +
    + +

    + + post_mime_type, 0, 5 ) ) : ?> +

    +
    + +

    + + + 'strong,em,link,block,del,ins,img,ul,ol,li,code,close' ); + $editor_args = array( + 'textarea_name' => 'content', + 'textarea_rows' => 5, + 'media_buttons' => false, + 'tinymce' => false, + 'quicktags' => $quicktags_settings, + ); + ?> + + + post_content, 'attachment_content', $editor_args ); ?> + +
    + ID ); + echo $extras['item']; + echo '' . "\n"; +} + +/** + * Displays non-editable attachment metadata in the publish metabox + * + * @since 3.5.0 + */ +function attachment_submitbox_metadata() { + $post = get_post(); + + $filename = esc_html( wp_basename( $post->guid ) ); + + $media_dims = ''; + $meta = wp_get_attachment_metadata( $post->ID ); + if ( isset( $meta['width'], $meta['height'] ) ) + $media_dims .= "{$meta['width']} × {$meta['height']} "; + $media_dims = apply_filters( 'media_meta', $media_dims, $post ); + + $att_url = wp_get_attachment_url( $post->ID ); +?> +
    + + +
    +
    + +
    +
    + ID ), $matches ) ) + echo esc_html( strtoupper( $matches[1] ) ); + else + echo strtoupper( str_replace( 'image/', '', $post->post_mime_type ) ); + ?> +
    + + ID ); + $file_size = false; + + if ( isset( $meta['filesize'] ) ) + $file_size = $meta['filesize']; + elseif ( file_exists( $file ) ) + $file_size = filesize( $file ); + + if ( ! empty( $file_size ) ) : ?> +
    + +
    + post_mime_type ) ): + + /** + * Audio and video metadata fields to be shown in the publish meta box. + * + * The key for each item in the array should correspond to an attachment + * metadata key, and the value should be the desired label. + * + * @since 3.7.0 + * + * @param array $fields { + * An array of the attachment metadata keys and labels. + * + * @type string 'mime_type' Label to be shown before the field mime_type. + * @type string 'year' Label to be shown before the field year. + * @type string 'genre' Label to be shown before the field genre. + * @type string 'length_formatted' Label to be shown before the field length_formatted. + * } + */ + $fields = apply_filters( 'media_submitbox_misc_sections', array( + 'mime_type' => __( 'Mime-type:' ), + 'year' => __( 'Year:' ), + 'genre' => __( 'Genre:' ), + 'length_formatted' => __( 'Length:' ), + ) ); + + foreach ( $fields as $key => $label ): + if ( ! empty( $meta[$key] ) ) : ?> +
    + +
    + +
    + +
    + __( 'Audio Format:' ), + 'codec' => __( 'Audio Codec:' ) + ) ); + + foreach ( $audio_fields as $key => $label ): + if ( ! empty( $meta['audio'][$key] ) ) : ?> +
    + +
    + +
    + +
    + $list ) { + if ( ! empty( $list ) ) { + $metadata[$key] = reset( $list ); + // fix bug in byte stream analysis + if ( 'terms_of_use' === $key && 0 === strpos( $metadata[$key], 'yright notice.' ) ) + $metadata[$key] = 'Cop' . $metadata[$key]; + } + } + break; + } + } + + if ( ! empty( $data['id3v2']['APIC'] ) ) { + $image = reset( $data['id3v2']['APIC']); + if ( ! empty( $image['data'] ) ) { + $metadata['image'] = array( + 'data' => $image['data'], + 'mime' => $image['image_mime'], + 'width' => $image['image_width'], + 'height' => $image['image_height'] + ); + } + } elseif ( ! empty( $data['comments']['picture'] ) ) { + $image = reset( $data['comments']['picture'] ); + if ( ! empty( $image['data'] ) ) { + $metadata['image'] = array( + 'data' => $image['data'], + 'mime' => $image['image_mime'] + ); + } + } +} + +/** + * Retrieve metadata from a video file's ID3 tags + * + * @since 3.6.0 + * + * @param string $file Path to file. + * @return array|boolean Returns array of metadata, if found. + */ +function wp_read_video_metadata( $file ) { + if ( ! file_exists( $file ) ) + return false; + + $metadata = array(); + + if ( ! class_exists( 'getID3' ) ) + require( ABSPATH . WPINC . '/ID3/getid3.php' ); + $id3 = new getID3(); + $data = $id3->analyze( $file ); + + if ( isset( $data['video']['lossless'] ) ) + $metadata['lossless'] = $data['video']['lossless']; + if ( ! empty( $data['video']['bitrate'] ) ) + $metadata['bitrate'] = (int) $data['video']['bitrate']; + if ( ! empty( $data['video']['bitrate_mode'] ) ) + $metadata['bitrate_mode'] = $data['video']['bitrate_mode']; + if ( ! empty( $data['filesize'] ) ) + $metadata['filesize'] = (int) $data['filesize']; + if ( ! empty( $data['mime_type'] ) ) + $metadata['mime_type'] = $data['mime_type']; + if ( ! empty( $data['playtime_seconds'] ) ) + $metadata['length'] = (int) ceil( $data['playtime_seconds'] ); + if ( ! empty( $data['playtime_string'] ) ) + $metadata['length_formatted'] = $data['playtime_string']; + if ( ! empty( $data['video']['resolution_x'] ) ) + $metadata['width'] = (int) $data['video']['resolution_x']; + if ( ! empty( $data['video']['resolution_y'] ) ) + $metadata['height'] = (int) $data['video']['resolution_y']; + if ( ! empty( $data['fileformat'] ) ) + $metadata['fileformat'] = $data['fileformat']; + if ( ! empty( $data['video']['dataformat'] ) ) + $metadata['dataformat'] = $data['video']['dataformat']; + if ( ! empty( $data['video']['encoder'] ) ) + $metadata['encoder'] = $data['video']['encoder']; + if ( ! empty( $data['video']['codec'] ) ) + $metadata['codec'] = $data['video']['codec']; + + if ( ! empty( $data['audio'] ) ) { + unset( $data['audio']['streams'] ); + $metadata['audio'] = $data['audio']; + } + + wp_add_id3_tag_data( $metadata, $data ); + + return $metadata; +} + +/** + * Retrieve metadata from a audio file's ID3 tags + * + * @since 3.6.0 + * + * @param string $file Path to file. + * @return array|boolean Returns array of metadata, if found. + */ +function wp_read_audio_metadata( $file ) { + if ( ! file_exists( $file ) ) + return false; + $metadata = array(); + + if ( ! class_exists( 'getID3' ) ) + require( ABSPATH . WPINC . '/ID3/getid3.php' ); + $id3 = new getID3(); + $data = $id3->analyze( $file ); + + if ( ! empty( $data['audio'] ) ) { + unset( $data['audio']['streams'] ); + $metadata = $data['audio']; + } + + if ( ! empty( $data['fileformat'] ) ) + $metadata['fileformat'] = $data['fileformat']; + if ( ! empty( $data['filesize'] ) ) + $metadata['filesize'] = (int) $data['filesize']; + if ( ! empty( $data['mime_type'] ) ) + $metadata['mime_type'] = $data['mime_type']; + if ( ! empty( $data['playtime_seconds'] ) ) + $metadata['length'] = (int) ceil( $data['playtime_seconds'] ); + if ( ! empty( $data['playtime_string'] ) ) + $metadata['length_formatted'] = $data['playtime_string']; + + wp_add_id3_tag_data( $metadata, $data ); + + return $metadata; +} diff --git a/sources/wp-admin/includes/menu.php b/sources/wp-admin/includes/menu.php new file mode 100644 index 0000000..e315c76 --- /dev/null +++ b/sources/wp-admin/includes/menu.php @@ -0,0 +1,229 @@ + $sub) { + foreach ($sub as $index => $data) { + if ( ! current_user_can($data[1]) ) { + unset(${$sub_loop}[$parent][$index]); + $_wp_submenu_nopriv[$parent][$data[2]] = true; + } + } + unset($index, $data); + + if ( empty(${$sub_loop}[$parent]) ) + unset(${$sub_loop}[$parent]); + } + unset($sub, $parent); +} +unset($sub_loop); + +// Loop over the top-level menu. +// Menus for which the original parent is not accessible due to lack of privs will have the next +// submenu in line be assigned as the new menu parent. +foreach ( $menu as $id => $data ) { + if ( empty($submenu[$data[2]]) ) + continue; + $subs = $submenu[$data[2]]; + $first_sub = array_shift($subs); + $old_parent = $data[2]; + $new_parent = $first_sub[2]; + // If the first submenu is not the same as the assigned parent, + // make the first submenu the new parent. + if ( $new_parent != $old_parent ) { + $_wp_real_parent_file[$old_parent] = $new_parent; + $menu[$id][2] = $new_parent; + + foreach ($submenu[$old_parent] as $index => $data) { + $submenu[$new_parent][$index] = $submenu[$old_parent][$index]; + unset($submenu[$old_parent][$index]); + } + unset($submenu[$old_parent], $index); + + if ( isset($_wp_submenu_nopriv[$old_parent]) ) + $_wp_submenu_nopriv[$new_parent] = $_wp_submenu_nopriv[$old_parent]; + } +} +unset($id, $data, $subs, $first_sub, $old_parent, $new_parent); + +if ( is_network_admin() ) + do_action('network_admin_menu', ''); +elseif ( is_user_admin() ) + do_action('user_admin_menu', ''); +else + do_action('admin_menu', ''); + +// Remove menus that have no accessible submenus and require privs that the user does not have. +// Run re-parent loop again. +foreach ( $menu as $id => $data ) { + if ( ! current_user_can($data[1]) ) + $_wp_menu_nopriv[$data[2]] = true; + + // If there is only one submenu and it is has same destination as the parent, + // remove the submenu. + if ( ! empty( $submenu[$data[2]] ) && 1 == count ( $submenu[$data[2]] ) ) { + $subs = $submenu[$data[2]]; + $first_sub = array_shift($subs); + if ( $data[2] == $first_sub[2] ) + unset( $submenu[$data[2]] ); + } + + // If submenu is empty... + if ( empty($submenu[$data[2]]) ) { + // And user doesn't have privs, remove menu. + if ( isset( $_wp_menu_nopriv[$data[2]] ) ) { + unset($menu[$id]); + } + } +} +unset($id, $data, $subs, $first_sub); + +// Remove any duplicated separators +$separator_found = false; +foreach ( $menu as $id => $data ) { + if ( 0 == strcmp('wp-menu-separator', $data[4] ) ) { + if (false == $separator_found) { + $separator_found = true; + } else { + unset($menu[$id]); + $separator_found = false; + } + } else { + $separator_found = false; + } +} +unset($id, $data); + +function add_cssclass($add, $class) { + $class = empty($class) ? $add : $class .= ' ' . $add; + return $class; +} + +function add_menu_classes($menu) { + + $first = $lastorder = false; + $i = 0; + $mc = count($menu); + foreach ( $menu as $order => $top ) { + $i++; + + if ( 0 == $order ) { // dashboard is always shown/single + $menu[0][4] = add_cssclass('menu-top-first', $top[4]); + $lastorder = 0; + continue; + } + + if ( 0 === strpos($top[2], 'separator') && false !== $lastorder ) { // if separator + $first = true; + $c = $menu[$lastorder][4]; + $menu[$lastorder][4] = add_cssclass('menu-top-last', $c); + continue; + } + + if ( $first ) { + $c = $menu[$order][4]; + $menu[$order][4] = add_cssclass('menu-top-first', $c); + $first = false; + } + + if ( $mc == $i ) { // last item + $c = $menu[$order][4]; + $menu[$order][4] = add_cssclass('menu-top-last', $c); + } + + $lastorder = $order; + } + + return apply_filters( 'add_menu_classes', $menu ); +} + +uksort($menu, "strnatcasecmp"); // make it all pretty + +if ( apply_filters('custom_menu_order', false) ) { + $menu_order = array(); + foreach ( $menu as $menu_item ) { + $menu_order[] = $menu_item[2]; + } + unset($menu_item); + $default_menu_order = $menu_order; + $menu_order = apply_filters('menu_order', $menu_order); + $menu_order = array_flip($menu_order); + $default_menu_order = array_flip($default_menu_order); + + function sort_menu($a, $b) { + global $menu_order, $default_menu_order; + $a = $a[2]; + $b = $b[2]; + if ( isset($menu_order[$a]) && !isset($menu_order[$b]) ) { + return -1; + } elseif ( !isset($menu_order[$a]) && isset($menu_order[$b]) ) { + return 1; + } elseif ( isset($menu_order[$a]) && isset($menu_order[$b]) ) { + if ( $menu_order[$a] == $menu_order[$b] ) + return 0; + return ($menu_order[$a] < $menu_order[$b]) ? -1 : 1; + } else { + return ($default_menu_order[$a] <= $default_menu_order[$b]) ? -1 : 1; + } + } + + usort($menu, 'sort_menu'); + unset($menu_order, $default_menu_order); +} + +// Remove the last menu item if it is a separator. +$last_menu_key = array_keys( $menu ); +$last_menu_key = array_pop( $last_menu_key ); +if ( !empty( $menu ) && 'wp-menu-separator' == $menu[ $last_menu_key ][ 4 ] ) + unset( $menu[ $last_menu_key ] ); +unset( $last_menu_key ); + +if ( !user_can_access_admin_page() ) { + do_action('admin_page_access_denied'); + wp_die( __('You do not have sufficient permissions to access this page.') ); +} + +$menu = add_menu_classes($menu); diff --git a/sources/wp-admin/includes/meta-boxes.php b/sources/wp-admin/includes/meta-boxes.php new file mode 100644 index 0000000..357fec8 --- /dev/null +++ b/sources/wp-admin/includes/meta-boxes.php @@ -0,0 +1,1000 @@ +post_type; + $post_type_object = get_post_type_object($post_type); + $can_publish = current_user_can($post_type_object->cap->publish_posts); +?> +
    + +
    + + +
    + +
    + +
    +
    +post_status && 'future' != $post->post_status && 'pending' != $post->post_status ) { ?> +post_status ) { ?>style="display:none" type="submit" name="save" id="save-post" value="" class="button" /> +post_status && $can_publish ) { ?> + + + +
    +public ) : ?> +
    +post_status ) { + $preview_link = esc_url( get_permalink( $post->ID ) ); + $preview_button = __( 'Preview Changes' ); +} else { + $preview_link = set_url_scheme( get_permalink( $post->ID ) ); + $preview_link = esc_url( apply_filters( 'preview_post_link', add_query_arg( 'preview', 'true', $preview_link ) ) ); + $preview_button = __( 'Preview' ); +} +?> + + +
    + +
    +
    + +
    + +
    + +post_status ) { + case 'private': + _e('Privately Published'); + break; + case 'publish': + _e('Published'); + break; + case 'future': + _e('Scheduled'); + break; + case 'pending': + _e('Pending Review'); + break; + case 'draft': + case 'auto-draft': + _e('Draft'); + break; +} +?> + +post_status || 'private' == $post->post_status || $can_publish ) { ?> +post_status ) { ?>style="display:none;" class="edit-post-status hide-if-no-js"> + +
    + + + + +
    + + +
    + +
    + post_status ) { + $post->post_password = ''; + $visibility = 'private'; + $visibility_trans = __('Private'); +} elseif ( !empty( $post->post_password ) ) { + $visibility = 'password'; + $visibility_trans = __('Password protected'); +} elseif ( $post_type == 'post' && is_sticky( $post->ID ) ) { + $visibility = 'public'; + $visibility_trans = __('Public, Sticky'); +} else { + $visibility = 'public'; + $visibility_trans = __('Public'); +} + +echo esc_html( $visibility_trans ); ?> + + + +
    + + +ID)); ?> /> + + + />
    + +ID ) ); ?> />
    + + />
    +
    + />
    + +

    + + +

    +
    + + +
    + +ID ) { + if ( 'future' == $post->post_status ) { // scheduled for publishing at a future date + $stamp = __('Scheduled for: %1$s'); + } else if ( 'publish' == $post->post_status || 'private' == $post->post_status ) { // already published + $stamp = __('Published on: %1$s'); + } else if ( '0000-00-00 00:00:00' == $post->post_date_gmt ) { // draft, 1 or more saves, no date specified + $stamp = __('Publish immediately'); + } else if ( time() < strtotime( $post->post_date_gmt . ' +0000' ) ) { // draft, 1 or more saves, future date specified + $stamp = __('Schedule for: %1$s'); + } else { // draft, 1 or more saves, date specified + $stamp = __('Publish on: %1$s'); + } + $date = date_i18n( $datef, strtotime( $post->post_date ) ); +} else { // draft (no saves, and thus no date specified) + $stamp = __('Publish immediately'); + $date = date_i18n( $datef, strtotime( current_time('mysql') ) ); +} + +if ( ! empty( $args['args']['revisions_count'] ) ) : + $revisions_to_keep = wp_revisions_to_keep( $post ); +?> +
    + 0 && $revisions_to_keep <= $args['args']['revisions_count'] ) { + echo ''; + printf( __( 'Revisions: %s' ), '' . number_format_i18n( $args['args']['revisions_count'] ) . '+' ); + echo ''; + } else { + printf( __( 'Revisions: %s' ), '' . number_format_i18n( $args['args']['revisions_count'] ) . '' ); + } +?> + +
    + +
    + + + +
    +
    + + + +
    +
    +
    + +
    + +
    +ID ) ) { + if ( !EMPTY_TRASH_DAYS ) + $delete_text = __('Delete Permanently'); + else + $delete_text = __('Move to Trash'); + ?> + +
    + +
    + +post_status, array('publish', 'future', 'private') ) || 0 == $post->ID ) { + if ( $can_publish ) : + if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) : ?> + + 'p' ) ); ?> + + + 'p' ) ); ?> + + + 'p' ) ); ?> + + + + +
    +
    +
    +
    + +post_type; + $post_type_object = get_post_type_object($post_type); + $can_publish = current_user_can($post_type_object->cap->publish_posts); +?> +
    + +
    + + +
    + +
    + + +
    + %1$s'); + $date = date_i18n( $datef, strtotime( $post->post_date ) ); + ?> +
    + +
    + + +
    +
    +
    + +
    +
    + ID ) ) + if ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { + echo "" . __( 'Trash' ) . ""; + } else { + $delete_ays = ! MEDIA_TRASH ? " onclick='return showNotice.warn();'" : ''; + echo "" . __( 'Delete Permanently' ) . ""; + } + ?> +
    + +
    + + + +
    +
    +
    + +
    + +post_type, 'post-formats' ) ) : + $post_formats = get_theme_support( 'post-formats' ); + + if ( is_array( $post_formats[0] ) ) : + $post_format = get_post_format( $post->ID ); + if ( !$post_format ) + $post_format = '0'; + // Add in the current one if it isn't there yet, in case the current theme doesn't support it + if ( $post_format && !in_array( $post_format, $post_formats[0] ) ) + $post_formats[0][] = $post_format; + ?> +
    + /> + +
    /> +
    +
    + 'post_tag'); + if ( !isset($box['args']) || !is_array($box['args']) ) + $args = array(); + else + $args = $box['args']; + extract( wp_parse_args($args, $defaults), EXTR_SKIP ); + $tax_name = esc_attr($taxonomy); + $taxonomy = get_taxonomy($taxonomy); + $user_can_assign_terms = current_user_can( $taxonomy->cap->assign_terms ); + $comma = _x( ',', 'tag delimiter' ); +?> +
    +
    +
    +

    labels->add_or_remove_items; ?>

    +
    + +
    + +
    labels->add_new_item; ?>
    +

    +

    +
    +

    labels->separate_items_with_commas; ?>

    + +
    +
    +
    + +

    labels->choose_from_most_used; ?>

    + + 'category'); + if ( !isset($box['args']) || !is_array($box['args']) ) + $args = array(); + else + $args = $box['args']; + extract( wp_parse_args($args, $defaults), EXTR_SKIP ); + $tax = get_taxonomy($taxonomy); + + ?> +
    + + + + +
    + "; // Allows for an empty term set to be sent. 0 is an invalid Term ID and will be ignored by empty() checks. + ?> +
      + ID, array( 'taxonomy' => $taxonomy, 'popular_cats' => $popular_ids ) ) ?> +
    +
    + cap->edit_terms) ) : ?> +
    +

    + + labels->add_new_item ); + ?> + +

    +

    + + + + $taxonomy, 'hide_empty' => 0, 'name' => 'new'.$taxonomy.'_parent', 'orderby' => 'name', 'hierarchical' => 1, 'show_option_none' => '— ' . $tax->labels->parent_item . ' —' ) ); ?> + + + +

    +
    + +
    + + +

    Learn more about manual excerpts.'); ?>

    +to_ping) ) .'" />'; + if ('' != $post->pinged) { + $pings = '

    '. __('Already pinged:') . '

      '; + $already_pinged = explode("\n", trim($post->pinged)); + foreach ($already_pinged as $pinged_url) { + $pings .= "\n\t
    • " . esc_html($pinged_url) . "
    • "; + } + $pings .= '
    '; + } + +?> +


    ()

    +

    pingbacks, no other action necessary.'); ?>

    + +
    +
    +ID); +foreach ( $metadata as $key => $value ) { + if ( is_protected_meta( $metadata[ $key ][ 'meta_key' ], 'post' ) || ! current_user_can( 'edit_post_meta', $post->ID, $metadata[ $key ][ 'meta_key' ] ) ) + unset( $metadata[ $key ] ); +} +list_meta( $metadata ); +meta_form( $post ); ?> +
    +

    use in your theme.'); ?>

    + + +

    +
    + + +

    + +

    + $post->ID, 'number' => 1, 'count' => true ) ); + $wp_list_table = _get_list_table('WP_Post_Comments_List_Table'); + $wp_list_table->display( true ); + + if ( 1 > $total ) { + echo '

    ' . __('No comments yet.') . '

    '; + } else { + $hidden = get_hidden_meta_boxes( get_current_screen() ); + if ( ! in_array('commentsdiv', $hidden) ) { + ?> + + +

    + + + + + 'authors', + 'name' => 'post_author_override', + 'selected' => empty($post->ID) ? $user_ID : $post->post_author, + 'include_selected' => true + ) ); +} + +/** + * Display list of revisions. + * + * @since 2.6.0 + * + * @param object $post + */ +function post_revisions_meta_box( $post ) { + wp_list_post_revisions( $post ); +} + +// -- Page related Meta Boxes + +/** + * Display page attributes form fields. + * + * @since 2.7.0 + * + * @param object $post + */ +function page_attributes_meta_box($post) { + $post_type_object = get_post_type_object($post->post_type); + if ( $post_type_object->hierarchical ) { + $dropdown_args = array( + 'post_type' => $post->post_type, + 'exclude_tree' => $post->ID, + 'selected' => $post->post_parent, + 'name' => 'parent_id', + 'show_option_none' => __('(no parent)'), + 'sort_column' => 'menu_order, post_title', + 'echo' => 0, + ); + + $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); + $pages = wp_dropdown_pages( $dropdown_args ); + if ( ! empty($pages) ) { +?> +

    + + +post_type && 0 != count( get_page_templates() ) ) { + $template = !empty($post->page_template) ? $post->page_template : false; + ?> +

    + + +

    +

    +

    post_type ) _e( 'Need help? Use the Help tab in the upper right of your screen.' ); ?>

    + + + +
    +
      +
    • +
    • +
    + +
    +
      + link_id) ) + wp_link_category_checklist($link->link_id); + else + wp_link_category_checklist(); + ?> +
    +
    + + + +
    +

    + +
    +
    + +
    +

    +

    +

    +
    +

    +link_rel ) ? $link->link_rel : ''; // In PHP 5.3: $link_rel = $link->link_rel ?: ''; + $rels = preg_split('/\s+/', $link_rel); + + if ('' != $value && in_array($value, $rels) ) { + echo ' checked="checked"'; + } + + if ('' == $value) { + if ('family' == $class && strpos($link_rel, 'child') === false && strpos($link_rel, 'parent') === false && strpos($link_rel, 'sibling') === false && strpos($link_rel, 'spouse') === false && strpos($link_rel, 'kin') === false) echo ' checked="checked"'; + if ('friendship' == $class && strpos($link_rel, 'friend') === false && strpos($link_rel, 'acquaintance') === false && strpos($link_rel, 'contact') === false) echo ' checked="checked"'; + if ('geographical' == $class && strpos($link_rel, 'co-resident') === false && strpos($link_rel, 'neighbor') === false) echo ' checked="checked"'; + if ('identity' == $class && in_array('me', $rels) ) echo ' checked="checked"'; + } +} + +/** + * Display xfn form fields. + * + * @since 2.6.0 + * + * @param object $link + */ +function link_xfn_meta_box($link) { +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    XFN.'); ?>

    + + + + + + + + + + + + + + + + + + + +ID, '_thumbnail_id', true ); + echo _wp_post_thumbnail_html( $thumbnail_id, $post->ID ); +} diff --git a/sources/wp-admin/includes/misc.php b/sources/wp-admin/includes/misc.php new file mode 100644 index 0000000..5a3b970 --- /dev/null +++ b/sources/wp-admin/includes/misc.php @@ -0,0 +1,700 @@ + $markerline ) { + if (strpos($markerline, '# BEGIN ' . $marker) !== false) + $state = false; + if ( $state ) { + if ( $n + 1 < count( $markerdata ) ) + fwrite( $f, "{$markerline}\n" ); + else + fwrite( $f, "{$markerline}" ); + } + if (strpos($markerline, '# END ' . $marker) !== false) { + fwrite( $f, "# BEGIN {$marker}\n" ); + if ( is_array( $insertion )) + foreach ( $insertion as $insertline ) + fwrite( $f, "{$insertline}\n" ); + fwrite( $f, "# END {$marker}\n" ); + $state = true; + $foundit = true; + } + } + } + if (!$foundit) { + fwrite( $f, "\n# BEGIN {$marker}\n" ); + foreach ( $insertion as $insertline ) + fwrite( $f, "{$insertline}\n" ); + fwrite( $f, "# END {$marker}\n" ); + } + fclose( $f ); + return true; + } else { + return false; + } +} + +/** + * Updates the htaccess file with the current rules if it is writable. + * + * Always writes to the file if it exists and is writable to ensure that we + * blank out old rules. + * + * @since 1.5.0 + */ +function save_mod_rewrite_rules() { + if ( is_multisite() ) + return; + + global $wp_rewrite; + + $home_path = get_home_path(); + $htaccess_file = $home_path.'.htaccess'; + + // If the file doesn't already exist check for write access to the directory and whether we have some rules. + // else check for write access to the file. + if ((!file_exists($htaccess_file) && is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks()) || is_writable($htaccess_file)) { + if ( got_mod_rewrite() ) { + $rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() ); + return insert_with_markers( $htaccess_file, 'WordPress', $rules ); + } + } + + return false; +} + +/** + * Updates the IIS web.config file with the current rules if it is writable. + * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file. + * + * @since 2.8.0 + * + * @return bool True if web.config was updated successfully + */ +function iis7_save_url_rewrite_rules(){ + if ( is_multisite() ) + return; + + global $wp_rewrite; + + $home_path = get_home_path(); + $web_config_file = $home_path . 'web.config'; + + // Using win_is_writable() instead of is_writable() because of a bug in Windows PHP + if ( iis7_supports_permalinks() && ( ( ! file_exists($web_config_file) && win_is_writable($home_path) && $wp_rewrite->using_mod_rewrite_permalinks() ) || win_is_writable($web_config_file) ) ) { + $rule = $wp_rewrite->iis7_url_rewrite_rules(false, '', ''); + if ( ! empty($rule) ) { + return iis7_add_rewrite_rule($web_config_file, $rule); + } else { + return iis7_delete_rewrite_rule($web_config_file); + } + } + return false; +} + +/** + * {@internal Missing Short Description}} + * + * @since 1.5.0 + * + * @param unknown_type $file + */ +function update_recently_edited( $file ) { + $oldfiles = (array ) get_option( 'recently_edited' ); + if ( $oldfiles ) { + $oldfiles = array_reverse( $oldfiles ); + $oldfiles[] = $file; + $oldfiles = array_reverse( $oldfiles ); + $oldfiles = array_unique( $oldfiles ); + if ( 5 < count( $oldfiles )) + array_pop( $oldfiles ); + } else { + $oldfiles[] = $file; + } + update_option( 'recently_edited', $oldfiles ); +} + +/** + * If siteurl, home or page_on_front changed, flush rewrite rules. + * + * @since 2.1.0 + * + * @param string $old_value + * @param string $value + */ +function update_home_siteurl( $old_value, $value ) { + if ( defined( "WP_INSTALLING" ) ) + return; + + // If home changed, write rewrite rules to new location. + flush_rewrite_rules(); +} + +add_action( 'update_option_home', 'update_home_siteurl', 10, 2 ); +add_action( 'update_option_siteurl', 'update_home_siteurl', 10, 2 ); +add_action( 'update_option_page_on_front', 'update_home_siteurl', 10, 2 ); + +/** + * Shorten an URL, to be used as link text + * + * @since 1.2.1 + * + * @param string $url + * @return string + */ +function url_shorten( $url ) { + $short_url = str_replace( array( 'http://', 'www.' ), '', $url ); + $short_url = untrailingslashit( $short_url ); + if ( strlen( $short_url ) > 35 ) + $short_url = substr( $short_url, 0, 32 ) . '…'; + return $short_url; +} + +/** + * Resets global variables based on $_GET and $_POST + * + * This function resets global variables based on the names passed + * in the $vars array to the value of $_POST[$var] or $_GET[$var] or '' + * if neither is defined. + * + * @since 2.0.0 + * + * @param array $vars An array of globals to reset. + */ +function wp_reset_vars( $vars ) { + for ( $i=0; $iget_error_data() && is_string( $message->get_error_data() ) ) + $message = $message->get_error_message() . ': ' . $message->get_error_data(); + else + $message = $message->get_error_message(); + } + echo "

    $message

    \n"; + wp_ob_end_flush_all(); + flush(); +} + +function wp_doc_link_parse( $content ) { + if ( !is_string( $content ) || empty( $content ) ) + return array(); + + if ( !function_exists('token_get_all') ) + return array(); + + $tokens = token_get_all( $content ); + $functions = array(); + $ignore_functions = array(); + for ( $t = 0, $count = count( $tokens ); $t < $count; $t++ ) { + if ( !is_array( $tokens[$t] ) ) continue; + if ( T_STRING == $tokens[$t][0] && ( '(' == $tokens[ $t + 1 ] || '(' == $tokens[ $t + 2 ] ) ) { + // If it's a function or class defined locally, there's not going to be any docs available + if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ) ) ) || ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR == $tokens[ $t - 1 ][0] ) ) { + $ignore_functions[] = $tokens[$t][1]; + } + // Add this to our stack of unique references + $functions[] = $tokens[$t][1]; + } + } + + $functions = array_unique( $functions ); + sort( $functions ); + $ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions ); + $ignore_functions = array_unique( $ignore_functions ); + + $out = array(); + foreach ( $functions as $function ) { + if ( in_array( $function, $ignore_functions ) ) + continue; + $out[] = $function; + } + + return $out; +} + +/** + * Saves option for number of rows when listing posts, pages, comments, etc. + * + * @since 2.8 +**/ +function set_screen_options() { + + if ( isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options']) ) { + check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' ); + + if ( !$user = wp_get_current_user() ) + return; + $option = $_POST['wp_screen_options']['option']; + $value = $_POST['wp_screen_options']['value']; + + if ( $option != sanitize_key( $option ) ) + return; + + $map_option = $option; + $type = str_replace('edit_', '', $map_option); + $type = str_replace('_per_page', '', $type); + if ( in_array( $type, get_taxonomies() ) ) + $map_option = 'edit_tags_per_page'; + elseif ( in_array( $type, get_post_types() ) ) + $map_option = 'edit_per_page'; + else + $option = str_replace('-', '_', $option); + + switch ( $map_option ) { + case 'edit_per_page': + case 'users_per_page': + case 'edit_comments_per_page': + case 'upload_per_page': + case 'edit_tags_per_page': + case 'plugins_per_page': + // Network admin + case 'sites_network_per_page': + case 'users_network_per_page': + case 'site_users_network_per_page': + case 'plugins_network_per_page': + case 'themes_network_per_page': + case 'site_themes_network_per_page': + $value = (int) $value; + if ( $value < 1 || $value > 999 ) + return; + break; + default: + $value = apply_filters('set-screen-option', false, $option, $value); + if ( false === $value ) + return; + break; + } + + update_user_meta($user->ID, $option, $value); + wp_safe_redirect( remove_query_arg( array('pagenum', 'apage', 'paged'), wp_get_referer() ) ); + exit; + } +} + +/** + * Check if rewrite rule for WordPress already exists in the IIS 7+ configuration file + * + * @since 2.8.0 + * + * @return bool + * @param string $filename The file path to the configuration file + */ +function iis7_rewrite_rule_exists($filename) { + if ( ! file_exists($filename) ) + return false; + if ( ! class_exists('DOMDocument') ) + return false; + + $doc = new DOMDocument(); + if ( $doc->load($filename) === false ) + return false; + $xpath = new DOMXPath($doc); + $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')]'); + if ( $rules->length == 0 ) + return false; + else + return true; +} + +/** + * Delete WordPress rewrite rule from web.config file if it exists there + * + * @since 2.8.0 + * + * @param string $filename Name of the configuration file + * @return bool + */ +function iis7_delete_rewrite_rule($filename) { + // If configuration file does not exist then rules also do not exist so there is nothing to delete + if ( ! file_exists($filename) ) + return true; + + if ( ! class_exists('DOMDocument') ) + return false; + + $doc = new DOMDocument(); + $doc->preserveWhiteSpace = false; + + if ( $doc -> load($filename) === false ) + return false; + $xpath = new DOMXPath($doc); + $rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')]'); + if ( $rules->length > 0 ) { + $child = $rules->item(0); + $parent = $child->parentNode; + $parent->removeChild($child); + $doc->formatOutput = true; + saveDomDocument($doc, $filename); + } + return true; +} + +/** + * Add WordPress rewrite rule to the IIS 7+ configuration file. + * + * @since 2.8.0 + * + * @param string $filename The file path to the configuration file + * @param string $rewrite_rule The XML fragment with URL Rewrite rule + * @return bool + */ +function iis7_add_rewrite_rule($filename, $rewrite_rule) { + if ( ! class_exists('DOMDocument') ) + return false; + + // If configuration file does not exist then we create one. + if ( ! file_exists($filename) ) { + $fp = fopen( $filename, 'w'); + fwrite($fp, ''); + fclose($fp); + } + + $doc = new DOMDocument(); + $doc->preserveWhiteSpace = false; + + if ( $doc->load($filename) === false ) + return false; + + $xpath = new DOMXPath($doc); + + // First check if the rule already exists as in that case there is no need to re-add it + $wordpress_rules = $xpath->query('/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')]'); + if ( $wordpress_rules->length > 0 ) + return true; + + // Check the XPath to the rewrite rule and create XML nodes if they do not exist + $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite/rules'); + if ( $xmlnodes->length > 0 ) { + $rules_node = $xmlnodes->item(0); + } else { + $rules_node = $doc->createElement('rules'); + + $xmlnodes = $xpath->query('/configuration/system.webServer/rewrite'); + if ( $xmlnodes->length > 0 ) { + $rewrite_node = $xmlnodes->item(0); + $rewrite_node->appendChild($rules_node); + } else { + $rewrite_node = $doc->createElement('rewrite'); + $rewrite_node->appendChild($rules_node); + + $xmlnodes = $xpath->query('/configuration/system.webServer'); + if ( $xmlnodes->length > 0 ) { + $system_webServer_node = $xmlnodes->item(0); + $system_webServer_node->appendChild($rewrite_node); + } else { + $system_webServer_node = $doc->createElement('system.webServer'); + $system_webServer_node->appendChild($rewrite_node); + + $xmlnodes = $xpath->query('/configuration'); + if ( $xmlnodes->length > 0 ) { + $config_node = $xmlnodes->item(0); + $config_node->appendChild($system_webServer_node); + } else { + $config_node = $doc->createElement('configuration'); + $doc->appendChild($config_node); + $config_node->appendChild($system_webServer_node); + } + } + } + } + + $rule_fragment = $doc->createDocumentFragment(); + $rule_fragment->appendXML($rewrite_rule); + $rules_node->appendChild($rule_fragment); + + $doc->encoding = "UTF-8"; + $doc->formatOutput = true; + saveDomDocument($doc, $filename); + + return true; +} + +/** + * Saves the XML document into a file + * + * @since 2.8.0 + * + * @param DOMDocument $doc + * @param string $filename + */ +function saveDomDocument($doc, $filename) { + $config = $doc->saveXML(); + $config = preg_replace("/([^\r])\n/", "$1\r\n", $config); + $fp = fopen($filename, 'w'); + fwrite($fp, $config); + fclose($fp); +} + +/** + * Display the default admin color scheme picker (Used in user-edit.php) + * + * @since 3.0.0 + */ +function admin_color_scheme_picker() { + global $_wp_admin_css_colors, $user_id; ?> +
    + $color_info ): ?> +
    /> + + + colors as $html_color ): ?> + + + +
     
    + + +
    + +
    + + + sprintf( __( '%s is currently editing' ), $user->display_name ) ); + + if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) + $send['avatar_src'] = $matches[1]; + + $checked[$key] = $send; + } + } + } + + if ( ! empty( $checked ) ) + $response['wp-check-locked-posts'] = $checked; + + return $response; +} +add_filter( 'heartbeat_received', 'wp_check_locked_posts', 10, 3 ); + +/** + * Check lock status on the New/Edit Post screen and refresh the lock + * + * @since 3.6 + */ +function wp_refresh_post_lock( $response, $data, $screen_id ) { + if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) { + $received = $data['wp-refresh-post-lock']; + $send = array(); + + if ( ! $post_id = absint( $received['post_id'] ) ) + return $response; + + if ( ! current_user_can('edit_post', $post_id) ) + return $response; + + if ( ( $user_id = wp_check_post_lock( $post_id ) ) && ( $user = get_userdata( $user_id ) ) ) { + $error = array( + 'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ) + ); + + if ( $avatar = get_avatar( $user->ID, 64 ) ) { + if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) + $error['avatar_src'] = $matches[1]; + } + + $send['lock_error'] = $error; + } else { + if ( $new_lock = wp_set_post_lock( $post_id ) ) + $send['new_lock'] = implode( ':', $new_lock ); + } + + $response['wp-refresh-post-lock'] = $send; + } + + return $response; +} +add_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 ); + +/** + * Check nonce expiration on the New/Edit Post screen and refresh if needed + * + * @since 3.6 + */ +function wp_refresh_post_nonces( $response, $data, $screen_id ) { + if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) { + $received = $data['wp-refresh-post-nonces']; + $response['wp-refresh-post-nonces'] = array( 'check' => 1 ); + + if ( ! $post_id = absint( $received['post_id'] ) ) + return $response; + + if ( ! current_user_can( 'edit_post', $post_id ) || empty( $received['post_nonce'] ) ) + return $response; + + if ( 2 === wp_verify_nonce( $received['post_nonce'], 'update-post_' . $post_id ) ) { + $response['wp-refresh-post-nonces'] = array( + 'replace' => array( + 'autosavenonce' => wp_create_nonce('autosave'), + 'getpermalinknonce' => wp_create_nonce('getpermalink'), + 'samplepermalinknonce' => wp_create_nonce('samplepermalink'), + 'closedpostboxesnonce' => wp_create_nonce('closedpostboxes'), + '_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ), + '_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ), + ), + 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ), + ); + } + } + + return $response; +} +add_filter( 'heartbeat_received', 'wp_refresh_post_nonces', 10, 3 ); diff --git a/sources/wp-admin/includes/ms-deprecated.php b/sources/wp-admin/includes/ms-deprecated.php new file mode 100644 index 0000000..702e3e1 --- /dev/null +++ b/sources/wp-admin/includes/ms-deprecated.php @@ -0,0 +1,78 @@ + ( 1024 * get_site_option( 'fileupload_maxk', 1500 ) ) ) + $file['error'] = sprintf(__('This file is too big. Files must be less than %1$s KB in size.'), get_site_option( 'fileupload_maxk', 1500 ) ); + if ( upload_is_user_over_quota( false ) ) { + $file['error'] = __( 'You have used your space quota. Please delete files before uploading.' ); + } + if ( $file['error'] != '0' && !isset($_POST['html-upload']) ) + wp_die( $file['error'] . ' ' . __( 'Back' ) . '' ); + + return $file; +} +add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' ); + +/** + * Delete a blog + * + * @since 3.0.0 + * + * @param int $blog_id Blog ID + * @param bool $drop True if blog's table should be dropped. Default is false. + * @return void + */ +function wpmu_delete_blog( $blog_id, $drop = false ) { + global $wpdb, $current_site; + + $switch = false; + if ( get_current_blog_id() != $blog_id ) { + $switch = true; + switch_to_blog( $blog_id ); + } + + $blog = get_blog_details( $blog_id ); + /** + * Fires before a blog is deleted. + * + * @since MU + * + * @param int $blog_id The blog ID. + * @param bool $drop True if blog's table should be dropped. Default is false. + */ + do_action( 'delete_blog', $blog_id, $drop ); + + $users = get_users( array( 'blog_id' => $blog_id, 'fields' => 'ids' ) ); + + // Remove users from this blog. + if ( ! empty( $users ) ) { + foreach ( $users as $user_id ) { + remove_user_from_blog( $user_id, $blog_id ); + } + } + + update_blog_status( $blog_id, 'deleted', 1 ); + + // Don't destroy the initial, main, or root blog. + if ( $drop && ( 1 == $blog_id || is_main_site( $blog_id ) || ( $blog->path == $current_site->path && $blog->domain == $current_site->domain ) ) ) + $drop = false; + + if ( $drop ) { + $tables = $wpdb->tables( 'blog' ); + /** + * Filter the tables to drop when the blog is deleted. + * + * @since MU + * + * @param array $tables The blog tables to be dropped. + * @param int $blog_id The ID of the blog to drop tables for. + */ + $drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $blog_id ); + + foreach ( (array) $drop_tables as $table ) { + $wpdb->query( "DROP TABLE IF EXISTS `$table`" ); + } + + $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $blog_id ) ); + + $uploads = wp_upload_dir(); + /** + * Filter the upload base directory to delete when the blog is deleted. + * + * @since MU + * + * @param string $uploads['basedir'] Uploads path without subdirectory. @see wp_upload_dir() + * @param int $blog_id The blog ID. + */ + $dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $blog_id ); + $dir = rtrim( $dir, DIRECTORY_SEPARATOR ); + $top_dir = $dir; + $stack = array($dir); + $index = 0; + + while ( $index < count( $stack ) ) { + # Get indexed directory from stack + $dir = $stack[$index]; + + $dh = @opendir( $dir ); + if ( $dh ) { + while ( ( $file = @readdir( $dh ) ) !== false ) { + if ( $file == '.' || $file == '..' ) + continue; + + if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) ) + $stack[] = $dir . DIRECTORY_SEPARATOR . $file; + else if ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) ) + @unlink( $dir . DIRECTORY_SEPARATOR . $file ); + } + @closedir( $dh ); + } + $index++; + } + + $stack = array_reverse( $stack ); // Last added dirs are deepest + foreach( (array) $stack as $dir ) { + if ( $dir != $top_dir) + @rmdir( $dir ); + } + + clean_blog_cache( $blog ); + } + + if ( $switch ) + restore_current_blog(); +} + +// @todo Merge with wp_delete_user() ? +function wpmu_delete_user( $id ) { + global $wpdb; + + $id = (int) $id; + $user = new WP_User( $id ); + + if ( !$user->exists() ) + return false; + /** + * Fires before a user is deleted from the network. + * + * @since MU + * + * @param int $id ID of the user about to be deleted from the network. + */ + do_action( 'wpmu_delete_user', $id ); + + $blogs = get_blogs_of_user( $id ); + + if ( ! empty( $blogs ) ) { + foreach ( $blogs as $blog ) { + switch_to_blog( $blog->userblog_id ); + remove_user_from_blog( $id, $blog->userblog_id ); + + $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) ); + foreach ( (array) $post_ids as $post_id ) { + wp_delete_post( $post_id ); + } + + // Clean links + $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) ); + + if ( $link_ids ) { + foreach ( $link_ids as $link_id ) + wp_delete_link( $link_id ); + } + + restore_current_blog(); + } + } + + $meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) ); + foreach ( $meta as $mid ) + delete_metadata_by_mid( 'user', $mid ); + + $wpdb->delete( $wpdb->users, array( 'ID' => $id ) ); + + clean_user_cache( $user ); + + /** + * Fires after the user is deleted from the network. + * + * @since 2.8.0 + * + * @param int $id ID of the user that was deleted from the network. + */ + do_action( 'deleted_user', $id ); + + return true; +} + +function update_option_new_admin_email( $old_value, $value ) { + $email = get_option( 'admin_email' ); + if ( $value == get_option( 'admin_email' ) || !is_email( $value ) ) + return; + + $hash = md5( $value. time() .mt_rand() ); + $new_admin_email = array( + 'hash' => $hash, + 'newemail' => $value + ); + update_option( 'adminhash', $new_admin_email ); + + $email_text = __( 'Dear user, + +You recently requested to have the administration email address on +your site changed. +If this is correct, please click on the following link to change it: +###ADMIN_URL### + +You can safely ignore and delete this email if you do not want to +take this action. + +This email has been sent to ###EMAIL### + +Regards, +All at ###SITENAME### +###SITEURL###' ); + + /** + * Filter the email text sent when the site admin email is changed. + * + * The following strings have a special meaning and will get replaced dynamically: + * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break. + * ###EMAIL### The new email. + * ###SITENAME### The name of the site. + * ###SITEURL### The URL to the site. + * + * @since MU + * + * @param string $email_text Text in the email. + * @param string $new_admin_email New admin email that the current administration email was changed to. + */ + $content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email ); + + $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'options.php?adminhash='.$hash ) ), $content ); + $content = str_replace( '###EMAIL###', $value, $content ); + $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content ); + $content = str_replace( '###SITEURL###', network_home_url(), $content ); + + wp_mail( $value, sprintf( __( '[%s] New Admin Email Address' ), get_option( 'blogname' ) ), $content ); +} +add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 ); +add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 ); + +function send_confirmation_on_profile_email() { + global $errors, $wpdb; + $current_user = wp_get_current_user(); + if ( ! is_object($errors) ) + $errors = new WP_Error(); + + if ( $current_user->ID != $_POST['user_id'] ) + return false; + + if ( $current_user->user_email != $_POST['email'] ) { + if ( !is_email( $_POST['email'] ) ) { + $errors->add( 'user_email', __( "ERROR: The email address isn’t correct." ), array( 'form-field' => 'email' ) ); + return; + } + + if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) { + $errors->add( 'user_email', __( "ERROR: The email address is already used." ), array( 'form-field' => 'email' ) ); + delete_option( $current_user->ID . '_new_email' ); + return; + } + + $hash = md5( $_POST['email'] . time() . mt_rand() ); + $new_user_email = array( + 'hash' => $hash, + 'newemail' => $_POST['email'] + ); + update_option( $current_user->ID . '_new_email', $new_user_email ); + + $email_text = __( 'Dear user, + +You recently requested to have the email address on your account changed. +If this is correct, please click on the following link to change it: +###ADMIN_URL### + +You can safely ignore and delete this email if you do not want to +take this action. + +This email has been sent to ###EMAIL### + +Regards, +All at ###SITENAME### +###SITEURL###' ); + + /** + * Filter the email text sent when a user changes emails. + * + * The following strings have a special meaning and will get replaced dynamically: + * ###ADMIN_URL### The link to click on to confirm the email change. Required otherwise this functunalty is will break. + * ###EMAIL### The new email. + * ###SITENAME### The name of the site. + * ###SITEURL### The URL to the site. + * + * @since MU + * + * @param string $email_text Text in the email. + * @param string $new_user_email New user email that the current user has changed to. + */ + $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email ); + + $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content ); + $content = str_replace( '###EMAIL###', $_POST['email'], $content); + $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content ); + $content = str_replace( '###SITEURL###', network_home_url(), $content ); + + wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content ); + $_POST['email'] = $current_user->user_email; + } +} +add_action( 'personal_options_update', 'send_confirmation_on_profile_email' ); + +function new_user_email_admin_notice() { + if ( strpos( $_SERVER['PHP_SELF'], 'profile.php' ) && isset( $_GET['updated'] ) && $email = get_option( get_current_user_id() . '_new_email' ) ) + echo "
    " . sprintf( __( "Your email address has not been updated yet. Please check your inbox at %s for a confirmation email." ), $email['newemail'] ) . "
    "; +} +add_action( 'admin_notices', 'new_user_email_admin_notice' ); + +/** + * Check whether a blog has used its allotted upload space. + * + * @since MU + * + * @param bool $echo Optional. If $echo is set and the quota is exceeded, a warning message is echoed. Default is true. + * @return int + */ +function upload_is_user_over_quota( $echo = true ) { + if ( get_site_option( 'upload_space_check_disabled' ) ) + return false; + + $space_allowed = get_space_allowed(); + if ( empty( $space_allowed ) || !is_numeric( $space_allowed ) ) + $space_allowed = 10; // Default space allowed is 10 MB + + $space_used = get_space_used(); + + if ( ( $space_allowed - $space_used ) < 0 ) { + if ( $echo ) + _e( 'Sorry, you have used your space allocation. Please delete some files to upload more files.' ); + return true; + } else { + return false; + } +} + +/** + * Displays the amount of disk space used by the current blog. Not used in core. + * + * @since MU + */ +function display_space_usage() { + $space_allowed = get_space_allowed(); + $space_used = get_space_used(); + + $percent_used = ( $space_used / $space_allowed ) * 100; + + if ( $space_allowed > 1000 ) { + $space = number_format( $space_allowed / 1024 ); + /* translators: Gigabytes */ + $space .= __( 'GB' ); + } else { + $space = number_format( $space_allowed ); + /* translators: Megabytes */ + $space .= __( 'MB' ); + } + ?> + + + + + + + update( $wpdb->users, array( sanitize_key( $pref ) => $value ), array( 'ID' => $id ) ); + + $user = new WP_User( $id ); + clean_user_cache( $user ); + + if ( $pref == 'spam' ) { + if ( $value == 1 ) { + /** + * Fires after the user is marked as a SPAM user. + * + * @since 3.0.0 + * + * @param int $id ID of the user marked as SPAM. + */ + do_action( 'make_spam_user', $id ); + } else { + /** + * Fires after the user is marked as a HAM user. Opposite of SPAM. + * + * @since 3.0.0 + * + * @param int $id ID of the user marked as HAM. + */ + do_action( 'make_ham_user', $id ); + } + } + + return $value; +} + +function refresh_user_details( $id ) { + $id = (int) $id; + + if ( !$user = get_userdata( $id ) ) + return false; + + clean_user_cache( $user ); + + return $id; +} + +function format_code_lang( $code = '' ) { + $code = strtolower( substr( $code, 0, 2 ) ); + $lang_codes = array( + 'aa' => 'Afar', 'ab' => 'Abkhazian', 'af' => 'Afrikaans', 'ak' => 'Akan', 'sq' => 'Albanian', 'am' => 'Amharic', 'ar' => 'Arabic', 'an' => 'Aragonese', 'hy' => 'Armenian', 'as' => 'Assamese', 'av' => 'Avaric', 'ae' => 'Avestan', 'ay' => 'Aymara', 'az' => 'Azerbaijani', 'ba' => 'Bashkir', 'bm' => 'Bambara', 'eu' => 'Basque', 'be' => 'Belarusian', 'bn' => 'Bengali', + 'bh' => 'Bihari', 'bi' => 'Bislama', 'bs' => 'Bosnian', 'br' => 'Breton', 'bg' => 'Bulgarian', 'my' => 'Burmese', 'ca' => 'Catalan; Valencian', 'ch' => 'Chamorro', 'ce' => 'Chechen', 'zh' => 'Chinese', 'cu' => 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic', 'cv' => 'Chuvash', 'kw' => 'Cornish', 'co' => 'Corsican', 'cr' => 'Cree', + 'cs' => 'Czech', 'da' => 'Danish', 'dv' => 'Divehi; Dhivehi; Maldivian', 'nl' => 'Dutch; Flemish', 'dz' => 'Dzongkha', 'en' => 'English', 'eo' => 'Esperanto', 'et' => 'Estonian', 'ee' => 'Ewe', 'fo' => 'Faroese', 'fj' => 'Fijjian', 'fi' => 'Finnish', 'fr' => 'French', 'fy' => 'Western Frisian', 'ff' => 'Fulah', 'ka' => 'Georgian', 'de' => 'German', 'gd' => 'Gaelic; Scottish Gaelic', + 'ga' => 'Irish', 'gl' => 'Galician', 'gv' => 'Manx', 'el' => 'Greek, Modern', 'gn' => 'Guarani', 'gu' => 'Gujarati', 'ht' => 'Haitian; Haitian Creole', 'ha' => 'Hausa', 'he' => 'Hebrew', 'hz' => 'Herero', 'hi' => 'Hindi', 'ho' => 'Hiri Motu', 'hu' => 'Hungarian', 'ig' => 'Igbo', 'is' => 'Icelandic', 'io' => 'Ido', 'ii' => 'Sichuan Yi', 'iu' => 'Inuktitut', 'ie' => 'Interlingue', + 'ia' => 'Interlingua (International Auxiliary Language Association)', 'id' => 'Indonesian', 'ik' => 'Inupiaq', 'it' => 'Italian', 'jv' => 'Javanese', 'ja' => 'Japanese', 'kl' => 'Kalaallisut; Greenlandic', 'kn' => 'Kannada', 'ks' => 'Kashmiri', 'kr' => 'Kanuri', 'kk' => 'Kazakh', 'km' => 'Central Khmer', 'ki' => 'Kikuyu; Gikuyu', 'rw' => 'Kinyarwanda', 'ky' => 'Kirghiz; Kyrgyz', + 'kv' => 'Komi', 'kg' => 'Kongo', 'ko' => 'Korean', 'kj' => 'Kuanyama; Kwanyama', 'ku' => 'Kurdish', 'lo' => 'Lao', 'la' => 'Latin', 'lv' => 'Latvian', 'li' => 'Limburgan; Limburger; Limburgish', 'ln' => 'Lingala', 'lt' => 'Lithuanian', 'lb' => 'Luxembourgish; Letzeburgesch', 'lu' => 'Luba-Katanga', 'lg' => 'Ganda', 'mk' => 'Macedonian', 'mh' => 'Marshallese', 'ml' => 'Malayalam', + 'mi' => 'Maori', 'mr' => 'Marathi', 'ms' => 'Malay', 'mg' => 'Malagasy', 'mt' => 'Maltese', 'mo' => 'Moldavian', 'mn' => 'Mongolian', 'na' => 'Nauru', 'nv' => 'Navajo; Navaho', 'nr' => 'Ndebele, South; South Ndebele', 'nd' => 'Ndebele, North; North Ndebele', 'ng' => 'Ndonga', 'ne' => 'Nepali', 'nn' => 'Norwegian Nynorsk; Nynorsk, Norwegian', 'nb' => 'Bokmål, Norwegian, Norwegian Bokmål', + 'no' => 'Norwegian', 'ny' => 'Chichewa; Chewa; Nyanja', 'oc' => 'Occitan, Provençal', 'oj' => 'Ojibwa', 'or' => 'Oriya', 'om' => 'Oromo', 'os' => 'Ossetian; Ossetic', 'pa' => 'Panjabi; Punjabi', 'fa' => 'Persian', 'pi' => 'Pali', 'pl' => 'Polish', 'pt' => 'Portuguese', 'ps' => 'Pushto', 'qu' => 'Quechua', 'rm' => 'Romansh', 'ro' => 'Romanian', 'rn' => 'Rundi', 'ru' => 'Russian', + 'sg' => 'Sango', 'sa' => 'Sanskrit', 'sr' => 'Serbian', 'hr' => 'Croatian', 'si' => 'Sinhala; Sinhalese', 'sk' => 'Slovak', 'sl' => 'Slovenian', 'se' => 'Northern Sami', 'sm' => 'Samoan', 'sn' => 'Shona', 'sd' => 'Sindhi', 'so' => 'Somali', 'st' => 'Sotho, Southern', 'es' => 'Spanish; Castilian', 'sc' => 'Sardinian', 'ss' => 'Swati', 'su' => 'Sundanese', 'sw' => 'Swahili', + 'sv' => 'Swedish', 'ty' => 'Tahitian', 'ta' => 'Tamil', 'tt' => 'Tatar', 'te' => 'Telugu', 'tg' => 'Tajik', 'tl' => 'Tagalog', 'th' => 'Thai', 'bo' => 'Tibetan', 'ti' => 'Tigrinya', 'to' => 'Tonga (Tonga Islands)', 'tn' => 'Tswana', 'ts' => 'Tsonga', 'tk' => 'Turkmen', 'tr' => 'Turkish', 'tw' => 'Twi', 'ug' => 'Uighur; Uyghur', 'uk' => 'Ukrainian', 'ur' => 'Urdu', 'uz' => 'Uzbek', + 've' => 'Venda', 'vi' => 'Vietnamese', 'vo' => 'Volapük', 'cy' => 'Welsh','wa' => 'Walloon','wo' => 'Wolof', 'xh' => 'Xhosa', 'yi' => 'Yiddish', 'yo' => 'Yoruba', 'za' => 'Zhuang; Chuang', 'zu' => 'Zulu' ); + + /** + * Filter the language codes. + * + * @since MU + * + * @param array $lang_codes Key/value pair of language codes where key is the short version. + * @param string $code A two-letter designation of the language. + */ + $lang_codes = apply_filters( 'lang_codes', $lang_codes, $code ); + return strtr( $code, $lang_codes ); +} + +function sync_category_tag_slugs( $term, $taxonomy ) { + if ( global_terms_enabled() && ( $taxonomy == 'category' || $taxonomy == 'post_tag' ) ) { + if ( is_object( $term ) ) { + $term->slug = sanitize_title( $term->name ); + } else { + $term['slug'] = sanitize_title( $term['name'] ); + } + } + return $term; +} +add_filter( 'get_term', 'sync_category_tag_slugs', 10, 2 ); + +function _access_denied_splash() { + if ( ! is_user_logged_in() || is_network_admin() ) + return; + + $blogs = get_blogs_of_user( get_current_user_id() ); + + if ( wp_list_filter( $blogs, array( 'userblog_id' => get_current_blog_id() ) ) ) + return; + + $blog_name = get_bloginfo( 'name' ); + + if ( empty( $blogs ) ) + wp_die( sprintf( __( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ), $blog_name ) ); + + $output = '

    ' . sprintf( __( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ), $blog_name ) . '

    '; + $output .= '

    ' . __( 'If you reached this screen by accident and meant to visit one of your own sites, here are some shortcuts to help you find your way.' ) . '

    '; + + $output .= '

    ' . __('Your Sites') . '

    '; + $output .= ''; + + foreach ( $blogs as $blog ) { + $output .= ""; + $output .= ""; + $output .= ""; + $output .= ""; + } + $output .= '
    "; + $output .= "{$blog->blogname}"; + $output .= ""; + $output .= "" . __( 'Visit Dashboard' ) . " | " . __( 'View Site' ) . "" ; + $output .= "
    '; + + wp_die( $output ); +} +add_action( 'admin_page_access_denied', '_access_denied_splash', 99 ); + +function check_import_new_users( $permission ) { + if ( !is_super_admin() ) + return false; + return true; +} +add_filter( 'import_allow_create_users', 'check_import_new_users' ); +// See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too. + +function mu_dropdown_languages( $lang_files = array(), $current = '' ) { + $flag = false; + $output = array(); + + foreach ( (array) $lang_files as $val ) { + $code_lang = basename( $val, '.mo' ); + + if ( $code_lang == 'en_US' ) { // American English + $flag = true; + $ae = __( 'American English' ); + $output[$ae] = ''; + } elseif ( $code_lang == 'en_GB' ) { // British English + $flag = true; + $be = __( 'British English' ); + $output[$be] = ''; + } else { + $translated = format_code_lang( $code_lang ); + $output[$translated] = ''; + } + + } + + if ( $flag === false ) // WordPress english + $output[] = '"; + + // Order by name + uksort( $output, 'strnatcasecmp' ); + /** + * Filter the languages available in the dropdown. + * + * @since MU + * + * @param array $output HTML output of the dropdown. + * @param array $lang_files Available language files. + * @param string $current The current language code. + */ + $output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current ); + echo implode( "\n\t", $output ); +} + +function site_admin_notice() { + global $wp_db_version; + if ( !is_super_admin() ) + return false; + if ( get_site_option( 'wpmu_upgrade_site' ) != $wp_db_version ) + echo "
    " . sprintf( __( 'Thank you for Updating! Please visit the Upgrade Network page to update all your sites.' ), esc_url( network_admin_url( 'upgrade.php' ) ) ) . "
    "; +} +add_action( 'admin_notices', 'site_admin_notice' ); +add_action( 'network_admin_notices', 'site_admin_notice' ); + +function avoid_blog_page_permalink_collision( $data, $postarr ) { + if ( is_subdomain_install() ) + return $data; + if ( $data['post_type'] != 'page' ) + return $data; + if ( !isset( $data['post_name'] ) || $data['post_name'] == '' ) + return $data; + if ( !is_main_site() ) + return $data; + + $post_name = $data['post_name']; + $c = 0; + while( $c < 10 && get_id_from_blogname( $post_name ) ) { + $post_name .= mt_rand( 1, 10 ); + $c ++; + } + if ( $post_name != $data['post_name'] ) { + $data['post_name'] = $post_name; + } + return $data; +} +add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 ); + +function choose_primary_blog() { + ?> + + + + + + + + + + + +
    + 1 ) { + $found = false; + ?> + + userblog_id ); + } + } elseif ( count( $all_blogs ) == 1 ) { + $blog = array_shift( $all_blogs ); + echo $blog->domain; + if ( $primary_blog != $blog->userblog_id ) // Set the primary blog again if it's out of sync with blog list. + update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id ); + } else { + echo "N/A"; + } + ?> +
    + + +
    + user_login, $super_admins ) ) { + $super_admins[] = $user->user_login; + update_site_option( 'site_admins' , $super_admins ); + + /** + * Fires after the user is granted Super Admin privileges. + * + * @since 3.0.0 + * + * @param int $user_id ID of the user that was granted Super Admin privileges. + */ + do_action( 'granted_super_admin', $user_id ); + return true; + } + return false; +} + +/** + * Revokes Super Admin privileges. + * + * @since 3.0.0 + * @param int $user_id ID of the user Super Admin privileges to be revoked from. + */ +function revoke_super_admin( $user_id ) { + global $super_admins; + + // If global super_admins override is defined, there is nothing to do here. + if ( isset( $super_admins ) ) + return false; + + /** + * Fires before the user's Super Admin privileges are revoked. + * + * @since 3.0.0 + * + * @param int $user_id ID of the user Super Admin privileges are being revoked from. + */ + do_action( 'revoke_super_admin', $user_id ); + + // Directly fetch site_admins instead of using get_super_admins() + $super_admins = get_site_option( 'site_admins', array( 'admin' ) ); + + $user = get_userdata( $user_id ); + if ( $user && $user->user_email != get_site_option( 'admin_email' ) ) { + if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) { + unset( $super_admins[$key] ); + update_site_option( 'site_admins', $super_admins ); + + /** + * Fires after the user's Super Admin privileges are revoked. + * + * @since 3.0.0 + * + * @param int $user_id ID of the user Super Admin privileges were revoked from. + */ + do_action( 'revoked_super_admin', $user_id ); + return true; + } + } + return false; +} + +/** + * Whether or not we can edit this network from this page + * + * By default editing of network is restricted to the Network Admin for that site_id this allows for this to be overridden + * + * @since 3.1.0 + * @param integer $site_id The network/site ID to check. + */ +function can_edit_network( $site_id ) { + global $wpdb; + + if ( $site_id == $wpdb->siteid ) + $result = true; + else + $result = false; + + /** + * Filter whether this network can be edited from this page. + * + * @since 3.1.0 + * + * @param bool $result Whether the network can be edited from this page. + * @param int $site_id The network/site ID to check. + */ + return apply_filters( 'can_edit_network', $result, $site_id ); +} + +/** + * Thickbox image paths for Network Admin. + * + * @since 3.1.0 + * @access private + */ +function _thickbox_path_admin_subfolder() { +?> + + $_wp_nav_menu_max_depth ? $depth : $_wp_nav_menu_max_depth; + + ob_start(); + $item_id = esc_attr( $item->ID ); + $removed_args = array( + 'action', + 'customlink-tab', + 'edit-menu-item', + 'menu-item', + 'page-tab', + '_wpnonce', + ); + + $original_title = ''; + if ( 'taxonomy' == $item->type ) { + $original_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' ); + if ( is_wp_error( $original_title ) ) + $original_title = false; + } elseif ( 'post_type' == $item->type ) { + $original_object = get_post( $item->object_id ); + $original_title = get_the_title( $original_object->ID ); + } + + $classes = array( + 'menu-item menu-item-depth-' . $depth, + 'menu-item-' . esc_attr( $item->object ), + 'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'), + ); + + $title = $item->title; + + if ( ! empty( $item->_invalid ) ) { + $classes[] = 'menu-item-invalid'; + /* translators: %s: title of menu item which is invalid */ + $title = sprintf( __( '%s (Invalid)' ), $item->title ); + } elseif ( isset( $item->post_status ) && 'draft' == $item->post_status ) { + $classes[] = 'pending'; + /* translators: %s: title of menu item in draft status */ + $title = sprintf( __('%s (Pending)'), $item->title ); + } + + $title = ( ! isset( $item->label ) || '' == $item->label ) ? $title : $item->label; + + $submenu_text = ''; + if ( 0 == $depth ) + $submenu_text = 'style="display: none;"'; + + ?> +
  • '; + $output .= ''; + + // Menu item hidden fields + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + } + +} // Walker_Nav_Menu_Checklist + +/** + * Prints the appropriate response to a menu quick search. + * + * @since 3.0.0 + * + * @param array $request The unsanitized request values. + */ +function _wp_ajax_menu_quick_search( $request = array() ) { + $args = array(); + $type = isset( $request['type'] ) ? $request['type'] : ''; + $object_type = isset( $request['object_type'] ) ? $request['object_type'] : ''; + $query = isset( $request['q'] ) ? $request['q'] : ''; + $response_format = isset( $request['response-format'] ) && in_array( $request['response-format'], array( 'json', 'markup' ) ) ? $request['response-format'] : 'json'; + + if ( 'markup' == $response_format ) { + $args['walker'] = new Walker_Nav_Menu_Checklist; + } + + if ( 'get-post-item' == $type ) { + if ( post_type_exists( $object_type ) ) { + if ( isset( $request['ID'] ) ) { + $object_id = (int) $request['ID']; + if ( 'markup' == $response_format ) { + echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_post( $object_id ) ) ), 0, (object) $args ); + } elseif ( 'json' == $response_format ) { + $post_obj = get_post( $object_id ); + echo json_encode( + array( + 'ID' => $object_id, + 'post_title' => get_the_title( $object_id ), + 'post_type' => get_post_type( $object_id ), + ) + ); + echo "\n"; + } + } + } elseif ( taxonomy_exists( $object_type ) ) { + if ( isset( $request['ID'] ) ) { + $object_id = (int) $request['ID']; + if ( 'markup' == $response_format ) { + echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_term( $object_id, $object_type ) ) ), 0, (object) $args ); + } elseif ( 'json' == $response_format ) { + $post_obj = get_term( $object_id, $object_type ); + echo json_encode( + array( + 'ID' => $object_id, + 'post_title' => $post_obj->name, + 'post_type' => $object_type, + ) + ); + echo "\n"; + } + } + + } + + } elseif ( preg_match('/quick-search-(posttype|taxonomy)-([a-zA-Z_-]*\b)/', $type, $matches) ) { + if ( 'posttype' == $matches[1] && get_post_type_object( $matches[2] ) ) { + query_posts(array( + 'posts_per_page' => 10, + 'post_type' => $matches[2], + 's' => $query, + )); + if ( ! have_posts() ) + return; + while ( have_posts() ) { + the_post(); + if ( 'markup' == $response_format ) { + $var_by_ref = get_the_ID(); + echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_post( $var_by_ref ) ) ), 0, (object) $args ); + } elseif ( 'json' == $response_format ) { + echo json_encode( + array( + 'ID' => get_the_ID(), + 'post_title' => get_the_title(), + 'post_type' => get_post_type(), + ) + ); + echo "\n"; + } + } + } elseif ( 'taxonomy' == $matches[1] ) { + $terms = get_terms( $matches[2], array( + 'name__like' => $query, + 'number' => 10, + )); + if ( empty( $terms ) || is_wp_error( $terms ) ) + return; + foreach( (array) $terms as $term ) { + if ( 'markup' == $response_format ) { + echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( $term ) ), 0, (object) $args ); + } elseif ( 'json' == $response_format ) { + echo json_encode( + array( + 'ID' => $term->term_id, + 'post_title' => $term->name, + 'post_type' => $matches[2], + ) + ); + echo "\n"; + } + } + } + } +} + +/** + * Register nav menu metaboxes and advanced menu items + * + * @since 3.0.0 + **/ +function wp_nav_menu_setup() { + // Register meta boxes + wp_nav_menu_post_type_meta_boxes(); + add_meta_box( 'add-custom-links', __( 'Links' ), 'wp_nav_menu_item_link_meta_box', 'nav-menus', 'side', 'default' ); + wp_nav_menu_taxonomy_meta_boxes(); + + // Register advanced menu items (columns) + add_filter( 'manage_nav-menus_columns', 'wp_nav_menu_manage_columns' ); + + // If first time editing, disable advanced items by default. + if( false === get_user_option( 'managenav-menuscolumnshidden' ) ) { + $user = wp_get_current_user(); + update_user_option($user->ID, 'managenav-menuscolumnshidden', + array( 0 => 'link-target', 1 => 'css-classes', 2 => 'xfn', 3 => 'description', ), + true); + } +} + +/** + * Limit the amount of meta boxes to just links, pages and cats for first time users. + * + * @since 3.0.0 + **/ +function wp_initial_nav_menu_meta_boxes() { + global $wp_meta_boxes; + + if ( get_user_option( 'metaboxhidden_nav-menus' ) !== false || ! is_array($wp_meta_boxes) ) + return; + + $initial_meta_boxes = array( 'nav-menu-theme-locations', 'add-page', 'add-custom-links', 'add-category' ); + $hidden_meta_boxes = array(); + + foreach ( array_keys($wp_meta_boxes['nav-menus']) as $context ) { + foreach ( array_keys($wp_meta_boxes['nav-menus'][$context]) as $priority ) { + foreach ( $wp_meta_boxes['nav-menus'][$context][$priority] as $box ) { + if ( in_array( $box['id'], $initial_meta_boxes ) ) { + unset( $box['id'] ); + } else { + $hidden_meta_boxes[] = $box['id']; + } + } + } + } + + $user = wp_get_current_user(); + update_user_option( $user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true ); +} + +/** + * Creates metaboxes for any post type menu item. + * + * @since 3.0.0 + */ +function wp_nav_menu_post_type_meta_boxes() { + $post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'object' ); + + if ( ! $post_types ) + return; + + foreach ( $post_types as $post_type ) { + $post_type = apply_filters( 'nav_menu_meta_box_object', $post_type ); + if ( $post_type ) { + $id = $post_type->name; + // give pages a higher priority + $priority = ( 'page' == $post_type->name ? 'core' : 'default' ); + add_meta_box( "add-{$id}", $post_type->labels->name, 'wp_nav_menu_item_post_type_meta_box', 'nav-menus', 'side', $priority, $post_type ); + } + } +} + +/** + * Creates metaboxes for any taxonomy menu item. + * + * @since 3.0.0 + */ +function wp_nav_menu_taxonomy_meta_boxes() { + $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'object' ); + + if ( !$taxonomies ) + return; + + foreach ( $taxonomies as $tax ) { + $tax = apply_filters( 'nav_menu_meta_box_object', $tax ); + if ( $tax ) { + $id = $tax->name; + add_meta_box( "add-{$id}", $tax->labels->name, 'wp_nav_menu_item_taxonomy_meta_box', 'nav-menus', 'side', 'default', $tax ); + } + } +} + +/** + * Check whether to disable the Menu Locations meta box submit button + * + * @since 3.6.0 + * + * @uses global $one_theme_location_no_menus to determine if no menus exist + * @uses disabled() to output the disabled attribute in $other_attributes param in submit_button() + * + * @param int|string $nav_menu_selected_id (id, name or slug) of the currently-selected menu + * @return string Disabled attribute if at least one menu exists, false if not +*/ +function wp_nav_menu_disabled_check( $nav_menu_selected_id ) { + global $one_theme_location_no_menus; + + if ( $one_theme_location_no_menus ) + return false; + + return disabled( $nav_menu_selected_id, 0 ); +} + +/** + * Displays a metabox for the custom links menu item. + * + * @since 3.0.0 + */ +function wp_nav_menu_item_link_meta_box() { + global $_nav_menu_placeholder, $nav_menu_selected_id; + + $_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1; + + ?> +
    + + + + + +

    + + class="button-secondary submit-add-to-menu right" value="" name="add-custom-menu-item" id="submit-customlinkdiv" /> + + +

    + +
    + name; + + // paginate browsing for large numbers of post objects + $per_page = 50; + $pagenum = isset( $_REQUEST[$post_type_name . '-tab'] ) && isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1; + $offset = 0 < $pagenum ? $per_page * ( $pagenum - 1 ) : 0; + + $args = array( + 'offset' => $offset, + 'order' => 'ASC', + 'orderby' => 'title', + 'posts_per_page' => $per_page, + 'post_type' => $post_type_name, + 'suppress_filters' => true, + 'update_post_term_cache' => false, + 'update_post_meta_cache' => false + ); + + if ( isset( $post_type['args']->_default_query ) ) + $args = array_merge($args, (array) $post_type['args']->_default_query ); + + // @todo transient caching of these results with proper invalidation on updating of a post of this type + $get_posts = new WP_Query; + $posts = $get_posts->query( $args ); + if ( ! $get_posts->post_count ) { + echo '

    ' . __( 'No items.' ) . '

    '; + return; + } + + $post_type_object = get_post_type_object($post_type_name); + + $num_pages = $get_posts->max_num_pages; + + $page_links = paginate_links( array( + 'base' => add_query_arg( + array( + $post_type_name . '-tab' => 'all', + 'paged' => '%#%', + 'item-type' => 'post_type', + 'item-object' => $post_type_name, + ) + ), + 'format' => '', + 'prev_text' => __('«'), + 'next_text' => __('»'), + 'total' => $num_pages, + 'current' => $pagenum + )); + + if ( !$posts ) + $error = '
  • '. $post_type['args']->labels->not_found .'
  • '; + + $db_fields = false; + if ( is_post_type_hierarchical( $post_type_name ) ) { + $db_fields = array( 'parent' => 'post_parent', 'id' => 'ID' ); + } + + $walker = new Walker_Nav_Menu_Checklist( $db_fields ); + + $current_tab = 'most-recent'; + if ( isset( $_REQUEST[$post_type_name . '-tab'] ) && in_array( $_REQUEST[$post_type_name . '-tab'], array('all', 'search') ) ) { + $current_tab = $_REQUEST[$post_type_name . '-tab']; + } + + if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) { + $current_tab = 'search'; + } + + $removed_args = array( + 'action', + 'customlink-tab', + 'edit-menu-item', + 'menu-item', + 'page-tab', + '_wpnonce', + ); + + ?> +
    + + +
    +
      + 'post_date', 'order' => 'DESC', 'posts_per_page' => 15 ) ); + $most_recent = $get_posts->query( $recent_args ); + $args['walker'] = $walker; + echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $most_recent), 0, (object) $args ); + ?> +
    +
    + + + +
    + + + +
      + front_or_home = true; + array_unshift( $posts, $front_page_obj ); + } else { + $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1; + array_unshift( $posts, (object) array( + 'front_or_home' => true, + 'ID' => 0, + 'object_id' => $_nav_menu_placeholder, + 'post_content' => '', + 'post_excerpt' => '', + 'post_parent' => '', + 'post_title' => _x('Home', 'nav menu home label'), + 'post_type' => 'nav_menu_item', + 'type' => 'custom', + 'url' => home_url('/'), + ) ); + } + } + + $posts = apply_filters( 'nav_menu_items_'.$post_type_name, $posts, $args, $post_type ); + $checkbox_items = walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $posts), 0, (object) $args ); + + if ( 'all' == $current_tab && ! empty( $_REQUEST['selectall'] ) ) { + $checkbox_items = preg_replace('/(type=(.)checkbox(\2))/', '$1 checked=$2checked$2', $checkbox_items); + + } + + echo $checkbox_items; + ?> +
    + + + +
    + +

    + + + + + + class="button-secondary submit-add-to-menu right" value="" name="add-post-type-menu-item" id="" /> + + +

    + +
    + name; + + // paginate browsing for large numbers of objects + $per_page = 50; + $pagenum = isset( $_REQUEST[$taxonomy_name . '-tab'] ) && isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1; + $offset = 0 < $pagenum ? $per_page * ( $pagenum - 1 ) : 0; + + $args = array( + 'child_of' => 0, + 'exclude' => '', + 'hide_empty' => false, + 'hierarchical' => 1, + 'include' => '', + 'number' => $per_page, + 'offset' => $offset, + 'order' => 'ASC', + 'orderby' => 'name', + 'pad_counts' => false, + ); + + $terms = get_terms( $taxonomy_name, $args ); + + if ( ! $terms || is_wp_error($terms) ) { + echo '

    ' . __( 'No items.' ) . '

    '; + return; + } + + $num_pages = ceil( wp_count_terms( $taxonomy_name , array_merge( $args, array('number' => '', 'offset' => '') ) ) / $per_page ); + + $page_links = paginate_links( array( + 'base' => add_query_arg( + array( + $taxonomy_name . '-tab' => 'all', + 'paged' => '%#%', + 'item-type' => 'taxonomy', + 'item-object' => $taxonomy_name, + ) + ), + 'format' => '', + 'prev_text' => __('«'), + 'next_text' => __('»'), + 'total' => $num_pages, + 'current' => $pagenum + )); + + $db_fields = false; + if ( is_taxonomy_hierarchical( $taxonomy_name ) ) { + $db_fields = array( 'parent' => 'parent', 'id' => 'term_id' ); + } + + $walker = new Walker_Nav_Menu_Checklist( $db_fields ); + + $current_tab = 'most-used'; + if ( isset( $_REQUEST[$taxonomy_name . '-tab'] ) && in_array( $_REQUEST[$taxonomy_name . '-tab'], array('all', 'most-used', 'search') ) ) { + $current_tab = $_REQUEST[$taxonomy_name . '-tab']; + } + + if ( ! empty( $_REQUEST['quick-search-taxonomy-' . $taxonomy_name] ) ) { + $current_tab = 'search'; + } + + $removed_args = array( + 'action', + 'customlink-tab', + 'edit-menu-item', + 'menu-item', + 'page-tab', + '_wpnonce', + ); + + ?> +
    + + +
    +
      + 'count', 'order' => 'DESC', 'number' => 10, 'hierarchical' => false ) ); + $args['walker'] = $walker; + echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $popular_terms), 0, (object) $args ); + ?> +
    +
    + +
    + + + +
      + +
    + + + +
    + +
    + $searched, 'fields' => 'all', 'orderby' => 'count', 'order' => 'DESC', 'hierarchical' => false ) ); + } else { + $searched = ''; + $search_results = array(); + } + ?> +

    + + + 'submit-quick-search-taxonomy-' . $taxonomy_name ) ); ?> +

    + +
      + + + +
    • get_error_message(); ?>
    • + +
    • + +
    +
    + +

    + + + + + + class="button-secondary submit-add-to-menu right" value="" name="add-taxonomy-menu-item" id="" /> + + +

    + +
    + $_item_object_data ) { + if ( + empty( $_item_object_data['menu-item-object-id'] ) && // checkbox is not checked + ( + ! isset( $_item_object_data['menu-item-type'] ) || // and item type either isn't set + in_array( $_item_object_data['menu-item-url'], array( 'http://', '' ) ) || // or URL is the default + ! ( 'custom' == $_item_object_data['menu-item-type'] && ! isset( $_item_object_data['menu-item-db-id'] ) ) || // or it's not a custom menu item (but not the custom home page) + ! empty( $_item_object_data['menu-item-db-id'] ) // or it *is* a custom menu item that already exists + ) + ) { + continue; // then this potential menu item is not getting added to this menu + } + + // if this possible menu item doesn't actually have a menu database ID yet + if ( + empty( $_item_object_data['menu-item-db-id'] ) || + ( 0 > $_possible_db_id ) || + $_possible_db_id != $_item_object_data['menu-item-db-id'] + ) { + $_actual_db_id = 0; + } else { + $_actual_db_id = (int) $_item_object_data['menu-item-db-id']; + } + + $args = array( + 'menu-item-db-id' => ( isset( $_item_object_data['menu-item-db-id'] ) ? $_item_object_data['menu-item-db-id'] : '' ), + 'menu-item-object-id' => ( isset( $_item_object_data['menu-item-object-id'] ) ? $_item_object_data['menu-item-object-id'] : '' ), + 'menu-item-object' => ( isset( $_item_object_data['menu-item-object'] ) ? $_item_object_data['menu-item-object'] : '' ), + 'menu-item-parent-id' => ( isset( $_item_object_data['menu-item-parent-id'] ) ? $_item_object_data['menu-item-parent-id'] : '' ), + 'menu-item-position' => ( isset( $_item_object_data['menu-item-position'] ) ? $_item_object_data['menu-item-position'] : '' ), + 'menu-item-type' => ( isset( $_item_object_data['menu-item-type'] ) ? $_item_object_data['menu-item-type'] : '' ), + 'menu-item-title' => ( isset( $_item_object_data['menu-item-title'] ) ? $_item_object_data['menu-item-title'] : '' ), + 'menu-item-url' => ( isset( $_item_object_data['menu-item-url'] ) ? $_item_object_data['menu-item-url'] : '' ), + 'menu-item-description' => ( isset( $_item_object_data['menu-item-description'] ) ? $_item_object_data['menu-item-description'] : '' ), + 'menu-item-attr-title' => ( isset( $_item_object_data['menu-item-attr-title'] ) ? $_item_object_data['menu-item-attr-title'] : '' ), + 'menu-item-target' => ( isset( $_item_object_data['menu-item-target'] ) ? $_item_object_data['menu-item-target'] : '' ), + 'menu-item-classes' => ( isset( $_item_object_data['menu-item-classes'] ) ? $_item_object_data['menu-item-classes'] : '' ), + 'menu-item-xfn' => ( isset( $_item_object_data['menu-item-xfn'] ) ? $_item_object_data['menu-item-xfn'] : '' ), + ); + + $items_saved[] = wp_update_nav_menu_item( $menu_id, $_actual_db_id, $args ); + + } + } + return $items_saved; +} + +/** + * Adds custom arguments to some of the meta box object types. + * + * @since 3.0.0 + * + * @access private + * + * @param object $object The post type or taxonomy meta-object. + * @return object The post type of taxonomy object. + */ +function _wp_nav_menu_meta_box_object( $object = null ) { + if ( isset( $object->name ) ) { + + if ( 'page' == $object->name ) { + $object->_default_query = array( + 'orderby' => 'menu_order title', + 'post_status' => 'publish', + ); + + // posts should show only published items + } elseif ( 'post' == $object->name ) { + $object->_default_query = array( + 'post_status' => 'publish', + ); + + // cats should be in reverse chronological order + } elseif ( 'category' == $object->name ) { + $object->_default_query = array( + 'orderby' => 'id', + 'order' => 'DESC', + ); + + // custom post types should show only published items + } else { + $object->_default_query = array( + 'post_status' => 'publish', + ); + } + } + + return $object; +} + +/** + * Returns the menu formatted to edit. + * + * @since 3.0.0 + * + * @param string $menu_id The ID of the menu to format. + * @return string|WP_Error $output The menu formatted to edit or error object on failure. + */ +function wp_get_nav_menu_to_edit( $menu_id = 0 ) { + $menu = wp_get_nav_menu_object( $menu_id ); + + // If the menu exists, get its items. + if ( is_nav_menu( $menu ) ) { + $menu_items = wp_get_nav_menu_items( $menu->term_id, array('post_status' => 'any') ); + $result = '
    ' : '">'; + $result .= '

    ' . __( 'Add menu items from the column on the left.' ) . '

    '; + $result .= '
    '; + + if( empty($menu_items) ) + return $result . ' '; + + $walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $menu_id ); + + if ( class_exists( $walker_class_name ) ) + $walker = new $walker_class_name; + else + return new WP_Error( 'menu_walker_not_exist', sprintf( __('The Walker class named %s does not exist.'), $walker_class_name ) ); + + $some_pending_menu_items = $some_invalid_menu_items = false; + foreach( (array) $menu_items as $menu_item ) { + if ( isset( $menu_item->post_status ) && 'draft' == $menu_item->post_status ) + $some_pending_menu_items = true; + if ( ! empty( $menu_item->_invalid ) ) + $some_invalid_menu_items = true; + } + + if ( $some_pending_menu_items ) + $result .= '

    ' . __('Click Save Menu to make pending menu items public.') . '

    '; + + if ( $some_invalid_menu_items ) + $result .= '

    ' . __('There are some invalid menu items. Please check or delete them.') . '

    '; + + $result .= ' '; + return $result; + } elseif ( is_wp_error( $menu ) ) { + return $menu; + } + +} + +/** + * Returns the columns for the nav menus page. + * + * @since 3.0.0 + * + * @return string|WP_Error $output The menu formatted to edit or error object on failure. + */ +function wp_nav_menu_manage_columns() { + return array( + '_title' => __('Show advanced menu properties'), + 'cb' => '', + 'link-target' => __('Link Target'), + 'css-classes' => __('CSS Classes'), + 'xfn' => __('Link Relationship (XFN)'), + 'description' => __('Description'), + ); +} + +/** + * Deletes orphaned draft menu items + * + * @access private + * @since 3.0.0 + * + */ +function _wp_delete_orphaned_draft_menu_items() { + global $wpdb; + $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS ); + + // delete orphaned draft menu items + $menu_items_to_delete = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts AS p LEFT JOIN $wpdb->postmeta AS m ON p.ID = m.post_id WHERE post_type = 'nav_menu_item' AND post_status = 'draft' AND meta_key = '_menu_item_orphaned' AND meta_value < '%d'", $delete_timestamp ) ); + + foreach( (array) $menu_items_to_delete as $menu_item_id ) + wp_delete_post( $menu_item_id, true ); +} +add_action('admin_head-nav-menus.php', '_wp_delete_orphaned_draft_menu_items'); + +/** + * Saves nav menu items + * + * @since 3.6.0 + * + * @uses wp_get_nav_menu_items() to retrieve the nav menu's menu items + * @uses wp_defer_term_counter() to enable then disable term counting + * + * @param int|string $nav_menu_selected_id (id, slug, or name ) of the currently-selected menu + * @param string $nav_menu_selected_title Title of the currently-selected menu + * @return array $messages The menu updated message + */ +function wp_nav_menu_update_menu_items ( $nav_menu_selected_id, $nav_menu_selected_title ) { + $unsorted_menu_items = wp_get_nav_menu_items( $nav_menu_selected_id, array( 'orderby' => 'ID', 'output' => ARRAY_A, 'output_key' => 'ID', 'post_status' => 'draft,publish' ) ); + + $menu_items = array(); + // Index menu items by db ID + foreach ( $unsorted_menu_items as $_item ) + $menu_items[$_item->db_id] = $_item; + + $post_fields = array( + 'menu-item-db-id', 'menu-item-object-id', 'menu-item-object', + 'menu-item-parent-id', 'menu-item-position', 'menu-item-type', + 'menu-item-title', 'menu-item-url', 'menu-item-description', + 'menu-item-attr-title', 'menu-item-target', 'menu-item-classes', 'menu-item-xfn' + ); + + wp_defer_term_counting( true ); + // Loop through all the menu items' POST variables + if ( ! empty( $_POST['menu-item-db-id'] ) ) { + foreach( (array) $_POST['menu-item-db-id'] as $_key => $k ) { + + // Menu item title can't be blank + if ( ! isset( $_POST['menu-item-title'][ $_key ] ) || '' == $_POST['menu-item-title'][ $_key ] ) + continue; + + $args = array(); + foreach ( $post_fields as $field ) + $args[$field] = isset( $_POST[$field][$_key] ) ? $_POST[$field][$_key] : ''; + + $menu_item_db_id = wp_update_nav_menu_item( $nav_menu_selected_id, ( $_POST['menu-item-db-id'][$_key] != $_key ? 0 : $_key ), $args ); + + if ( is_wp_error( $menu_item_db_id ) ) + $messages[] = '

    ' . $menu_item_db_id->get_error_message() . '

    '; + elseif ( isset( $menu_items[$menu_item_db_id] ) ) + unset( $menu_items[$menu_item_db_id] ); + } + } + + // Remove menu items from the menu that weren't in $_POST + if ( ! empty( $menu_items ) ) { + foreach ( array_keys( $menu_items ) as $menu_item_id ) { + if ( is_nav_menu_item( $menu_item_id ) ) { + wp_delete_post( $menu_item_id ); + } + } + } + + // Store 'auto-add' pages. + $auto_add = ! empty( $_POST['auto-add-pages'] ); + $nav_menu_option = (array) get_option( 'nav_menu_options' ); + if ( ! isset( $nav_menu_option['auto_add'] ) ) + $nav_menu_option['auto_add'] = array(); + if ( $auto_add ) { + if ( ! in_array( $nav_menu_selected_id, $nav_menu_option['auto_add'] ) ) + $nav_menu_option['auto_add'][] = $nav_menu_selected_id; + } else { + if ( false !== ( $key = array_search( $nav_menu_selected_id, $nav_menu_option['auto_add'] ) ) ) + unset( $nav_menu_option['auto_add'][$key] ); + } + // Remove nonexistent/deleted menus + $nav_menu_option['auto_add'] = array_intersect( $nav_menu_option['auto_add'], wp_get_nav_menus( array( 'fields' => 'ids' ) ) ); + update_option( 'nav_menu_options', $nav_menu_option ); + + wp_defer_term_counting( false ); + + do_action( 'wp_update_nav_menu', $nav_menu_selected_id ); + + $messages[] = '

    ' . sprintf( __( '%1$s has been updated.' ), $nav_menu_selected_title ) . '

    '; + unset( $menu_items, $unsorted_menu_items ); + + return $messages; +} diff --git a/sources/wp-admin/includes/plugin-install.php b/sources/wp-admin/includes/plugin-install.php new file mode 100644 index 0000000..58a9e9b --- /dev/null +++ b/sources/wp-admin/includes/plugin-install.php @@ -0,0 +1,454 @@ +per_page) ) + $args->per_page = 24; + + /** + * Override the Plugin Install API arguments. + * + * Please ensure that an object is returned. + * + * @since 2.7.0 + * + * @param object $args Plugin API arguments. + * @param string $action The type of information being requested from the Plugin Install API. + */ + $args = apply_filters( 'plugins_api_args', $args, $action ); + + /** + * Allows a plugin to override the WordPress.org Plugin Install API entirely. + * + * Please ensure that an object is returned. + * + * @since 2.7.0 + * + * @param bool|object The result object. Default is false. + * @param string $action The type of information being requested from the Plugin Install API. + * @param object $args Plugin API arguments. + */ + $res = apply_filters( 'plugins_api', false, $action, $args ); + + if ( false === $res ) { + $url = $http_url = 'http://api.wordpress.org/plugins/info/1.0/'; + if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) + $url = set_url_scheme( $url, 'https' ); + + $args = array( + 'timeout' => 15, + 'body' => array( + 'action' => $action, + 'request' => serialize( $args ) + ) + ); + $request = wp_remote_post( $url, $args ); + + if ( $ssl && is_wp_error( $request ) ) { + trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE ); + $request = wp_remote_post( $http_url, $args ); + } + + if ( is_wp_error($request) ) { + $res = new WP_Error('plugins_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), $request->get_error_message() ); + } else { + $res = maybe_unserialize( wp_remote_retrieve_body( $request ) ); + if ( ! is_object( $res ) && ! is_array( $res ) ) + $res = new WP_Error('plugins_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), wp_remote_retrieve_body( $request ) ); + } + } elseif ( !is_wp_error($res) ) { + $res->external = true; + } + + /** + * Filter the Plugin Install API response results. + * + * @since 2.7.0 + * + * @param object|WP_Error $res Response object or WP_Error. + * @param string $action The type of information being requested from the Plugin Install API. + * @param object $args Plugin API arguments. + */ + return apply_filters( 'plugins_api_result', $res, $action, $args ); +} + +/** + * Retrieve popular WordPress plugin tags. + * + * @since 2.7.0 + * + * @param array $args + * @return array + */ +function install_popular_tags( $args = array() ) { + $key = md5(serialize($args)); + if ( false !== ($tags = get_site_transient('poptags_' . $key) ) ) + return $tags; + + $tags = plugins_api('hot_tags', $args); + + if ( is_wp_error($tags) ) + return $tags; + + set_site_transient( 'poptags_' . $key, $tags, 3 * HOUR_IN_SECONDS ); + + return $tags; +} + +function install_dashboard() { + ?> +

    WordPress Plugin Directory or upload a plugin in .zip format via this page.' ), 'http://wordpress.org/plugins/', self_admin_url( 'plugin-install.php?tab=upload' ) ); ?>

    + +

    + + +

    +

    + '; + if ( is_wp_error($api_tags) ) { + echo $api_tags->get_error_message(); + } else { + //Set up the tags in a way which can be interpreted by wp_generate_tag_cloud() + $tags = array(); + foreach ( (array)$api_tags as $tag ) + $tags[ $tag['name'] ] = (object) array( + 'link' => esc_url( self_admin_url('plugin-install.php?tab=search&type=tag&s=' . urlencode($tag['name'])) ), + 'name' => $tag['name'], + 'id' => sanitize_title_with_dashes($tag['name']), + 'count' => $tag['count'] ); + echo wp_generate_tag_cloud($tags, array( 'single_text' => __('%s plugin'), 'multiple_text' => __('%s plugins') ) ); + } + echo '


    '; +} +add_action('install_plugins_dashboard', 'install_dashboard'); + +/** + * Display search form for searching plugins. + * + * @since 2.7.0 + */ +function install_search_form( $type_selector = true ) { + $type = isset($_REQUEST['type']) ? wp_unslash( $_REQUEST['type'] ) : 'term'; + $term = isset($_REQUEST['s']) ? wp_unslash( $_REQUEST['s'] ) : ''; + + ?>
    + + + + + + + +
    +

    +

    +
    + + + + +
    + +

    +
    + +

    + + + +

    +
    + display(); +} +add_action( 'install_plugins_search', 'display_plugins_table' ); +add_action( 'install_plugins_featured', 'display_plugins_table' ); +add_action( 'install_plugins_popular', 'display_plugins_table' ); +add_action( 'install_plugins_new', 'display_plugins_table' ); +add_action( 'install_plugins_favorites', 'display_plugins_table' ); + +/** + * Determine the status we can perform on a plugin. + * + * @since 3.0.0 + */ +function install_plugin_install_status($api, $loop = false) { + // this function is called recursively, $loop prevents further loops. + if ( is_array($api) ) + $api = (object) $api; + + //Default to a "new" plugin + $status = 'install'; + $url = false; + + //Check to see if this plugin is known to be installed, and has an update awaiting it. + $update_plugins = get_site_transient('update_plugins'); + if ( isset( $update_plugins->response ) ) { + foreach ( (array)$update_plugins->response as $file => $plugin ) { + if ( $plugin->slug === $api->slug ) { + $status = 'update_available'; + $update_file = $file; + $version = $plugin->new_version; + if ( current_user_can('update_plugins') ) + $url = wp_nonce_url(self_admin_url('update.php?action=upgrade-plugin&plugin=' . $update_file), 'upgrade-plugin_' . $update_file); + break; + } + } + } + + if ( 'install' == $status ) { + if ( is_dir( WP_PLUGIN_DIR . '/' . $api->slug ) ) { + $installed_plugin = get_plugins('/' . $api->slug); + if ( empty($installed_plugin) ) { + if ( current_user_can('install_plugins') ) + $url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $api->slug), 'install-plugin_' . $api->slug); + } else { + $key = array_keys( $installed_plugin ); + $key = array_shift( $key ); //Use the first plugin regardless of the name, Could have issues for multiple-plugins in one directory if they share different version numbers + if ( version_compare($api->version, $installed_plugin[ $key ]['Version'], '=') ){ + $status = 'latest_installed'; + } elseif ( version_compare($api->version, $installed_plugin[ $key ]['Version'], '<') ) { + $status = 'newer_installed'; + $version = $installed_plugin[ $key ]['Version']; + } else { + //If the above update check failed, Then that probably means that the update checker has out-of-date information, force a refresh + if ( ! $loop ) { + delete_site_transient('update_plugins'); + wp_update_plugins(); + return install_plugin_install_status($api, true); + } + } + } + } else { + // "install" & no directory with that slug + if ( current_user_can('install_plugins') ) + $url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $api->slug), 'install-plugin_' . $api->slug); + } + } + if ( isset($_GET['from']) ) + $url .= '&from=' . urlencode( wp_unslash( $_GET['from'] ) ); + + return compact('status', 'url', 'version'); +} + +/** + * Display plugin information in dialog box form. + * + * @since 2.7.0 + */ +function install_plugin_information() { + global $tab; + + $api = plugins_api( 'plugin_information', array( 'slug' => wp_unslash( $_REQUEST['plugin'] ), 'is_ssl' => is_ssl() ) ); + + if ( is_wp_error($api) ) + wp_die($api); + + $plugins_allowedtags = array( + 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ), + 'abbr' => array( 'title' => array() ), 'acronym' => array( 'title' => array() ), + 'code' => array(), 'pre' => array(), 'em' => array(), 'strong' => array(), + 'div' => array(), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array(), + 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), + 'img' => array( 'src' => array(), 'class' => array(), 'alt' => array() ) + ); + + $plugins_section_titles = array( + 'description' => _x('Description', 'Plugin installer section title'), + 'installation' => _x('Installation', 'Plugin installer section title'), + 'faq' => _x('FAQ', 'Plugin installer section title'), + 'screenshots' => _x('Screenshots', 'Plugin installer section title'), + 'changelog' => _x('Changelog', 'Plugin installer section title'), + 'other_notes' => _x('Other Notes', 'Plugin installer section title') + ); + + //Sanitize HTML + foreach ( (array)$api->sections as $section_name => $content ) + $api->sections[$section_name] = wp_kses($content, $plugins_allowedtags); + foreach ( array( 'version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug' ) as $key ) { + if ( isset( $api->$key ) ) + $api->$key = wp_kses( $api->$key, $plugins_allowedtags ); + } + + $section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description'; //Default to the Description tab, Do not translate, API returns English. + if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) { + $section_titles = array_keys( (array) $api->sections ); + $section = array_shift( $section_titles ); + } + + iframe_header( __('Plugin Install') ); + echo "
    \n"; + echo "
      \n"; + foreach ( (array)$api->sections as $section_name => $content ) { + + if ( isset( $plugins_section_titles[ $section_name ] ) ) + $title = $plugins_section_titles[ $section_name ]; + else + $title = ucwords( str_replace( '_', ' ', $section_name ) ); + + $class = ( $section_name == $section ) ? ' class="current"' : ''; + $href = add_query_arg( array('tab' => $tab, 'section' => $section_name) ); + $href = esc_url($href); + $san_section = esc_attr( $section_name ); + echo "\t
    • $title
    • \n"; + } + echo "
    \n"; + echo "
    \n"; + ?> +
    + download_link) && ( current_user_can('install_plugins') || current_user_can('update_plugins') ) ) : ?> +

    + ' . __('Install Now') . ''; + break; + case 'update_available': + if ( $status['url'] ) + echo '' . __('Install Update Now') .''; + break; + case 'newer_installed': + echo '' . sprintf(__('Newer Version (%s) Installed'), $status['version']) . ''; + break; + case 'latest_installed': + echo '' . __('Latest Version Installed') . ''; + break; + } + ?> +

    + +

    +
      +version) ) : ?> +
    • version ?>
    • +author) ) : ?> +
    • author, '_blank') ?>
    • +last_updated) ) : ?> +
    • last_updated)) ) ?>
    • +requires) ) : ?> +
    • requires) ?>
    • +tested) ) : ?> +
    • tested ?>
    • +downloaded) ) : ?> +
    • downloaded), number_format_i18n($api->downloaded)) ?>
    • +slug) && empty($api->external) ) : ?> +
    • +homepage) ) : ?> +
    • + +
    + rating) ) : ?> +

    +
    +
    +
    + num_ratings), number_format_i18n($api->num_ratings)); ?> + +
    +
    + tested) && version_compare( substr($GLOBALS['wp_version'], 0, strlen($api->tested)), $api->tested, '>') ) + echo '

    ' . __('Warning: This plugin has not been tested with your current version of WordPress.') . '

    '; + + else if ( !empty($api->requires) && version_compare( substr($GLOBALS['wp_version'], 0, strlen($api->requires)), $api->requires, '<') ) + echo '

    ' . __('Warning: This plugin has not been marked as compatible with your version of WordPress.') . '

    '; + + foreach ( (array)$api->sections as $section_name => $content ) { + + if ( isset( $plugins_section_titles[ $section_name ] ) ) + $title = $plugins_section_titles[ $section_name ]; + else + $title = ucwords( str_replace( '_', ' ', $section_name ) ); + + $content = links_add_base_url($content, 'http://wordpress.org/plugins/' . $api->slug . '/'); + $content = links_add_target($content, '_blank'); + + $san_section = esc_attr( $section_name ); + + $display = ( $section_name == $section ) ? 'block' : 'none'; + + echo "\t
    \n"; + echo "\t\t

    $title

    "; + echo $content; + echo "\t
    \n"; + } + echo "
    \n"; + + iframe_footer(); + exit; +} +add_action('install_plugins_pre_plugin-information', 'install_plugin_information'); diff --git a/sources/wp-admin/includes/plugin.php b/sources/wp-admin/includes/plugin.php new file mode 100644 index 0000000..4e2126a --- /dev/null +++ b/sources/wp-admin/includes/plugin.php @@ -0,0 +1,1851 @@ + + * /* + * Plugin Name: Name of Plugin + * Plugin URI: Link to plugin information + * Description: Plugin Description + * Author: Plugin author's name + * Author URI: Link to the author's web site + * Version: Must be set in the plugin for WordPress 2.3+ + * Text Domain: Optional. Unique identifier, should be same as the one used in + * plugin_text_domain() + * Domain Path: Optional. Only useful if the translations are located in a + * folder above the plugin's base path. For example, if .mo files are + * located in the locale folder then Domain Path will be "/locale/" and + * must have the first slash. Defaults to the base folder the plugin is + * located in. + * Network: Optional. Specify "Network: true" to require that a plugin is activated + * across all sites in an installation. This will prevent a plugin from being + * activated on a single site when Multisite is enabled. + * * / # Remove the space to close comment + * + * + * Plugin data returned array contains the following: + * 'Name' - Name of the plugin, must be unique. + * 'Title' - Title of the plugin and the link to the plugin's web site. + * 'Description' - Description of what the plugin does and/or notes + * from the author. + * 'Author' - The author's name + * 'AuthorURI' - The authors web site address. + * 'Version' - The plugin version number. + * 'PluginURI' - Plugin web site address. + * 'TextDomain' - Plugin's text domain for localization. + * 'DomainPath' - Plugin's relative directory path to .mo files. + * 'Network' - Boolean. Whether the plugin can only be activated network wide. + * + * Some users have issues with opening large files and manipulating the contents + * for want is usually the first 1kiB or 2kiB. This function stops pulling in + * the plugin contents when it has all of the required plugin data. + * + * The first 8kiB of the file will be pulled in and if the plugin data is not + * within that first 8kiB, then the plugin author should correct their plugin + * and move the plugin data headers to the top. + * + * The plugin file is assumed to have permissions to allow for scripts to read + * the file. This is not checked however and the file is only opened for + * reading. + * + * @link http://trac.wordpress.org/ticket/5651 Previous Optimizations. + * @link http://trac.wordpress.org/ticket/7372 Further and better Optimizations. + * @since 1.5.0 + * + * @param string $plugin_file Path to the plugin file + * @param bool $markup Optional. If the returned data should have HTML markup applied. Defaults to true. + * @param bool $translate Optional. If the returned data should be translated. Defaults to true. + * @return array See above for description. + */ +function get_plugin_data( $plugin_file, $markup = true, $translate = true ) { + + $default_headers = array( + 'Name' => 'Plugin Name', + 'PluginURI' => 'Plugin URI', + 'Version' => 'Version', + 'Description' => 'Description', + 'Author' => 'Author', + 'AuthorURI' => 'Author URI', + 'TextDomain' => 'Text Domain', + 'DomainPath' => 'Domain Path', + 'Network' => 'Network', + // Site Wide Only is deprecated in favor of Network. + '_sitewide' => 'Site Wide Only', + ); + + $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' ); + + // Site Wide Only is the old header for Network + if ( ! $plugin_data['Network'] && $plugin_data['_sitewide'] ) { + _deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The %1$s plugin header is deprecated. Use %2$s instead.' ), 'Site Wide Only: true', 'Network: true' ) ); + $plugin_data['Network'] = $plugin_data['_sitewide']; + } + $plugin_data['Network'] = ( 'true' == strtolower( $plugin_data['Network'] ) ); + unset( $plugin_data['_sitewide'] ); + + if ( $markup || $translate ) { + $plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate ); + } else { + $plugin_data['Title'] = $plugin_data['Name']; + $plugin_data['AuthorName'] = $plugin_data['Author']; + } + + return $plugin_data; +} + +/** + * Sanitizes plugin data, optionally adds markup, optionally translates. + * + * @since 2.7.0 + * @access private + * @see get_plugin_data() + */ +function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) { + + // Sanitize the plugin filename to a WP_PLUGIN_DIR relative path + $plugin_file = plugin_basename( $plugin_file ); + + // Translate fields + if ( $translate ) { + if ( $textdomain = $plugin_data['TextDomain'] ) { + if ( $plugin_data['DomainPath'] ) + load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] ); + else + load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) ); + } elseif ( in_array( basename( $plugin_file ), array( 'hello.php', 'akismet.php' ) ) ) { + $textdomain = 'default'; + } + if ( $textdomain ) { + foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) + $plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain ); + } + } + + // Sanitize fields + $allowed_tags = $allowed_tags_in_links = array( + 'abbr' => array( 'title' => true ), + 'acronym' => array( 'title' => true ), + 'code' => true, + 'em' => true, + 'strong' => true, + ); + $allowed_tags['a'] = array( 'href' => true, 'title' => true ); + + // Name is marked up inside tags. Don't allow these. + // Author is too, but some plugins have used here (omitting Author URI). + $plugin_data['Name'] = wp_kses( $plugin_data['Name'], $allowed_tags_in_links ); + $plugin_data['Author'] = wp_kses( $plugin_data['Author'], $allowed_tags ); + + $plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags ); + $plugin_data['Version'] = wp_kses( $plugin_data['Version'], $allowed_tags ); + + $plugin_data['PluginURI'] = esc_url( $plugin_data['PluginURI'] ); + $plugin_data['AuthorURI'] = esc_url( $plugin_data['AuthorURI'] ); + + $plugin_data['Title'] = $plugin_data['Name']; + $plugin_data['AuthorName'] = $plugin_data['Author']; + + // Apply markup + if ( $markup ) { + if ( $plugin_data['PluginURI'] && $plugin_data['Name'] ) + $plugin_data['Title'] = '' . $plugin_data['Name'] . ''; + + if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] ) + $plugin_data['Author'] = '' . $plugin_data['Author'] . ''; + + $plugin_data['Description'] = wptexturize( $plugin_data['Description'] ); + + if ( $plugin_data['Author'] ) + $plugin_data['Description'] .= ' ' . sprintf( __('By %s.'), $plugin_data['Author'] ) . ''; + } + + return $plugin_data; +} + +/** + * Get a list of a plugin's files. + * + * @since 2.8.0 + * + * @param string $plugin Plugin ID + * @return array List of files relative to the plugin root. + */ +function get_plugin_files($plugin) { + $plugin_file = WP_PLUGIN_DIR . '/' . $plugin; + $dir = dirname($plugin_file); + $plugin_files = array($plugin); + if ( is_dir($dir) && $dir != WP_PLUGIN_DIR ) { + $plugins_dir = @ opendir( $dir ); + if ( $plugins_dir ) { + while (($file = readdir( $plugins_dir ) ) !== false ) { + if ( substr($file, 0, 1) == '.' ) + continue; + if ( is_dir( $dir . '/' . $file ) ) { + $plugins_subdir = @ opendir( $dir . '/' . $file ); + if ( $plugins_subdir ) { + while (($subfile = readdir( $plugins_subdir ) ) !== false ) { + if ( substr($subfile, 0, 1) == '.' ) + continue; + $plugin_files[] = plugin_basename("$dir/$file/$subfile"); + } + @closedir( $plugins_subdir ); + } + } else { + if ( plugin_basename("$dir/$file") != $plugin ) + $plugin_files[] = plugin_basename("$dir/$file"); + } + } + @closedir( $plugins_dir ); + } + } + + return $plugin_files; +} + +/** + * Check the plugins directory and retrieve all plugin files with plugin data. + * + * WordPress only supports plugin files in the base plugins directory + * (wp-content/plugins) and in one directory above the plugins directory + * (wp-content/plugins/my-plugin). The file it looks for has the plugin data and + * must be found in those two locations. It is recommended that do keep your + * plugin files in directories. + * + * The file with the plugin data is the file that will be included and therefore + * needs to have the main execution for the plugin. This does not mean + * everything must be contained in the file and it is recommended that the file + * be split for maintainability. Keep everything in one file for extreme + * optimization purposes. + * + * @since 1.5.0 + * + * @param string $plugin_folder Optional. Relative path to single plugin folder. + * @return array Key is the plugin file path and the value is an array of the plugin data. + */ +function get_plugins($plugin_folder = '') { + + if ( ! $cache_plugins = wp_cache_get('plugins', 'plugins') ) + $cache_plugins = array(); + + if ( isset($cache_plugins[ $plugin_folder ]) ) + return $cache_plugins[ $plugin_folder ]; + + $wp_plugins = array (); + $plugin_root = WP_PLUGIN_DIR; + if ( !empty($plugin_folder) ) + $plugin_root .= $plugin_folder; + + // Files in wp-content/plugins directory + $plugins_dir = @ opendir( $plugin_root); + $plugin_files = array(); + if ( $plugins_dir ) { + while (($file = readdir( $plugins_dir ) ) !== false ) { + if ( substr($file, 0, 1) == '.' ) + continue; + if ( is_dir( $plugin_root.'/'.$file ) ) { + $plugins_subdir = @ opendir( $plugin_root.'/'.$file ); + if ( $plugins_subdir ) { + while (($subfile = readdir( $plugins_subdir ) ) !== false ) { + if ( substr($subfile, 0, 1) == '.' ) + continue; + if ( substr($subfile, -4) == '.php' ) + $plugin_files[] = "$file/$subfile"; + } + closedir( $plugins_subdir ); + } + } else { + if ( substr($file, -4) == '.php' ) + $plugin_files[] = $file; + } + } + closedir( $plugins_dir ); + } + + if ( empty($plugin_files) ) + return $wp_plugins; + + foreach ( $plugin_files as $plugin_file ) { + if ( !is_readable( "$plugin_root/$plugin_file" ) ) + continue; + + $plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. + + if ( empty ( $plugin_data['Name'] ) ) + continue; + + $wp_plugins[plugin_basename( $plugin_file )] = $plugin_data; + } + + uasort( $wp_plugins, '_sort_uname_callback' ); + + $cache_plugins[ $plugin_folder ] = $wp_plugins; + wp_cache_set('plugins', $cache_plugins, 'plugins'); + + return $wp_plugins; +} + +/** + * Check the mu-plugins directory and retrieve all mu-plugin files with any plugin data. + * + * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins). + * + * @since 3.0.0 + * @return array Key is the mu-plugin file path and the value is an array of the mu-plugin data. + */ +function get_mu_plugins() { + $wp_plugins = array(); + // Files in wp-content/mu-plugins directory + $plugin_files = array(); + + if ( ! is_dir( WPMU_PLUGIN_DIR ) ) + return $wp_plugins; + if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) { + while ( ( $file = readdir( $plugins_dir ) ) !== false ) { + if ( substr( $file, -4 ) == '.php' ) + $plugin_files[] = $file; + } + } else { + return $wp_plugins; + } + + @closedir( $plugins_dir ); + + if ( empty($plugin_files) ) + return $wp_plugins; + + foreach ( $plugin_files as $plugin_file ) { + if ( !is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) ) + continue; + + $plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. + + if ( empty ( $plugin_data['Name'] ) ) + $plugin_data['Name'] = $plugin_file; + + $wp_plugins[ $plugin_file ] = $plugin_data; + } + + if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php') <= 30 ) // silence is golden + unset( $wp_plugins['index.php'] ); + + uasort( $wp_plugins, '_sort_uname_callback' ); + + return $wp_plugins; +} + +/** + * Callback to sort array by a 'Name' key. + * + * @since 3.1.0 + * @access private + */ +function _sort_uname_callback( $a, $b ) { + return strnatcasecmp( $a['Name'], $b['Name'] ); +} + +/** + * Check the wp-content directory and retrieve all drop-ins with any plugin data. + * + * @since 3.0.0 + * @return array Key is the file path and the value is an array of the plugin data. + */ +function get_dropins() { + $dropins = array(); + $plugin_files = array(); + + $_dropins = _get_dropins(); + + // These exist in the wp-content directory + if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) { + while ( ( $file = readdir( $plugins_dir ) ) !== false ) { + if ( isset( $_dropins[ $file ] ) ) + $plugin_files[] = $file; + } + } else { + return $dropins; + } + + @closedir( $plugins_dir ); + + if ( empty($plugin_files) ) + return $dropins; + + foreach ( $plugin_files as $plugin_file ) { + if ( !is_readable( WP_CONTENT_DIR . "/$plugin_file" ) ) + continue; + $plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. + if ( empty( $plugin_data['Name'] ) ) + $plugin_data['Name'] = $plugin_file; + $dropins[ $plugin_file ] = $plugin_data; + } + + uksort( $dropins, 'strnatcasecmp' ); + + return $dropins; +} + +/** + * Returns drop-ins that WordPress uses. + * + * Includes Multisite drop-ins only when is_multisite() + * + * @since 3.0.0 + * @return array Key is file name. The value is an array, with the first value the + * purpose of the drop-in and the second value the name of the constant that must be + * true for the drop-in to be used, or true if no constant is required. + */ +function _get_dropins() { + $dropins = array( + 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE + 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load + 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error + 'install.php' => array( __( 'Custom install script.' ), true ), // auto on install + 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance + 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load + ); + + if ( is_multisite() ) { + $dropins['sunrise.php' ] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE + $dropins['blog-deleted.php' ] = array( __( 'Custom site deleted message.' ), true ); // auto on deleted blog + $dropins['blog-inactive.php' ] = array( __( 'Custom site inactive message.' ), true ); // auto on inactive blog + $dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // auto on archived or spammed blog + } + + return $dropins; +} + +/** + * Check whether the plugin is active by checking the active_plugins list. + * + * @since 2.5.0 + * + * @param string $plugin Base plugin path from plugins directory. + * @return bool True, if in the active plugins list. False, not in the list. + */ +function is_plugin_active( $plugin ) { + return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin ); +} + +/** + * Check whether the plugin is inactive. + * + * Reverse of is_plugin_active(). Used as a callback. + * + * @since 3.1.0 + * @see is_plugin_active() + * + * @param string $plugin Base plugin path from plugins directory. + * @return bool True if inactive. False if active. + */ +function is_plugin_inactive( $plugin ) { + return ! is_plugin_active( $plugin ); +} + +/** + * Check whether the plugin is active for the entire network. + * + * @since 3.0.0 + * + * @param string $plugin Base plugin path from plugins directory. + * @return bool True, if active for the network, otherwise false. + */ +function is_plugin_active_for_network( $plugin ) { + if ( !is_multisite() ) + return false; + + $plugins = get_site_option( 'active_sitewide_plugins'); + if ( isset($plugins[$plugin]) ) + return true; + + return false; +} + +/** + * Checks for "Network: true" in the plugin header to see if this should + * be activated only as a network wide plugin. The plugin would also work + * when Multisite is not enabled. + * + * Checks for "Site Wide Only: true" for backwards compatibility. + * + * @since 3.0.0 + * + * @param string $plugin Plugin to check + * @return bool True if plugin is network only, false otherwise. + */ +function is_network_only_plugin( $plugin ) { + $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); + if ( $plugin_data ) + return $plugin_data['Network']; + return false; +} + +/** + * Attempts activation of plugin in a "sandbox" and redirects on success. + * + * A plugin that is already activated will not attempt to be activated again. + * + * The way it works is by setting the redirection to the error before trying to + * include the plugin file. If the plugin fails, then the redirection will not + * be overwritten with the success message. Also, the options will not be + * updated and the activation hook will not be called on plugin error. + * + * It should be noted that in no way the below code will actually prevent errors + * within the file. The code should not be used elsewhere to replicate the + * "sandbox", which uses redirection to work. + * {@source 13 1} + * + * If any errors are found or text is outputted, then it will be captured to + * ensure that the success redirection will update the error redirection. + * + * @since 2.5.0 + * + * @param string $plugin Plugin path to main plugin file with plugin data. + * @param string $redirect Optional. URL to redirect to. + * @param bool $network_wide Whether to enable the plugin for all sites in the + * network or just the current site. Multisite only. Default is false. + * @param bool $silent Prevent calling activation hooks. Optional, default is false. + * @return WP_Error|null WP_Error on invalid file or null on success. + */ +function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) { + $plugin = plugin_basename( trim( $plugin ) ); + + if ( is_multisite() && ( $network_wide || is_network_only_plugin($plugin) ) ) { + $network_wide = true; + $current = get_site_option( 'active_sitewide_plugins', array() ); + $_GET['networkwide'] = 1; // Back compat for plugins looking for this value. + } else { + $current = get_option( 'active_plugins', array() ); + } + + $valid = validate_plugin($plugin); + if ( is_wp_error($valid) ) + return $valid; + + if ( !in_array($plugin, $current) ) { + if ( !empty($redirect) ) + wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect)); // we'll override this later if the plugin can be included without fatal error + ob_start(); + include_once(WP_PLUGIN_DIR . '/' . $plugin); + + if ( ! $silent ) { + /** + * Fires before a plugin is activated in activate_plugin() when the $silent parameter is false. + * + * @since 2.9.0 + * + * @param string $plugin Plugin path to main plugin file with plugin data. + * @param bool $network_wide Whether to enable the plugin for all sites in the network + * or just the current site. Multisite only. Default is false. + */ + do_action( 'activate_plugin', $plugin, $network_wide ); + + /** + * Fires before a plugin is activated in activate_plugin() when the $silent parameter is false. + * + * The action concatenates the 'activate_' prefix with the $plugin value passed to + * activate_plugin() to create a dynamically-named action. + * + * @since 2.0.0 + * + * @param bool $network_wide Whether to enable the plugin for all sites in the network + * or just the current site. Multisite only. Default is false. + */ + do_action( 'activate_' . $plugin, $network_wide ); + } + + if ( $network_wide ) { + $current[$plugin] = time(); + update_site_option( 'active_sitewide_plugins', $current ); + } else { + $current[] = $plugin; + sort($current); + update_option('active_plugins', $current); + } + + if ( ! $silent ) { + /** + * Fires after a plugin has been activated in activate_plugin() when the $silent parameter is false. + * + * @since 2.9.0 + * + * @param string $plugin Plugin path to main plugin file with plugin data. + * @param bool $network_wide Whether to enable the plugin for all sites in the network + * or just the current site. Multisite only. Default is false. + */ + do_action( 'activated_plugin', $plugin, $network_wide ); + } + + if ( ob_get_length() > 0 ) { + $output = ob_get_clean(); + return new WP_Error('unexpected_output', __('The plugin generated unexpected output.'), $output); + } + ob_end_clean(); + } + + return null; +} + +/** + * Deactivate a single plugin or multiple plugins. + * + * The deactivation hook is disabled by the plugin upgrader by using the $silent + * parameter. + * + * @since 2.5.0 + * + * @param string|array $plugins Single plugin or list of plugins to deactivate. + * @param bool $silent Prevent calling deactivation hooks. Default is false. + * @param mixed $network_wide Whether to deactivate the plugin for all sites in the network. + * A value of null (the default) will deactivate plugins for both the site and the network. + */ +function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) { + if ( is_multisite() ) + $network_current = get_site_option( 'active_sitewide_plugins', array() ); + $current = get_option( 'active_plugins', array() ); + $do_blog = $do_network = false; + + foreach ( (array) $plugins as $plugin ) { + $plugin = plugin_basename( trim( $plugin ) ); + if ( ! is_plugin_active($plugin) ) + continue; + + $network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin ); + + if ( ! $silent ) + /** + * Fires for each plugin being deactivated in deactivate_plugins(), before deactivation + * and when the $silent parameter is false. + * + * @since 2.9.0 + * + * @param string $plugin Plugin path to main plugin file with plugin data. + * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network + * or just the current site. Multisite only. Default is false. + */ + do_action( 'deactivate_plugin', $plugin, $network_deactivating ); + + if ( false !== $network_wide ) { + if ( is_plugin_active_for_network( $plugin ) ) { + $do_network = true; + unset( $network_current[ $plugin ] ); + } elseif ( $network_wide ) { + continue; + } + } + + if ( true !== $network_wide ) { + $key = array_search( $plugin, $current ); + if ( false !== $key ) { + $do_blog = true; + unset( $current[ $key ] ); + } + } + + if ( ! $silent ) { + /** + * Fires for each plugin being deactivated in deactivate_plugins(), after deactivation + * and when the $silent parameter is false. + * + * The action concatenates the 'deactivate_' prefix with the plugin's basename + * to create a dynamically-named action. + * + * @since 2.0.0 + * + * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network + * or just the current site. Multisite only. Default is false. + */ + do_action( 'deactivate_' . $plugin, $network_deactivating ); + + /** + * Fires for each plugin being deactivated in deactivate_plugins(), after deactivation + * and when the $silent parameter is false. + * + * @since 2.9.0 + * + * @param string $plugin Plugin path to main plugin file with plugin data. + * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network + * or just the current site. Multisite only. Default is false. + */ + do_action( 'deactivated_plugin', $plugin, $network_deactivating ); + } + } + + if ( $do_blog ) + update_option('active_plugins', $current); + if ( $do_network ) + update_site_option( 'active_sitewide_plugins', $network_current ); +} + +/** + * Activate multiple plugins. + * + * When WP_Error is returned, it does not mean that one of the plugins had + * errors. It means that one or more of the plugins file path was invalid. + * + * The execution will be halted as soon as one of the plugins has an error. + * + * @since 2.6.0 + * + * @param string|array $plugins + * @param string $redirect Redirect to page after successful activation. + * @param bool $network_wide Whether to enable the plugin for all sites in the network. + * @param bool $silent Prevent calling activation hooks. Default is false. + * @return bool|WP_Error True when finished or WP_Error if there were errors during a plugin activation. + */ +function activate_plugins( $plugins, $redirect = '', $network_wide = false, $silent = false ) { + if ( !is_array($plugins) ) + $plugins = array($plugins); + + $errors = array(); + foreach ( $plugins as $plugin ) { + if ( !empty($redirect) ) + $redirect = add_query_arg('plugin', $plugin, $redirect); + $result = activate_plugin($plugin, $redirect, $network_wide, $silent); + if ( is_wp_error($result) ) + $errors[$plugin] = $result; + } + + if ( !empty($errors) ) + return new WP_Error('plugins_invalid', __('One of the plugins is invalid.'), $errors); + + return true; +} + +/** + * Remove directory and files of a plugin for a single or list of plugin(s). + * + * If the plugins parameter list is empty, false will be returned. True when + * completed. + * + * @since 2.6.0 + * + * @param array $plugins List of plugin + * @param string $redirect Redirect to page when complete. + * @return mixed + */ +function delete_plugins($plugins, $redirect = '' ) { + global $wp_filesystem; + + if ( empty($plugins) ) + return false; + + $checked = array(); + foreach( $plugins as $plugin ) + $checked[] = 'checked[]=' . $plugin; + + ob_start(); + $url = wp_nonce_url('plugins.php?action=delete-selected&verify-delete=1&' . implode('&', $checked), 'bulk-plugins'); + if ( false === ($credentials = request_filesystem_credentials($url)) ) { + $data = ob_get_contents(); + ob_end_clean(); + if ( ! empty($data) ){ + include_once( ABSPATH . 'wp-admin/admin-header.php'); + echo $data; + include( ABSPATH . 'wp-admin/admin-footer.php'); + exit; + } + return; + } + + if ( ! WP_Filesystem($credentials) ) { + request_filesystem_credentials($url, '', true); //Failed to connect, Error and request again + $data = ob_get_contents(); + ob_end_clean(); + if ( ! empty($data) ){ + include_once( ABSPATH . 'wp-admin/admin-header.php'); + echo $data; + include( ABSPATH . 'wp-admin/admin-footer.php'); + exit; + } + return; + } + + if ( ! is_object($wp_filesystem) ) + return new WP_Error('fs_unavailable', __('Could not access filesystem.')); + + if ( is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code() ) + return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); + + //Get the base plugin folder + $plugins_dir = $wp_filesystem->wp_plugins_dir(); + if ( empty($plugins_dir) ) + return new WP_Error('fs_no_plugins_dir', __('Unable to locate WordPress Plugin directory.')); + + $plugins_dir = trailingslashit( $plugins_dir ); + + $errors = array(); + + foreach( $plugins as $plugin_file ) { + // Run Uninstall hook + if ( is_uninstallable_plugin( $plugin_file ) ) + uninstall_plugin($plugin_file); + + $this_plugin_dir = trailingslashit( dirname($plugins_dir . $plugin_file) ); + // If plugin is in its own directory, recursively delete the directory. + if ( strpos($plugin_file, '/') && $this_plugin_dir != $plugins_dir ) //base check on if plugin includes directory separator AND that it's not the root plugin folder + $deleted = $wp_filesystem->delete($this_plugin_dir, true); + else + $deleted = $wp_filesystem->delete($plugins_dir . $plugin_file); + + if ( ! $deleted ) + $errors[] = $plugin_file; + } + + if ( ! empty($errors) ) + return new WP_Error('could_not_remove_plugin', sprintf(__('Could not fully remove the plugin(s) %s.'), implode(', ', $errors)) ); + + // Force refresh of plugin update information + if ( $current = get_site_transient('update_plugins') ) { + unset( $current->response[ $plugin_file ] ); + set_site_transient('update_plugins', $current); + } + + return true; +} + +/** + * Validate active plugins + * + * Validate all active plugins, deactivates invalid and + * returns an array of deactivated ones. + * + * @since 2.5.0 + * @return array invalid plugins, plugin as key, error as value + */ +function validate_active_plugins() { + $plugins = get_option( 'active_plugins', array() ); + // validate vartype: array + if ( ! is_array( $plugins ) ) { + update_option( 'active_plugins', array() ); + $plugins = array(); + } + + if ( is_multisite() && is_super_admin() ) { + $network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() ); + $plugins = array_merge( $plugins, array_keys( $network_plugins ) ); + } + + if ( empty( $plugins ) ) + return; + + $invalid = array(); + + // invalid plugins get deactivated + foreach ( $plugins as $plugin ) { + $result = validate_plugin( $plugin ); + if ( is_wp_error( $result ) ) { + $invalid[$plugin] = $result; + deactivate_plugins( $plugin, true ); + } + } + return $invalid; +} + +/** + * Validate the plugin path. + * + * Checks that the file exists and {@link validate_file() is valid file}. + * + * @since 2.5.0 + * + * @param string $plugin Plugin Path + * @return WP_Error|int 0 on success, WP_Error on failure. + */ +function validate_plugin($plugin) { + if ( validate_file($plugin) ) + return new WP_Error('plugin_invalid', __('Invalid plugin path.')); + if ( ! file_exists(WP_PLUGIN_DIR . '/' . $plugin) ) + return new WP_Error('plugin_not_found', __('Plugin file does not exist.')); + + $installed_plugins = get_plugins(); + if ( ! isset($installed_plugins[$plugin]) ) + return new WP_Error('no_plugin_header', __('The plugin does not have a valid header.')); + return 0; +} + +/** + * Whether the plugin can be uninstalled. + * + * @since 2.7.0 + * + * @param string $plugin Plugin path to check. + * @return bool Whether plugin can be uninstalled. + */ +function is_uninstallable_plugin($plugin) { + $file = plugin_basename($plugin); + + $uninstallable_plugins = (array) get_option('uninstall_plugins'); + if ( isset( $uninstallable_plugins[$file] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) + return true; + + return false; +} + +/** + * Uninstall a single plugin. + * + * Calls the uninstall hook, if it is available. + * + * @since 2.7.0 + * + * @param string $plugin Relative plugin path from Plugin Directory. + */ +function uninstall_plugin($plugin) { + $file = plugin_basename($plugin); + + $uninstallable_plugins = (array) get_option('uninstall_plugins'); + if ( file_exists( WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php' ) ) { + if ( isset( $uninstallable_plugins[$file] ) ) { + unset($uninstallable_plugins[$file]); + update_option('uninstall_plugins', $uninstallable_plugins); + } + unset($uninstallable_plugins); + + define('WP_UNINSTALL_PLUGIN', $file); + include WP_PLUGIN_DIR . '/' . dirname($file) . '/uninstall.php'; + + return true; + } + + if ( isset( $uninstallable_plugins[$file] ) ) { + $callable = $uninstallable_plugins[$file]; + unset($uninstallable_plugins[$file]); + update_option('uninstall_plugins', $uninstallable_plugins); + unset($uninstallable_plugins); + + include WP_PLUGIN_DIR . '/' . $file; + + add_action( 'uninstall_' . $file, $callable ); + + /** + * Fires in uninstall_plugin() once the plugin has been uninstalled. + * + * The action concatenates the 'uninstall_' prefix with the basename of the + * plugin passed to {@see uninstall_plugin()} to create a dynamically-named action. + * + * @since 2.7.0 + */ + do_action( 'uninstall_' . $file ); + } +} + +// +// Menu +// + +/** + * Add a top level menu page + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * @param string $icon_url The url to the icon to be used for this menu. Using 'none' would leave div.wp-menu-image empty + * so an icon can be added as background with CSS. + * @param int $position The position in the menu order this one should appear + * + * @return string The resulting page's hook_suffix + */ +function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) { + global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages; + + $menu_slug = plugin_basename( $menu_slug ); + + $admin_page_hooks[$menu_slug] = sanitize_title( $menu_title ); + + $hookname = get_plugin_page_hookname( $menu_slug, '' ); + + if ( !empty( $function ) && !empty( $hookname ) && current_user_can( $capability ) ) + add_action( $hookname, $function ); + + if ( empty($icon_url) ) { + $icon_url = 'none'; + $icon_class = 'menu-icon-generic '; + } else { + $icon_url = set_url_scheme( $icon_url ); + $icon_class = ''; + } + + $new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url ); + + if ( null === $position ) + $menu[] = $new_menu; + else + $menu[$position] = $new_menu; + + $_registered_pages[$hookname] = true; + + // No parent as top level + $_parent_pages[$menu_slug] = false; + + return $hookname; +} + +/** + * Add a top level menu page in the 'objects' section + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * @param string $icon_url The url to the icon to be used for this menu + * + * @return string The resulting page's hook_suffix + */ +function add_object_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') { + global $_wp_last_object_menu; + + $_wp_last_object_menu++; + + return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_object_menu); +} + +/** + * Add a top level menu page in the 'utility' section + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * @param string $icon_url The url to the icon to be used for this menu + * + * @return string The resulting page's hook_suffix + */ +function add_utility_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '') { + global $_wp_last_utility_menu; + + $_wp_last_utility_menu++; + + return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $_wp_last_utility_menu); +} + +/** + * Add a sub menu page + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page) + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + global $submenu; + global $menu; + global $_wp_real_parent_file; + global $_wp_submenu_nopriv; + global $_registered_pages; + global $_parent_pages; + + $menu_slug = plugin_basename( $menu_slug ); + $parent_slug = plugin_basename( $parent_slug); + + if ( isset( $_wp_real_parent_file[$parent_slug] ) ) + $parent_slug = $_wp_real_parent_file[$parent_slug]; + + if ( !current_user_can( $capability ) ) { + $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true; + return false; + } + + // If the parent doesn't already have a submenu, add a link to the parent + // as the first item in the submenu. If the submenu file is the same as the + // parent file someone is trying to link back to the parent manually. In + // this case, don't automatically add a link back to avoid duplication. + if (!isset( $submenu[$parent_slug] ) && $menu_slug != $parent_slug ) { + foreach ( (array)$menu as $parent_menu ) { + if ( $parent_menu[2] == $parent_slug && current_user_can( $parent_menu[1] ) ) + $submenu[$parent_slug][] = $parent_menu; + } + } + + $submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title ); + + $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug); + if (!empty ( $function ) && !empty ( $hookname )) + add_action( $hookname, $function ); + + $_registered_pages[$hookname] = true; + // backwards-compatibility for plugins using add_management page. See wp-admin/admin.php for redirect from edit.php to tools.php + if ( 'tools.php' == $parent_slug ) + $_registered_pages[get_plugin_page_hookname( $menu_slug, 'edit.php')] = true; + + // No parent as top level + $_parent_pages[$menu_slug] = $parent_slug; + + return $hookname; +} + +/** + * Add sub menu page to the tools main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the options main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the themes main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the plugins main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the Users/Profile main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + if ( current_user_can('edit_users') ) + $parent = 'users.php'; + else + $parent = 'profile.php'; + return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $function ); +} +/** + * Add sub menu page to the Dashboard main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the posts main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the media main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the links main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. + */ +function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the pages main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. +*/ +function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Add sub menu page to the comments main menu. + * + * This function takes a capability which will be used to determine whether + * or not a page is included in the menu. + * + * The function which is hooked in to handle the output of the page must check + * that the user has the required capability as well. + * + * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected + * @param string $menu_title The text to be used for the menu + * @param string $capability The capability required for this menu to be displayed to the user. + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param callback $function The function to be called to output the content for this page. + * + * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required. +*/ +function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { + return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $function ); +} + +/** + * Remove a top level admin menu + * + * @since 3.1.0 + * + * @param string $menu_slug The slug of the menu + * @return array|bool The removed menu on success, False if not found + */ +function remove_menu_page( $menu_slug ) { + global $menu; + + foreach ( $menu as $i => $item ) { + if ( $menu_slug == $item[2] ) { + unset( $menu[$i] ); + return $item; + } + } + + return false; +} + +/** + * Remove an admin submenu + * + * @since 3.1.0 + * + * @param string $menu_slug The slug for the parent menu + * @param string $submenu_slug The slug of the submenu + * @return array|bool The removed submenu on success, False if not found + */ +function remove_submenu_page( $menu_slug, $submenu_slug ) { + global $submenu; + + if ( !isset( $submenu[$menu_slug] ) ) + return false; + + foreach ( $submenu[$menu_slug] as $i => $item ) { + if ( $submenu_slug == $item[2] ) { + unset( $submenu[$menu_slug][$i] ); + return $item; + } + } + + return false; +} + +/** + * Get the url to access a particular menu page based on the slug it was registered with. + * + * If the slug hasn't been registered properly no url will be returned + * + * @since 3.0 + * + * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu) + * @param bool $echo Whether or not to echo the url - default is true + * @return string the url + */ +function menu_page_url($menu_slug, $echo = true) { + global $_parent_pages; + + if ( isset( $_parent_pages[$menu_slug] ) ) { + $parent_slug = $_parent_pages[$menu_slug]; + if ( $parent_slug && ! isset( $_parent_pages[$parent_slug] ) ) { + $url = admin_url( add_query_arg( 'page', $menu_slug, $parent_slug ) ); + } else { + $url = admin_url( 'admin.php?page=' . $menu_slug ); + } + } else { + $url = ''; + } + + $url = esc_url($url); + + if ( $echo ) + echo $url; + + return $url; +} + +// +// Pluggable Menu Support -- Private +// + +function get_admin_page_parent( $parent = '' ) { + global $parent_file; + global $menu; + global $submenu; + global $pagenow; + global $typenow; + global $plugin_page; + global $_wp_real_parent_file; + global $_wp_menu_nopriv; + global $_wp_submenu_nopriv; + + if ( !empty ( $parent ) && 'admin.php' != $parent ) { + if ( isset( $_wp_real_parent_file[$parent] ) ) + $parent = $_wp_real_parent_file[$parent]; + return $parent; + } + + /* + if ( !empty ( $parent_file ) ) { + if ( isset( $_wp_real_parent_file[$parent_file] ) ) + $parent_file = $_wp_real_parent_file[$parent_file]; + + return $parent_file; + } + */ + + if ( $pagenow == 'admin.php' && isset( $plugin_page ) ) { + foreach ( (array)$menu as $parent_menu ) { + if ( $parent_menu[2] == $plugin_page ) { + $parent_file = $plugin_page; + if ( isset( $_wp_real_parent_file[$parent_file] ) ) + $parent_file = $_wp_real_parent_file[$parent_file]; + return $parent_file; + } + } + if ( isset( $_wp_menu_nopriv[$plugin_page] ) ) { + $parent_file = $plugin_page; + if ( isset( $_wp_real_parent_file[$parent_file] ) ) + $parent_file = $_wp_real_parent_file[$parent_file]; + return $parent_file; + } + } + + if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$pagenow][$plugin_page] ) ) { + $parent_file = $pagenow; + if ( isset( $_wp_real_parent_file[$parent_file] ) ) + $parent_file = $_wp_real_parent_file[$parent_file]; + return $parent_file; + } + + foreach (array_keys( (array)$submenu ) as $parent) { + foreach ( $submenu[$parent] as $submenu_array ) { + if ( isset( $_wp_real_parent_file[$parent] ) ) + $parent = $_wp_real_parent_file[$parent]; + if ( !empty($typenow) && ($submenu_array[2] == "$pagenow?post_type=$typenow") ) { + $parent_file = $parent; + return $parent; + } elseif ( $submenu_array[2] == $pagenow && empty($typenow) && ( empty($parent_file) || false === strpos($parent_file, '?') ) ) { + $parent_file = $parent; + return $parent; + } else + if ( isset( $plugin_page ) && ($plugin_page == $submenu_array[2] ) ) { + $parent_file = $parent; + return $parent; + } + } + } + + if ( empty($parent_file) ) + $parent_file = ''; + return ''; +} + +function get_admin_page_title() { + global $title; + global $menu; + global $submenu; + global $pagenow; + global $plugin_page; + global $typenow; + + if ( ! empty ( $title ) ) + return $title; + + $hook = get_plugin_page_hook( $plugin_page, $pagenow ); + + $parent = $parent1 = get_admin_page_parent(); + + if ( empty ( $parent) ) { + foreach ( (array)$menu as $menu_array ) { + if ( isset( $menu_array[3] ) ) { + if ( $menu_array[2] == $pagenow ) { + $title = $menu_array[3]; + return $menu_array[3]; + } else + if ( isset( $plugin_page ) && ($plugin_page == $menu_array[2] ) && ($hook == $menu_array[3] ) ) { + $title = $menu_array[3]; + return $menu_array[3]; + } + } else { + $title = $menu_array[0]; + return $title; + } + } + } else { + foreach ( array_keys( $submenu ) as $parent ) { + foreach ( $submenu[$parent] as $submenu_array ) { + if ( isset( $plugin_page ) && + ( $plugin_page == $submenu_array[2] ) && + ( + ( $parent == $pagenow ) || + ( $parent == $plugin_page ) || + ( $plugin_page == $hook ) || + ( $pagenow == 'admin.php' && $parent1 != $submenu_array[2] ) || + ( !empty($typenow) && $parent == $pagenow . '?post_type=' . $typenow) + ) + ) { + $title = $submenu_array[3]; + return $submenu_array[3]; + } + + if ( $submenu_array[2] != $pagenow || isset( $_GET['page'] ) ) // not the current page + continue; + + if ( isset( $submenu_array[3] ) ) { + $title = $submenu_array[3]; + return $submenu_array[3]; + } else { + $title = $submenu_array[0]; + return $title; + } + } + } + if ( empty ( $title ) ) { + foreach ( $menu as $menu_array ) { + if ( isset( $plugin_page ) && + ( $plugin_page == $menu_array[2] ) && + ( $pagenow == 'admin.php' ) && + ( $parent1 == $menu_array[2] ) ) + { + $title = $menu_array[3]; + return $menu_array[3]; + } + } + } + } + + return $title; +} + +function get_plugin_page_hook( $plugin_page, $parent_page ) { + $hook = get_plugin_page_hookname( $plugin_page, $parent_page ); + if ( has_action($hook) ) + return $hook; + else + return null; +} + +function get_plugin_page_hookname( $plugin_page, $parent_page ) { + global $admin_page_hooks; + + $parent = get_admin_page_parent( $parent_page ); + + $page_type = 'admin'; + if ( empty ( $parent_page ) || 'admin.php' == $parent_page || isset( $admin_page_hooks[$plugin_page] ) ) { + if ( isset( $admin_page_hooks[$plugin_page] ) ) + $page_type = 'toplevel'; + else + if ( isset( $admin_page_hooks[$parent] )) + $page_type = $admin_page_hooks[$parent]; + } else if ( isset( $admin_page_hooks[$parent] ) ) { + $page_type = $admin_page_hooks[$parent]; + } + + $plugin_name = preg_replace( '!\.php!', '', $plugin_page ); + + return $page_type . '_page_' . $plugin_name; +} + +function user_can_access_admin_page() { + global $pagenow; + global $menu; + global $submenu; + global $_wp_menu_nopriv; + global $_wp_submenu_nopriv; + global $plugin_page; + global $_registered_pages; + + $parent = get_admin_page_parent(); + + if ( !isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$parent][$pagenow] ) ) + return false; + + if ( isset( $plugin_page ) ) { + if ( isset( $_wp_submenu_nopriv[$parent][$plugin_page] ) ) + return false; + + $hookname = get_plugin_page_hookname($plugin_page, $parent); + + if ( !isset($_registered_pages[$hookname]) ) + return false; + } + + if ( empty( $parent) ) { + if ( isset( $_wp_menu_nopriv[$pagenow] ) ) + return false; + if ( isset( $_wp_submenu_nopriv[$pagenow][$pagenow] ) ) + return false; + if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$pagenow][$plugin_page] ) ) + return false; + if ( isset( $plugin_page ) && isset( $_wp_menu_nopriv[$plugin_page] ) ) + return false; + foreach (array_keys( $_wp_submenu_nopriv ) as $key ) { + if ( isset( $_wp_submenu_nopriv[$key][$pagenow] ) ) + return false; + if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[$key][$plugin_page] ) ) + return false; + } + return true; + } + + if ( isset( $plugin_page ) && ( $plugin_page == $parent ) && isset( $_wp_menu_nopriv[$plugin_page] ) ) + return false; + + if ( isset( $submenu[$parent] ) ) { + foreach ( $submenu[$parent] as $submenu_array ) { + if ( isset( $plugin_page ) && ( $submenu_array[2] == $plugin_page ) ) { + if ( current_user_can( $submenu_array[1] )) + return true; + else + return false; + } else if ( $submenu_array[2] == $pagenow ) { + if ( current_user_can( $submenu_array[1] )) + return true; + else + return false; + } + } + } + + foreach ( $menu as $menu_array ) { + if ( $menu_array[2] == $parent) { + if ( current_user_can( $menu_array[1] )) + return true; + else + return false; + } + } + + return true; +} + +/* Whitelist functions */ + +/** + * Register a setting and its sanitization callback + * + * @since 2.7.0 + * + * @param string $option_group A settings group name. Should correspond to a whitelisted option key name. + * Default whitelisted option key names include "general," "discussion," and "reading," among others. + * @param string $option_name The name of an option to sanitize and save. + * @param unknown_type $sanitize_callback A callback function that sanitizes the option's value. + * @return unknown + */ +function register_setting( $option_group, $option_name, $sanitize_callback = '' ) { + global $new_whitelist_options; + + if ( 'misc' == $option_group ) { + _deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'misc' ) ); + $option_group = 'general'; + } + + if ( 'privacy' == $option_group ) { + _deprecated_argument( __FUNCTION__, '3.5', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'privacy' ) ); + $option_group = 'reading'; + } + + $new_whitelist_options[ $option_group ][] = $option_name; + if ( $sanitize_callback != '' ) + add_filter( "sanitize_option_{$option_name}", $sanitize_callback ); +} + +/** + * Unregister a setting + * + * @since 2.7.0 + * + * @param unknown_type $option_group + * @param unknown_type $option_name + * @param unknown_type $sanitize_callback + * @return unknown + */ +function unregister_setting( $option_group, $option_name, $sanitize_callback = '' ) { + global $new_whitelist_options; + + if ( 'misc' == $option_group ) { + _deprecated_argument( __FUNCTION__, '3.0', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'misc' ) ); + $option_group = 'general'; + } + + if ( 'privacy' == $option_group ) { + _deprecated_argument( __FUNCTION__, '3.5', sprintf( __( 'The "%s" options group has been removed. Use another settings group.' ), 'privacy' ) ); + $option_group = 'reading'; + } + + $pos = array_search( $option_name, (array) $new_whitelist_options ); + if ( $pos !== false ) + unset( $new_whitelist_options[ $option_group ][ $pos ] ); + if ( $sanitize_callback != '' ) + remove_filter( "sanitize_option_{$option_name}", $sanitize_callback ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.7.0 + * + * @param unknown_type $options + * @return unknown + */ +function option_update_filter( $options ) { + global $new_whitelist_options; + + if ( is_array( $new_whitelist_options ) ) + $options = add_option_whitelist( $new_whitelist_options, $options ); + + return $options; +} +add_filter( 'whitelist_options', 'option_update_filter' ); + +/** + * {@internal Missing Short Description}} + * + * @since 2.7.0 + * + * @param unknown_type $new_options + * @param unknown_type $options + * @return unknown + */ +function add_option_whitelist( $new_options, $options = '' ) { + if ( $options == '' ) + global $whitelist_options; + else + $whitelist_options = $options; + + foreach ( $new_options as $page => $keys ) { + foreach ( $keys as $key ) { + if ( !isset($whitelist_options[ $page ]) || !is_array($whitelist_options[ $page ]) ) { + $whitelist_options[ $page ] = array(); + $whitelist_options[ $page ][] = $key; + } else { + $pos = array_search( $key, $whitelist_options[ $page ] ); + if ( $pos === false ) + $whitelist_options[ $page ][] = $key; + } + } + } + + return $whitelist_options; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.7.0 + * + * @param unknown_type $del_options + * @param unknown_type $options + * @return unknown + */ +function remove_option_whitelist( $del_options, $options = '' ) { + if ( $options == '' ) + global $whitelist_options; + else + $whitelist_options = $options; + + foreach ( $del_options as $page => $keys ) { + foreach ( $keys as $key ) { + if ( isset($whitelist_options[ $page ]) && is_array($whitelist_options[ $page ]) ) { + $pos = array_search( $key, $whitelist_options[ $page ] ); + if ( $pos !== false ) + unset( $whitelist_options[ $page ][ $pos ] ); + } + } + } + + return $whitelist_options; +} + +/** + * Output nonce, action, and option_page fields for a settings page. + * + * @since 2.7.0 + * + * @param string $option_group A settings group name. This should match the group name used in register_setting(). + */ +function settings_fields($option_group) { + echo ""; + echo ''; + wp_nonce_field("$option_group-options"); +} + +/** + * Clears the Plugins cache used by get_plugins() and by default, the Plugin Update cache. + * + * @since 3.7.0 + * + * @param bool $clear_update_cache Whether to clear the Plugin updates cache + */ +function wp_clean_plugins_cache( $clear_update_cache = true ) { + if ( $clear_update_cache ) + delete_site_transient( 'update_plugins' ); + wp_cache_delete( 'plugins', 'plugins' ); +} diff --git a/sources/wp-admin/includes/post.php b/sources/wp-admin/includes/post.php new file mode 100644 index 0000000..7d074dd --- /dev/null +++ b/sources/wp-admin/includes/post.php @@ -0,0 +1,1452 @@ +cap->create_posts ) ) { + if ( 'page' == $post_data['post_type'] ) + return new WP_Error( 'edit_others_pages', __( 'You are not allowed to create pages as this user.' ) ); + else + return new WP_Error( 'edit_others_posts', __( 'You are not allowed to create posts as this user.' ) ); + } + + if ( isset( $post_data['content'] ) ) + $post_data['post_content'] = $post_data['content']; + + if ( isset( $post_data['excerpt'] ) ) + $post_data['post_excerpt'] = $post_data['excerpt']; + + if ( isset( $post_data['parent_id'] ) ) + $post_data['post_parent'] = (int) $post_data['parent_id']; + + if ( isset($post_data['trackback_url']) ) + $post_data['to_ping'] = $post_data['trackback_url']; + + $post_data['user_ID'] = get_current_user_id(); + + if (!empty ( $post_data['post_author_override'] ) ) { + $post_data['post_author'] = (int) $post_data['post_author_override']; + } else { + if (!empty ( $post_data['post_author'] ) ) { + $post_data['post_author'] = (int) $post_data['post_author']; + } else { + $post_data['post_author'] = (int) $post_data['user_ID']; + } + } + + if ( isset( $post_data['user_ID'] ) && ( $post_data['post_author'] != $post_data['user_ID'] ) + && ! current_user_can( $ptype->cap->edit_others_posts ) ) { + if ( $update ) { + if ( 'page' == $post_data['post_type'] ) + return new WP_Error( 'edit_others_pages', __( 'You are not allowed to edit pages as this user.' ) ); + else + return new WP_Error( 'edit_others_posts', __( 'You are not allowed to edit posts as this user.' ) ); + } else { + if ( 'page' == $post_data['post_type'] ) + return new WP_Error( 'edit_others_pages', __( 'You are not allowed to create pages as this user.' ) ); + else + return new WP_Error( 'edit_others_posts', __( 'You are not allowed to create posts as this user.' ) ); + } + } + + if ( ! empty( $post_data['post_status'] ) ) + $post_data['post_status'] = sanitize_key( $post_data['post_status'] ); + + // What to do based on which button they pressed + if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] ) + $post_data['post_status'] = 'draft'; + if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] ) + $post_data['post_status'] = 'private'; + if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( !isset($post_data['post_status']) || $post_data['post_status'] != 'private' ) ) + $post_data['post_status'] = 'publish'; + if ( isset($post_data['advanced']) && '' != $post_data['advanced'] ) + $post_data['post_status'] = 'draft'; + if ( isset($post_data['pending']) && '' != $post_data['pending'] ) + $post_data['post_status'] = 'pending'; + + if ( isset( $post_data['ID'] ) ) + $post_id = $post_data['ID']; + else + $post_id = false; + $previous_status = $post_id ? get_post_field( 'post_status', $post_id ) : false; + + $published_statuses = array( 'publish', 'future' ); + + // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published. + // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts. + if ( isset($post_data['post_status']) && (in_array( $post_data['post_status'], $published_statuses ) && !current_user_can( $ptype->cap->publish_posts )) ) + if ( ! in_array( $previous_status, $published_statuses ) || !current_user_can( 'edit_post', $post_id ) ) + $post_data['post_status'] = 'pending'; + + if ( ! isset($post_data['post_status']) ) + $post_data['post_status'] = $previous_status; + + if (!isset( $post_data['comment_status'] )) + $post_data['comment_status'] = 'closed'; + + if (!isset( $post_data['ping_status'] )) + $post_data['ping_status'] = 'closed'; + + foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) { + if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) { + $post_data['edit_date'] = '1'; + break; + } + } + + if ( !empty( $post_data['edit_date'] ) ) { + $aa = $post_data['aa']; + $mm = $post_data['mm']; + $jj = $post_data['jj']; + $hh = $post_data['hh']; + $mn = $post_data['mn']; + $ss = $post_data['ss']; + $aa = ($aa <= 0 ) ? date('Y') : $aa; + $mm = ($mm <= 0 ) ? date('n') : $mm; + $jj = ($jj > 31 ) ? 31 : $jj; + $jj = ($jj <= 0 ) ? date('j') : $jj; + $hh = ($hh > 23 ) ? $hh -24 : $hh; + $mn = ($mn > 59 ) ? $mn -60 : $mn; + $ss = ($ss > 59 ) ? $ss -60 : $ss; + $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss ); + $valid_date = wp_checkdate( $mm, $jj, $aa, $post_data['post_date'] ); + if ( !$valid_date ) { + return new WP_Error( 'invalid_date', __( 'Whoops, the provided date is invalid.' ) ); + } + $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] ); + } + + return $post_data; +} + +/** + * Update an existing post with values provided in $_POST. + * + * @since 1.5.0 + * + * @param array $post_data Optional. + * @return int Post ID. + */ +function edit_post( $post_data = null ) { + + if ( empty($post_data) ) + $post_data = &$_POST; + + // Clear out any data in internal vars. + unset( $post_data['filter'] ); + + $post_ID = (int) $post_data['post_ID']; + $post = get_post( $post_ID ); + $post_data['post_type'] = $post->post_type; + $post_data['post_mime_type'] = $post->post_mime_type; + + $ptype = get_post_type_object($post_data['post_type']); + if ( !current_user_can( 'edit_post', $post_ID ) ) { + if ( 'page' == $post_data['post_type'] ) + wp_die( __('You are not allowed to edit this page.' )); + else + wp_die( __('You are not allowed to edit this post.' )); + } + + if ( post_type_supports( $ptype->name, 'revisions' ) ) { + $revisions = wp_get_post_revisions( $post_ID, array( 'order' => 'ASC', 'posts_per_page' => 1 ) ); + $revision = current( $revisions ); + + // Check if the revisions have been upgraded + if ( $revisions && _wp_get_post_revision_version( $revision ) < 1 ) + _wp_upgrade_revisions_of_post( $post, wp_get_post_revisions( $post_ID ) ); + } + + $post_data = _wp_translate_postdata( true, $post_data ); + if ( is_wp_error($post_data) ) + wp_die( $post_data->get_error_message() ); + if ( ( empty( $post_data['action'] ) || 'autosave' != $post_data['action'] ) && 'auto-draft' == $post_data['post_status'] ) { + $post_data['post_status'] = 'draft'; + } + + if ( isset($post_data['visibility']) ) { + switch ( $post_data['visibility'] ) { + case 'public' : + $post_data['post_password'] = ''; + break; + case 'password' : + unset( $post_data['sticky'] ); + break; + case 'private' : + $post_data['post_status'] = 'private'; + $post_data['post_password'] = ''; + unset( $post_data['sticky'] ); + break; + } + } + + // Post Formats + if ( isset( $post_data['post_format'] ) ) + set_post_format( $post_ID, $post_data['post_format'] ); + + $format_meta_urls = array( 'url', 'link_url', 'quote_source_url' ); + foreach ( $format_meta_urls as $format_meta_url ) { + $keyed = '_format_' . $format_meta_url; + if ( isset( $post_data[ $keyed ] ) ) + update_post_meta( $post_ID, $keyed, wp_slash( esc_url_raw( wp_unslash( $post_data[ $keyed ] ) ) ) ); + } + + $format_keys = array( 'quote', 'quote_source_name', 'image', 'gallery', 'audio_embed', 'video_embed' ); + + foreach ( $format_keys as $key ) { + $keyed = '_format_' . $key; + if ( isset( $post_data[ $keyed ] ) ) { + if ( current_user_can( 'unfiltered_html' ) ) + update_post_meta( $post_ID, $keyed, $post_data[ $keyed ] ); + else + update_post_meta( $post_ID, $keyed, wp_filter_post_kses( $post_data[ $keyed ] ) ); + } + } + + // Meta Stuff + if ( isset($post_data['meta']) && $post_data['meta'] ) { + foreach ( $post_data['meta'] as $key => $value ) { + if ( !$meta = get_post_meta_by_id( $key ) ) + continue; + if ( $meta->post_id != $post_ID ) + continue; + if ( is_protected_meta( $value['key'], 'post' ) || ! current_user_can( 'edit_post_meta', $post_ID, $value['key'] ) ) + continue; + update_meta( $key, $value['key'], $value['value'] ); + } + } + + if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) { + foreach ( $post_data['deletemeta'] as $key => $value ) { + if ( !$meta = get_post_meta_by_id( $key ) ) + continue; + if ( $meta->post_id != $post_ID ) + continue; + if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $post_ID, $meta->meta_key ) ) + continue; + delete_meta( $key ); + } + } + + // Attachment stuff + if ( 'attachment' == $post_data['post_type'] ) { + if ( isset( $post_data[ '_wp_attachment_image_alt' ] ) ) { + $image_alt = wp_unslash( $post_data['_wp_attachment_image_alt'] ); + if ( $image_alt != get_post_meta( $post_ID, '_wp_attachment_image_alt', true ) ) { + $image_alt = wp_strip_all_tags( $image_alt, true ); + // update_meta expects slashed + update_post_meta( $post_ID, '_wp_attachment_image_alt', wp_slash( $image_alt ) ); + } + } + + $attachment_data = isset( $post_data['attachments'][ $post_ID ] ) ? $post_data['attachments'][ $post_ID ] : array(); + /** This filter is documented in wp-admin/includes/media.php */ + $post_data = apply_filters( 'attachment_fields_to_save', $post_data, $attachment_data ); + } + + add_meta( $post_ID ); + + update_post_meta( $post_ID, '_edit_last', get_current_user_id() ); + + wp_update_post( $post_data ); + + // Now that we have an ID we can fix any attachment anchor hrefs + _fix_attachment_links( $post_ID ); + + wp_set_post_lock( $post_ID ); + + if ( current_user_can( $ptype->cap->edit_others_posts ) ) { + if ( ! empty( $post_data['sticky'] ) ) + stick_post( $post_ID ); + else + unstick_post( $post_ID ); + } + + return $post_ID; +} + +/** + * Process the post data for the bulk editing of posts. + * + * Updates all bulk edited posts/pages, adding (but not removing) tags and + * categories. Skips pages when they would be their own parent or child. + * + * @since 2.7.0 + * + * @param array $post_data Optional, the array of post data to process if not provided will use $_POST superglobal. + * @return array + */ +function bulk_edit_posts( $post_data = null ) { + global $wpdb; + + if ( empty($post_data) ) + $post_data = &$_POST; + + if ( isset($post_data['post_type']) ) + $ptype = get_post_type_object($post_data['post_type']); + else + $ptype = get_post_type_object('post'); + + if ( !current_user_can( $ptype->cap->edit_posts ) ) { + if ( 'page' == $ptype->name ) + wp_die( __('You are not allowed to edit pages.')); + else + wp_die( __('You are not allowed to edit posts.')); + } + + if ( -1 == $post_data['_status'] ) { + $post_data['post_status'] = null; + unset($post_data['post_status']); + } else { + $post_data['post_status'] = $post_data['_status']; + } + unset($post_data['_status']); + + $post_IDs = array_map( 'intval', (array) $post_data['post'] ); + + $reset = array( + 'post_author', 'post_status', 'post_password', + 'post_parent', 'page_template', 'comment_status', + 'ping_status', 'keep_private', 'tax_input', + 'post_category', 'sticky', 'post_format', + ); + + foreach ( $reset as $field ) { + if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) ) + unset($post_data[$field]); + } + + if ( isset($post_data['post_category']) ) { + if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) ) + $new_cats = array_map( 'absint', $post_data['post_category'] ); + else + unset($post_data['post_category']); + } + + $tax_input = array(); + if ( isset($post_data['tax_input'])) { + foreach ( $post_data['tax_input'] as $tax_name => $terms ) { + if ( empty($terms) ) + continue; + if ( is_taxonomy_hierarchical( $tax_name ) ) { + $tax_input[ $tax_name ] = array_map( 'absint', $terms ); + } else { + $comma = _x( ',', 'tag delimiter' ); + if ( ',' !== $comma ) + $terms = str_replace( $comma, ',', $terms ); + $tax_input[ $tax_name ] = explode( ',', trim( $terms, " \n\t\r\0\x0B," ) ); + } + } + } + + if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) { + $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'"); + $children = array(); + + for ( $i = 0; $i < 50 && $parent > 0; $i++ ) { + $children[] = $parent; + + foreach ( $pages as $page ) { + if ( $page->ID == $parent ) { + $parent = $page->post_parent; + break; + } + } + } + } + + $updated = $skipped = $locked = array(); + foreach ( $post_IDs as $post_ID ) { + $post_type_object = get_post_type_object( get_post_type( $post_ID ) ); + + if ( !isset( $post_type_object ) || ( isset($children) && in_array($post_ID, $children) ) || !current_user_can( 'edit_post', $post_ID ) ) { + $skipped[] = $post_ID; + continue; + } + + if ( wp_check_post_lock( $post_ID ) ) { + $locked[] = $post_ID; + continue; + } + + $post = get_post( $post_ID ); + $tax_names = get_object_taxonomies( $post ); + foreach ( $tax_names as $tax_name ) { + $taxonomy_obj = get_taxonomy($tax_name); + if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) + $new_terms = $tax_input[$tax_name]; + else + $new_terms = array(); + + if ( $taxonomy_obj->hierarchical ) + $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'ids') ); + else + $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'names') ); + + $post_data['tax_input'][$tax_name] = array_merge( $current_terms, $new_terms ); + } + + if ( isset($new_cats) && in_array( 'category', $tax_names ) ) { + $cats = (array) wp_get_post_categories($post_ID); + $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) ); + unset( $post_data['tax_input']['category'] ); + } + + $post_data['post_mime_type'] = $post->post_mime_type; + $post_data['guid'] = $post->guid; + + $post_data['ID'] = $post_ID; + $updated[] = wp_update_post( $post_data ); + + if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) { + if ( 'sticky' == $post_data['sticky'] ) + stick_post( $post_ID ); + else + unstick_post( $post_ID ); + } + + if ( isset( $post_data['post_format'] ) ) + set_post_format( $post_ID, $post_data['post_format'] ); + } + + return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked ); +} + +/** + * Default post information to use when populating the "Write Post" form. + * + * @since 2.0.0 + * + * @param string $post_type A post type string, defaults to 'post'. + * @return WP_Post Post object containing all the default post data as attributes + */ +function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) { + global $wpdb; + + $post_title = ''; + if ( !empty( $_REQUEST['post_title'] ) ) + $post_title = esc_html( wp_unslash( $_REQUEST['post_title'] )); + + $post_content = ''; + if ( !empty( $_REQUEST['content'] ) ) + $post_content = esc_html( wp_unslash( $_REQUEST['content'] )); + + $post_excerpt = ''; + if ( !empty( $_REQUEST['excerpt'] ) ) + $post_excerpt = esc_html( wp_unslash( $_REQUEST['excerpt'] )); + + if ( $create_in_db ) { + $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) ); + $post = get_post( $post_id ); + if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) ) + set_post_format( $post, get_option( 'default_post_format' ) ); + } else { + $post = new stdClass; + $post->ID = 0; + $post->post_author = ''; + $post->post_date = ''; + $post->post_date_gmt = ''; + $post->post_password = ''; + $post->post_type = $post_type; + $post->post_status = 'draft'; + $post->to_ping = ''; + $post->pinged = ''; + $post->comment_status = get_option( 'default_comment_status' ); + $post->ping_status = get_option( 'default_ping_status' ); + $post->post_pingback = get_option( 'default_pingback_flag' ); + $post->post_category = get_option( 'default_category' ); + $post->page_template = 'default'; + $post->post_parent = 0; + $post->menu_order = 0; + $post = new WP_Post( $post ); + } + + $post->post_content = apply_filters( 'default_content', $post_content, $post ); + $post->post_title = apply_filters( 'default_title', $post_title, $post ); + $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post ); + $post->post_name = ''; + + return $post; +} + +/** + * Determine if a post exists based on title, content, and date + * + * @since 2.0.0 + * + * @param string $title Post title + * @param string $content Optional post content + * @param string $date Optional post date + * @return int Post ID if post exists, 0 otherwise. + */ +function post_exists($title, $content = '', $date = '') { + global $wpdb; + + $post_title = wp_unslash( sanitize_post_field( 'post_title', $title, 0, 'db' ) ); + $post_content = wp_unslash( sanitize_post_field( 'post_content', $content, 0, 'db' ) ); + $post_date = wp_unslash( sanitize_post_field( 'post_date', $date, 0, 'db' ) ); + + $query = "SELECT ID FROM $wpdb->posts WHERE 1=1"; + $args = array(); + + if ( !empty ( $date ) ) { + $query .= ' AND post_date = %s'; + $args[] = $post_date; + } + + if ( !empty ( $title ) ) { + $query .= ' AND post_title = %s'; + $args[] = $post_title; + } + + if ( !empty ( $content ) ) { + $query .= 'AND post_content = %s'; + $args[] = $post_content; + } + + if ( !empty ( $args ) ) + return (int) $wpdb->get_var( $wpdb->prepare($query, $args) ); + + return 0; +} + +/** + * Creates a new post from the "Write Post" form using $_POST information. + * + * @since 2.1.0 + * + * @return unknown + */ +function wp_write_post() { + if ( isset($_POST['post_type']) ) + $ptype = get_post_type_object($_POST['post_type']); + else + $ptype = get_post_type_object('post'); + + if ( !current_user_can( $ptype->cap->edit_posts ) ) { + if ( 'page' == $ptype->name ) + return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this site.' ) ); + else + return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this site.' ) ); + } + + $_POST['post_mime_type'] = ''; + + // Clear out any data in internal vars. + unset( $_POST['filter'] ); + + // Edit don't write if we have a post id. + if ( isset( $_POST['post_ID'] ) ) + return edit_post(); + + $translated = _wp_translate_postdata( false ); + if ( is_wp_error($translated) ) + return $translated; + + if ( isset($_POST['visibility']) ) { + switch ( $_POST['visibility'] ) { + case 'public' : + $_POST['post_password'] = ''; + break; + case 'password' : + unset( $_POST['sticky'] ); + break; + case 'private' : + $_POST['post_status'] = 'private'; + $_POST['post_password'] = ''; + unset( $_POST['sticky'] ); + break; + } + } + + // Create the post. + $post_ID = wp_insert_post( $_POST ); + if ( is_wp_error( $post_ID ) ) + return $post_ID; + + if ( empty($post_ID) ) + return 0; + + add_meta( $post_ID ); + + add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID ); + + // Now that we have an ID we can fix any attachment anchor hrefs + _fix_attachment_links( $post_ID ); + + wp_set_post_lock( $post_ID ); + + return $post_ID; +} + +/** + * Calls wp_write_post() and handles the errors. + * + * @since 2.0.0 + + * @uses wp_write_post() + * @uses is_wp_error() + * @uses wp_die() + * @return unknown + */ +function write_post() { + $result = wp_write_post(); + if ( is_wp_error( $result ) ) + wp_die( $result->get_error_message() ); + else + return $result; +} + +// +// Post Meta +// + +/** + * {@internal Missing Short Description}} + * + * @since 1.2.0 + * + * @param unknown_type $post_ID + * @return unknown + */ +function add_meta( $post_ID ) { + global $wpdb; + $post_ID = (int) $post_ID; + + $metakeyselect = isset($_POST['metakeyselect']) ? wp_unslash( trim( $_POST['metakeyselect'] ) ) : ''; + $metakeyinput = isset($_POST['metakeyinput']) ? wp_unslash( trim( $_POST['metakeyinput'] ) ) : ''; + $metavalue = isset($_POST['metavalue']) ? $_POST['metavalue'] : ''; + if ( is_string( $metavalue ) ) + $metavalue = trim( $metavalue ); + + if ( ('0' === $metavalue || ! empty ( $metavalue ) ) && ( ( ( '#NONE#' != $metakeyselect ) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput ) ) ) { + // We have a key/value pair. If both the select and the + // input for the key have data, the input takes precedence: + + if ( '#NONE#' != $metakeyselect ) + $metakey = $metakeyselect; + + if ( $metakeyinput ) + $metakey = $metakeyinput; // default + + if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_ID, $metakey ) ) + return false; + + $metakey = wp_slash( $metakey ); + + return add_post_meta( $post_ID, $metakey, $metavalue ); + } + + return false; +} // add_meta + +/** + * {@internal Missing Short Description}} + * + * @since 1.2.0 + * + * @param unknown_type $mid + * @return unknown + */ +function delete_meta( $mid ) { + return delete_metadata_by_mid( 'post' , $mid ); +} + +/** + * Get a list of previously defined keys. + * + * @since 1.2.0 + * + * @return unknown + */ +function get_meta_keys() { + global $wpdb; + + $keys = $wpdb->get_col( " + SELECT meta_key + FROM $wpdb->postmeta + GROUP BY meta_key + ORDER BY meta_key" ); + + return $keys; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.1.0 + * + * @param unknown_type $mid + * @return unknown + */ +function get_post_meta_by_id( $mid ) { + return get_metadata_by_mid( 'post', $mid ); +} + +/** + * {@internal Missing Short Description}} + * + * Some postmeta stuff. + * + * @since 1.2.0 + * + * @param unknown_type $postid + * @return unknown + */ +function has_meta( $postid ) { + global $wpdb; + + return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id + FROM $wpdb->postmeta WHERE post_id = %d + ORDER BY meta_key,meta_id", $postid), ARRAY_A ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 1.2.0 + * + * @param unknown_type $meta_id + * @param unknown_type $meta_key Expect Slashed + * @param unknown_type $meta_value Expect Slashed + * @return unknown + */ +function update_meta( $meta_id, $meta_key, $meta_value ) { + $meta_key = wp_unslash( $meta_key ); + $meta_value = wp_unslash( $meta_value ); + + return update_metadata_by_mid( 'post', $meta_id, $meta_value, $meta_key ); +} + +// +// Private +// + +/** + * Replace hrefs of attachment anchors with up-to-date permalinks. + * + * @since 2.3.0 + * @access private + * + * @param int|object $post Post ID or post object. + * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success. + */ +function _fix_attachment_links( $post ) { + $post = get_post( $post, ARRAY_A ); + $content = $post['post_content']; + + // Don't run if no pretty permalinks or post is not published, scheduled, or privately published. + if ( ! get_option( 'permalink_structure' ) || ! in_array( $post['post_status'], array( 'publish', 'future', 'private' ) ) ) + return; + + // Short if there aren't any links or no '?attachment_id=' strings (strpos cannot be zero) + if ( !strpos($content, '?attachment_id=') || !preg_match_all( '/]+)>[\s\S]+?<\/a>/', $content, $link_matches ) ) + return; + + $site_url = get_bloginfo('url'); + $site_url = substr( $site_url, (int) strpos($site_url, '://') ); // remove the http(s) + $replace = ''; + + foreach ( $link_matches[1] as $key => $value ) { + if ( !strpos($value, '?attachment_id=') || !strpos($value, 'wp-att-') + || !preg_match( '/href=(["\'])[^"\']*\?attachment_id=(\d+)[^"\']*\\1/', $value, $url_match ) + || !preg_match( '/rel=["\'][^"\']*wp-att-(\d+)/', $value, $rel_match ) ) + continue; + + $quote = $url_match[1]; // the quote (single or double) + $url_id = (int) $url_match[2]; + $rel_id = (int) $rel_match[1]; + + if ( !$url_id || !$rel_id || $url_id != $rel_id || strpos($url_match[0], $site_url) === false ) + continue; + + $link = $link_matches[0][$key]; + $replace = str_replace( $url_match[0], 'href=' . $quote . get_attachment_link( $url_id ) . $quote, $link ); + + $content = str_replace( $link, $replace, $content ); + } + + if ( $replace ) { + $post['post_content'] = $content; + // Escape data pulled from DB. + $post = add_magic_quotes($post); + + return wp_update_post($post); + } +} + +/** + * Move child posts to a new parent. + * + * @since 2.3.0 + * @access private + * + * @param unknown_type $old_ID + * @param unknown_type $new_ID + * @return unknown + */ +function _relocate_children( $old_ID, $new_ID ) { + global $wpdb; + $old_ID = (int) $old_ID; + $new_ID = (int) $new_ID; + + $children = $wpdb->get_col( $wpdb->prepare(" + SELECT post_id + FROM $wpdb->postmeta + WHERE meta_key = '_wp_attachment_temp_parent' + AND meta_value = %d", $old_ID) ); + + foreach ( $children as $child_id ) { + $wpdb->update($wpdb->posts, array('post_parent' => $new_ID), array('ID' => $child_id) ); + delete_post_meta($child_id, '_wp_attachment_temp_parent'); + } +} + +/** + * Get all the possible statuses for a post_type + * + * @since 2.5.0 + * + * @param string $type The post_type you want the statuses for + * @return array As array of all the statuses for the supplied post type + */ +function get_available_post_statuses($type = 'post') { + $stati = wp_count_posts($type); + + return array_keys(get_object_vars($stati)); +} + +/** + * Run the wp query to fetch the posts for listing on the edit posts page + * + * @since 2.5.0 + * + * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal. + * @return array + */ +function wp_edit_posts_query( $q = false ) { + if ( false === $q ) + $q = $_GET; + $q['m'] = isset($q['m']) ? (int) $q['m'] : 0; + $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0; + $post_stati = get_post_stati(); + + if ( isset($q['post_type']) && in_array( $q['post_type'], get_post_types() ) ) + $post_type = $q['post_type']; + else + $post_type = 'post'; + + $avail_post_stati = get_available_post_statuses($post_type); + + if ( isset($q['post_status']) && in_array( $q['post_status'], $post_stati ) ) { + $post_status = $q['post_status']; + $perm = 'readable'; + } + + if ( isset($q['orderby']) ) + $orderby = $q['orderby']; + elseif ( isset($q['post_status']) && in_array($q['post_status'], array('pending', 'draft')) ) + $orderby = 'modified'; + + if ( isset($q['order']) ) + $order = $q['order']; + elseif ( isset($q['post_status']) && 'pending' == $q['post_status'] ) + $order = 'ASC'; + + $per_page = 'edit_' . $post_type . '_per_page'; + $posts_per_page = (int) get_user_option( $per_page ); + if ( empty( $posts_per_page ) || $posts_per_page < 1 ) + $posts_per_page = 20; + + $posts_per_page = apply_filters( $per_page, $posts_per_page ); + $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type ); + + $query = compact('post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page'); + + // Hierarchical types require special args. + if ( is_post_type_hierarchical( $post_type ) && !isset($orderby) ) { + $query['orderby'] = 'menu_order title'; + $query['order'] = 'asc'; + $query['posts_per_page'] = -1; + $query['posts_per_archive_page'] = -1; + } + + if ( ! empty( $q['show_sticky'] ) ) + $query['post__in'] = (array) get_option( 'sticky_posts' ); + + wp( $query ); + + return $avail_post_stati; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param unknown_type $type + * @return unknown + */ +function get_available_post_mime_types($type = 'attachment') { + global $wpdb; + + $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type)); + return $types; +} + +/** + * Executes a query for attachments. An array of WP_Query arguments + * can be passed in, which will override the arguments set by this function. + * + * @since 2.5.0 + * @uses apply_filters() Calls 'upload_per_page' on posts_per_page argument + * + * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal. + * @return array + */ +function wp_edit_attachments_query( $q = false ) { + if ( false === $q ) + $q = $_GET; + + $q['m'] = isset( $q['m'] ) ? (int) $q['m'] : 0; + $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0; + $q['post_type'] = 'attachment'; + $post_type = get_post_type_object( 'attachment' ); + $states = 'inherit'; + if ( current_user_can( $post_type->cap->read_private_posts ) ) + $states .= ',private'; + + $q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : $states; + $media_per_page = (int) get_user_option( 'upload_per_page' ); + if ( empty( $media_per_page ) || $media_per_page < 1 ) + $media_per_page = 20; + $q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page ); + + $post_mime_types = get_post_mime_types(); + $avail_post_mime_types = get_available_post_mime_types('attachment'); + + if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) ) + unset($q['post_mime_type']); + + if ( isset($q['detached']) ) + add_filter('posts_where', '_edit_attachments_query_helper'); + + wp( $q ); + + if ( isset($q['detached']) ) + remove_filter('posts_where', '_edit_attachments_query_helper'); + + return array($post_mime_types, $avail_post_mime_types); +} + +function _edit_attachments_query_helper($where) { + global $wpdb; + return $where .= " AND {$wpdb->posts}.post_parent < 1"; +} + +/** + * Returns the list of classes to be used by a metabox + * + * @uses get_user_option() + * @since 2.5.0 + * + * @param unknown_type $id + * @param unknown_type $page + * @return unknown + */ +function postbox_classes( $id, $page ) { + if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id ) { + $classes = array( '' ); + } elseif ( $closed = get_user_option('closedpostboxes_'.$page ) ) { + if ( !is_array( $closed ) ) { + $classes = array( '' ); + } else { + $classes = in_array( $id, $closed ) ? array( 'closed' ) : array( '' ); + } + } else { + $classes = array( '' ); + } + + $classes = apply_filters( "postbox_classes_{$page}_{$id}", $classes ); + return implode( ' ', $classes ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param int|object $id Post ID or post object. + * @param string $title (optional) Title + * @param string $name (optional) Name + * @return array With two entries of type string + */ +function get_sample_permalink($id, $title = null, $name = null) { + $post = get_post( $id ); + if ( ! $post ) + return array( '', '' ); + + $ptype = get_post_type_object($post->post_type); + + $original_status = $post->post_status; + $original_date = $post->post_date; + $original_name = $post->post_name; + + // Hack: get_permalink() would return ugly permalink for drafts, so we will fake that our post is published. + if ( in_array( $post->post_status, array( 'draft', 'pending' ) ) ) { + $post->post_status = 'publish'; + $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID); + } + + // If the user wants to set a new name -- override the current one + // Note: if empty name is supplied -- use the title instead, see #6072 + if ( !is_null($name) ) + $post->post_name = sanitize_title($name ? $name : $title, $post->ID); + + $post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent); + + $post->filter = 'sample'; + + $permalink = get_permalink($post, true); + + // Replace custom post_type Token with generic pagename token for ease of use. + $permalink = str_replace("%$post->post_type%", '%pagename%', $permalink); + + // Handle page hierarchy + if ( $ptype->hierarchical ) { + $uri = get_page_uri($post); + $uri = untrailingslashit($uri); + $uri = strrev( stristr( strrev( $uri ), '/' ) ); + $uri = untrailingslashit($uri); + $uri = apply_filters( 'editable_slug', $uri ); + if ( !empty($uri) ) + $uri .= '/'; + $permalink = str_replace('%pagename%', "{$uri}%pagename%", $permalink); + } + + $permalink = array($permalink, apply_filters('editable_slug', $post->post_name)); + $post->post_status = $original_status; + $post->post_date = $original_date; + $post->post_name = $original_name; + unset($post->filter); + + return $permalink; +} + +/** + * Returns the HTML of the sample permalink slug editor. + * + * @since 2.5.0 + * + * @param int|object $id Post ID or post object. + * @param string $new_title Optional. New title. + * @param string $new_slug Optional. New slug. + * @return string The HTML of the sample permalink slug editor. + */ +function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) { + $post = get_post( $id ); + if ( ! $post ) + return ''; + + list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug); + + if ( 'publish' == get_post_status( $post ) ) { + $ptype = get_post_type_object($post->post_type); + $view_post = $ptype->labels->view_item; + $title = __('Click to edit this part of the permalink'); + } else { + $title = __('Temporary permalink. Click to edit this part.'); + } + + if ( false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%') ) { + $return = '' . __('Permalink:') . "\n" . '' . $permalink . "\n"; + if ( '' == get_option( 'permalink_structure' ) && current_user_can( 'manage_options' ) && !( 'page' == get_option('show_on_front') && $id == get_option('page_on_front') ) ) + $return .= '' . __('Change Permalinks') . "\n"; + if ( isset( $view_post ) ) + $return .= "$view_post\n"; + + $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug); + + return $return; + } + + if ( function_exists('mb_strlen') ) { + if ( mb_strlen($post_name) > 30 ) { + $post_name_abridged = mb_substr($post_name, 0, 14). '…' . mb_substr($post_name, -14); + } else { + $post_name_abridged = $post_name; + } + } else { + if ( strlen($post_name) > 30 ) { + $post_name_abridged = substr($post_name, 0, 14). '…' . substr($post_name, -14); + } else { + $post_name_abridged = $post_name; + } + } + + $post_name_html = '' . $post_name_abridged . ''; + $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink); + $view_link = str_replace(array('%pagename%','%postname%'), $post_name, $permalink); + $return = '' . __('Permalink:') . "\n"; + $return .= '' . $display_link . "\n"; + $return .= '‎'; // Fix bi-directional text display defect in RTL languages. + $return .= '' . __('Edit') . "\n"; + $return .= '' . $post_name . "\n"; + if ( isset($view_post) ) + $return .= "$view_post\n"; + + $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug); + + return $return; +} + +/** + * Output HTML for the post thumbnail meta-box. + * + * @since 2.9.0 + * + * @param int $thumbnail_id ID of the attachment used for thumbnail + * @param mixed $post The post ID or object associated with the thumbnail, defaults to global $post. + * @return string html + */ +function _wp_post_thumbnail_html( $thumbnail_id = null, $post = null ) { + global $content_width, $_wp_additional_image_sizes; + + $post = get_post( $post ); + + $upload_iframe_src = esc_url( get_upload_iframe_src('image', $post->ID ) ); + $set_thumbnail_link = '

    %s

    '; + $content = sprintf( $set_thumbnail_link, $upload_iframe_src, esc_html__( 'Set featured image' ) ); + + if ( $thumbnail_id && get_post( $thumbnail_id ) ) { + $old_content_width = $content_width; + $content_width = 266; + if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) ) + $thumbnail_html = wp_get_attachment_image( $thumbnail_id, array( $content_width, $content_width ) ); + else + $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'post-thumbnail' ); + if ( !empty( $thumbnail_html ) ) { + $ajax_nonce = wp_create_nonce( 'set_post_thumbnail-' . $post->ID ); + $content = sprintf( $set_thumbnail_link, $upload_iframe_src, $thumbnail_html ); + $content .= '

    ' . esc_html__( 'Remove featured image' ) . '

    '; + } + $content_width = $old_content_width; + } + + return apply_filters( 'admin_post_thumbnail_html', $content, $post->ID ); +} + +/** + * Check to see if the post is currently being edited by another user. + * + * @since 2.5.0 + * + * @param int $post_id ID of the post to check for editing + * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock. + */ +function wp_check_post_lock( $post_id ) { + if ( !$post = get_post( $post_id ) ) + return false; + + if ( !$lock = get_post_meta( $post->ID, '_edit_lock', true ) ) + return false; + + $lock = explode( ':', $lock ); + $time = $lock[0]; + $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true ); + + $time_window = apply_filters( 'wp_check_post_lock_window', 120 ); + + if ( $time && $time > time() - $time_window && $user != get_current_user_id() ) + return $user; + return false; +} + +/** + * Mark the post as currently being edited by the current user + * + * @since 2.5.0 + * + * @param int $post_id ID of the post to being edited + * @return bool|array Returns false if the post doesn't exist of there is no current user, or + * an array of the lock time and the user ID. + */ +function wp_set_post_lock( $post_id ) { + if ( !$post = get_post( $post_id ) ) + return false; + if ( 0 == ($user_id = get_current_user_id()) ) + return false; + + $now = time(); + $lock = "$now:$user_id"; + + update_post_meta( $post->ID, '_edit_lock', $lock ); + return array( $now, $user_id ); +} + +/** + * Outputs the HTML for the notice to say that someone else is editing or has taken over editing of this post. + * + * @since 2.8.5 + * @return none + */ +function _admin_notice_post_locked() { + if ( ! $post = get_post() ) + return; + + $user = null; + if ( $user_id = wp_check_post_lock( $post->ID ) ) + $user = get_userdata( $user_id ); + + if ( $user ) { + if ( ! apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) + return; + + $locked = true; + } else { + $locked = false; + } + + if ( $locked && ( $sendback = wp_get_referer() ) && + false === strpos( $sendback, 'post.php' ) && false === strpos( $sendback, 'post-new.php' ) ) { + + $sendback_text = __('Go back'); + } else { + $sendback = admin_url( 'edit.php' ); + + if ( 'post' != $post->post_type ) + $sendback = add_query_arg( 'post_type', $post->post_type, $sendback ); + + $sendback_text = get_post_type_object( $post->post_type )->labels->all_items; + } + + $hidden = $locked ? '' : ' hidden'; + + ?> +
    +
    +
    + post_type )->public ) { + $preview_link = set_url_scheme( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ); + + if ( 'publish' == $post->post_status || $user->ID != $post->post_author ) { + // Latest content is in autosave + $nonce = wp_create_nonce( 'post_preview_' . $post->ID ); + $preview_link = add_query_arg( array( 'preview_id' => $post->ID, 'preview_nonce' => $nonce ), $preview_link ); + } + } else { + $preview_link = ''; + } + + $preview_link = apply_filters( 'preview_post_link', $preview_link ); + $override = apply_filters( 'override_post_lock', true, $post, $user ); + $tab_last = $override ? '' : ' wp-tab-last'; + + ?> +
    +
    ID, 64 ); ?>
    +

    + display_name ) ); + ?> +

    + +

    + + + + + + +

    +
    + +
    +
    +

    +
    + + +

    + +

    +
    + +
    +
    + ID; + $new_autosave['post_author'] = $post_author; + + // If the new autosave is the same content as the post, delete the old autosave. + $post = get_post( $post_id ); + $autosave_is_different = false; + foreach ( array_keys( _wp_post_revision_fields() ) as $field ) { + if ( normalize_whitespace( $new_autosave[ $field ] ) != normalize_whitespace( $post->$field ) ) { + $autosave_is_different = true; + break; + } + } + + if ( ! $autosave_is_different ) { + wp_delete_post_revision( $old_autosave->ID ); + return; + } + + return wp_update_post( $new_autosave ); + } + + // _wp_put_post_revision() expects unescaped. + $post_data = wp_unslash( $_POST ); + + // Otherwise create the new autosave as a special post revision + return _wp_put_post_revision( $post_data, true ); +} + +/** + * Save draft or manually autosave for showing preview. + * + * @package WordPress + * @since 2.7.0 + * + * @uses get_post_status() + * @uses edit_post() + * @uses get_post() + * @uses current_user_can() + * @uses wp_die() + * @uses wp_create_post_autosave() + * @uses add_query_arg() + * @uses wp_create_nonce() + * + * @return str URL to redirect to show the preview + */ +function post_preview() { + + $post_ID = (int) $_POST['post_ID']; + $status = get_post_status( $post_ID ); + if ( 'auto-draft' == $status ) + wp_die( __('Preview not available. Please save as a draft first.') ); + + if ( isset($_POST['catslist']) ) + $_POST['post_category'] = explode(",", $_POST['catslist']); + + if ( isset($_POST['tags_input']) ) + $_POST['tags_input'] = explode(",", $_POST['tags_input']); + + if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) ) + unset($_POST['post_category']); + + $_POST['ID'] = $post_ID; + $post = get_post($post_ID); + + if ( 'page' == $post->post_type ) { + if ( ! current_user_can('edit_page', $post_ID) ) + wp_die( __('You are not allowed to edit this page.') ); + } else { + if ( ! current_user_can('edit_post', $post_ID) ) + wp_die( __('You are not allowed to edit this post.') ); + } + + $user_id = get_current_user_id(); + $locked = wp_check_post_lock( $post->ID ); + if ( ! $locked && 'draft' == $post->post_status && $user_id == $post->post_author ) { + $id = edit_post(); + } else { // Non drafts are not overwritten. The autosave is stored in a special post revision. + $id = wp_create_post_autosave( $post->ID ); + if ( ! is_wp_error($id) ) + $id = $post->ID; + } + + if ( is_wp_error($id) ) + wp_die( $id->get_error_message() ); + + if ( ! $locked && $_POST['post_status'] == 'draft' && $user_id == $post->post_author ) { + $url = add_query_arg( 'preview', 'true', get_permalink($id) ); + } else { + $nonce = wp_create_nonce('post_preview_' . $id); + $args = array( + 'preview' => 'true', + 'preview_id' => $id, + 'preview_nonce' => $nonce, + ); + + if ( isset( $_POST['post_format'] ) ) + $args['post_format'] = empty( $_POST['post_format'] ) ? 'standard' : sanitize_key( $_POST['post_format'] ); + + $url = add_query_arg( $args, get_permalink($id) ); + } + + return apply_filters( 'preview_post_link', $url ); +} diff --git a/sources/wp-admin/includes/revision.php b/sources/wp-admin/includes/revision.php new file mode 100644 index 0000000..737c3b1 --- /dev/null +++ b/sources/wp-admin/includes/revision.php @@ -0,0 +1,224 @@ +post_parent !== $post->ID && $compare_from->ID !== $post->ID ) + return false; + if ( $compare_to->post_parent !== $post->ID && $compare_to->ID !== $post->ID ) + return false; + + if ( $compare_from && strtotime( $compare_from->post_date_gmt ) > strtotime( $compare_to->post_date_gmt ) ) { + $temp = $compare_from; + $compare_from = $compare_to; + $compare_to = $temp; + } + + // Add default title if title field is empty + if ( $compare_from && empty( $compare_from->post_title ) ) + $compare_from->post_title = __( '(no title)' ); + if ( empty( $compare_to->post_title ) ) + $compare_to->post_title = __( '(no title)' ); + + $return = array(); + + foreach ( _wp_post_revision_fields() as $field => $name ) { + /** + * Contextually filter a post revision field. + * + * The dynamic portion of the hook name, $field, corresponds to each of the post + * fields of the revision object being iterated over in a foreach statement. + * + * @since 3.6.0 + * + * @param string $compare_from->$field The current revision field to compare to or from. + * @param string $field The current revision field. + * @param WP_Post $compare_from The revision post object to compare to or from. + * @param string null The context of whether the current revision is the old or the new one. Values are 'to' or 'from'. + */ + $content_from = $compare_from ? apply_filters( "_wp_post_revision_field_$field", $compare_from->$field, $field, $compare_from, 'from' ) : ''; + + /** This filter is documented in wp-admin/includes/revision.php */ + $content_to = apply_filters( "_wp_post_revision_field_$field", $compare_to->$field, $field, $compare_to, 'to' ); + + $diff = wp_text_diff( $content_from, $content_to, array( 'show_split_view' => true ) ); + + if ( ! $diff && 'post_title' === $field ) { + // It's a better user experience to still show the Title, even if it didn't change. + // No, you didn't see this. + $diff = ''; + $diff .= ''; + $diff .= ''; + $diff .= '
    ' . esc_html( $compare_from->post_title ) . '' . esc_html( $compare_to->post_title ) . '
    '; + } + + if ( $diff ) { + $return[] = array( + 'id' => $field, + 'name' => $name, + 'diff' => $diff, + ); + } + } + return $return; +} + +/** + * Prepare revisions for JavaScript. + * + * @since 3.6.0 + * + * @param object|int $post The post object. Also accepts a post ID. + * @param int $selected_revision_id The selected revision ID. + * @param int $from Optional. The revision ID to compare from. + * + * @return array An associative array of revision data and related settings. + */ +function wp_prepare_revisions_for_js( $post, $selected_revision_id, $from = null ) { + $post = get_post( $post ); + $revisions = $authors = array(); + $now_gmt = time(); + + $revisions = wp_get_post_revisions( $post->ID, array( 'order' => 'ASC', 'check_enabled' => false ) ); + // If revisions are disabled, we only want autosaves and the current post. + if ( ! wp_revisions_enabled( $post ) ) { + foreach ( $revisions as $revision_id => $revision ) { + if ( ! wp_is_post_autosave( $revision ) ) + unset( $revisions[ $revision_id ] ); + } + $revisions = array( $post->ID => $post ) + $revisions; + } + + $show_avatars = get_option( 'show_avatars' ); + + cache_users( wp_list_pluck( $revisions, 'post_author' ) ); + + $can_restore = current_user_can( 'edit_post', $post->ID ); + + foreach ( $revisions as $revision ) { + $modified = strtotime( $revision->post_modified ); + $modified_gmt = strtotime( $revision->post_modified_gmt ); + if ( $can_restore ) { + $restore_link = str_replace( '&', '&', wp_nonce_url( + add_query_arg( + array( 'revision' => $revision->ID, + 'action' => 'restore' ), + admin_url( 'revision.php' ) + ), + "restore-post_{$revision->ID}" + ) ); + } + + if ( ! isset( $authors[ $revision->post_author ] ) ) { + $authors[ $revision->post_author ] = array( + 'id' => (int) $revision->post_author, + 'avatar' => $show_avatars ? get_avatar( $revision->post_author, 32 ) : '', + 'name' => get_the_author_meta( 'display_name', $revision->post_author ), + ); + } + + $autosave = (bool) wp_is_post_autosave( $revision ); + $current = ! $autosave && $revision->post_modified_gmt === $post->post_modified_gmt; + if ( $current && ! empty( $current_id ) ) { + // If multiple revisions have the same post_modified_gmt, highest ID is current. + if ( $current_id < $revision->ID ) { + $revisions[ $current_id ]['current'] = false; + $current_id = $revision->ID; + } else { + $current = false; + } + } elseif ( $current ) { + $current_id = $revision->ID; + } + + $revisions[ $revision->ID ] = array( + 'id' => $revision->ID, + 'title' => get_the_title( $post->ID ), + 'author' => $authors[ $revision->post_author ], + 'date' => date_i18n( __( 'M j, Y @ G:i' ), $modified ), + 'dateShort' => date_i18n( _x( 'j M @ G:i', 'revision date short format' ), $modified ), + 'timeAgo' => sprintf( __( '%s ago' ), human_time_diff( $modified_gmt, $now_gmt ) ), + 'autosave' => $autosave, + 'current' => $current, + 'restoreUrl' => $can_restore ? $restore_link : false, + ); + } + + // If a post has been saved since the last revision (no revisioned fields were changed) + // we may not have a "current" revision. Mark the latest revision as "current". + if ( empty( $current_id ) ) { + if ( $revisions[ $revision->ID ]['autosave'] ) { + $revision = end( $revisions ); + while ( $revision['autosave'] ) { + $revision = prev( $revisions ); + } + $current_id = $revision['id']; + } else { + $current_id = $revision->ID; + } + $revisions[ $current_id ]['current'] = true; + } + + // Now, grab the initial diff + $compare_two_mode = is_numeric( $from ); + if ( ! $compare_two_mode ) { + $found = array_search( $selected_revision_id, array_keys( $revisions ) ); + if ( $found ) { + $from = array_keys( array_slice( $revisions, $found - 1, 1, true ) ); + $from = reset( $from ); + } else { + $from = 0; + } + } + + $from = absint( $from ); + + $diffs = array( array( + 'id' => $from . ':' . $selected_revision_id, + 'fields' => wp_get_revision_ui_diff( $post->ID, $from, $selected_revision_id ), + )); + + return array( + 'postId' => $post->ID, + 'nonce' => wp_create_nonce( 'revisions-ajax-nonce' ), + 'revisionData' => array_values( $revisions ), + 'to' => $selected_revision_id, + 'from' => $from, + 'diffData' => $diffs, + 'baseUrl' => parse_url( admin_url( 'revision.php' ), PHP_URL_PATH ), + 'compareTwoMode' => absint( $compare_two_mode ), // Apparently booleans are not allowed + 'revisionIds' => array_keys( $revisions ), + ); +} diff --git a/sources/wp-admin/includes/schema.php b/sources/wp-admin/includes/schema.php new file mode 100644 index 0000000..f88f79d --- /dev/null +++ b/sources/wp-admin/includes/schema.php @@ -0,0 +1,1008 @@ +get_charset_collate(); + +/** + * Retrieve the SQL for creating database tables. + * + * @since 3.3.0 + * + * @param string $scope Optional. The tables for which to retrieve SQL. Can be all, global, ms_global, or blog tables. Defaults to all. + * @param int $blog_id Optional. The blog ID for which to retrieve SQL. Default is the current blog ID. + * @return string The SQL needed to create the requested tables. + */ +function wp_get_db_schema( $scope = 'all', $blog_id = null ) { + global $wpdb; + + $charset_collate = ''; + + if ( ! empty($wpdb->charset) ) + $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset"; + if ( ! empty($wpdb->collate) ) + $charset_collate .= " COLLATE $wpdb->collate"; + + if ( $blog_id && $blog_id != $wpdb->blogid ) + $old_blog_id = $wpdb->set_blog_id( $blog_id ); + + // Engage multisite if in the middle of turning it on from network.php. + $is_multisite = is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ); + + // Blog specific tables. + $blog_tables = "CREATE TABLE $wpdb->terms ( + term_id bigint(20) unsigned NOT NULL auto_increment, + name varchar(200) NOT NULL default '', + slug varchar(200) NOT NULL default '', + term_group bigint(10) NOT NULL default 0, + PRIMARY KEY (term_id), + UNIQUE KEY slug (slug), + KEY name (name) +) $charset_collate; +CREATE TABLE $wpdb->term_taxonomy ( + term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment, + term_id bigint(20) unsigned NOT NULL default 0, + taxonomy varchar(32) NOT NULL default '', + description longtext NOT NULL, + parent bigint(20) unsigned NOT NULL default 0, + count bigint(20) NOT NULL default 0, + PRIMARY KEY (term_taxonomy_id), + UNIQUE KEY term_id_taxonomy (term_id,taxonomy), + KEY taxonomy (taxonomy) +) $charset_collate; +CREATE TABLE $wpdb->term_relationships ( + object_id bigint(20) unsigned NOT NULL default 0, + term_taxonomy_id bigint(20) unsigned NOT NULL default 0, + term_order int(11) NOT NULL default 0, + PRIMARY KEY (object_id,term_taxonomy_id), + KEY term_taxonomy_id (term_taxonomy_id) +) $charset_collate; +CREATE TABLE $wpdb->commentmeta ( + meta_id bigint(20) unsigned NOT NULL auto_increment, + comment_id bigint(20) unsigned NOT NULL default '0', + meta_key varchar(255) default NULL, + meta_value longtext, + PRIMARY KEY (meta_id), + KEY comment_id (comment_id), + KEY meta_key (meta_key) +) $charset_collate; +CREATE TABLE $wpdb->comments ( + comment_ID bigint(20) unsigned NOT NULL auto_increment, + comment_post_ID bigint(20) unsigned NOT NULL default '0', + comment_author tinytext NOT NULL, + comment_author_email varchar(100) NOT NULL default '', + comment_author_url varchar(200) NOT NULL default '', + comment_author_IP varchar(100) NOT NULL default '', + comment_date datetime NOT NULL default '0000-00-00 00:00:00', + comment_date_gmt datetime NOT NULL default '0000-00-00 00:00:00', + comment_content text NOT NULL, + comment_karma int(11) NOT NULL default '0', + comment_approved varchar(20) NOT NULL default '1', + comment_agent varchar(255) NOT NULL default '', + comment_type varchar(20) NOT NULL default '', + comment_parent bigint(20) unsigned NOT NULL default '0', + user_id bigint(20) unsigned NOT NULL default '0', + PRIMARY KEY (comment_ID), + KEY comment_post_ID (comment_post_ID), + KEY comment_approved_date_gmt (comment_approved,comment_date_gmt), + KEY comment_date_gmt (comment_date_gmt), + KEY comment_parent (comment_parent) +) $charset_collate; +CREATE TABLE $wpdb->links ( + link_id bigint(20) unsigned NOT NULL auto_increment, + link_url varchar(255) NOT NULL default '', + link_name varchar(255) NOT NULL default '', + link_image varchar(255) NOT NULL default '', + link_target varchar(25) NOT NULL default '', + link_description varchar(255) NOT NULL default '', + link_visible varchar(20) NOT NULL default 'Y', + link_owner bigint(20) unsigned NOT NULL default '1', + link_rating int(11) NOT NULL default '0', + link_updated datetime NOT NULL default '0000-00-00 00:00:00', + link_rel varchar(255) NOT NULL default '', + link_notes mediumtext NOT NULL, + link_rss varchar(255) NOT NULL default '', + PRIMARY KEY (link_id), + KEY link_visible (link_visible) +) $charset_collate; +CREATE TABLE $wpdb->options ( + option_id bigint(20) unsigned NOT NULL auto_increment, + option_name varchar(64) NOT NULL default '', + option_value longtext NOT NULL, + autoload varchar(20) NOT NULL default 'yes', + PRIMARY KEY (option_id), + UNIQUE KEY option_name (option_name) +) $charset_collate; +CREATE TABLE $wpdb->postmeta ( + meta_id bigint(20) unsigned NOT NULL auto_increment, + post_id bigint(20) unsigned NOT NULL default '0', + meta_key varchar(255) default NULL, + meta_value longtext, + PRIMARY KEY (meta_id), + KEY post_id (post_id), + KEY meta_key (meta_key) +) $charset_collate; +CREATE TABLE $wpdb->posts ( + ID bigint(20) unsigned NOT NULL auto_increment, + post_author bigint(20) unsigned NOT NULL default '0', + post_date datetime NOT NULL default '0000-00-00 00:00:00', + post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00', + post_content longtext NOT NULL, + post_title text NOT NULL, + post_excerpt text NOT NULL, + post_status varchar(20) NOT NULL default 'publish', + comment_status varchar(20) NOT NULL default 'open', + ping_status varchar(20) NOT NULL default 'open', + post_password varchar(20) NOT NULL default '', + post_name varchar(200) NOT NULL default '', + to_ping text NOT NULL, + pinged text NOT NULL, + post_modified datetime NOT NULL default '0000-00-00 00:00:00', + post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00', + post_content_filtered longtext NOT NULL, + post_parent bigint(20) unsigned NOT NULL default '0', + guid varchar(255) NOT NULL default '', + menu_order int(11) NOT NULL default '0', + post_type varchar(20) NOT NULL default 'post', + post_mime_type varchar(100) NOT NULL default '', + comment_count bigint(20) NOT NULL default '0', + PRIMARY KEY (ID), + KEY post_name (post_name), + KEY type_status_date (post_type,post_status,post_date,ID), + KEY post_parent (post_parent), + KEY post_author (post_author) +) $charset_collate;\n"; + + // Single site users table. The multisite flavor of the users table is handled below. + $users_single_table = "CREATE TABLE $wpdb->users ( + ID bigint(20) unsigned NOT NULL auto_increment, + user_login varchar(60) NOT NULL default '', + user_pass varchar(64) NOT NULL default '', + user_nicename varchar(50) NOT NULL default '', + user_email varchar(100) NOT NULL default '', + user_url varchar(100) NOT NULL default '', + user_registered datetime NOT NULL default '0000-00-00 00:00:00', + user_activation_key varchar(60) NOT NULL default '', + user_status int(11) NOT NULL default '0', + display_name varchar(250) NOT NULL default '', + PRIMARY KEY (ID), + KEY user_login_key (user_login), + KEY user_nicename (user_nicename) +) $charset_collate;\n"; + + // Multisite users table + $users_multi_table = "CREATE TABLE $wpdb->users ( + ID bigint(20) unsigned NOT NULL auto_increment, + user_login varchar(60) NOT NULL default '', + user_pass varchar(64) NOT NULL default '', + user_nicename varchar(50) NOT NULL default '', + user_email varchar(100) NOT NULL default '', + user_url varchar(100) NOT NULL default '', + user_registered datetime NOT NULL default '0000-00-00 00:00:00', + user_activation_key varchar(60) NOT NULL default '', + user_status int(11) NOT NULL default '0', + display_name varchar(250) NOT NULL default '', + spam tinyint(2) NOT NULL default '0', + deleted tinyint(2) NOT NULL default '0', + PRIMARY KEY (ID), + KEY user_login_key (user_login), + KEY user_nicename (user_nicename) +) $charset_collate;\n"; + + // usermeta + $usermeta_table = "CREATE TABLE $wpdb->usermeta ( + umeta_id bigint(20) unsigned NOT NULL auto_increment, + user_id bigint(20) unsigned NOT NULL default '0', + meta_key varchar(255) default NULL, + meta_value longtext, + PRIMARY KEY (umeta_id), + KEY user_id (user_id), + KEY meta_key (meta_key) +) $charset_collate;\n"; + + // Global tables + if ( $is_multisite ) + $global_tables = $users_multi_table . $usermeta_table; + else + $global_tables = $users_single_table . $usermeta_table; + + // Multisite global tables. + $ms_global_tables = "CREATE TABLE $wpdb->blogs ( + blog_id bigint(20) NOT NULL auto_increment, + site_id bigint(20) NOT NULL default '0', + domain varchar(200) NOT NULL default '', + path varchar(100) NOT NULL default '', + registered datetime NOT NULL default '0000-00-00 00:00:00', + last_updated datetime NOT NULL default '0000-00-00 00:00:00', + public tinyint(2) NOT NULL default '1', + archived tinyint(2) NOT NULL default '0', + mature tinyint(2) NOT NULL default '0', + spam tinyint(2) NOT NULL default '0', + deleted tinyint(2) NOT NULL default '0', + lang_id int(11) NOT NULL default '0', + PRIMARY KEY (blog_id), + KEY domain (domain(50),path(5)), + KEY lang_id (lang_id) +) $charset_collate; +CREATE TABLE $wpdb->blog_versions ( + blog_id bigint(20) NOT NULL default '0', + db_version varchar(20) NOT NULL default '', + last_updated datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (blog_id), + KEY db_version (db_version) +) $charset_collate; +CREATE TABLE $wpdb->registration_log ( + ID bigint(20) NOT NULL auto_increment, + email varchar(255) NOT NULL default '', + IP varchar(30) NOT NULL default '', + blog_id bigint(20) NOT NULL default '0', + date_registered datetime NOT NULL default '0000-00-00 00:00:00', + PRIMARY KEY (ID), + KEY IP (IP) +) $charset_collate; +CREATE TABLE $wpdb->site ( + id bigint(20) NOT NULL auto_increment, + domain varchar(200) NOT NULL default '', + path varchar(100) NOT NULL default '', + PRIMARY KEY (id), + KEY domain (domain,path) +) $charset_collate; +CREATE TABLE $wpdb->sitemeta ( + meta_id bigint(20) NOT NULL auto_increment, + site_id bigint(20) NOT NULL default '0', + meta_key varchar(255) default NULL, + meta_value longtext, + PRIMARY KEY (meta_id), + KEY meta_key (meta_key), + KEY site_id (site_id) +) $charset_collate; +CREATE TABLE $wpdb->signups ( + signup_id bigint(20) NOT NULL auto_increment, + domain varchar(200) NOT NULL default '', + path varchar(100) NOT NULL default '', + title longtext NOT NULL, + user_login varchar(60) NOT NULL default '', + user_email varchar(100) NOT NULL default '', + registered datetime NOT NULL default '0000-00-00 00:00:00', + activated datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(1) NOT NULL default '0', + activation_key varchar(50) NOT NULL default '', + meta longtext, + PRIMARY KEY (signup_id), + KEY activation_key (activation_key), + KEY user_email (user_email), + KEY user_login_email (user_login,user_email), + KEY domain_path (domain,path) +) $charset_collate;"; + + switch ( $scope ) { + case 'blog' : + $queries = $blog_tables; + break; + case 'global' : + $queries = $global_tables; + if ( $is_multisite ) + $queries .= $ms_global_tables; + break; + case 'ms_global' : + $queries = $ms_global_tables; + break; + default: + case 'all' : + $queries = $global_tables . $blog_tables; + if ( $is_multisite ) + $queries .= $ms_global_tables; + break; + } + + if ( isset( $old_blog_id ) ) + $wpdb->set_blog_id( $old_blog_id ); + + return $queries; +} + +// Populate for back compat. +$wp_queries = wp_get_db_schema( 'all' ); + +/** + * Create WordPress options and set the default values. + * + * @since 1.5.0 + * @uses $wpdb + * @uses $wp_db_version + */ +function populate_options() { + global $wpdb, $wp_db_version, $current_site, $wp_current_db_version; + + $guessurl = wp_guess_url(); + + do_action('populate_options'); + + if ( ini_get('safe_mode') ) { + // Safe mode can break mkdir() so use a flat structure by default. + $uploads_use_yearmonth_folders = 0; + } else { + $uploads_use_yearmonth_folders = 1; + } + + $template = WP_DEFAULT_THEME; + // If default theme is a child theme, we need to get its template + $theme = wp_get_theme( $template ); + if ( ! $theme->errors() ) + $template = $theme->get_template(); + + $timezone_string = ''; + $gmt_offset = 0; + /* translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14) + or a valid timezone string (America/New_York). See http://us3.php.net/manual/en/timezones.php + for all timezone strings supported by PHP. + */ + $offset_or_tz = _x( '0', 'default GMT offset or timezone string' ); + if ( is_numeric( $offset_or_tz ) ) + $gmt_offset = $offset_or_tz; + elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list() ) ) + $timezone_string = $offset_or_tz; + + $options = array( + 'siteurl' => $guessurl, + 'blogname' => __('My Site'), + /* translators: blog tagline */ + 'blogdescription' => __('Just another WordPress site'), + 'users_can_register' => 0, + 'admin_email' => 'you@example.com', + /* translators: default start of the week. 0 = Sunday, 1 = Monday */ + 'start_of_week' => _x( '1', 'start of week' ), + 'use_balanceTags' => 0, + 'use_smilies' => 1, + 'require_name_email' => 1, + 'comments_notify' => 1, + 'posts_per_rss' => 10, + 'rss_use_excerpt' => 0, + 'mailserver_url' => 'mail.example.com', + 'mailserver_login' => 'login@example.com', + 'mailserver_pass' => 'password', + 'mailserver_port' => 110, + 'default_category' => 1, + 'default_comment_status' => 'open', + 'default_ping_status' => 'open', + 'default_pingback_flag' => 1, + 'posts_per_page' => 10, + /* translators: default date format, see http://php.net/date */ + 'date_format' => __('F j, Y'), + /* translators: default time format, see http://php.net/date */ + 'time_format' => __('g:i a'), + /* translators: links last updated date format, see http://php.net/date */ + 'links_updated_date_format' => __('F j, Y g:i a'), + 'links_recently_updated_prepend' => '', + 'links_recently_updated_append' => '', + 'links_recently_updated_time' => 120, + 'comment_moderation' => 0, + 'moderation_notify' => 1, + 'permalink_structure' => '', + 'gzipcompression' => 0, + 'hack_file' => 0, + 'blog_charset' => 'UTF-8', + 'moderation_keys' => '', + 'active_plugins' => array(), + 'home' => $guessurl, + 'category_base' => '', + 'ping_sites' => 'http://rpc.pingomatic.com/', + 'advanced_edit' => 0, + 'comment_max_links' => 2, + 'gmt_offset' => $gmt_offset, + + // 1.5 + 'default_email_category' => 1, + 'recently_edited' => '', + 'template' => $template, + 'stylesheet' => WP_DEFAULT_THEME, + 'comment_whitelist' => 1, + 'blacklist_keys' => '', + 'comment_registration' => 0, + 'html_type' => 'text/html', + + // 1.5.1 + 'use_trackback' => 0, + + // 2.0 + 'default_role' => 'subscriber', + 'db_version' => $wp_db_version, + + // 2.0.1 + 'uploads_use_yearmonth_folders' => $uploads_use_yearmonth_folders, + 'upload_path' => '', + + // 2.1 + 'blog_public' => '1', + 'default_link_category' => 2, + 'show_on_front' => 'posts', + + // 2.2 + 'tag_base' => '', + + // 2.5 + 'show_avatars' => '1', + 'avatar_rating' => 'G', + 'upload_url_path' => '', + 'thumbnail_size_w' => 150, + 'thumbnail_size_h' => 150, + 'thumbnail_crop' => 1, + 'medium_size_w' => 300, + 'medium_size_h' => 300, + + // 2.6 + 'avatar_default' => 'mystery', + + // 2.7 + 'large_size_w' => 1024, + 'large_size_h' => 1024, + 'image_default_link_type' => 'file', + 'image_default_size' => '', + 'image_default_align' => '', + 'close_comments_for_old_posts' => 0, + 'close_comments_days_old' => 14, + 'thread_comments' => 1, + 'thread_comments_depth' => 5, + 'page_comments' => 0, + 'comments_per_page' => 50, + 'default_comments_page' => 'newest', + 'comment_order' => 'asc', + 'sticky_posts' => array(), + 'widget_categories' => array(), + 'widget_text' => array(), + 'widget_rss' => array(), + 'uninstall_plugins' => array(), + + // 2.8 + 'timezone_string' => $timezone_string, + + // 3.0 + 'page_for_posts' => 0, + 'page_on_front' => 0, + + // 3.1 + 'default_post_format' => 0, + + // 3.5 + 'link_manager_enabled' => 0, + ); + + // 3.3 + if ( ! is_multisite() ) { + $options['initial_db_version'] = ! empty( $wp_current_db_version ) && $wp_current_db_version < $wp_db_version + ? $wp_current_db_version : $wp_db_version; + } + + // 3.0 multisite + if ( is_multisite() ) { + /* translators: blog tagline */ + $options[ 'blogdescription' ] = sprintf(__('Just another %s site'), $current_site->site_name ); + $options[ 'permalink_structure' ] = '/%year%/%monthnum%/%day%/%postname%/'; + } + + // Set autoload to no for these options + $fat_options = array( 'moderation_keys', 'recently_edited', 'blacklist_keys', 'uninstall_plugins' ); + + $keys = "'" . implode( "', '", array_keys( $options ) ) . "'"; + $existing_options = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name in ( $keys )" ); + + $insert = ''; + foreach ( $options as $option => $value ) { + if ( in_array($option, $existing_options) ) + continue; + if ( in_array($option, $fat_options) ) + $autoload = 'no'; + else + $autoload = 'yes'; + + if ( is_array($value) ) + $value = serialize($value); + if ( !empty($insert) ) + $insert .= ', '; + $insert .= $wpdb->prepare( "(%s, %s, %s)", $option, $value, $autoload ); + } + + if ( !empty($insert) ) + $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert); + + // in case it is set, but blank, update "home" + if ( !__get_option('home') ) update_option('home', $guessurl); + + // Delete unused options + $unusedoptions = array( + 'blodotgsping_url', 'bodyterminator', 'emailtestonly', 'phoneemail_separator', 'smilies_directory', + 'subjectprefix', 'use_bbcode', 'use_blodotgsping', 'use_phoneemail', 'use_quicktags', 'use_weblogsping', + 'weblogs_cache_file', 'use_preview', 'use_htmltrans', 'smilies_directory', 'fileupload_allowedusers', + 'use_phoneemail', 'default_post_status', 'default_post_category', 'archive_mode', 'time_difference', + 'links_minadminlevel', 'links_use_adminlevels', 'links_rating_type', 'links_rating_char', + 'links_rating_ignore_zero', 'links_rating_single_image', 'links_rating_image0', 'links_rating_image1', + 'links_rating_image2', 'links_rating_image3', 'links_rating_image4', 'links_rating_image5', + 'links_rating_image6', 'links_rating_image7', 'links_rating_image8', 'links_rating_image9', + 'weblogs_cacheminutes', 'comment_allowed_tags', 'search_engine_friendly_urls', 'default_geourl_lat', + 'default_geourl_lon', 'use_default_geourl', 'weblogs_xml_url', 'new_users_can_blog', '_wpnonce', + '_wp_http_referer', 'Update', 'action', 'rich_editing', 'autosave_interval', 'deactivated_plugins', + 'can_compress_scripts', 'page_uris', 'update_core', 'update_plugins', 'update_themes', 'doing_cron', + 'random_seed', 'rss_excerpt_length', 'secret', 'use_linksupdate', 'default_comment_status_page', + 'wporg_popular_tags', 'what_to_show', 'rss_language', 'language', 'enable_xmlrpc', 'enable_app', + 'embed_autourls', 'default_post_edit_rows', + ); + foreach ( $unusedoptions as $option ) + delete_option($option); + + // delete obsolete magpie stuff + $wpdb->query("DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'"); + + // Deletes all expired transients. + // The multi-table delete syntax is used to delete the transient record from table a, + // and the corresponding transient_timeout record from table b. + $time = time(); + $wpdb->query("DELETE a, b FROM $wpdb->options a, $wpdb->options b WHERE + a.option_name LIKE '\_transient\_%' AND + a.option_name NOT LIKE '\_transient\_timeout\_%' AND + b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) ) + AND b.option_value < $time"); + + if ( is_main_site() && is_main_network() ) { + $wpdb->query("DELETE a, b FROM $wpdb->options a, $wpdb->options b WHERE + a.option_name LIKE '\_site\_transient\_%' AND + a.option_name NOT LIKE '\_site\_transient\_timeout\_%' AND + b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) ) + AND b.option_value < $time"); + } +} + +/** + * Execute WordPress role creation for the various WordPress versions. + * + * @since 2.0.0 + */ +function populate_roles() { + populate_roles_160(); + populate_roles_210(); + populate_roles_230(); + populate_roles_250(); + populate_roles_260(); + populate_roles_270(); + populate_roles_280(); + populate_roles_300(); +} + +/** + * Create the roles for WordPress 2.0 + * + * @since 2.0.0 + */ +function populate_roles_160() { + // Add roles + + // Dummy gettext calls to get strings in the catalog. + /* translators: user role */ + _x('Administrator', 'User role'); + /* translators: user role */ + _x('Editor', 'User role'); + /* translators: user role */ + _x('Author', 'User role'); + /* translators: user role */ + _x('Contributor', 'User role'); + /* translators: user role */ + _x('Subscriber', 'User role'); + + add_role('administrator', 'Administrator'); + add_role('editor', 'Editor'); + add_role('author', 'Author'); + add_role('contributor', 'Contributor'); + add_role('subscriber', 'Subscriber'); + + // Add caps for Administrator role + $role = get_role('administrator'); + $role->add_cap('switch_themes'); + $role->add_cap('edit_themes'); + $role->add_cap('activate_plugins'); + $role->add_cap('edit_plugins'); + $role->add_cap('edit_users'); + $role->add_cap('edit_files'); + $role->add_cap('manage_options'); + $role->add_cap('moderate_comments'); + $role->add_cap('manage_categories'); + $role->add_cap('manage_links'); + $role->add_cap('upload_files'); + $role->add_cap('import'); + $role->add_cap('unfiltered_html'); + $role->add_cap('edit_posts'); + $role->add_cap('edit_others_posts'); + $role->add_cap('edit_published_posts'); + $role->add_cap('publish_posts'); + $role->add_cap('edit_pages'); + $role->add_cap('read'); + $role->add_cap('level_10'); + $role->add_cap('level_9'); + $role->add_cap('level_8'); + $role->add_cap('level_7'); + $role->add_cap('level_6'); + $role->add_cap('level_5'); + $role->add_cap('level_4'); + $role->add_cap('level_3'); + $role->add_cap('level_2'); + $role->add_cap('level_1'); + $role->add_cap('level_0'); + + // Add caps for Editor role + $role = get_role('editor'); + $role->add_cap('moderate_comments'); + $role->add_cap('manage_categories'); + $role->add_cap('manage_links'); + $role->add_cap('upload_files'); + $role->add_cap('unfiltered_html'); + $role->add_cap('edit_posts'); + $role->add_cap('edit_others_posts'); + $role->add_cap('edit_published_posts'); + $role->add_cap('publish_posts'); + $role->add_cap('edit_pages'); + $role->add_cap('read'); + $role->add_cap('level_7'); + $role->add_cap('level_6'); + $role->add_cap('level_5'); + $role->add_cap('level_4'); + $role->add_cap('level_3'); + $role->add_cap('level_2'); + $role->add_cap('level_1'); + $role->add_cap('level_0'); + + // Add caps for Author role + $role = get_role('author'); + $role->add_cap('upload_files'); + $role->add_cap('edit_posts'); + $role->add_cap('edit_published_posts'); + $role->add_cap('publish_posts'); + $role->add_cap('read'); + $role->add_cap('level_2'); + $role->add_cap('level_1'); + $role->add_cap('level_0'); + + // Add caps for Contributor role + $role = get_role('contributor'); + $role->add_cap('edit_posts'); + $role->add_cap('read'); + $role->add_cap('level_1'); + $role->add_cap('level_0'); + + // Add caps for Subscriber role + $role = get_role('subscriber'); + $role->add_cap('read'); + $role->add_cap('level_0'); +} + +/** + * Create and modify WordPress roles for WordPress 2.1. + * + * @since 2.1.0 + */ +function populate_roles_210() { + $roles = array('administrator', 'editor'); + foreach ($roles as $role) { + $role = get_role($role); + if ( empty($role) ) + continue; + + $role->add_cap('edit_others_pages'); + $role->add_cap('edit_published_pages'); + $role->add_cap('publish_pages'); + $role->add_cap('delete_pages'); + $role->add_cap('delete_others_pages'); + $role->add_cap('delete_published_pages'); + $role->add_cap('delete_posts'); + $role->add_cap('delete_others_posts'); + $role->add_cap('delete_published_posts'); + $role->add_cap('delete_private_posts'); + $role->add_cap('edit_private_posts'); + $role->add_cap('read_private_posts'); + $role->add_cap('delete_private_pages'); + $role->add_cap('edit_private_pages'); + $role->add_cap('read_private_pages'); + } + + $role = get_role('administrator'); + if ( ! empty($role) ) { + $role->add_cap('delete_users'); + $role->add_cap('create_users'); + } + + $role = get_role('author'); + if ( ! empty($role) ) { + $role->add_cap('delete_posts'); + $role->add_cap('delete_published_posts'); + } + + $role = get_role('contributor'); + if ( ! empty($role) ) { + $role->add_cap('delete_posts'); + } +} + +/** + * Create and modify WordPress roles for WordPress 2.3. + * + * @since 2.3.0 + */ +function populate_roles_230() { + $role = get_role( 'administrator' ); + + if ( !empty( $role ) ) { + $role->add_cap( 'unfiltered_upload' ); + } +} + +/** + * Create and modify WordPress roles for WordPress 2.5. + * + * @since 2.5.0 + */ +function populate_roles_250() { + $role = get_role( 'administrator' ); + + if ( !empty( $role ) ) { + $role->add_cap( 'edit_dashboard' ); + } +} + +/** + * Create and modify WordPress roles for WordPress 2.6. + * + * @since 2.6.0 + */ +function populate_roles_260() { + $role = get_role( 'administrator' ); + + if ( !empty( $role ) ) { + $role->add_cap( 'update_plugins' ); + $role->add_cap( 'delete_plugins' ); + } +} + +/** + * Create and modify WordPress roles for WordPress 2.7. + * + * @since 2.7.0 + */ +function populate_roles_270() { + $role = get_role( 'administrator' ); + + if ( !empty( $role ) ) { + $role->add_cap( 'install_plugins' ); + $role->add_cap( 'update_themes' ); + } +} + +/** + * Create and modify WordPress roles for WordPress 2.8. + * + * @since 2.8.0 + */ +function populate_roles_280() { + $role = get_role( 'administrator' ); + + if ( !empty( $role ) ) { + $role->add_cap( 'install_themes' ); + } +} + +/** + * Create and modify WordPress roles for WordPress 3.0. + * + * @since 3.0.0 + */ +function populate_roles_300() { + $role = get_role( 'administrator' ); + + if ( !empty( $role ) ) { + $role->add_cap( 'update_core' ); + $role->add_cap( 'list_users' ); + $role->add_cap( 'remove_users' ); + + // Never used, will be removed. create_users or + // promote_users is the capability you're looking for. + $role->add_cap( 'add_users' ); + + $role->add_cap( 'promote_users' ); + $role->add_cap( 'edit_theme_options' ); + $role->add_cap( 'delete_themes' ); + $role->add_cap( 'export' ); + } +} + +/** + * Install Network. + * + * @since 3.0.0 + * + */ +if ( !function_exists( 'install_network' ) ) : +function install_network() { + if ( ! defined( 'WP_INSTALLING_NETWORK' ) ) + define( 'WP_INSTALLING_NETWORK', true ); + + dbDelta( wp_get_db_schema( 'global' ) ); +} +endif; + +/** + * populate network settings + * + * @since 3.0.0 + * + * @param int $network_id id of network to populate + * @return bool|WP_Error True on success, or WP_Error on warning (with the install otherwise successful, + * so the error code must be checked) or failure. + */ +function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) { + global $wpdb, $current_site, $wp_db_version, $wp_rewrite; + + $errors = new WP_Error(); + if ( '' == $domain ) + $errors->add( 'empty_domain', __( 'You must provide a domain name.' ) ); + if ( '' == $site_name ) + $errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) ); + + // check for network collision + if ( $network_id == $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id ) ) ) + $errors->add( 'siteid_exists', __( 'The network already exists.' ) ); + + $site_user = get_user_by( 'email', $email ); + if ( ! is_email( $email ) ) + $errors->add( 'invalid_email', __( 'You must provide a valid e-mail address.' ) ); + + if ( $errors->get_error_code() ) + return $errors; + + // set up site tables + $template = get_option( 'template' ); + $stylesheet = get_option( 'stylesheet' ); + $allowed_themes = array( $stylesheet => true ); + if ( $template != $stylesheet ) + $allowed_themes[ $template ] = true; + if ( WP_DEFAULT_THEME != $stylesheet && WP_DEFAULT_THEME != $template ) + $allowed_themes[ WP_DEFAULT_THEME ] = true; + + if ( 1 == $network_id ) { + $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path ) ); + $network_id = $wpdb->insert_id; + } else { + $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path, 'id' => $network_id ) ); + } + + if ( !is_multisite() ) { + $site_admins = array( $site_user->user_login ); + $users = get_users( array( 'fields' => array( 'ID', 'user_login' ) ) ); + if ( $users ) { + foreach ( $users as $user ) { + if ( is_super_admin( $user->ID ) && !in_array( $user->user_login, $site_admins ) ) + $site_admins[] = $user->user_login; + } + } + } else { + $site_admins = get_site_option( 'site_admins' ); + } + + $welcome_email = __( 'Dear User, + +Your new SITE_NAME site has been successfully set up at: +BLOG_URL + +You can log in to the administrator account with the following information: +Username: USERNAME +Password: PASSWORD +Log in here: BLOG_URLwp-login.php + +We hope you enjoy your new site. Thanks! + +--The Team @ SITE_NAME' ); + + $sitemeta = array( + 'site_name' => $site_name, + 'admin_email' => $site_user->user_email, + 'admin_user_id' => $site_user->ID, + 'registration' => 'none', + 'upload_filetypes' => 'jpg jpeg png gif mp3 mov avi wmv midi mid pdf', + 'blog_upload_space' => 100, + 'fileupload_maxk' => 1500, + 'site_admins' => $site_admins, + 'allowedthemes' => $allowed_themes, + 'illegal_names' => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ), + 'wpmu_upgrade_site' => $wp_db_version, + 'welcome_email' => $welcome_email, + 'first_post' => __( 'Welcome to SITE_NAME. This is your first post. Edit or delete it, then start blogging!' ), + // @todo - network admins should have a method of editing the network siteurl (used for cookie hash) + 'siteurl' => get_option( 'siteurl' ) . '/', + 'add_new_users' => '0', + 'upload_space_check_disabled' => is_multisite() ? get_site_option( 'upload_space_check_disabled' ) : '1', + 'subdomain_install' => intval( $subdomain_install ), + 'global_terms_enabled' => global_terms_enabled() ? '1' : '0', + 'ms_files_rewriting' => is_multisite() ? get_site_option( 'ms_files_rewriting' ) : '0', + 'initial_db_version' => get_option( 'initial_db_version' ), + 'active_sitewide_plugins' => array(), + 'WPLANG' => get_locale(), + ); + if ( ! $subdomain_install ) + $sitemeta['illegal_names'][] = 'blog'; + + /** + * Filter meta for a network on creation. + * + * @since 3.7.0 + * + * @param array $sitemeta Associative of meta keys and values to be inserted. + * @param int $network_id Network ID being created. + */ + $sitemeta = apply_filters( 'populate_network_meta', $sitemeta, $network_id ); + + $insert = ''; + foreach ( $sitemeta as $meta_key => $meta_value ) { + if ( is_array( $meta_value ) ) + $meta_value = serialize( $meta_value ); + if ( !empty( $insert ) ) + $insert .= ', '; + $insert .= $wpdb->prepare( "( %d, %s, %s)", $network_id, $meta_key, $meta_value ); + } + $wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert ); + + // When upgrading from single to multisite, assume the current site will become the main site of the network. + // When using populate_network() to create another network in an existing multisite environment, + // skip these steps since the main site of the new network has not yet been created. + if ( ! is_multisite() ) { + $current_site = new stdClass; + $current_site->domain = $domain; + $current_site->path = $path; + $current_site->site_name = ucfirst( $domain ); + $wpdb->insert( $wpdb->blogs, array( 'site_id' => $network_id, 'blog_id' => 1, 'domain' => $domain, 'path' => $path, 'registered' => current_time( 'mysql' ) ) ); + $current_site->blog_id = $blog_id = $wpdb->insert_id; + update_user_meta( $site_user->ID, 'source_domain', $domain ); + update_user_meta( $site_user->ID, 'primary_blog', $blog_id ); + + if ( $subdomain_install ) + $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' ); + else + $wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' ); + + flush_rewrite_rules(); + + if ( ! $subdomain_install ) + return true; + + $vhost_ok = false; + $errstr = ''; + $hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname! + $page = wp_remote_get( 'http://' . $hostname, array( 'timeout' => 5, 'httpversion' => '1.1' ) ); + if ( is_wp_error( $page ) ) + $errstr = $page->get_error_message(); + elseif ( 200 == wp_remote_retrieve_response_code( $page ) ) + $vhost_ok = true; + + if ( ! $vhost_ok ) { + $msg = '

    ' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '

    '; + $msg .= '

    ' . sprintf( __( 'The installer attempted to contact a random hostname (%1$s) on your domain.' ), $hostname ); + if ( ! empty ( $errstr ) ) + $msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '' . $errstr . '' ); + $msg .= '

    '; + $msg .= '

    ' . __( 'To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a * hostname record pointing at your web server in your DNS configuration tool.' ) . '

    '; + $msg .= '

    ' . __( 'You can still use your site but any subdomain you create may not be accessible. If you know your DNS is correct, ignore this message.' ) . '

    '; + return new WP_Error( 'no_wildcard_dns', $msg ); + } + } + + return true; +} diff --git a/sources/wp-admin/includes/screen.php b/sources/wp-admin/includes/screen.php new file mode 100644 index 0000000..2ab5161 --- /dev/null +++ b/sources/wp-admin/includes/screen.php @@ -0,0 +1,1080 @@ + UI String + */ +function get_column_headers( $screen ) { + if ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + static $column_headers = array(); + + if ( ! isset( $column_headers[ $screen->id ] ) ) + $column_headers[ $screen->id ] = apply_filters( 'manage_' . $screen->id . '_columns', array() ); + + return $column_headers[ $screen->id ]; +} + +/** + * Get a list of hidden columns. + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen The screen you want the hidden columns for + * @return array + */ +function get_hidden_columns( $screen ) { + if ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + return (array) get_user_option( 'manage' . $screen->id . 'columnshidden' ); +} + +/** + * Prints the meta box preferences for screen meta. + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen + */ +function meta_box_prefs( $screen ) { + global $wp_meta_boxes; + + if ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + if ( empty($wp_meta_boxes[$screen->id]) ) + return; + + $hidden = get_hidden_meta_boxes($screen); + + foreach ( array_keys($wp_meta_boxes[$screen->id]) as $context ) { + foreach ( array_keys($wp_meta_boxes[$screen->id][$context]) as $priority ) { + foreach ( $wp_meta_boxes[$screen->id][$context][$priority] as $box ) { + if ( false == $box || ! $box['title'] ) + continue; + // Submit box cannot be hidden + if ( 'submitdiv' == $box['id'] || 'linksubmitdiv' == $box['id'] ) + continue; + $box_id = $box['id']; + echo '\n"; + } + } + } +} + +/** + * Get Hidden Meta Boxes + * + * @since 2.7.0 + * + * @param string|WP_Screen $screen Screen identifier + * @return array Hidden Meta Boxes + */ +function get_hidden_meta_boxes( $screen ) { + if ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + $hidden = get_user_option( "metaboxhidden_{$screen->id}" ); + + $use_defaults = ! is_array( $hidden ); + + // Hide slug boxes by default + if ( $use_defaults ) { + $hidden = array(); + if ( 'post' == $screen->base ) { + if ( 'post' == $screen->post_type || 'page' == $screen->post_type || 'attachment' == $screen->post_type ) + $hidden = array('slugdiv', 'trackbacksdiv', 'postcustom', 'postexcerpt', 'commentstatusdiv', 'commentsdiv', 'authordiv', 'revisionsdiv'); + else + $hidden = array( 'slugdiv' ); + } + $hidden = apply_filters( 'default_hidden_meta_boxes', $hidden, $screen ); + } + + return apply_filters( 'hidden_meta_boxes', $hidden, $screen, $use_defaults ); +} + +/** + * Register and configure an admin screen option + * + * @since 3.1.0 + * + * @param string $option An option name. + * @param mixed $args Option-dependent arguments. + */ +function add_screen_option( $option, $args = array() ) { + $current_screen = get_current_screen(); + + if ( ! $current_screen ) + return; + + $current_screen->add_option( $option, $args ); +} + +/** + * Displays a screen icon. + * + * @uses get_screen_icon() + * @since 2.7.0 + * + * @param string|WP_Screen $screen Optional. Accepts a screen object (and defaults to the current screen object) + * which it uses to determine an icon HTML ID. Or, if a string is provided, it is used to form the icon HTML ID. + */ +function screen_icon( $screen = '' ) { + echo get_screen_icon( $screen ); +} + +/** + * Gets a screen icon. + * + * @since 3.2.0 + * + * @global $post_ID + * @param string|WP_Screen $screen Optional. Accepts a screen object (and defaults to the current screen object) + * which it uses to determine an icon HTML ID. Or, if a string is provided, it is used to form the icon HTML ID. + * @return string HTML for the screen icon. + */ +function get_screen_icon( $screen = '' ) { + if ( empty( $screen ) ) + $screen = get_current_screen(); + elseif ( is_string( $screen ) ) + $icon_id = $screen; + + $class = 'icon32'; + + if ( empty( $icon_id ) ) { + if ( ! empty( $screen->parent_base ) ) + $icon_id = $screen->parent_base; + else + $icon_id = $screen->base; + + if ( 'page' == $screen->post_type ) + $icon_id = 'edit-pages'; + + if ( $screen->post_type ) + $class .= ' ' . sanitize_html_class( 'icon32-posts-' . $screen->post_type ); + } + + return '

    '; +} + +/** + * Get the current screen object + * + * @since 3.1.0 + * + * @return WP_Screen Current screen object + */ +function get_current_screen() { + global $current_screen; + + if ( ! isset( $current_screen ) ) + return null; + + return $current_screen; +} + +/** + * Set the current screen object + * + * @since 3.0.0 + * @uses $current_screen + * + * @param mixed $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen, + * or an existing screen object. + */ +function set_current_screen( $hook_name = '' ) { + WP_Screen::get( $hook_name )->set_current_screen(); +} + +/** + * A class representing the admin screen. + * + * @since 3.3.0 + * @access public + */ +final class WP_Screen { + /** + * Any action associated with the screen. 'add' for *-add.php and *-new.php screens. Empty otherwise. + * + * @since 3.3.0 + * @var string + * @access public + */ + public $action; + + /** + * The base type of the screen. This is typically the same as $id but with any post types and taxonomies stripped. + * For example, for an $id of 'edit-post' the base is 'edit'. + * + * @since 3.3.0 + * @var string + * @access public + */ + public $base; + + /** + * The number of columns to display. Access with get_columns(). + * + * @since 3.4.0 + * @var int + * @access private + */ + private $columns = 0; + + /** + * The unique ID of the screen. + * + * @since 3.3.0 + * @var string + * @access public + */ + public $id; + + /** + * Which admin the screen is in. network | user | site | false + * + * @since 3.5.0 + * @var string + * @access protected + */ + protected $in_admin; + + /** + * Whether the screen is in the network admin. + * + * Deprecated. Use in_admin() instead. + * + * @since 3.3.0 + * @deprecated 3.5.0 + * @var bool + * @access public + */ + public $is_network; + + /** + * Whether the screen is in the user admin. + * + * Deprecated. Use in_admin() instead. + * + * @since 3.3.0 + * @deprecated 3.5.0 + * @var bool + * @access public + */ + public $is_user; + + /** + * The base menu parent. + * This is derived from $parent_file by removing the query string and any .php extension. + * $parent_file values of 'edit.php?post_type=page' and 'edit.php?post_type=post' have a $parent_base of 'edit'. + * + * @since 3.3.0 + * @var string + * @access public + */ + public $parent_base; + + /** + * The parent_file for the screen per the admin menu system. + * Some $parent_file values are 'edit.php?post_type=page', 'edit.php', and 'options-general.php'. + * + * @since 3.3.0 + * @var string + * @access public + */ + public $parent_file; + + /** + * The post type associated with the screen, if any. + * The 'edit.php?post_type=page' screen has a post type of 'page'. + * The 'edit-tags.php?taxonomy=$taxonomy&post_type=page' screen has a post type of 'page'. + * + * @since 3.3.0 + * @var string + * @access public + */ + public $post_type; + + /** + * The taxonomy associated with the screen, if any. + * The 'edit-tags.php?taxonomy=category' screen has a taxonomy of 'category'. + * @since 3.3.0 + * @var string + * @access public + */ + public $taxonomy; + + /** + * The help tab data associated with the screen, if any. + * + * @since 3.3.0 + * @var array + * @access private + */ + private $_help_tabs = array(); + + /** + * The help sidebar data associated with screen, if any. + * + * @since 3.3.0 + * @var string + * @access private + */ + private $_help_sidebar = ''; + + /** + * Stores old string-based help. + */ + private static $_old_compat_help = array(); + + /** + * The screen options associated with screen, if any. + * + * @since 3.3.0 + * @var array + * @access private + */ + private $_options = array(); + + /** + * The screen object registry. + * + * @since 3.3.0 + * @var array + * @access private + */ + private static $_registry = array(); + + /** + * Stores the result of the public show_screen_options function. + * + * @since 3.3.0 + * @var bool + * @access private + */ + private $_show_screen_options; + + /** + * Stores the 'screen_settings' section of screen options. + * + * @since 3.3.0 + * @var string + * @access private + */ + private $_screen_settings; + + /** + * Fetches a screen object. + * + * @since 3.3.0 + * @access public + * + * @param string $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen. + * Defaults to the current $hook_suffix global. + * @return WP_Screen Screen object. + */ + public static function get( $hook_name = '' ) { + + if ( is_a( $hook_name, 'WP_Screen' ) ) + return $hook_name; + + $post_type = $taxonomy = null; + $in_admin = false; + $action = ''; + + if ( $hook_name ) + $id = $hook_name; + else + $id = $GLOBALS['hook_suffix']; + + // For those pesky meta boxes. + if ( $hook_name && post_type_exists( $hook_name ) ) { + $post_type = $id; + $id = 'post'; // changes later. ends up being $base. + } else { + if ( '.php' == substr( $id, -4 ) ) + $id = substr( $id, 0, -4 ); + + if ( 'post-new' == $id || 'link-add' == $id || 'media-new' == $id || 'user-new' == $id ) { + $id = substr( $id, 0, -4 ); + $action = 'add'; + } + } + + if ( ! $post_type && $hook_name ) { + if ( '-network' == substr( $id, -8 ) ) { + $id = substr( $id, 0, -8 ); + $in_admin = 'network'; + } elseif ( '-user' == substr( $id, -5 ) ) { + $id = substr( $id, 0, -5 ); + $in_admin = 'user'; + } + + $id = sanitize_key( $id ); + if ( 'edit-comments' != $id && 'edit-tags' != $id && 'edit-' == substr( $id, 0, 5 ) ) { + $maybe = substr( $id, 5 ); + if ( taxonomy_exists( $maybe ) ) { + $id = 'edit-tags'; + $taxonomy = $maybe; + } elseif ( post_type_exists( $maybe ) ) { + $id = 'edit'; + $post_type = $maybe; + } + } + + if ( ! $in_admin ) + $in_admin = 'site'; + } else { + if ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) + $in_admin = 'network'; + elseif ( defined( 'WP_USER_ADMIN' ) && WP_USER_ADMIN ) + $in_admin = 'user'; + else + $in_admin = 'site'; + } + + if ( 'index' == $id ) + $id = 'dashboard'; + elseif ( 'front' == $id ) + $in_admin = false; + + $base = $id; + + // If this is the current screen, see if we can be more accurate for post types and taxonomies. + if ( ! $hook_name ) { + if ( isset( $_REQUEST['post_type'] ) ) + $post_type = post_type_exists( $_REQUEST['post_type'] ) ? $_REQUEST['post_type'] : false; + if ( isset( $_REQUEST['taxonomy'] ) ) + $taxonomy = taxonomy_exists( $_REQUEST['taxonomy'] ) ? $_REQUEST['taxonomy'] : false; + + switch ( $base ) { + case 'post' : + if ( isset( $_GET['post'] ) ) + $post_id = (int) $_GET['post']; + elseif ( isset( $_POST['post_ID'] ) ) + $post_id = (int) $_POST['post_ID']; + else + $post_id = 0; + + if ( $post_id ) { + $post = get_post( $post_id ); + if ( $post ) + $post_type = $post->post_type; + } + break; + case 'edit-tags' : + if ( null === $post_type && is_object_in_taxonomy( 'post', $taxonomy ? $taxonomy : 'post_tag' ) ) + $post_type = 'post'; + break; + } + } + + switch ( $base ) { + case 'post' : + if ( null === $post_type ) + $post_type = 'post'; + $id = $post_type; + break; + case 'edit' : + if ( null === $post_type ) + $post_type = 'post'; + $id .= '-' . $post_type; + break; + case 'edit-tags' : + if ( null === $taxonomy ) + $taxonomy = 'post_tag'; + // The edit-tags ID does not contain the post type. Look for it in the request. + if ( null === $post_type ) { + $post_type = 'post'; + if ( isset( $_REQUEST['post_type'] ) && post_type_exists( $_REQUEST['post_type'] ) ) + $post_type = $_REQUEST['post_type']; + } + + $id = 'edit-' . $taxonomy; + break; + } + + if ( 'network' == $in_admin ) { + $id .= '-network'; + $base .= '-network'; + } elseif ( 'user' == $in_admin ) { + $id .= '-user'; + $base .= '-user'; + } + + if ( isset( self::$_registry[ $id ] ) ) { + $screen = self::$_registry[ $id ]; + if ( $screen === get_current_screen() ) + return $screen; + } else { + $screen = new WP_Screen(); + $screen->id = $id; + } + + $screen->base = $base; + $screen->action = $action; + $screen->post_type = (string) $post_type; + $screen->taxonomy = (string) $taxonomy; + $screen->is_user = ( 'user' == $in_admin ); + $screen->is_network = ( 'network' == $in_admin ); + $screen->in_admin = $in_admin; + + self::$_registry[ $id ] = $screen; + + return $screen; + } + + /** + * Makes the screen object the current screen. + * + * @see set_current_screen() + * @since 3.3.0 + */ + function set_current_screen() { + global $current_screen, $taxnow, $typenow; + $current_screen = $this; + $taxnow = $this->taxonomy; + $typenow = $this->post_type; + do_action( 'current_screen', $current_screen ); + } + + /** + * Constructor + * + * @since 3.3.0 + * @access private + */ + private function __construct() {} + + /** + * Indicates whether the screen is in a particular admin + * + * @since 3.5.0 + * + * @param string $admin The admin to check against (network | user | site). + * If empty any of the three admins will result in true. + * @return boolean True if the screen is in the indicated admin, false otherwise. + * + */ + public function in_admin( $admin = null ) { + if ( empty( $admin ) ) + return (bool) $this->in_admin; + + return ( $admin == $this->in_admin ); + } + + /** + * Sets the old string-based contextual help for the screen. + * + * For backwards compatibility. + * + * @since 3.3.0 + * + * @param WP_Screen $screen A screen object. + * @param string $help Help text. + */ + static function add_old_compat_help( $screen, $help ) { + self::$_old_compat_help[ $screen->id ] = $help; + } + + /** + * Set the parent information for the screen. + * This is called in admin-header.php after the menu parent for the screen has been determined. + * + * @since 3.3.0 + * + * @param string $parent_file The parent file of the screen. Typically the $parent_file global. + */ + function set_parentage( $parent_file ) { + $this->parent_file = $parent_file; + list( $this->parent_base ) = explode( '?', $parent_file ); + $this->parent_base = str_replace( '.php', '', $this->parent_base ); + } + + /** + * Adds an option for the screen. + * Call this in template files after admin.php is loaded and before admin-header.php is loaded to add screen options. + * + * @since 3.3.0 + * + * @param string $option Option ID + * @param mixed $args Option-dependent arguments. + */ + public function add_option( $option, $args = array() ) { + $this->_options[ $option ] = $args; + } + + /** + * Gets the arguments for an option for the screen. + * + * @since 3.3.0 + * + * @param string $option Option ID. + * @param mixed $key Optional. Specific array key for when the option is an array. + */ + public function get_option( $option, $key = false ) { + if ( ! isset( $this->_options[ $option ] ) ) + return null; + if ( $key ) { + if ( isset( $this->_options[ $option ][ $key ] ) ) + return $this->_options[ $option ][ $key ]; + return null; + } + return $this->_options[ $option ]; + } + + /** + * Gets the help tabs registered for the screen. + * + * @since 3.4.0 + * + * @return array Help tabs with arguments. + */ + public function get_help_tabs() { + return $this->_help_tabs; + } + + /** + * Gets the arguments for a help tab. + * + * @since 3.4.0 + * + * @param string $id Help Tab ID. + * @return array Help tab arguments. + */ + public function get_help_tab( $id ) { + if ( ! isset( $this->_help_tabs[ $id ] ) ) + return null; + return $this->_help_tabs[ $id ]; + } + + /** + * Add a help tab to the contextual help for the screen. + * Call this on the load-$pagenow hook for the relevant screen. + * + * @since 3.3.0 + * + * @param array $args + * - string - title - Title for the tab. + * - string - id - Tab ID. Must be HTML-safe. + * - string - content - Help tab content in plain text or HTML. Optional. + * - callback - callback - A callback to generate the tab content. Optional. + * + */ + public function add_help_tab( $args ) { + $defaults = array( + 'title' => false, + 'id' => false, + 'content' => '', + 'callback' => false, + ); + $args = wp_parse_args( $args, $defaults ); + + $args['id'] = sanitize_html_class( $args['id'] ); + + // Ensure we have an ID and title. + if ( ! $args['id'] || ! $args['title'] ) + return; + + // Allows for overriding an existing tab with that ID. + $this->_help_tabs[ $args['id'] ] = $args; + } + + /** + * Removes a help tab from the contextual help for the screen. + * + * @since 3.3.0 + * + * @param string $id The help tab ID. + */ + public function remove_help_tab( $id ) { + unset( $this->_help_tabs[ $id ] ); + } + + /** + * Removes all help tabs from the contextual help for the screen. + * + * @since 3.3.0 + */ + public function remove_help_tabs() { + $this->_help_tabs = array(); + } + + /** + * Gets the content from a contextual help sidebar. + * + * @since 3.4.0 + * + * @return string Contents of the help sidebar. + */ + public function get_help_sidebar() { + return $this->_help_sidebar; + } + + /** + * Add a sidebar to the contextual help for the screen. + * Call this in template files after admin.php is loaded and before admin-header.php is loaded to add a sidebar to the contextual help. + * + * @since 3.3.0 + * + * @param string $content Sidebar content in plain text or HTML. + */ + public function set_help_sidebar( $content ) { + $this->_help_sidebar = $content; + } + + /** + * Gets the number of layout columns the user has selected. + * + * The layout_columns option controls the max number and default number of + * columns. This method returns the number of columns within that range selected + * by the user via Screen Options. If no selection has been made, the default + * provisioned in layout_columns is returned. If the screen does not support + * selecting the number of layout columns, 0 is returned. + * + * @since 3.4.0 + * + * @return int Number of columns to display. + */ + public function get_columns() { + return $this->columns; + } + + /** + * Render the screen's help section. + * + * This will trigger the deprecated filters for backwards compatibility. + * + * @since 3.3.0 + */ + public function render_screen_meta() { + + // Call old contextual_help_list filter. + self::$_old_compat_help = apply_filters( 'contextual_help_list', self::$_old_compat_help, $this ); + + $old_help = isset( self::$_old_compat_help[ $this->id ] ) ? self::$_old_compat_help[ $this->id ] : ''; + $old_help = apply_filters( 'contextual_help', $old_help, $this->id, $this ); + + // Default help only if there is no old-style block of text and no new-style help tabs. + if ( empty( $old_help ) && ! $this->get_help_tabs() ) { + $default_help = apply_filters( 'default_contextual_help', '' ); + if ( $default_help ) + $old_help = '

    ' . $default_help . '

    '; + } + + if ( $old_help ) { + $this->add_help_tab( array( + 'id' => 'old-contextual-help', + 'title' => __('Overview'), + 'content' => $old_help, + ) ); + } + + $help_sidebar = $this->get_help_sidebar(); + + $help_class = 'hidden'; + if ( ! $help_sidebar ) + $help_class .= ' no-sidebar'; + + // Time to render! + ?> +
    + +
    +
    +
    +
    +
      + get_help_tabs() as $tab ) : + $link_id = "tab-link-{$tab['id']}"; + $panel_id = "tab-panel-{$tab['id']}"; + ?> + + + +
    +
    + + +
    + +
    + + +
    + get_help_tabs() as $tab ): + $panel_id = "tab-panel-{$tab['id']}"; + ?> + +
    + +
    + +
    +
    +
    + id, $this ); + + if ( ! empty( $columns ) && isset( $columns[ $this->id ] ) ) + $this->add_option( 'layout_columns', array('max' => $columns[ $this->id ] ) ); + + if ( $this->get_option( 'layout_columns' ) ) { + $this->columns = (int) get_user_option("screen_layout_$this->id"); + + if ( ! $this->columns && $this->get_option( 'layout_columns', 'default' ) ) + $this->columns = $this->get_option( 'layout_columns', 'default' ); + } + $GLOBALS[ 'screen_layout_columns' ] = $this->columns; // Set the global for back-compat. + + // Add screen options + if ( $this->show_screen_options() ) + $this->render_screen_options(); + ?> +
    + get_help_tabs() && ! $this->show_screen_options() ) + return; + ?> + + _show_screen_options ) ) + return $this->_show_screen_options; + + $columns = get_column_headers( $this ); + + $show_screen = ! empty( $wp_meta_boxes[ $this->id ] ) || $columns || $this->get_option( 'per_page' ); + + switch ( $this->id ) { + case 'widgets': + $this->_screen_settings = '

    ' . __('Enable accessibility mode') . '' . __('Disable accessibility mode') . "

    \n"; + break; + default: + $this->_screen_settings = ''; + break; + } + + $this->_screen_settings = apply_filters( 'screen_settings', $this->_screen_settings, $this ); + + if ( $this->_screen_settings || $this->_options ) + $show_screen = true; + + $this->_show_screen_options = apply_filters( 'screen_options_show_screen', $show_screen, $this ); + return $this->_show_screen_options; + } + + /** + * Render the screen options tab. + * + * @since 3.3.0 + */ + public function render_screen_options() { + global $wp_meta_boxes, $wp_list_table; + + $columns = get_column_headers( $this ); + $hidden = get_hidden_columns( $this ); + $post = get_post(); + + ?> + + get_option('layout_columns') ) + return; + + $screen_layout_columns = $this->get_columns(); + $num = $this->get_option( 'layout_columns', 'max' ); + + ?> +
    +
    + + +
    + get_option( 'per_page' ) ) + return; + + $per_page_label = $this->get_option( 'per_page', 'label' ); + + $option = $this->get_option( 'per_page', 'option' ); + if ( ! $option ) + $option = str_replace( '-', '_', "{$this->id}_per_page" ); + + $per_page = (int) get_user_option( $option ); + if ( empty( $per_page ) || $per_page < 1 ) { + $per_page = $this->get_option( 'per_page', 'default' ); + if ( ! $per_page ) + $per_page = 20; + } + + if ( 'edit_comments_per_page' == $option ) { + $comment_status = isset( $_REQUEST['comment_status'] ) ? $_REQUEST['comment_status'] : 'all'; + $per_page = apply_filters( 'comments_per_page', $per_page, $comment_status ); + } elseif ( 'categories_per_page' == $option ) { + $per_page = apply_filters( 'edit_categories_per_page', $per_page ); + } else { + $per_page = apply_filters( $option, $per_page ); + } + + // Back compat + if ( isset( $this->post_type ) ) + $per_page = apply_filters( 'edit_posts_per_page', $per_page, $this->post_type ); + + ?> +
    + + + + + +
    + $cat_name, 'category_parent' => $parent) ); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.0.0 + * + * @param unknown_type $categories + * @param unknown_type $post_id + * @return unknown + */ +function wp_create_categories($categories, $post_id = '') { + $cat_ids = array (); + foreach ($categories as $category) { + if ($id = category_exists($category)) + $cat_ids[] = $id; + else + if ($id = wp_create_category($category)) + $cat_ids[] = $id; + } + + if ( $post_id ) + wp_set_post_categories($post_id, $cat_ids); + + return $cat_ids; +} + +/** + * Updates an existing Category or creates a new Category. + * + * @since 2.0.0 + * + * @param mixed $catarr See defaults below. Set 'cat_ID' to a non-zero value to update an existing category. The 'taxonomy' key was added in 3.0.0. + * @param bool $wp_error Optional, since 2.5.0. Set this to true if the caller handles WP_Error return values. + * @return int|object The ID number of the new or updated Category on success. Zero or a WP_Error on failure, depending on param $wp_error. + */ +function wp_insert_category($catarr, $wp_error = false) { + $cat_defaults = array('cat_ID' => 0, 'taxonomy' => 'category', 'cat_name' => '', 'category_description' => '', 'category_nicename' => '', 'category_parent' => ''); + $catarr = wp_parse_args($catarr, $cat_defaults); + extract($catarr, EXTR_SKIP); + + if ( trim( $cat_name ) == '' ) { + if ( ! $wp_error ) + return 0; + else + return new WP_Error( 'cat_name', __('You did not enter a category name.') ); + } + + $cat_ID = (int) $cat_ID; + + // Are we updating or creating? + if ( !empty ($cat_ID) ) + $update = true; + else + $update = false; + + $name = $cat_name; + $description = $category_description; + $slug = $category_nicename; + $parent = $category_parent; + + $parent = (int) $parent; + if ( $parent < 0 ) + $parent = 0; + + if ( empty( $parent ) || ! term_exists( $parent, $taxonomy ) || ( $cat_ID && term_is_ancestor_of( $cat_ID, $parent, $taxonomy ) ) ) + $parent = 0; + + $args = compact('name', 'slug', 'parent', 'description'); + + if ( $update ) + $cat_ID = wp_update_term($cat_ID, $taxonomy, $args); + else + $cat_ID = wp_insert_term($cat_name, $taxonomy, $args); + + if ( is_wp_error($cat_ID) ) { + if ( $wp_error ) + return $cat_ID; + else + return 0; + } + + return $cat_ID['term_id']; +} + +/** + * Aliases wp_insert_category() with minimal args. + * + * If you want to update only some fields of an existing category, call this + * function with only the new values set inside $catarr. + * + * @since 2.0.0 + * + * @param array $catarr The 'cat_ID' value is required. All other keys are optional. + * @return int|bool The ID number of the new or updated Category on success. Zero or FALSE on failure. + */ +function wp_update_category($catarr) { + $cat_ID = (int) $catarr['cat_ID']; + + if ( isset($catarr['category_parent']) && ($cat_ID == $catarr['category_parent']) ) + return false; + + // First, get all of the original fields + $category = get_term( $cat_ID, 'category', ARRAY_A ); + _make_cat_compat( $category ); + + // Escape data pulled from DB. + $category = wp_slash($category); + + // Merge old and new fields with new fields overwriting old ones. + $catarr = array_merge($category, $catarr); + + return wp_insert_category($catarr); +} + +// +// Tags +// + +/** + * {@internal Missing Short Description}} + * + * @since 2.3.0 + * + * @param unknown_type $tag_name + * @return unknown + */ +function tag_exists($tag_name) { + return term_exists($tag_name, 'post_tag'); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.3.0 + * + * @param unknown_type $tag_name + * @return unknown + */ +function wp_create_tag($tag_name) { + return wp_create_term( $tag_name, 'post_tag'); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.3.0 + * + * @param unknown_type $post_id + * @return unknown + */ +function get_tags_to_edit( $post_id, $taxonomy = 'post_tag' ) { + return get_terms_to_edit( $post_id, $taxonomy); +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.8.0 + * + * @param unknown_type $post_id + * @return unknown + */ +function get_terms_to_edit( $post_id, $taxonomy = 'post_tag' ) { + $post_id = (int) $post_id; + if ( !$post_id ) + return false; + + $tags = wp_get_post_terms($post_id, $taxonomy, array()); + + if ( !$tags ) + return false; + + if ( is_wp_error($tags) ) + return $tags; + + foreach ( $tags as $tag ) + $tag_names[] = $tag->name; + $tags_to_edit = join( ',', $tag_names ); + $tags_to_edit = esc_attr( $tags_to_edit ); + $tags_to_edit = apply_filters( 'terms_to_edit', $tags_to_edit, $taxonomy ); + + return $tags_to_edit; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.8.0 + * + * @param unknown_type $tag_name + * @return unknown + */ +function wp_create_term($tag_name, $taxonomy = 'post_tag') { + if ( $id = term_exists($tag_name, $taxonomy) ) + return $id; + + return wp_insert_term($tag_name, $taxonomy); +} diff --git a/sources/wp-admin/includes/template.php b/sources/wp-admin/includes/template.php new file mode 100644 index 0000000..ad42074 --- /dev/null +++ b/sources/wp-admin/includes/template.php @@ -0,0 +1,1962 @@ + elements. + * + * @see Walker + * @see wp_category_checklist() + * @see wp_terms_checklist() + * @since 2.5.1 + */ +class Walker_Category_Checklist extends Walker { + var $tree_type = 'category'; + var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); //TODO: decouple this + + /** + * Starts the list before the elements are added. + * + * @see Walker:start_lvl() + * + * @since 2.5.1 + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of category. Used for tab indentation. + * @param array $args An array of arguments. @see wp_terms_checklist() + */ + function start_lvl( &$output, $depth = 0, $args = array() ) { + $indent = str_repeat("\t", $depth); + $output .= "$indent
      \n"; + } + + /** + * Ends the list of after the elements are added. + * + * @see Walker::end_lvl() + * + * @since 2.5.1 + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of category. Used for tab indentation. + * @param array $args An array of arguments. @see wp_terms_checklist() + */ + function end_lvl( &$output, $depth = 0, $args = array() ) { + $indent = str_repeat("\t", $depth); + $output .= "$indent
    \n"; + } + + /** + * Start the element output. + * + * @see Walker::start_el() + * + * @since 2.5.1 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $category The current term object. + * @param int $depth Depth of the term in reference to parents. Default 0. + * @param array $args An array of arguments. @see wp_terms_checklist() + * @param int $id ID of the current term. + */ + function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) { + extract($args); + if ( empty($taxonomy) ) + $taxonomy = 'category'; + + if ( $taxonomy == 'category' ) + $name = 'post_category'; + else + $name = 'tax_input['.$taxonomy.']'; + + $class = in_array( $category->term_id, $popular_cats ) ? ' class="popular-category"' : ''; + $output .= "\n
  • " . ''; + } + + /** + * Ends the element output, if needed. + * + * @see Walker::end_el() + * + * @since 2.5.1 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $category The current term object. + * @param int $depth Depth of the term in reference to parents. Default 0. + * @param array $args An array of arguments. @see wp_terms_checklist() + */ + function end_el( &$output, $category, $depth = 0, $args = array() ) { + $output .= "
  • \n"; + } +} + +/** + * Output an unordered list of checkbox elements labelled + * with category names. + * + * @see wp_terms_checklist() + * @since 2.5.1 + * + * @param int $post_id Mark categories associated with this post as checked. $selected_cats must not be an array. + * @param int $descendants_and_self ID of the category to output along with its descendents. + * @param bool|array $selected_cats List of categories to mark as checked. + * @param bool|array $popular_cats Override the list of categories that receive the "popular-category" class. + * @param object $walker Walker object to use to build the output. + * @param bool $checked_ontop Move checked items out of the hierarchy and to the top of the list. + */ +function wp_category_checklist( $post_id = 0, $descendants_and_self = 0, $selected_cats = false, $popular_cats = false, $walker = null, $checked_ontop = true ) { + wp_terms_checklist( $post_id, array( + 'taxonomy' => 'category', + 'descendants_and_self' => $descendants_and_self, + 'selected_cats' => $selected_cats, + 'popular_cats' => $popular_cats, + 'walker' => $walker, + 'checked_ontop' => $checked_ontop + ) ); +} + +/** + * Output an unordered list of checkbox elements labelled + * with term names. Taxonomy independent version of wp_category_checklist(). + * + * @since 3.0.0 + * + * @param int $post_id + * @param array $args + */ +function wp_terms_checklist($post_id = 0, $args = array()) { + $defaults = array( + 'descendants_and_self' => 0, + 'selected_cats' => false, + 'popular_cats' => false, + 'walker' => null, + 'taxonomy' => 'category', + 'checked_ontop' => true + ); + $args = apply_filters( 'wp_terms_checklist_args', $args, $post_id ); + + extract( wp_parse_args($args, $defaults), EXTR_SKIP ); + + if ( empty($walker) || !is_a($walker, 'Walker') ) + $walker = new Walker_Category_Checklist; + + $descendants_and_self = (int) $descendants_and_self; + + $args = array('taxonomy' => $taxonomy); + + $tax = get_taxonomy($taxonomy); + $args['disabled'] = !current_user_can($tax->cap->assign_terms); + + if ( is_array( $selected_cats ) ) + $args['selected_cats'] = $selected_cats; + elseif ( $post_id ) + $args['selected_cats'] = wp_get_object_terms($post_id, $taxonomy, array_merge($args, array('fields' => 'ids'))); + else + $args['selected_cats'] = array(); + + if ( is_array( $popular_cats ) ) + $args['popular_cats'] = $popular_cats; + else + $args['popular_cats'] = get_terms( $taxonomy, array( 'fields' => 'ids', 'orderby' => 'count', 'order' => 'DESC', 'number' => 10, 'hierarchical' => false ) ); + + if ( $descendants_and_self ) { + $categories = (array) get_terms($taxonomy, array( 'child_of' => $descendants_and_self, 'hierarchical' => 0, 'hide_empty' => 0 ) ); + $self = get_term( $descendants_and_self, $taxonomy ); + array_unshift( $categories, $self ); + } else { + $categories = (array) get_terms($taxonomy, array('get' => 'all')); + } + + if ( $checked_ontop ) { + // Post process $categories rather than adding an exclude to the get_terms() query to keep the query the same across all posts (for any query cache) + $checked_categories = array(); + $keys = array_keys( $categories ); + + foreach( $keys as $k ) { + if ( in_array( $categories[$k]->term_id, $args['selected_cats'] ) ) { + $checked_categories[] = $categories[$k]; + unset( $categories[$k] ); + } + } + + // Put checked cats on top + echo call_user_func_array(array(&$walker, 'walk'), array($checked_categories, 0, $args)); + } + // Then the rest of them + echo call_user_func_array(array(&$walker, 'walk'), array($categories, 0, $args)); +} + +/** + * Retrieve a list of the most popular terms from the specified taxonomy. + * + * If the $echo argument is true then the elements for a list of checkbox + * elements labelled with the names of the selected terms is output. + * If the $post_ID global isn't empty then the terms associated with that + * post will be marked as checked. + * + * @since 2.5.0 + * + * @param string $taxonomy Taxonomy to retrieve terms from. + * @param int $default Unused. + * @param int $number Number of terms to retrieve. Defaults to 10. + * @param bool $echo Optionally output the list as well. Defaults to true. + * @return array List of popular term IDs. + */ +function wp_popular_terms_checklist( $taxonomy, $default = 0, $number = 10, $echo = true ) { + $post = get_post(); + + if ( $post && $post->ID ) + $checked_terms = wp_get_object_terms($post->ID, $taxonomy, array('fields'=>'ids')); + else + $checked_terms = array(); + + $terms = get_terms( $taxonomy, array( 'orderby' => 'count', 'order' => 'DESC', 'number' => $number, 'hierarchical' => false ) ); + + $tax = get_taxonomy($taxonomy); + + $popular_ids = array(); + foreach ( (array) $terms as $term ) { + $popular_ids[] = $term->term_id; + if ( !$echo ) // hack for AJAX use + continue; + $id = "popular-$taxonomy-$term->term_id"; + $checked = in_array( $term->term_id, $checked_terms ) ? 'checked="checked"' : ''; + ?> + + + + 'name', 'hide_empty' => 0 ) ); + + if ( empty( $categories ) ) + return; + + foreach ( $categories as $category ) { + $cat_id = $category->term_id; + $name = esc_html( apply_filters( 'the_category', $category->name ) ); + $checked = in_array( $cat_id, $checked_categories ) ? ' checked="checked"' : ''; + echo '"; + } +} + +// adds hidden fields with the data for use in the inline editor for posts and pages +/** + * {@internal Missing Short Description}} + * + * @since 2.7.0 + * + * @param unknown_type $post + */ +function get_inline_data($post) { + $post_type_object = get_post_type_object($post->post_type); + if ( ! current_user_can( 'edit_post', $post->ID ) ) + return; + + $title = esc_textarea( trim( $post->post_title ) ); + + echo ' +'; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.7.0 + * + * @param unknown_type $position + * @param unknown_type $checkbox + * @param unknown_type $mode + */ +function wp_comment_reply($position = '1', $checkbox = false, $mode = 'single', $table_row = true) { + // allow plugin to replace the popup content + $content = apply_filters( 'wp_comment_reply', '', array('position' => $position, 'checkbox' => $checkbox, 'mode' => $mode) ); + + if ( ! empty($content) ) { + echo $content; + return; + } + + if ( $mode == 'single' ) { + $wp_list_table = _get_list_table('WP_Post_Comments_List_Table'); + } else { + $wp_list_table = _get_list_table('WP_Comments_List_Table'); + } + +?> +
    + +
    + + + +
    + + + + + + + ' . _x( 'Name', 'meta name' ) . ' + ' . __( 'Value' ) . ' + + + + + +'; //TBODY needed for list-manipulation JS + return; + } + $count = 0; +?> + + + + + + + + + + +
    + + $entry['meta_id'] = (int) $entry['meta_id']; + + $delete_nonce = wp_create_nonce( 'delete-meta_' . $entry['meta_id'] ); + + $r .= "\n\t"; + $r .= "\n\t\t"; + + $r .= "\n\t\t
    "; + $r .= get_submit_button( __( 'Delete' ), 'deletemeta small', "deletemeta[{$entry['meta_id']}]", false, array( 'data-wp-lists' => "delete:the-list:meta-{$entry['meta_id']}::_ajax_nonce=$delete_nonce" ) ); + $r .= "\n\t\t"; + $r .= get_submit_button( __( 'Update' ), 'updatemeta small', "meta-{$entry['meta_id']}-submit", false, array( 'data-wp-lists' => "add:the-list:meta-{$entry['meta_id']}::_ajax_nonce-add-meta=$update_nonce" ) ); + $r .= "
    "; + $r .= wp_nonce_field( 'change-meta', '_ajax_nonce', false, false ); + $r .= ""; + + $r .= "\n\t\t\n\t"; + return $r; +} + +/** + * Prints the form in the Custom Fields meta box. + * + * @since 1.2.0 + * + * @param WP_Post $post Optional. The post being edited. + */ +function meta_form( $post = null ) { + global $wpdb; + $post = get_post( $post ); + $limit = (int) apply_filters( 'postmeta_form_limit', 30 ); + $keys = $wpdb->get_col( " + SELECT meta_key + FROM $wpdb->postmeta + GROUP BY meta_key + HAVING meta_key NOT LIKE '\_%' + ORDER BY meta_key + LIMIT $limit" ); + if ( $keys ) + natcasesort($keys); +?> +

    + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    +
    + 'newmeta-submit', 'data-wp-lists' => 'add:the-list:newmeta' ) ); ?> +
    + +
    +post_status, array('draft', 'pending') ) && (!$post->post_date_gmt || '0000-00-00 00:00:00' == $post->post_date_gmt ) ); + + $tab_index_attribute = ''; + if ( (int) $tab_index > 0 ) + $tab_index_attribute = " tabindex=\"$tab_index\""; + + // echo '
    '; + + $time_adj = current_time('timestamp'); + $post_date = ($for_post) ? $post->post_date : $comment->comment_date; + $jj = ($edit) ? mysql2date( 'd', $post_date, false ) : gmdate( 'd', $time_adj ); + $mm = ($edit) ? mysql2date( 'm', $post_date, false ) : gmdate( 'm', $time_adj ); + $aa = ($edit) ? mysql2date( 'Y', $post_date, false ) : gmdate( 'Y', $time_adj ); + $hh = ($edit) ? mysql2date( 'H', $post_date, false ) : gmdate( 'H', $time_adj ); + $mn = ($edit) ? mysql2date( 'i', $post_date, false ) : gmdate( 'i', $time_adj ); + $ss = ($edit) ? mysql2date( 's', $post_date, false ) : gmdate( 's', $time_adj ); + + $cur_jj = gmdate( 'd', $time_adj ); + $cur_mm = gmdate( 'm', $time_adj ); + $cur_aa = gmdate( 'Y', $time_adj ); + $cur_hh = gmdate( 'H', $time_adj ); + $cur_mn = gmdate( 'i', $time_adj ); + + $month = "'; + + $day = ''; + $year = ''; + $hour = ''; + $minute = ''; + + echo '
    '; + /* translators: 1: month, 2: day, 3: year, 4: hour, 5: minute */ + printf( __( '%1$s %2$s, %3$s @ %4$s : %5$s' ), $month, $day, $year, $hour, $minute ); + + echo '
    '; + + if ( $multi ) return; + + echo "\n\n"; + foreach ( array('mm', 'jj', 'aa', 'hh', 'mn') as $timeunit ) { + echo '' . "\n"; + $cur_timeunit = 'cur_' . $timeunit; + echo '' . "\n"; + } +?> + +

    + + +

    +$template"; + endforeach; +} + +/** + * {@internal Missing Short Description}} + * + * @since 1.5.0 + * + * @param unknown_type $default + * @param unknown_type $parent + * @param unknown_type $level + * @return unknown + */ +function parent_dropdown( $default = 0, $parent = 0, $level = 0 ) { + global $wpdb; + $post = get_post(); + $items = $wpdb->get_results( $wpdb->prepare("SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' ORDER BY menu_order", $parent) ); + + if ( $items ) { + foreach ( $items as $item ) { + // A page cannot be its own parent. + if ( $post && $post->ID && $item->ID == $post->ID ) + continue; + + $pad = str_repeat( ' ', $level * 3 ); + if ( $item->ID == $default) + $current = ' selected="selected"'; + else + $current = ''; + + echo "\n\t"; + parent_dropdown( $default, $item->ID, $level +1 ); + } + } else { + return false; + } +} + +/** + * Print out "; + else + $r .= "\n\t"; + } + echo $p . $r; +} + +/** + * Outputs the form used by the importers to accept the data to be imported + * + * @since 2.0.0 + * + * @param string $action The action attribute for the form. + */ +function wp_import_upload_form( $action ) { + $bytes = apply_filters( 'import_upload_size_limit', wp_max_upload_size() ); + $size = size_format( $bytes ); + $upload_dir = wp_upload_dir(); + if ( ! empty( $upload_dir['error'] ) ) : + ?>

    +

    +
    +

    + () + + + +

    + +
    +id; + + if ( !isset($wp_meta_boxes) ) + $wp_meta_boxes = array(); + if ( !isset($wp_meta_boxes[$page]) ) + $wp_meta_boxes[$page] = array(); + if ( !isset($wp_meta_boxes[$page][$context]) ) + $wp_meta_boxes[$page][$context] = array(); + + foreach ( array_keys($wp_meta_boxes[$page]) as $a_context ) { + foreach ( array('high', 'core', 'default', 'low') as $a_priority ) { + if ( !isset($wp_meta_boxes[$page][$a_context][$a_priority][$id]) ) + continue; + + // If a core box was previously added or removed by a plugin, don't add. + if ( 'core' == $priority ) { + // If core box previously deleted, don't add + if ( false === $wp_meta_boxes[$page][$a_context][$a_priority][$id] ) + return; + // If box was added with default priority, give it core priority to maintain sort order + if ( 'default' == $a_priority ) { + $wp_meta_boxes[$page][$a_context]['core'][$id] = $wp_meta_boxes[$page][$a_context]['default'][$id]; + unset($wp_meta_boxes[$page][$a_context]['default'][$id]); + } + return; + } + // If no priority given and id already present, use existing priority + if ( empty($priority) ) { + $priority = $a_priority; + // else if we're adding to the sorted priority, we don't know the title or callback. Grab them from the previously added context/priority. + } elseif ( 'sorted' == $priority ) { + $title = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['title']; + $callback = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['callback']; + $callback_args = $wp_meta_boxes[$page][$a_context][$a_priority][$id]['args']; + } + // An id can be in only one priority and one context + if ( $priority != $a_priority || $context != $a_context ) + unset($wp_meta_boxes[$page][$a_context][$a_priority][$id]); + } + } + + if ( empty($priority) ) + $priority = 'low'; + + if ( !isset($wp_meta_boxes[$page][$context][$priority]) ) + $wp_meta_boxes[$page][$context][$priority] = array(); + + $wp_meta_boxes[$page][$context][$priority][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $callback_args); +} + +/** + * Meta-Box template function + * + * @since 2.5.0 + * + * @param string|object $screen Screen identifier + * @param string $context box context + * @param mixed $object gets passed to the box callback function as first parameter + * @return int number of meta_boxes + */ +function do_meta_boxes( $screen, $context, $object ) { + global $wp_meta_boxes; + static $already_sorted = false; + + if ( empty( $screen ) ) + $screen = get_current_screen(); + elseif ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + $page = $screen->id; + + $hidden = get_hidden_meta_boxes( $screen ); + + printf('
    ', htmlspecialchars($context)); + + $i = 0; + do { + // Grab the ones the user has manually sorted. Pull them out of their previous context/priority and into the one the user chose + if ( !$already_sorted && $sorted = get_user_option( "meta-box-order_$page" ) ) { + foreach ( $sorted as $box_context => $ids ) { + foreach ( explode(',', $ids ) as $id ) { + if ( $id && 'dashboard_browser_nag' !== $id ) + add_meta_box( $id, null, null, $screen, $box_context, 'sorted' ); + } + } + } + $already_sorted = true; + + if ( !isset($wp_meta_boxes) || !isset($wp_meta_boxes[$page]) || !isset($wp_meta_boxes[$page][$context]) ) + break; + + foreach ( array('high', 'sorted', 'core', 'default', 'low') as $priority ) { + if ( isset($wp_meta_boxes[$page][$context][$priority]) ) { + foreach ( (array) $wp_meta_boxes[$page][$context][$priority] as $box ) { + if ( false == $box || ! $box['title'] ) + continue; + $i++; + $hidden_class = in_array($box['id'], $hidden) ? ' hide-if-js' : ''; + echo '
    ' . "\n"; + if ( 'dashboard_browser_nag' != $box['id'] ) + echo '

    '; + echo "

    {$box['title']}

    \n"; + echo '
    ' . "\n"; + call_user_func($box['callback'], $object, $box); + echo "
    \n"; + echo "
    \n"; + } + } + } + } while(0); + + echo "
    "; + + return $i; + +} + +/** + * Remove a meta box from an edit form. + * + * @since 2.6.0 + * + * @param string $id String for use in the 'id' attribute of tags. + * @param string|object $screen The screen on which to show the box (post, page, link). + * @param string $context The context within the page where the boxes should show ('normal', 'advanced'). + */ +function remove_meta_box($id, $screen, $context) { + global $wp_meta_boxes; + + if ( empty( $screen ) ) + $screen = get_current_screen(); + elseif ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + $page = $screen->id; + + if ( !isset($wp_meta_boxes) ) + $wp_meta_boxes = array(); + if ( !isset($wp_meta_boxes[$page]) ) + $wp_meta_boxes[$page] = array(); + if ( !isset($wp_meta_boxes[$page][$context]) ) + $wp_meta_boxes[$page][$context] = array(); + + foreach ( array('high', 'core', 'default', 'low') as $priority ) + $wp_meta_boxes[$page][$context][$priority][$id] = false; +} + +/** + * Meta Box Accordion Template Function + * + * Largely made up of abstracted code from {@link do_meta_boxes()}, this + * function serves to build meta boxes as list items for display as + * a collapsible accordion. + * + * @since 3.6.0 + * + * @uses global $wp_meta_boxes Used to retrieve registered meta boxes. + * + * @param string|object $screen The screen identifier. + * @param string $context The meta box context. + * @param mixed $object gets passed to the section callback function as first parameter. + * @return int number of meta boxes as accordion sections. + */ +function do_accordion_sections( $screen, $context, $object ) { + global $wp_meta_boxes; + + wp_enqueue_script( 'accordion' ); + + if ( empty( $screen ) ) + $screen = get_current_screen(); + elseif ( is_string( $screen ) ) + $screen = convert_to_screen( $screen ); + + $page = $screen->id; + + $hidden = get_hidden_meta_boxes( $screen ); + ?> +
    +
      + +
    • +

      +
      +
      + +
      +
      +
    • + +
    +
    + $id, 'title' => $title, 'callback' => $callback); +} + +/** + * Add a new field to a section of a settings page + * + * Part of the Settings API. Use this to define a settings field that will show + * as part of a settings section inside a settings page. The fields are shown using + * do_settings_fields() in do_settings-sections() + * + * The $callback argument should be the name of a function that echoes out the + * html input tags for this setting field. Use get_option() to retrieve existing + * values to show. + * + * @since 2.7.0 + * + * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections + * + * @param string $id Slug-name to identify the field. Used in the 'id' attribute of tags. + * @param string $title Formatted title of the field. Shown as the label for the field during output. + * @param string $callback Function that fills the field with the desired form inputs. The function should echo its output. + * @param string $page The slug-name of the settings page on which to show the section (general, reading, writing, ...). + * @param string $section The slug-name of the section of the settings page in which to show the box (default, ...). + * @param array $args Additional arguments + */ +function add_settings_field($id, $title, $callback, $page, $section = 'default', $args = array()) { + global $wp_settings_fields; + + if ( 'misc' == $page ) { + _deprecated_argument( __FUNCTION__, '3.0', __( 'The miscellaneous options group has been removed. Use another settings group.' ) ); + $page = 'general'; + } + + if ( 'privacy' == $page ) { + _deprecated_argument( __FUNCTION__, '3.5', __( 'The privacy options group has been removed. Use another settings group.' ) ); + $page = 'reading'; + } + + $wp_settings_fields[$page][$section][$id] = array('id' => $id, 'title' => $title, 'callback' => $callback, 'args' => $args); +} + +/** + * Prints out all settings sections added to a particular settings page + * + * Part of the Settings API. Use this in a settings page callback function + * to output all the sections and fields that were added to that $page with + * add_settings_section() and add_settings_field() + * + * @global $wp_settings_sections Storage array of all settings sections added to admin pages + * @global $wp_settings_fields Storage array of settings fields and info about their pages/sections + * @since 2.7.0 + * + * @param string $page The slug name of the page whos settings sections you want to output + */ +function do_settings_sections( $page ) { + global $wp_settings_sections, $wp_settings_fields; + + if ( ! isset( $wp_settings_sections[$page] ) ) + return; + + foreach ( (array) $wp_settings_sections[$page] as $section ) { + if ( $section['title'] ) + echo "

    {$section['title']}

    \n"; + + if ( $section['callback'] ) + call_user_func( $section['callback'], $section ); + + if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[$page] ) || !isset( $wp_settings_fields[$page][$section['id']] ) ) + continue; + echo ''; + do_settings_fields( $page, $section['id'] ); + echo '
    '; + } +} + +/** + * Print out the settings fields for a particular settings section + * + * Part of the Settings API. Use this in a settings page to output + * a specific section. Should normally be called by do_settings_sections() + * rather than directly. + * + * @global $wp_settings_fields Storage array of settings fields and their pages/sections + * + * @since 2.7.0 + * + * @param string $page Slug title of the admin page who's settings fields you want to show. + * @param section $section Slug title of the settings section who's fields you want to show. + */ +function do_settings_fields($page, $section) { + global $wp_settings_fields; + + if ( ! isset( $wp_settings_fields[$page][$section] ) ) + return; + + foreach ( (array) $wp_settings_fields[$page][$section] as $field ) { + echo ''; + if ( !empty($field['args']['label_for']) ) + echo ''; + else + echo '' . $field['title'] . ''; + echo ''; + call_user_func($field['callback'], $field['args']); + echo ''; + echo ''; + } +} + +/** + * Register a settings error to be displayed to the user + * + * Part of the Settings API. Use this to show messages to users about settings validation + * problems, missing settings or anything else. + * + * Settings errors should be added inside the $sanitize_callback function defined in + * register_setting() for a given setting to give feedback about the submission. + * + * By default messages will show immediately after the submission that generated the error. + * Additional calls to settings_errors() can be used to show errors even when the settings + * page is first accessed. + * + * @since 3.0.0 + * + * @global array $wp_settings_errors Storage array of errors registered during this pageload + * + * @param string $setting Slug title of the setting to which this error applies + * @param string $code Slug-name to identify the error. Used as part of 'id' attribute in HTML output. + * @param string $message The formatted message text to display to the user (will be shown inside styled
    and

    ) + * @param string $type The type of message it is, controls HTML class. Use 'error' or 'updated'. + */ +function add_settings_error( $setting, $code, $message, $type = 'error' ) { + global $wp_settings_errors; + + $new_error = array( + 'setting' => $setting, + 'code' => $code, + 'message' => $message, + 'type' => $type + ); + $wp_settings_errors[] = $new_error; +} + +/** + * Fetch settings errors registered by add_settings_error() + * + * Checks the $wp_settings_errors array for any errors declared during the current + * pageload and returns them. + * + * If changes were just submitted ($_GET['settings-updated']) and settings errors were saved + * to the 'settings_errors' transient then those errors will be returned instead. This + * is used to pass errors back across pageloads. + * + * Use the $sanitize argument to manually re-sanitize the option before returning errors. + * This is useful if you have errors or notices you want to show even when the user + * hasn't submitted data (i.e. when they first load an options page, or in admin_notices action hook) + * + * @since 3.0.0 + * + * @global array $wp_settings_errors Storage array of errors registered during this pageload + * + * @param string $setting Optional slug title of a specific setting who's errors you want. + * @param boolean $sanitize Whether to re-sanitize the setting value before returning errors. + * @return array Array of settings errors + */ +function get_settings_errors( $setting = '', $sanitize = false ) { + global $wp_settings_errors; + + // If $sanitize is true, manually re-run the sanitization for this option + // This allows the $sanitize_callback from register_setting() to run, adding + // any settings errors you want to show by default. + if ( $sanitize ) + sanitize_option( $setting, get_option( $setting ) ); + + // If settings were passed back from options.php then use them + if ( isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] && get_transient( 'settings_errors' ) ) { + $wp_settings_errors = array_merge( (array) $wp_settings_errors, get_transient( 'settings_errors' ) ); + delete_transient( 'settings_errors' ); + } + + // Check global in case errors have been added on this pageload + if ( ! count( $wp_settings_errors ) ) + return array(); + + // Filter the results to those of a specific setting if one was set + if ( $setting ) { + $setting_errors = array(); + foreach ( (array) $wp_settings_errors as $key => $details ) { + if ( $setting == $details['setting'] ) + $setting_errors[] = $wp_settings_errors[$key]; + } + return $setting_errors; + } + + return $wp_settings_errors; +} + +/** + * Display settings errors registered by add_settings_error() + * + * Part of the Settings API. Outputs a

    for each error retrieved by get_settings_errors(). + * + * This is called automatically after a settings page based on the Settings API is submitted. + * Errors should be added during the validation callback function for a setting defined in register_setting() + * + * The $sanitize option is passed into get_settings_errors() and will re-run the setting sanitization + * on its current value. + * + * The $hide_on_update option will cause errors to only show when the settings page is first loaded. + * if the user has already saved new values it will be hidden to avoid repeating messages already + * shown in the default error reporting after submission. This is useful to show general errors like missing + * settings when the user arrives at the settings page. + * + * @since 3.0.0 + * + * @param string $setting Optional slug title of a specific setting who's errors you want. + * @param boolean $sanitize Whether to re-sanitize the setting value before returning errors. + * @param boolean $hide_on_update If set to true errors will not be shown if the settings page has already been submitted. + */ +function settings_errors( $setting = '', $sanitize = false, $hide_on_update = false ) { + + if ( $hide_on_update && ! empty( $_GET['settings-updated'] ) ) + return; + + $settings_errors = get_settings_errors( $setting, $sanitize ); + + if ( empty( $settings_errors ) ) + return; + + $output = ''; + foreach ( $settings_errors as $key => $details ) { + $css_id = 'setting-error-' . $details['code']; + $css_class = $details['type'] . ' settings-error'; + $output .= "
    \n"; + $output .= "

    {$details['message']}

    "; + $output .= "
    \n"; + } + echo $output; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.7.0 + * + * @param unknown_type $found_action + */ +function find_posts_div($found_action = '') { +?> + +post_password ) ) + echo esc_attr( $post->post_password ); +} + +/** + * Get the post title. + * + * The post title is fetched and if it is blank then a default string is + * returned. + * + * @since 2.7.0 + * @param mixed $post Post id or object. If not supplied the global $post is used. + * @return string The post title if set + */ +function _draft_or_post_title( $post = 0 ) { + $title = get_the_title( $post ); + if ( empty( $title ) ) + $title = __( '(no title)' ); + return $title; +} + +/** + * Display the search query. + * + * A simple wrapper to display the "s" parameter in a GET URI. This function + * should only be used when {@link the_search_query()} cannot. + * + * @uses attr + * @since 2.7.0 + * + */ +function _admin_search_query() { + echo isset($_REQUEST['s']) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : ''; +} + +/** + * Generic Iframe header for use with Thickbox + * + * @since 2.7.0 + * @param string $title Title of the Iframe page. + * @param bool $limit_styles Limit styles to colour-related styles only (unless others are enqueued). + * + */ +function iframe_header( $title = '', $limit_styles = false ) { + show_admin_bar( false ); + global $hook_suffix, $current_user, $admin_body_class, $wp_locale; + $admin_body_class = preg_replace('/[^a-z0-9_-]+/i', '-', $hook_suffix); + + $current_screen = get_current_screen(); + + @header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) ); + _wp_admin_html_begin(); +?> +<?php bloginfo('name') ?> › <?php echo $title ?> — <?php _e('WordPress'); ?> + + + + + class="wp-admin wp-core-ui no-js iframe "> + + + + + + +post_password) ) + $post_states['protected'] = __('Password protected'); + if ( 'private' == $post->post_status && 'private' != $post_status ) + $post_states['private'] = __('Private'); + if ( 'draft' == $post->post_status && 'draft' != $post_status ) + $post_states['draft'] = __('Draft'); + if ( 'pending' == $post->post_status && 'pending' != $post_status ) + /* translators: post state */ + $post_states['pending'] = _x('Pending', 'post state'); + if ( is_sticky($post->ID) ) + $post_states['sticky'] = __('Sticky'); + + $post_states = apply_filters( 'display_post_states', $post_states, $post ); + + if ( ! empty($post_states) ) { + $state_count = count($post_states); + $i = 0; + echo ' - '; + foreach ( $post_states as $state ) { + ++$i; + ( $i == $state_count ) ? $sep = '' : $sep = ', '; + echo "$state$sep"; + } + } + +} + +function _media_states( $post ) { + $media_states = array(); + $stylesheet = get_option('stylesheet'); + + if ( current_theme_supports( 'custom-header') ) { + $meta_header = get_post_meta($post->ID, '_wp_attachment_is_custom_header', true ); + if ( ! empty( $meta_header ) && $meta_header == $stylesheet ) + $media_states[] = __( 'Header Image' ); + } + + if ( current_theme_supports( 'custom-background') ) { + $meta_background = get_post_meta($post->ID, '_wp_attachment_is_custom_background', true ); + if ( ! empty( $meta_background ) && $meta_background == $stylesheet ) + $media_states[] = __( 'Background Image' ); + } + + $media_states = apply_filters( 'display_media_states', $media_states ); + + if ( ! empty( $media_states ) ) { + $state_count = count( $media_states ); + $i = 0; + echo ' - '; + foreach ( $media_states as $state ) { + ++$i; + ( $i == $state_count ) ? $sep = '' : $sep = ', '; + echo "$state$sep"; + } + } +} + +/** + * Test support for compressing JavaScript from PHP + * + * Outputs JavaScript that tests if compression from PHP works as expected + * and sets an option with the result. Has no effect when the current user + * is not an administrator. To run the test again the option 'can_compress_scripts' + * has to be deleted. + * + * @since 2.8.0 + */ +function compression_test() { +?> + + '1' ). + * These attributes will be output as attribute="value", such as tabindex="1". + * Defaults to no other attributes. Other attributes can also be provided as a + * string such as 'tabindex="1"', though the array format is typically cleaner. + */ +function submit_button( $text = null, $type = 'primary', $name = 'submit', $wrap = true, $other_attributes = null ) { + echo get_submit_button( $text, $type, $name, $wrap, $other_attributes ); +} + +/** + * Returns a submit button, with provided text and appropriate class + * + * @since 3.1.0 + * + * @param string $text The text of the button (defaults to 'Save Changes') + * @param string $type The type of button. One of: primary, secondary, delete + * @param string $name The HTML name of the submit button. Defaults to "submit". If no id attribute + * is given in $other_attributes below, $name will be used as the button's id. + * @param bool $wrap True if the output button should be wrapped in a paragraph tag, + * false otherwise. Defaults to true + * @param array|string $other_attributes Other attributes that should be output with the button, + * mapping attributes to their values, such as array( 'tabindex' => '1' ). + * These attributes will be output as attribute="value", such as tabindex="1". + * Defaults to no other attributes. Other attributes can also be provided as a + * string such as 'tabindex="1"', though the array format is typically cleaner. + */ +function get_submit_button( $text = null, $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = null ) { + if ( ! is_array( $type ) ) + $type = explode( ' ', $type ); + + $button_shorthand = array( 'primary', 'small', 'large' ); + $classes = array( 'button' ); + foreach ( $type as $t ) { + if ( 'secondary' === $t || 'button-secondary' === $t ) + continue; + $classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t; + } + $class = implode( ' ', array_unique( $classes ) ); + + if ( 'delete' === $type ) + $class = 'button-secondary delete'; + + $text = $text ? $text : __( 'Save Changes' ); + + // Default the id attribute to $name unless an id was specifically provided in $other_attributes + $id = $name; + if ( is_array( $other_attributes ) && isset( $other_attributes['id'] ) ) { + $id = $other_attributes['id']; + unset( $other_attributes['id'] ); + } + + $attributes = ''; + if ( is_array( $other_attributes ) ) { + foreach ( $other_attributes as $attribute => $value ) { + $attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important + } + } else if ( !empty( $other_attributes ) ) { // Attributes provided as a string + $attributes = $other_attributes; + } + + $button = ''; + + if ( $wrap ) { + $button = '

    ' . $button . '

    '; + } + + return $button; +} + +function _wp_admin_html_begin() { + $admin_html_class = ( is_admin_bar_showing() ) ? 'wp-toolbar' : ''; +?> + + + + > + + + + pointer_id ) + */ + + $registered_pointers = array( + 'index.php' => 'wp330_toolbar', + 'post-new.php' => 'wp350_media', + 'post.php' => array( 'wp350_media', 'wp360_revisions' ), + 'edit.php' => 'wp360_locks', + 'themes.php' => array( 'wp330_saving_widgets', 'wp340_customize_current_theme_link' ), + 'appearance_page_custom-header' => 'wp340_choose_image_from_library', + 'appearance_page_custom-background' => 'wp340_choose_image_from_library', + ); + + // Check if screen related pointer is registered + if ( empty( $registered_pointers[ $hook_suffix ] ) ) + return; + + $pointers = (array) $registered_pointers[ $hook_suffix ]; + + $caps_required = array( + 'wp330_saving_widgets' => array( 'edit_theme_options', 'switch_themes' ), + 'wp340_customize_current_theme_link' => array( 'edit_theme_options' ), + 'wp340_choose_image_from_library' => array( 'edit_theme_options' ), + 'wp350_media' => array( 'upload_files' ), + ); + + // Get dismissed pointers + $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ); + + $got_pointers = false; + foreach ( array_diff( $pointers, $dismissed ) as $pointer ) { + if ( isset( $caps_required[ $pointer ] ) ) { + foreach ( $caps_required[ $pointer ] as $cap ) { + if ( ! current_user_can( $cap ) ) + continue 2; + } + } + + // Bind pointer print function + add_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_' . $pointer ) ); + $got_pointers = true; + } + + if ( ! $got_pointers ) + return; + + // Add pointers script and style to queue + wp_enqueue_style( 'wp-pointer' ); + wp_enqueue_script( 'wp-pointer' ); + } + + /** + * Print the pointer javascript data. + * + * @since 3.3.0 + * + * @param string $pointer_id The pointer ID. + * @param string $selector The HTML elements, on which the pointer should be attached. + * @param array $args Arguments to be passed to the pointer JS (see wp-pointer.js). + */ + private static function print_js( $pointer_id, $selector, $args ) { + if ( empty( $pointer_id ) || empty( $selector ) || empty( $args ) || empty( $args['content'] ) ) + return; + + ?> + + ' . __( 'New Feature: Toolbar' ) . ''; + $content .= '

    ' . __( 'We’ve combined the admin bar and the old Dashboard header into one persistent toolbar. Hover over the toolbar items to see what’s new.' ) . '

    '; + + if ( is_multisite() && is_super_admin() ) + $content .= '

    ' . __( 'Network Admin is now located in the My Sites menu.' ) . '

    '; + + WP_Internal_Pointers::print_js( 'wp330_toolbar', '#wpadminbar', array( + 'content' => $content, + 'position' => array( 'edge' => 'top', 'align' => 'center' ), + ) ); + } + + /** + * Print 'Updated Media Uploader' for 3.3.0. + * + * @since 3.3.0 + */ + public static function pointer_wp330_media_uploader() {} + + /** + * Print 'New Feature: Saving Widgets' for 3.3.0. + * + * @since 3.3.0 + */ + public static function pointer_wp330_saving_widgets() { + $content = '

    ' . __( 'New Feature: Saving Widgets' ) . '

    '; + $content .= '

    ' . __( 'If you change your mind and revert to your previous theme, we’ll put the widgets back the way you had them.' ) . '

    '; + + WP_Internal_Pointers::print_js( 'wp330_saving_widgets', '#message2', array( + 'content' => $content, + 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left' ), + ) ); + } + + /** + * Print 'New Feature: Current Theme Customize Link' for 3.4.0. + * + * @since 3.4.0 + */ + public static function pointer_wp340_customize_current_theme_link() { + $content = '

    ' . __( 'New Feature: Customizer' ) . '

    '; + $content .= '

    ' . __( 'Click Customize to change the header, background, title and menus of the current theme, all in one place.' ) . '

    '; + $content .= '

    ' . __( 'Click the Live Preview links in the Available Themes list below to customize and preview another theme before activating it.' ) . '

    '; + + WP_Internal_Pointers::print_js( 'wp340_customize_current_theme_link', '#customize-current-theme-link', array( + 'content' => $content, + 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left', 'offset' => is_rtl() ? '32 0' : '-32 0' ), + ) ); + } + + /** + * Print 'New Feature: Choose Image from Library' for 3.4.0. + * + * @since 3.4.0 + */ + public static function pointer_wp340_choose_image_from_library() { + $content = '

    ' . __( 'New Feature: Choose Image from Library' ) . '

    '; + $content .= '

    ' . __( 'Want to use an image you uploaded earlier? Select it from your media library instead of uploading it again.' ) . '

    '; + + WP_Internal_Pointers::print_js( 'wp340_choose_image_from_library', '#choose-from-library-link', array( + 'content' => $content, + 'position' => array( 'edge' => 'top', 'align' => is_rtl() ? 'right' : 'left', 'defer_loading' => true ), + ) ); + } + + public static function pointer_wp350_media() { + $content = '

    ' . __( 'New Media Manager' ) . '

    '; + $content .= '

    ' . __( 'Uploading files and creating image galleries has a whole new look. Check it out!' ) . '

    '; + + self::print_js( 'wp350_media', '.insert-media', array( + 'content' => $content, + 'position' => array( 'edge' => is_rtl() ? 'right' : 'left', 'align' => 'center' ), + ) ); + } + + public static function pointer_wp360_revisions() { + $content = '

    ' . __( 'Compare Revisions' ) . '

    '; + $content .= '

    ' . __( 'View, compare, and restore other versions of this content on the improved revisions screen.' ) . '

    '; + + self::print_js( 'wp360_revisions', '.misc-pub-section.misc-pub-revisions', array( + 'content' => $content, + 'position' => array( 'edge' => is_rtl() ? 'left' : 'right', 'align' => 'center', 'my' => is_rtl() ? 'left' : 'right-14px' ), + ) ); + } + + public static function pointer_wp360_locks() { + $content = '

    ' . __( 'Edit Lock' ) . '

    '; + $content .= '

    ' . __( 'Someone else is editing this. No need to refresh; the lock will disappear when they’re done.' ) . '

    '; + + if ( ! is_multi_author() ) + return; + + self::print_js( 'wp360_locks', 'tr.wp-locked .locked-indicator', array( + 'content' => $content, + 'position' => array( 'edge' => 'left', 'align' => 'left' ), + ) ); + } + + /** + * Prevents new users from seeing existing 'new feature' pointers. + * + * @since 3.3.0 + */ + public static function dismiss_pointers_for_new_users( $user_id ) { + add_user_meta( $user_id, 'dismissed_wp_pointers', 'wp330_toolbar,wp330_saving_widgets,wp340_choose_image_from_library,wp340_customize_current_theme_link,wp350_media,wp360_revisions,wp360_locks' ); + } +} + +add_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) ); +add_action( 'user_register', array( 'WP_Internal_Pointers', 'dismiss_pointers_for_new_users' ) ); + +/** + * Convert a screen string to a screen object + * + * @since 3.0.0 + * + * @param string $hook_name The hook name (also known as the hook suffix) used to determine the screen. + * @return WP_Screen Screen object. + */ +function convert_to_screen( $hook_name ) { + if ( ! class_exists( 'WP_Screen' ) ) { + _doing_it_wrong( 'convert_to_screen(), add_meta_box()', __( "Likely direct inclusion of wp-admin/includes/template.php in order to use add_meta_box(). This is very wrong. Hook the add_meta_box() call into the add_meta_boxes action instead." ), '3.3' ); + return (object) array( 'id' => '_invalid', 'base' => '_are_belong_to_us' ); + } + + return WP_Screen::get( $hook_name ); +} + +/** + * Output the HTML for restoring the post data from DOM storage + * + * @since 3.6 + * @access private + */ +function _local_storage_notice() { + ?> + + array('href' => array(), 'title' => array(), 'target' => array()), + 'abbr' => array('title' => array()), 'acronym' => array('title' => array()), + 'code' => array(), 'pre' => array(), 'em' => array(), 'strong' => array(), + 'div' => array(), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array(), + 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), + 'img' => array('src' => array(), 'class' => array(), 'alt' => array()) +); + +$theme_field_defaults = array( 'description' => true, 'sections' => false, 'tested' => true, 'requires' => true, + 'rating' => true, 'downloaded' => true, 'downloadlink' => true, 'last_updated' => true, 'homepage' => true, + 'tags' => true, 'num_ratings' => true +); + +/** + * Retrieve list of WordPress theme features (aka theme tags) + * + * @since 2.8.0 + * + * @deprecated since 3.1.0 Use get_theme_feature_list() instead. + * + * @return array + */ +function install_themes_feature_list() { + _deprecated_function( __FUNCTION__, '3.1', 'get_theme_feature_list()' ); + + if ( !$cache = get_transient( 'wporg_theme_feature_list' ) ) + set_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS ); + + if ( $cache ) + return $cache; + + $feature_list = themes_api( 'feature_list', array() ); + if ( is_wp_error( $feature_list ) ) + return array(); + + set_transient( 'wporg_theme_feature_list', $feature_list, 3 * HOUR_IN_SECONDS ); + + return $feature_list; +} + +/** + * Display search form for searching themes. + * + * @since 2.8.0 + */ +function install_theme_search_form( $type_selector = true ) { + $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; + $term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : ''; + if ( ! $type_selector ) + echo '

    ' . __( 'Search for themes by keyword.' ) . '

    '; + ?> +
    + + + + + + + + + + +
    + +

    +

    + +
    + + '; + + foreach ( (array) $feature_list as $feature_name => $features ) { + $feature_name = esc_html( $feature_name ); + echo '
    ' . $feature_name . '
    '; + + echo '
      '; + foreach ( $features as $feature => $feature_name ) { + $feature_name = esc_html( $feature_name ); + $feature = esc_attr($feature); +?> + +
    1. + + +
    2. + + +
    +
    + + +
    +
    + + + +

    +

    +
    + + + +
    + single_row( $theme ); +} + +/** + * Display theme content based on theme list. + * + * @since 2.8.0 + */ +function display_themes() { + global $wp_list_table; + + $wp_list_table->display(); +} +add_action('install_themes_search', 'display_themes'); +add_action('install_themes_featured', 'display_themes'); +add_action('install_themes_new', 'display_themes'); +add_action('install_themes_updated', 'display_themes'); + +/** + * Display theme information in dialog box form. + * + * @since 2.8.0 + */ +function install_theme_information() { + global $tab, $themes_allowedtags, $wp_list_table; + + $theme = themes_api( 'theme_information', array( 'slug' => wp_unslash( $_REQUEST['theme'] ) ) ); + + if ( is_wp_error( $theme ) ) + wp_die( $theme ); + + iframe_header( __('Theme Install') ); + $wp_list_table->theme_installer_single( $theme ); + iframe_footer(); + exit; +} +add_action('install_themes_pre_theme-information', 'install_theme_information'); diff --git a/sources/wp-admin/includes/theme.php b/sources/wp-admin/includes/theme.php new file mode 100644 index 0000000..9ea69f2 --- /dev/null +++ b/sources/wp-admin/includes/theme.php @@ -0,0 +1,312 @@ +errors) && $wp_filesystem->errors->get_error_code() ) + return new WP_Error('fs_error', __('Filesystem error.'), $wp_filesystem->errors); + + //Get the base plugin folder + $themes_dir = $wp_filesystem->wp_themes_dir(); + if ( empty($themes_dir) ) + return new WP_Error('fs_no_themes_dir', __('Unable to locate WordPress theme directory.')); + + $themes_dir = trailingslashit( $themes_dir ); + $theme_dir = trailingslashit($themes_dir . $stylesheet); + $deleted = $wp_filesystem->delete($theme_dir, true); + + if ( ! $deleted ) + return new WP_Error('could_not_remove_theme', sprintf(__('Could not fully remove the theme %s.'), $stylesheet) ); + + // Force refresh of theme update information + delete_site_transient('update_themes'); + + return true; +} + +/** + * Get the Page Templates available in this theme + * + * @since 1.5.0 + * + * @return array Key is the template name, value is the filename of the template + */ +function get_page_templates() { + return array_flip( wp_get_theme()->get_page_templates() ); +} + +/** + * Tidies a filename for url display by the theme editor. + * + * @since 2.9.0 + * @access private + * + * @param string $fullpath Full path to the theme file + * @param string $containingfolder Path of the theme parent folder + * @return string + */ +function _get_template_edit_filename($fullpath, $containingfolder) { + return str_replace(dirname(dirname( $containingfolder )) , '', $fullpath); +} + +/** + * Check if there is an update for a theme available. + * + * Will display link, if there is an update available. + * + * @since 2.7.0 + * + * @param object $theme Theme data object. + * @return bool False if no valid info was passed. + */ +function theme_update_available( $theme ) { + static $themes_update; + + if ( !current_user_can('update_themes' ) ) + return; + + if ( !isset($themes_update) ) + $themes_update = get_site_transient('update_themes'); + + if ( ! is_a( $theme, 'WP_Theme' ) ) + return; + + $stylesheet = $theme->get_stylesheet(); + + if ( isset($themes_update->response[ $stylesheet ]) ) { + $update = $themes_update->response[ $stylesheet ]; + $theme_name = $theme->display('Name'); + $details_url = add_query_arg(array('TB_iframe' => 'true', 'width' => 1024, 'height' => 800), $update['url']); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list. + $update_url = wp_nonce_url('update.php?action=upgrade-theme&theme=' . urlencode($stylesheet), 'upgrade-theme_' . $stylesheet); + $update_onclick = 'onclick="if ( confirm(\'' . esc_js( __("Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.") ) . '\') ) {return true;}return false;"'; + + if ( !is_multisite() ) { + if ( ! current_user_can('update_themes') ) + printf( '

    ' . __('There is a new version of %1$s available. View version %3$s details.') . '

    ', $theme_name, $details_url, $update['new_version']); + else if ( empty($update['package']) ) + printf( '

    ' . __('There is a new version of %1$s available. View version %3$s details. Automatic update is unavailable for this theme.') . '

    ', $theme_name, $details_url, $update['new_version']); + else + printf( '

    ' . __('There is a new version of %1$s available. View version %3$s details or update now.') . '

    ', $theme_name, $details_url, $update['new_version'], $update_url, $update_onclick ); + } + } +} + +/** + * Retrieve list of WordPress theme features (aka theme tags) + * + * @since 3.1.0 + * + * @param bool $api Optional. Whether try to fetch tags from the WP.org API. Defaults to true. + * @return array Array of features keyed by category with translations keyed by slug. + */ +function get_theme_feature_list( $api = true ) { + // Hard-coded list is used if api not accessible. + $features = array( + __( 'Colors' ) => array( + 'black' => __( 'Black' ), + 'blue' => __( 'Blue' ), + 'brown' => __( 'Brown' ), + 'gray' => __( 'Gray' ), + 'green' => __( 'Green' ), + 'orange' => __( 'Orange' ), + 'pink' => __( 'Pink' ), + 'purple' => __( 'Purple' ), + 'red' => __( 'Red' ), + 'silver' => __( 'Silver' ), + 'tan' => __( 'Tan' ), + 'white' => __( 'White' ), + 'yellow' => __( 'Yellow' ), + 'dark' => __( 'Dark' ), + 'light' => __( 'Light' ), + ), + + __( 'Columns' ) => array( + 'one-column' => __( 'One Column' ), + 'two-columns' => __( 'Two Columns' ), + 'three-columns' => __( 'Three Columns' ), + 'four-columns' => __( 'Four Columns' ), + 'left-sidebar' => __( 'Left Sidebar' ), + 'right-sidebar' => __( 'Right Sidebar' ), + ), + + __( 'Width' ) => array( + 'fixed-width' => __( 'Fixed Width' ), + 'flexible-width' => __( 'Flexible Width' ), + ), + + __( 'Features' ) => array( + 'blavatar' => __( 'Blavatar' ), + 'buddypress' => __( 'BuddyPress' ), + 'custom-background' => __( 'Custom Background' ), + 'custom-colors' => __( 'Custom Colors' ), + 'custom-header' => __( 'Custom Header' ), + 'custom-menu' => __( 'Custom Menu' ), + 'editor-style' => __( 'Editor Style' ), + 'featured-image-header' => __( 'Featured Image Header' ), + 'featured-images' => __( 'Featured Images' ), + 'flexible-header' => __( 'Flexible Header' ), + 'front-page-post-form' => __( 'Front Page Posting' ), + 'full-width-template' => __( 'Full Width Template' ), + 'microformats' => __( 'Microformats' ), + 'post-formats' => __( 'Post Formats' ), + 'rtl-language-support' => __( 'RTL Language Support' ), + 'sticky-post' => __( 'Sticky Post' ), + 'theme-options' => __( 'Theme Options' ), + 'threaded-comments' => __( 'Threaded Comments' ), + 'translation-ready' => __( 'Translation Ready' ), + ), + + __( 'Subject' ) => array( + 'holiday' => __( 'Holiday' ), + 'photoblogging' => __( 'Photoblogging' ), + 'seasonal' => __( 'Seasonal' ), + ) + ); + + if ( ! $api || ! current_user_can( 'install_themes' ) ) + return $features; + + if ( !$feature_list = get_site_transient( 'wporg_theme_feature_list' ) ) + set_site_transient( 'wporg_theme_feature_list', array(), 10800); + + if ( !$feature_list ) { + $feature_list = themes_api( 'feature_list', array() ); + if ( is_wp_error( $feature_list ) ) + return $features; + } + + if ( !$feature_list ) + return $features; + + set_site_transient( 'wporg_theme_feature_list', $feature_list, 10800 ); + + $category_translations = array( 'Colors' => __('Colors'), 'Columns' => __('Columns'), 'Width' => __('Width'), + 'Features' => __('Features'), 'Subject' => __('Subject') ); + + // Loop over the wporg canonical list and apply translations + $wporg_features = array(); + foreach ( (array) $feature_list as $feature_category => $feature_items ) { + if ( isset($category_translations[$feature_category]) ) + $feature_category = $category_translations[$feature_category]; + $wporg_features[$feature_category] = array(); + + foreach ( $feature_items as $feature ) { + if ( isset($features[$feature_category][$feature]) ) + $wporg_features[$feature_category][$feature] = $features[$feature_category][$feature]; + else + $wporg_features[$feature_category][$feature] = $feature; + } + } + + return $wporg_features; +} + +/** + * Retrieve theme installer pages from WordPress Themes API. + * + * It is possible for a theme to override the Themes API result with three + * filters. Assume this is for themes, which can extend on the Theme Info to + * offer more choices. This is very powerful and must be used with care, when + * overridding the filters. + * + * The first filter, 'themes_api_args', is for the args and gives the action as + * the second parameter. The hook for 'themes_api_args' must ensure that an + * object is returned. + * + * The second filter, 'themes_api', is the result that would be returned. + * + * @since 2.8.0 + * + * @param string $action + * @param array|object $args Optional. Arguments to serialize for the Theme Info API. + * @return mixed + */ +function themes_api($action, $args = null) { + + if ( is_array($args) ) + $args = (object)$args; + + if ( !isset($args->per_page) ) + $args->per_page = 24; + + $args = apply_filters('themes_api_args', $args, $action); //NOTE: Ensure that an object is returned via this filter. + $res = apply_filters('themes_api', false, $action, $args); //NOTE: Allows a theme to completely override the builtin WordPress.org API. + + if ( ! $res ) { + $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/'; + if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) + $url = set_url_scheme( $url, 'https' ); + + $args = array( + 'body' => array( + 'action' => $action, + 'request' => serialize( $args ) + ) + ); + $request = wp_remote_post( $url, $args ); + + if ( $ssl && is_wp_error( $request ) ) { + trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE ); + $request = wp_remote_post( $http_url, $args ); + } + + if ( is_wp_error($request) ) { + $res = new WP_Error('themes_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), $request->get_error_message() ); + } else { + $res = maybe_unserialize( wp_remote_retrieve_body( $request ) ); + if ( ! is_object( $res ) && ! is_array( $res ) ) + $res = new WP_Error('themes_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ), wp_remote_retrieve_body( $request ) ); + } + } + + return apply_filters('themes_api_result', $res, $action, $args); +} diff --git a/sources/wp-admin/includes/update-core.php b/sources/wp-admin/includes/update-core.php new file mode 100644 index 0000000..b841268 --- /dev/null +++ b/sources/wp-admin/includes/update-core.php @@ -0,0 +1,1002 @@ + Introduced version + * Directories should be noted by suffixing it with a trailing slash (/) + * + * @since 3.2.0 + * @global array $_new_bundled_files + * @var array + * @name $_new_bundled_files + */ +global $_new_bundled_files; + +$_new_bundled_files = array( + 'plugins/akismet/' => '2.0', + 'themes/twentyten/' => '3.0', + 'themes/twentyeleven/' => '3.2', + 'themes/twentytwelve/' => '3.5', + 'themes/twentythirteen/' => '3.6', +); + +/** + * Upgrade the core of WordPress. + * + * This will create a .maintenance file at the base of the WordPress directory + * to ensure that people can not access the web site, when the files are being + * copied to their locations. + * + * The files in the {@link $_old_files} list will be removed and the new files + * copied from the zip file after the database is upgraded. + * + * The files in the {@link $_new_bundled_files} list will be added to the installation + * if the version is greater than or equal to the old version being upgraded. + * + * The steps for the upgrader for after the new release is downloaded and + * unzipped is: + * 1. Test unzipped location for select files to ensure that unzipped worked. + * 2. Create the .maintenance file in current WordPress base. + * 3. Copy new WordPress directory over old WordPress files. + * 4. Upgrade WordPress to new version. + * 4.1. Copy all files/folders other than wp-content + * 4.2. Copy any language files to WP_LANG_DIR (which may differ from WP_CONTENT_DIR + * 4.3. Copy any new bundled themes/plugins to their respective locations + * 5. Delete new WordPress directory path. + * 6. Delete .maintenance file. + * 7. Remove old files. + * 8. Delete 'update_core' option. + * + * There are several areas of failure. For instance if PHP times out before step + * 6, then you will not be able to access any portion of your site. Also, since + * the upgrade will not continue where it left off, you will not be able to + * automatically remove old files and remove the 'update_core' option. This + * isn't that bad. + * + * If the copy of the new WordPress over the old fails, then the worse is that + * the new WordPress directory will remain. + * + * If it is assumed that every file will be copied over, including plugins and + * themes, then if you edit the default theme, you should rename it, so that + * your changes remain. + * + * @since 2.7.0 + * + * @param string $from New release unzipped path. + * @param string $to Path to old WordPress installation. + * @return WP_Error|null WP_Error on failure, null on success. + */ +function update_core($from, $to) { + global $wp_filesystem, $_old_files, $_new_bundled_files, $wpdb; + + @set_time_limit( 300 ); + + // Sanity check the unzipped distribution + apply_filters( 'update_feedback', __('Verifying the unpacked files…') ); + $distro = ''; + $roots = array( '/wordpress/', '/wordpress-mu/' ); + foreach ( $roots as $root ) { + if ( $wp_filesystem->exists( $from . $root . 'readme.html' ) && $wp_filesystem->exists( $from . $root . 'wp-includes/version.php' ) ) { + $distro = $root; + break; + } + } + if ( ! $distro ) { + $wp_filesystem->delete( $from, true ); + return new WP_Error( 'insane_distro', __('The update could not be unpacked') ); + } + + // Import $wp_version, $required_php_version, and $required_mysql_version from the new version + // $wp_filesystem->wp_content_dir() returned unslashed pre-2.8 + $versions_file = trailingslashit( $wp_filesystem->wp_content_dir() ) . 'upgrade/version-current.php'; + if ( ! $wp_filesystem->copy( $from . $distro . 'wp-includes/version.php', $versions_file ) ) { + $wp_filesystem->delete( $from, true ); + return new WP_Error( 'copy_failed_for_version_file', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), 'wp-includes/version.php' ); + } + + $wp_filesystem->chmod( $versions_file, FS_CHMOD_FILE ); + require( WP_CONTENT_DIR . '/upgrade/version-current.php' ); + $wp_filesystem->delete( $versions_file ); + + $php_version = phpversion(); + $mysql_version = $wpdb->db_version(); + $old_wp_version = $GLOBALS['wp_version']; // The version of WordPress we're updating from + $development_build = ( false !== strpos( $old_wp_version . $wp_version, '-' ) ); // a dash in the version indicates a Development release + $php_compat = version_compare( $php_version, $required_php_version, '>=' ); + if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) + $mysql_compat = true; + else + $mysql_compat = version_compare( $mysql_version, $required_mysql_version, '>=' ); + + if ( !$mysql_compat || !$php_compat ) + $wp_filesystem->delete($from, true); + + if ( !$mysql_compat && !$php_compat ) + return new WP_Error( 'php_mysql_not_compatible', sprintf( __('The update cannot be installed because WordPress %1$s requires PHP version %2$s or higher and MySQL version %3$s or higher. You are running PHP version %4$s and MySQL version %5$s.'), $wp_version, $required_php_version, $required_mysql_version, $php_version, $mysql_version ) ); + elseif ( !$php_compat ) + return new WP_Error( 'php_not_compatible', sprintf( __('The update cannot be installed because WordPress %1$s requires PHP version %2$s or higher. You are running version %3$s.'), $wp_version, $required_php_version, $php_version ) ); + elseif ( !$mysql_compat ) + return new WP_Error( 'mysql_not_compatible', sprintf( __('The update cannot be installed because WordPress %1$s requires MySQL version %2$s or higher. You are running version %3$s.'), $wp_version, $required_mysql_version, $mysql_version ) ); + + apply_filters( 'update_feedback', __( 'Preparing to install the latest version…' ) ); + + // Don't copy wp-content, we'll deal with that below + $skip = array( 'wp-content' ); + $check_is_writable = array(); + + // Check to see which files don't really need updating - only available for 3.7 and higher + if ( function_exists( 'get_core_checksums' ) ) { + $checksums = get_core_checksums( $wp_version, isset( $wp_local_package ) ? $wp_local_package : 'en_US' ); + if ( is_array( $checksums ) && isset( $checksums[ $wp_version ] ) ) + $checksums = $checksums[ $wp_version ]; // Compat code for 3.7-beta2 + if ( is_array( $checksums ) ) { + foreach( $checksums as $file => $checksum ) { + if ( 'wp-content' == substr( $file, 0, 10 ) ) + continue; + if ( ! file_exists( ABSPATH . $file ) ) + continue; + if ( md5_file( ABSPATH . $file ) === $checksum ) + $skip[] = $file; + else + $check_is_writable[ $file ] = ABSPATH . $file; + } + } + } + + // If we're using the direct method, we can predict write failures that are due to permissions. + if ( $check_is_writable && 'direct' === $wp_filesystem->method ) { + $files_writable = array_filter( $check_is_writable, array( $wp_filesystem, 'is_writable' ) ); + if ( $files_writable !== $check_is_writable ) { + $files_not_writable = array_diff_key( $check_is_writable, $files_writable ); + foreach ( $files_not_writable as $relative_file_not_writable => $file_not_writable ) { + // If the writable check failed, chmod file to 0644 and try again, same as copy_dir(). + $wp_filesystem->chmod( $file_not_writable, FS_CHMOD_FILE ); + if ( $wp_filesystem->is_writable( $file_not_writable ) ) + unset( $files_not_writable[ $relative_file_not_writable ] ); + } + + // Store package-relative paths (the key) of non-writable files in the WP_Error object. + $error_data = version_compare( $old_wp_version, '3.7-beta2', '>' ) ? array_keys( $files_not_writable ) : ''; + + if ( $files_not_writable ) + return new WP_Error( 'files_not_writable', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), implode( ', ', $error_data ) ); + } + } + + apply_filters( 'update_feedback', __( 'Enabling Maintenance mode…' ) ); + // Create maintenance file to signal that we are upgrading + $maintenance_string = ''; + $maintenance_file = $to . '.maintenance'; + $wp_filesystem->delete($maintenance_file); + $wp_filesystem->put_contents($maintenance_file, $maintenance_string, FS_CHMOD_FILE); + + apply_filters( 'update_feedback', __( 'Copying the required files…' ) ); + // Copy new versions of WP files into place. + $result = _copy_dir( $from . $distro, $to, $skip ); + if ( is_wp_error( $result ) ) + $result = new WP_Error( $result->get_error_code(), $result->get_error_message(), substr( $result->get_error_data(), strlen( $to ) ) ); + + // Check to make sure everything copied correctly, ignoring the contents of wp-content + $skip = array( 'wp-content' ); + $failed = array(); + if ( isset( $checksums ) && is_array( $checksums ) ) { + foreach ( $checksums as $file => $checksum ) { + if ( 0 === strpos( $file, 'wp-content' ) ) + continue; + + if ( file_exists( ABSPATH . $file ) && md5_file( ABSPATH . $file ) == $checksum ) + $skip[] = $file; + else + $failed[] = $file; + } + } + + // Some files didn't copy properly + if ( ! empty( $failed ) ) { + $total_size = 0; + // Find the local version of the working directory + $working_dir_local = WP_CONTENT_DIR . '/upgrade/' . basename( $from ) . $distro; + foreach ( $failed as $file ) { + if ( file_exists( $working_dir_local . $file ) ) + $total_size += filesize( $working_dir_local . $file ); + } + + // If we don't have enough free space, it isn't worth trying again. + // Unlikely to be hit due to the check in unzip_file(). + $available_space = @disk_free_space( ABSPATH ); + if ( $available_space && $total_size >= $available_space ) { + $result = new WP_Error( 'disk_full', __( 'There is not enough free disk space to complete the update.' ) ); + } else { + $result = _copy_dir( $from . $distro, $to, $skip ); + if ( is_wp_error( $result ) ) + $result = new WP_Error( $result->get_error_code() . '_retry', $result->get_error_message(), substr( $result->get_error_data(), strlen( $to ) ) ); + } + } + + // Custom Content Directory needs updating now. + // Copy Languages + if ( !is_wp_error($result) && $wp_filesystem->is_dir($from . $distro . 'wp-content/languages') ) { + if ( WP_LANG_DIR != ABSPATH . WPINC . '/languages' || @is_dir(WP_LANG_DIR) ) + $lang_dir = WP_LANG_DIR; + else + $lang_dir = WP_CONTENT_DIR . '/languages'; + + if ( !@is_dir($lang_dir) && 0 === strpos($lang_dir, ABSPATH) ) { // Check the language directory exists first + $wp_filesystem->mkdir($to . str_replace(ABSPATH, '', $lang_dir), FS_CHMOD_DIR); // If it's within the ABSPATH we can handle it here, otherwise they're out of luck. + clearstatcache(); // for FTP, Need to clear the stat cache + } + + if ( @is_dir($lang_dir) ) { + $wp_lang_dir = $wp_filesystem->find_folder($lang_dir); + if ( $wp_lang_dir ) { + $result = copy_dir($from . $distro . 'wp-content/languages/', $wp_lang_dir); + if ( is_wp_error( $result ) ) + $result = new WP_Error( $result->get_error_code() . '_languages', $result->get_error_message(), substr( $result->get_error_data(), strlen( $wp_lang_dir ) ) ); + } + } + } + + apply_filters( 'update_feedback', __( 'Disabling Maintenance mode…' ) ); + // Remove maintenance file, we're done with potential site-breaking changes + $wp_filesystem->delete( $maintenance_file ); + + // 3.5 -> 3.5+ - an empty twentytwelve directory was created upon upgrade to 3.5 for some users, preventing installation of Twenty Twelve. + if ( '3.5' == $old_wp_version ) { + if ( is_dir( WP_CONTENT_DIR . '/themes/twentytwelve' ) && ! file_exists( WP_CONTENT_DIR . '/themes/twentytwelve/style.css' ) ) { + $wp_filesystem->delete( $wp_filesystem->wp_themes_dir() . 'twentytwelve/' ); + } + } + + // Copy New bundled plugins & themes + // This gives us the ability to install new plugins & themes bundled with future versions of WordPress whilst avoiding the re-install upon upgrade issue. + // $development_build controls us overwriting bundled themes and plugins when a non-stable release is being updated + if ( !is_wp_error($result) && ( ! defined('CORE_UPGRADE_SKIP_NEW_BUNDLED') || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) ) { + foreach ( (array) $_new_bundled_files as $file => $introduced_version ) { + // If a $development_build or if $introduced version is greater than what the site was previously running + if ( $development_build || version_compare( $introduced_version, $old_wp_version, '>' ) ) { + $directory = ('/' == $file[ strlen($file)-1 ]); + list($type, $filename) = explode('/', $file, 2); + + // Check to see if the bundled items exist before attempting to copy them + if ( ! $wp_filesystem->exists( $from . $distro . 'wp-content/' . $file ) ) + continue; + + if ( 'plugins' == $type ) + $dest = $wp_filesystem->wp_plugins_dir(); + elseif ( 'themes' == $type ) + $dest = trailingslashit($wp_filesystem->wp_themes_dir()); // Back-compat, ::wp_themes_dir() did not return trailingslash'd pre-3.2 + else + continue; + + if ( ! $directory ) { + if ( ! $development_build && $wp_filesystem->exists( $dest . $filename ) ) + continue; + + if ( ! $wp_filesystem->copy($from . $distro . 'wp-content/' . $file, $dest . $filename, FS_CHMOD_FILE) ) + $result = new WP_Error( "copy_failed_for_new_bundled_$type", __( 'Could not copy file.' ), $dest . $filename ); + } else { + if ( ! $development_build && $wp_filesystem->is_dir( $dest . $filename ) ) + continue; + + $wp_filesystem->mkdir($dest . $filename, FS_CHMOD_DIR); + $_result = copy_dir( $from . $distro . 'wp-content/' . $file, $dest . $filename); + + // If a error occurs partway through this final step, keep the error flowing through, but keep process going. + if ( is_wp_error( $_result ) ) { + if ( ! is_wp_error( $result ) ) + $result = new WP_Error; + $result->add( $_result->get_error_code() . "_$type", $_result->get_error_message(), substr( $_result->get_error_data(), strlen( $dest ) ) ); + } + } + } + } //end foreach + } + + // Handle $result error from the above blocks + if ( is_wp_error($result) ) { + $wp_filesystem->delete($from, true); + return $result; + } + + // Remove old files + foreach ( $_old_files as $old_file ) { + $old_file = $to . $old_file; + if ( !$wp_filesystem->exists($old_file) ) + continue; + $wp_filesystem->delete($old_file, true); + } + + // Upgrade DB with separate request + apply_filters('update_feedback', __('Upgrading database…')); + $db_upgrade_url = admin_url('upgrade.php?step=upgrade_db'); + wp_remote_post($db_upgrade_url, array('timeout' => 60)); + + // Remove working directory + $wp_filesystem->delete($from, true); + + // Force refresh of update information + if ( function_exists('delete_site_transient') ) + delete_site_transient('update_core'); + else + delete_option('update_core'); + + // If we made it this far: + do_action( '_core_updated_successfully', $wp_version ); + + // Clear the option that blocks auto updates after failures, now that we've been successful. + if ( function_exists( 'delete_site_option' ) ) + delete_site_option( 'auto_core_update_failed' ); + + return $wp_version; +} + +/** + * Copies a directory from one location to another via the WordPress Filesystem Abstraction. + * Assumes that WP_Filesystem() has already been called and setup. + * + * This is a temporary function for the 3.1 -> 3.2 upgrade, as well as for those upgrading to + * 3.7+ + * + * @ignore + * @since 3.2.0 + * @since 3.7.0 Updated not to use a regular expression for the skip list + * @see copy_dir() + * + * @param string $from source directory + * @param string $to destination directory + * @param array $skip_list a list of files/folders to skip copying + * @return mixed WP_Error on failure, True on success. + */ +function _copy_dir($from, $to, $skip_list = array() ) { + global $wp_filesystem; + + $dirlist = $wp_filesystem->dirlist($from); + + $from = trailingslashit($from); + $to = trailingslashit($to); + + foreach ( (array) $dirlist as $filename => $fileinfo ) { + if ( in_array( $filename, $skip_list ) ) + continue; + + if ( 'f' == $fileinfo['type'] ) { + if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) { + // If copy failed, chmod file to 0644 and try again. + $wp_filesystem->chmod( $to . $filename, FS_CHMOD_FILE ); + if ( ! $wp_filesystem->copy($from . $filename, $to . $filename, true, FS_CHMOD_FILE) ) + return new WP_Error( 'copy_failed__copy_dir', __( 'Could not copy file.' ), $to . $filename ); + } + } elseif ( 'd' == $fileinfo['type'] ) { + if ( !$wp_filesystem->is_dir($to . $filename) ) { + if ( !$wp_filesystem->mkdir($to . $filename, FS_CHMOD_DIR) ) + return new WP_Error( 'mkdir_failed__copy_dir', __( 'Could not create directory.' ), $to . $filename ); + } + + // generate the $sub_skip_list for the subdirectory as a sub-set of the existing $skip_list + $sub_skip_list = array(); + foreach ( $skip_list as $skip_item ) { + if ( 0 === strpos( $skip_item, $filename . '/' ) ) + $sub_skip_list[] = preg_replace( '!^' . preg_quote( $filename, '!' ) . '/!i', '', $skip_item ); + } + + $result = _copy_dir($from . $filename, $to . $filename, $sub_skip_list); + if ( is_wp_error($result) ) + return $result; + } + } + return true; +} + +/** + * Redirect to the About WordPress page after a successful upgrade. + * + * This function is only needed when the existing install is older than 3.4.0. + * + * @since 3.3.0 + * + */ +function _redirect_to_about_wordpress( $new_version ) { + global $wp_version, $pagenow, $action; + + if ( version_compare( $wp_version, '3.4-RC1', '>=' ) ) + return; + + // Ensure we only run this on the update-core.php page. The Core_Upgrader may be used in other contexts. + if ( 'update-core.php' != $pagenow ) + return; + + if ( 'do-core-upgrade' != $action && 'do-core-reinstall' != $action ) + return; + + // Load the updated default text localization domain for new strings + load_default_textdomain(); + + // See do_core_upgrade() + show_message( __('WordPress updated successfully') ); + + // self_admin_url() won't exist when upgrading from <= 3.0, so relative URLs are intentional. + show_message( '' . sprintf( __( 'Welcome to WordPress %1$s. You will be redirected to the About WordPress screen. If not, click here.' ), $new_version, 'about.php?updated' ) . '' ); + show_message( '' . sprintf( __( 'Welcome to WordPress %1$s. Learn more.' ), $new_version, 'about.php?updated' ) . '' ); + echo '
    '; + ?> + + 'latest' ); + return $updates[0]; +} + +/** + * Get available core updates + * + * @param array $options Set $options['dismissed'] to true to show dismissed upgrades too, + * set $options['available'] to false to skip not-dismissed updates. + * @return array Array of the update objects + */ +function get_core_updates( $options = array() ) { + $options = array_merge( array( 'available' => true, 'dismissed' => false ), $options ); + $dismissed = get_site_option( 'dismissed_update_core' ); + + if ( ! is_array( $dismissed ) ) + $dismissed = array(); + + $from_api = get_site_transient( 'update_core' ); + + if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) + return false; + + $updates = $from_api->updates; + $result = array(); + foreach ( $updates as $update ) { + if ( $update->response == 'autoupdate' ) + continue; + + if ( array_key_exists( $update->current . '|' . $update->locale, $dismissed ) ) { + if ( $options['dismissed'] ) { + $update->dismissed = true; + $result[] = $update; + } + } else { + if ( $options['available'] ) { + $update->dismissed = false; + $result[] = $update; + } + } + } + return $result; +} + +/** + * Gets the best available (and enabled) Auto-Update for WordPress Core. + * + * If there's 1.2.3 and 1.3 on offer, it'll choose 1.3 if the install allows it, else, 1.2.3 + * + * @since 3.7.0 + * + * @return bool|array False on failure, otherwise the core update offering. + */ +function find_core_auto_update() { + $updates = get_site_transient( 'update_core' ); + if ( ! $updates || empty( $updates->updates ) ) + return false; + + include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + + $auto_update = false; + $upgrader = new WP_Automatic_Updater; + foreach ( $updates->updates as $update ) { + if ( 'autoupdate' != $update->response ) + continue; + + if ( ! $upgrader->should_update( 'core', $update, ABSPATH ) ) + continue; + + if ( ! $auto_update || version_compare( $update->current, $auto_update->current, '>' ) ) + $auto_update = $update; + } + return $auto_update; +} + +/** + * Gets and caches the checksums for the given version of WordPress. + * + * @since 3.7.0 + * + * @param string $version Version string to query. + * @param string $locale Locale to query. + * @return bool|array False on failure. An array of checksums on success. + */ +function get_core_checksums( $version, $locale ) { + $return = array(); + + $url = $http_url = 'http://api.wordpress.org/core/checksums/1.0/?' . http_build_query( compact( 'version', 'locale' ), null, '&' ); + + if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) + $url = set_url_scheme( $url, 'https' ); + + $options = array( + 'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3 ), + ); + + $response = wp_remote_get( $url, $options ); + if ( $ssl && is_wp_error( $response ) ) { + trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE ); + $response = wp_remote_get( $http_url, $options ); + } + + if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) + return false; + + $body = trim( wp_remote_retrieve_body( $response ) ); + $body = json_decode( $body, true ); + + if ( ! is_array( $body ) || ! isset( $body['checksums'] ) || ! is_array( $body['checksums'] ) ) + return false; + + return $body['checksums']; +} + +function dismiss_core_update( $update ) { + $dismissed = get_site_option( 'dismissed_update_core' ); + $dismissed[ $update->current . '|' . $update->locale ] = true; + return update_site_option( 'dismissed_update_core', $dismissed ); +} + +function undismiss_core_update( $version, $locale ) { + $dismissed = get_site_option( 'dismissed_update_core' ); + $key = $version . '|' . $locale; + + if ( ! isset( $dismissed[$key] ) ) + return false; + + unset( $dismissed[$key] ); + return update_site_option( 'dismissed_update_core', $dismissed ); +} + +function find_core_update( $version, $locale ) { + $from_api = get_site_transient( 'update_core' ); + + if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) + return false; + + $updates = $from_api->updates; + foreach ( $updates as $update ) { + if ( $update->current == $version && $update->locale == $locale ) + return $update; + } + return false; +} + +function core_update_footer( $msg = '' ) { + if ( !current_user_can('update_core') ) + return sprintf( __( 'Version %s' ), get_bloginfo( 'version', 'display' ) ); + + $cur = get_preferred_from_update_core(); + if ( ! is_object( $cur ) ) + $cur = new stdClass; + + if ( ! isset( $cur->current ) ) + $cur->current = ''; + + if ( ! isset( $cur->url ) ) + $cur->url = ''; + + if ( ! isset( $cur->response ) ) + $cur->response = ''; + + switch ( $cur->response ) { + case 'development' : + return sprintf( __( 'You are using a development version (%1$s). Cool! Please stay updated.' ), get_bloginfo( 'version', 'display' ), network_admin_url( 'update-core.php' ) ); + break; + + case 'upgrade' : + return sprintf( ''.__( 'Get Version %2$s' ).'', network_admin_url( 'update-core.php' ), $cur->current); + break; + + case 'latest' : + default : + return sprintf( __( 'Version %s' ), get_bloginfo( 'version', 'display' ) ); + break; + } +} +add_filter( 'update_footer', 'core_update_footer' ); + +function update_nag() { + if ( is_multisite() && !current_user_can('update_core') ) + return false; + + global $pagenow; + + if ( 'update-core.php' == $pagenow ) + return; + + $cur = get_preferred_from_update_core(); + + if ( ! isset( $cur->response ) || $cur->response != 'upgrade' ) + return false; + + if ( current_user_can('update_core') ) { + $msg = sprintf( __('WordPress %1$s is available! Please update now.'), $cur->current, network_admin_url( 'update-core.php' ) ); + } else { + $msg = sprintf( __('WordPress %1$s is available! Please notify the site administrator.'), $cur->current ); + } + echo "
    $msg
    "; +} +add_action( 'admin_notices', 'update_nag', 3 ); +add_action( 'network_admin_notices', 'update_nag', 3 ); + +// Called directly from dashboard +function update_right_now_message() { + $msg = sprintf( __( 'You are using WordPress %s.' ), get_bloginfo( 'version', 'display' ) ); + + if ( current_user_can('update_core') ) { + $cur = get_preferred_from_update_core(); + + if ( isset( $cur->response ) && $cur->response == 'upgrade' ) + $msg .= " " . sprintf( __('Update to %s'), $cur->current ? $cur->current : __( 'Latest' ) ) . ''; + } + + echo "$msg"; +} + +function get_plugin_updates() { + $all_plugins = get_plugins(); + $upgrade_plugins = array(); + $current = get_site_transient( 'update_plugins' ); + foreach ( (array)$all_plugins as $plugin_file => $plugin_data) { + if ( isset( $current->response[ $plugin_file ] ) ) { + $upgrade_plugins[ $plugin_file ] = (object) $plugin_data; + $upgrade_plugins[ $plugin_file ]->update = $current->response[ $plugin_file ]; + } + } + + return $upgrade_plugins; +} + +function wp_plugin_update_rows() { + if ( !current_user_can('update_plugins' ) ) + return; + + $plugins = get_site_transient( 'update_plugins' ); + if ( isset($plugins->response) && is_array($plugins->response) ) { + $plugins = array_keys( $plugins->response ); + foreach( $plugins as $plugin_file ) { + add_action( "after_plugin_row_$plugin_file", 'wp_plugin_update_row', 10, 2 ); + } + } +} +add_action( 'admin_init', 'wp_plugin_update_rows' ); + +function wp_plugin_update_row( $file, $plugin_data ) { + $current = get_site_transient( 'update_plugins' ); + if ( !isset( $current->response[ $file ] ) ) + return false; + + $r = $current->response[ $file ]; + + $plugins_allowedtags = array('a' => array('href' => array(),'title' => array()),'abbr' => array('title' => array()),'acronym' => array('title' => array()),'code' => array(),'em' => array(),'strong' => array()); + $plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags ); + + $details_url = self_admin_url('plugin-install.php?tab=plugin-information&plugin=' . $r->slug . '§ion=changelog&TB_iframe=true&width=600&height=800'); + + $wp_list_table = _get_list_table('WP_Plugins_List_Table'); + + if ( is_network_admin() || !is_multisite() ) { + echo '
    '; + + if ( ! current_user_can('update_plugins') ) + printf( __('There is a new version of %1$s available. View version %4$s details.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version ); + else if ( empty($r->package) ) + printf( __('There is a new version of %1$s available. View version %4$s details. Automatic update is unavailable for this plugin.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version ); + else + printf( __('There is a new version of %1$s available. View version %4$s details or update now.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version, wp_nonce_url( self_admin_url('update.php?action=upgrade-plugin&plugin=') . $file, 'upgrade-plugin_' . $file) ); + + do_action( "in_plugin_update_message-$file", $plugin_data, $r ); + + echo '
    '; + } +} + +function get_theme_updates() { + $themes = wp_get_themes(); + $current = get_site_transient('update_themes'); + + if ( ! isset( $current->response ) ) + return array(); + + $update_themes = array(); + foreach ( $current->response as $stylesheet => $data ) { + $update_themes[ $stylesheet ] = wp_get_theme( $stylesheet ); + $update_themes[ $stylesheet ]->update = $data; + } + + return $update_themes; +} + +function wp_theme_update_rows() { + if ( !current_user_can('update_themes' ) ) + return; + + $themes = get_site_transient( 'update_themes' ); + if ( isset($themes->response) && is_array($themes->response) ) { + $themes = array_keys( $themes->response ); + + foreach( $themes as $theme ) { + add_action( "after_theme_row_$theme", 'wp_theme_update_row', 10, 2 ); + } + } +} +add_action( 'admin_init', 'wp_theme_update_rows' ); + +function wp_theme_update_row( $theme_key, $theme ) { + $current = get_site_transient( 'update_themes' ); + if ( !isset( $current->response[ $theme_key ] ) ) + return false; + $r = $current->response[ $theme_key ]; + $themes_allowedtags = array('a' => array('href' => array(),'title' => array()),'abbr' => array('title' => array()),'acronym' => array('title' => array()),'code' => array(),'em' => array(),'strong' => array()); + $theme_name = wp_kses( $theme['Name'], $themes_allowedtags ); + + $details_url = add_query_arg( array( 'TB_iframe' => 'true', 'width' => 1024, 'height' => 800 ), $current->response[ $theme_key ]['url'] ); + + $wp_list_table = _get_list_table('WP_MS_Themes_List_Table'); + + echo '
    '; + if ( ! current_user_can('update_themes') ) + printf( __('There is a new version of %1$s available. View version %4$s details.'), $theme['Name'], esc_url($details_url), esc_attr($theme['Name']), $r->new_version ); + else if ( empty( $r['package'] ) ) + printf( __('There is a new version of %1$s available. View version %4$s details. Automatic update is unavailable for this theme.'), $theme['Name'], esc_url($details_url), esc_attr($theme['Name']), $r['new_version'] ); + else + printf( __('There is a new version of %1$s available. View version %4$s details or update now.'), $theme['Name'], esc_url($details_url), esc_attr($theme['Name']), $r['new_version'], wp_nonce_url( self_admin_url('update.php?action=upgrade-theme&theme=') . $theme_key, 'upgrade-theme_' . $theme_key) ); + + do_action( "in_theme_update_message-$theme_key", $theme, $r ); + + echo '
    '; +} + +function maintenance_nag() { + include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version + global $upgrading; + $nag = isset( $upgrading ); + if ( ! $nag ) { + $failed = get_site_option( 'auto_core_update_failed' ); + /* + * If an update failed critically, we may have copied over version.php but not other files. + * In that case, if the install claims we're running the version we attempted, nag. + * This is serious enough to err on the side of nagging. + * + * If we simply failed to update before we tried to copy any files, then assume things are + * OK if they are now running the latest. + * + * This flag is cleared whenever a successful update occurs using Core_Upgrader. + */ + $comparison = ! empty( $failed['critical'] ) ? '>=' : '>'; + if ( version_compare( $failed['attempted'], $wp_version, '>=' ) ) + $nag = true; + } + + if ( ! $nag ) + return false; + + if ( current_user_can('update_core') ) + $msg = sprintf( __('An automated WordPress update has failed to complete - please attempt the update again now.'), 'update-core.php' ); + else + $msg = __('An automated WordPress update has failed to complete! Please notify the site administrator.'); + + echo "
    $msg
    "; +} +add_action( 'admin_notices', 'maintenance_nag' ); +add_action( 'network_admin_notices', 'maintenance_nag' ); diff --git a/sources/wp-admin/includes/upgrade.php b/sources/wp-admin/includes/upgrade.php new file mode 100644 index 0000000..b1b8555 --- /dev/null +++ b/sources/wp-admin/includes/upgrade.php @@ -0,0 +1,2050 @@ +Note that password carefully! It is a random password that was generated just for you.'); + $user_id = wp_create_user($user_name, $user_password, $user_email); + update_user_option($user_id, 'default_password_nag', true, true); + $email_password = true; + } else if ( !$user_id ) { + // Password has been provided + $message = ''.__('Your chosen password.').''; + $user_id = wp_create_user($user_name, $user_password, $user_email); + } else { + $message = __('User already exists. Password inherited.'); + } + + $user = new WP_User($user_id); + $user->set_role('administrator'); + + wp_install_defaults($user_id); + + flush_rewrite_rules(); + + wp_new_blog_notification($blog_title, $guessurl, $user_id, ($email_password ? $user_password : __('The password you chose during the install.') ) ); + + wp_cache_flush(); + + return array('url' => $guessurl, 'user_id' => $user_id, 'password' => $user_password, 'password_message' => $message); +} +endif; + +if ( !function_exists('wp_install_defaults') ) : +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * + * @param int $user_id User ID. + */ +function wp_install_defaults($user_id) { + global $wpdb, $wp_rewrite, $current_site, $table_prefix; + + // Default category + $cat_name = __('Uncategorized'); + /* translators: Default category slug */ + $cat_slug = sanitize_title(_x('Uncategorized', 'Default category slug')); + + if ( global_terms_enabled() ) { + $cat_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = %s", $cat_slug ) ); + if ( $cat_id == null ) { + $wpdb->insert( $wpdb->sitecategories, array('cat_ID' => 0, 'cat_name' => $cat_name, 'category_nicename' => $cat_slug, 'last_updated' => current_time('mysql', true)) ); + $cat_id = $wpdb->insert_id; + } + update_option('default_category', $cat_id); + } else { + $cat_id = 1; + } + + $wpdb->insert( $wpdb->terms, array('term_id' => $cat_id, 'name' => $cat_name, 'slug' => $cat_slug, 'term_group' => 0) ); + $wpdb->insert( $wpdb->term_taxonomy, array('term_id' => $cat_id, 'taxonomy' => 'category', 'description' => '', 'parent' => 0, 'count' => 1)); + $cat_tt_id = $wpdb->insert_id; + + // First post + $now = date('Y-m-d H:i:s'); + $now_gmt = gmdate('Y-m-d H:i:s'); + $first_post_guid = get_option('home') . '/?p=1'; + + if ( is_multisite() ) { + $first_post = get_site_option( 'first_post' ); + + if ( empty($first_post) ) + $first_post = __( 'Welcome to SITE_NAME. This is your first post. Edit or delete it, then start blogging!' ); + + $first_post = str_replace( "SITE_URL", esc_url( network_home_url() ), $first_post ); + $first_post = str_replace( "SITE_NAME", $current_site->site_name, $first_post ); + } else { + $first_post = __('Welcome to WordPress. This is your first post. Edit or delete it, then start blogging!'); + } + + $wpdb->insert( $wpdb->posts, array( + 'post_author' => $user_id, + 'post_date' => $now, + 'post_date_gmt' => $now_gmt, + 'post_content' => $first_post, + 'post_excerpt' => '', + 'post_title' => __('Hello world!'), + /* translators: Default post slug */ + 'post_name' => sanitize_title( _x('hello-world', 'Default post slug') ), + 'post_modified' => $now, + 'post_modified_gmt' => $now_gmt, + 'guid' => $first_post_guid, + 'comment_count' => 1, + 'to_ping' => '', + 'pinged' => '', + 'post_content_filtered' => '' + )); + $wpdb->insert( $wpdb->term_relationships, array('term_taxonomy_id' => $cat_tt_id, 'object_id' => 1) ); + + // Default comment + $first_comment_author = __('Mr WordPress'); + $first_comment_url = 'http://wordpress.org/'; + $first_comment = __('Hi, this is a comment. +To delete a comment, just log in and view the post's comments. There you will have the option to edit or delete them.'); + if ( is_multisite() ) { + $first_comment_author = get_site_option( 'first_comment_author', $first_comment_author ); + $first_comment_url = get_site_option( 'first_comment_url', network_home_url() ); + $first_comment = get_site_option( 'first_comment', $first_comment ); + } + $wpdb->insert( $wpdb->comments, array( + 'comment_post_ID' => 1, + 'comment_author' => $first_comment_author, + 'comment_author_email' => '', + 'comment_author_url' => $first_comment_url, + 'comment_date' => $now, + 'comment_date_gmt' => $now_gmt, + 'comment_content' => $first_comment + )); + + // First Page + $first_page = sprintf( __( "This is an example page. It's different from a blog post because it will stay in one place and will show up in your site navigation (in most themes). Most people start with an About page that introduces them to potential site visitors. It might say something like this: + +
    Hi there! I'm a bike messenger by day, aspiring actor by night, and this is my blog. I live in Los Angeles, have a great dog named Jack, and I like piña coladas. (And gettin' caught in the rain.)
    + +...or something like this: + +
    The XYZ Doohickey Company was founded in 1971, and has been providing quality doohickeys to the public ever since. Located in Gotham City, XYZ employs over 2,000 people and does all kinds of awesome things for the Gotham community.
    + +As a new WordPress user, you should go to your dashboard to delete this page and create new pages for your content. Have fun!" ), admin_url() ); + if ( is_multisite() ) + $first_page = get_site_option( 'first_page', $first_page ); + $first_post_guid = get_option('home') . '/?page_id=2'; + $wpdb->insert( $wpdb->posts, array( + 'post_author' => $user_id, + 'post_date' => $now, + 'post_date_gmt' => $now_gmt, + 'post_content' => $first_page, + 'post_excerpt' => '', + 'post_title' => __( 'Sample Page' ), + /* translators: Default page slug */ + 'post_name' => __( 'sample-page' ), + 'post_modified' => $now, + 'post_modified_gmt' => $now_gmt, + 'guid' => $first_post_guid, + 'post_type' => 'page', + 'to_ping' => '', + 'pinged' => '', + 'post_content_filtered' => '' + )); + $wpdb->insert( $wpdb->postmeta, array( 'post_id' => 2, 'meta_key' => '_wp_page_template', 'meta_value' => 'default' ) ); + + // Set up default widgets for default theme. + update_option( 'widget_search', array ( 2 => array ( 'title' => '' ), '_multiwidget' => 1 ) ); + update_option( 'widget_recent-posts', array ( 2 => array ( 'title' => '', 'number' => 5 ), '_multiwidget' => 1 ) ); + update_option( 'widget_recent-comments', array ( 2 => array ( 'title' => '', 'number' => 5 ), '_multiwidget' => 1 ) ); + update_option( 'widget_archives', array ( 2 => array ( 'title' => '', 'count' => 0, 'dropdown' => 0 ), '_multiwidget' => 1 ) ); + update_option( 'widget_categories', array ( 2 => array ( 'title' => '', 'count' => 0, 'hierarchical' => 0, 'dropdown' => 0 ), '_multiwidget' => 1 ) ); + update_option( 'widget_meta', array ( 2 => array ( 'title' => '' ), '_multiwidget' => 1 ) ); + update_option( 'sidebars_widgets', array ( 'wp_inactive_widgets' => array (), 'sidebar-1' => array ( 0 => 'search-2', 1 => 'recent-posts-2', 2 => 'recent-comments-2', 3 => 'archives-2', 4 => 'categories-2', 5 => 'meta-2', ), 'sidebar-2' => array (),'array_version' => 3 ) ); + + if ( ! is_multisite() ) + update_user_meta( $user_id, 'show_welcome_panel', 1 ); + elseif ( ! is_super_admin( $user_id ) && ! metadata_exists( 'user', $user_id, 'show_welcome_panel' ) ) + update_user_meta( $user_id, 'show_welcome_panel', 2 ); + + if ( is_multisite() ) { + // Flush rules to pick up the new page. + $wp_rewrite->init(); + $wp_rewrite->flush_rules(); + + $user = new WP_User($user_id); + $wpdb->update( $wpdb->options, array('option_value' => $user->user_email), array('option_name' => 'admin_email') ); + + // Remove all perms except for the login user. + $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix.'user_level') ); + $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix.'capabilities') ); + + // Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.) TODO: Get previous_blog_id. + if ( !is_super_admin( $user_id ) && $user_id != 1 ) + $wpdb->delete( $wpdb->usermeta, array( 'user_id' => $user_id , 'meta_key' => $wpdb->base_prefix.'1_capabilities' ) ); + } +} +endif; + +if ( !function_exists('wp_new_blog_notification') ) : +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * + * @param string $blog_title Blog title. + * @param string $blog_url Blog url. + * @param int $user_id User ID. + * @param string $password User's Password. + */ +function wp_new_blog_notification($blog_title, $blog_url, $user_id, $password) { + $user = new WP_User( $user_id ); + $email = $user->user_email; + $name = $user->user_login; + $message = sprintf(__("Your new WordPress site has been successfully set up at: + +%1\$s + +You can log in to the administrator account with the following information: + +Username: %2\$s +Password: %3\$s + +We hope you enjoy your new site. Thanks! + +--The WordPress Team +http://wordpress.org/ +"), $blog_url, $name, $password); + + @wp_mail($email, __('New WordPress Site'), $message); +} +endif; + +if ( !function_exists('wp_upgrade') ) : +/** + * Run WordPress Upgrade functions. + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + * + * @return null + */ +function wp_upgrade() { + global $wp_current_db_version, $wp_db_version, $wpdb; + + $wp_current_db_version = __get_option('db_version'); + + // We are up-to-date. Nothing to do. + if ( $wp_db_version == $wp_current_db_version ) + return; + + if ( ! is_blog_installed() ) + return; + + wp_check_mysql_version(); + wp_cache_flush(); + pre_schema_upgrade(); + make_db_current_silent(); + upgrade_all(); + if ( is_multisite() && is_main_site() ) + upgrade_network(); + wp_cache_flush(); + + if ( is_multisite() ) { + if ( $wpdb->get_row( "SELECT blog_id FROM {$wpdb->blog_versions} WHERE blog_id = '{$wpdb->blogid}'" ) ) + $wpdb->query( "UPDATE {$wpdb->blog_versions} SET db_version = '{$wp_db_version}' WHERE blog_id = '{$wpdb->blogid}'" ); + else + $wpdb->query( "INSERT INTO {$wpdb->blog_versions} ( `blog_id` , `db_version` , `last_updated` ) VALUES ( '{$wpdb->blogid}', '{$wp_db_version}', NOW());" ); + } +} +endif; + +/** + * Functions to be called in install and upgrade scripts. + * + * {@internal Missing Long Description}} + * + * @since 1.0.1 + */ +function upgrade_all() { + global $wp_current_db_version, $wp_db_version; + $wp_current_db_version = __get_option('db_version'); + + // We are up-to-date. Nothing to do. + if ( $wp_db_version == $wp_current_db_version ) + return; + + // If the version is not set in the DB, try to guess the version. + if ( empty($wp_current_db_version) ) { + $wp_current_db_version = 0; + + // If the template option exists, we have 1.5. + $template = __get_option('template'); + if ( !empty($template) ) + $wp_current_db_version = 2541; + } + + if ( $wp_current_db_version < 6039 ) + upgrade_230_options_table(); + + populate_options(); + + if ( $wp_current_db_version < 2541 ) { + upgrade_100(); + upgrade_101(); + upgrade_110(); + upgrade_130(); + } + + if ( $wp_current_db_version < 3308 ) + upgrade_160(); + + if ( $wp_current_db_version < 4772 ) + upgrade_210(); + + if ( $wp_current_db_version < 4351 ) + upgrade_old_slugs(); + + if ( $wp_current_db_version < 5539 ) + upgrade_230(); + + if ( $wp_current_db_version < 6124 ) + upgrade_230_old_tables(); + + if ( $wp_current_db_version < 7499 ) + upgrade_250(); + + if ( $wp_current_db_version < 7935 ) + upgrade_252(); + + if ( $wp_current_db_version < 8201 ) + upgrade_260(); + + if ( $wp_current_db_version < 8989 ) + upgrade_270(); + + if ( $wp_current_db_version < 10360 ) + upgrade_280(); + + if ( $wp_current_db_version < 11958 ) + upgrade_290(); + + if ( $wp_current_db_version < 15260 ) + upgrade_300(); + + if ( $wp_current_db_version < 19389 ) + upgrade_330(); + + if ( $wp_current_db_version < 20080 ) + upgrade_340(); + + if ( $wp_current_db_version < 22422 ) + upgrade_350(); + + if ( $wp_current_db_version < 25824 ) + upgrade_370(); + + maybe_disable_link_manager(); + + maybe_disable_automattic_widgets(); + + update_option( 'db_version', $wp_db_version ); + update_option( 'db_upgraded', true ); +} + +/** + * Execute changes made in WordPress 1.0. + * + * @since 1.0.0 + */ +function upgrade_100() { + global $wpdb; + + // Get the title and ID of every post, post_name to check if it already has a value + $posts = $wpdb->get_results("SELECT ID, post_title, post_name FROM $wpdb->posts WHERE post_name = ''"); + if ($posts) { + foreach($posts as $post) { + if ('' == $post->post_name) { + $newtitle = sanitize_title($post->post_title); + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_name = %s WHERE ID = %d", $newtitle, $post->ID) ); + } + } + } + + $categories = $wpdb->get_results("SELECT cat_ID, cat_name, category_nicename FROM $wpdb->categories"); + foreach ($categories as $category) { + if ('' == $category->category_nicename) { + $newtitle = sanitize_title($category->cat_name); + $wpdb->update( $wpdb->categories, array('category_nicename' => $newtitle), array('cat_ID' => $category->cat_ID) ); + } + } + + $wpdb->query("UPDATE $wpdb->options SET option_value = REPLACE(option_value, 'wp-links/links-images/', 'wp-images/links/') + WHERE option_name LIKE 'links_rating_image%' + AND option_value LIKE 'wp-links/links-images/%'"); + + $done_ids = $wpdb->get_results("SELECT DISTINCT post_id FROM $wpdb->post2cat"); + if ($done_ids) : + foreach ($done_ids as $done_id) : + $done_posts[] = $done_id->post_id; + endforeach; + $catwhere = ' AND ID NOT IN (' . implode(',', $done_posts) . ')'; + else: + $catwhere = ''; + endif; + + $allposts = $wpdb->get_results("SELECT ID, post_category FROM $wpdb->posts WHERE post_category != '0' $catwhere"); + if ($allposts) : + foreach ($allposts as $post) { + // Check to see if it's already been imported + $cat = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->post2cat WHERE post_id = %d AND category_id = %d", $post->ID, $post->post_category) ); + if (!$cat && 0 != $post->post_category) { // If there's no result + $wpdb->insert( $wpdb->post2cat, array('post_id' => $post->ID, 'category_id' => $post->post_category) ); + } + } + endif; +} + +/** + * Execute changes made in WordPress 1.0.1. + * + * @since 1.0.1 + */ +function upgrade_101() { + global $wpdb; + + // Clean up indices, add a few + add_clean_index($wpdb->posts, 'post_name'); + add_clean_index($wpdb->posts, 'post_status'); + add_clean_index($wpdb->categories, 'category_nicename'); + add_clean_index($wpdb->comments, 'comment_approved'); + add_clean_index($wpdb->comments, 'comment_post_ID'); + add_clean_index($wpdb->links , 'link_category'); + add_clean_index($wpdb->links , 'link_visible'); +} + +/** + * Execute changes made in WordPress 1.2. + * + * @since 1.2.0 + */ +function upgrade_110() { + global $wpdb; + + // Set user_nicename. + $users = $wpdb->get_results("SELECT ID, user_nickname, user_nicename FROM $wpdb->users"); + foreach ($users as $user) { + if ('' == $user->user_nicename) { + $newname = sanitize_title($user->user_nickname); + $wpdb->update( $wpdb->users, array('user_nicename' => $newname), array('ID' => $user->ID) ); + } + } + + $users = $wpdb->get_results("SELECT ID, user_pass from $wpdb->users"); + foreach ($users as $row) { + if (!preg_match('/^[A-Fa-f0-9]{32}$/', $row->user_pass)) { + $wpdb->update( $wpdb->users, array('user_pass' => md5($row->user_pass)), array('ID' => $row->ID) ); + } + } + + // Get the GMT offset, we'll use that later on + $all_options = get_alloptions_110(); + + $time_difference = $all_options->time_difference; + + $server_time = time()+date('Z'); + $weblogger_time = $server_time + $time_difference * HOUR_IN_SECONDS; + $gmt_time = time(); + + $diff_gmt_server = ($gmt_time - $server_time) / HOUR_IN_SECONDS; + $diff_weblogger_server = ($weblogger_time - $server_time) / HOUR_IN_SECONDS; + $diff_gmt_weblogger = $diff_gmt_server - $diff_weblogger_server; + $gmt_offset = -$diff_gmt_weblogger; + + // Add a gmt_offset option, with value $gmt_offset + add_option('gmt_offset', $gmt_offset); + + // Check if we already set the GMT fields (if we did, then + // MAX(post_date_gmt) can't be '0000-00-00 00:00:00' + // I just slapped myself silly for not thinking about it earlier + $got_gmt_fields = ! ($wpdb->get_var("SELECT MAX(post_date_gmt) FROM $wpdb->posts") == '0000-00-00 00:00:00'); + + if (!$got_gmt_fields) { + + // Add or subtract time to all dates, to get GMT dates + $add_hours = intval($diff_gmt_weblogger); + $add_minutes = intval(60 * ($diff_gmt_weblogger - $add_hours)); + $wpdb->query("UPDATE $wpdb->posts SET post_date_gmt = DATE_ADD(post_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)"); + $wpdb->query("UPDATE $wpdb->posts SET post_modified = post_date"); + $wpdb->query("UPDATE $wpdb->posts SET post_modified_gmt = DATE_ADD(post_modified, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE) WHERE post_modified != '0000-00-00 00:00:00'"); + $wpdb->query("UPDATE $wpdb->comments SET comment_date_gmt = DATE_ADD(comment_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)"); + $wpdb->query("UPDATE $wpdb->users SET user_registered = DATE_ADD(user_registered, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)"); + } + +} + +/** + * Execute changes made in WordPress 1.5. + * + * @since 1.5.0 + */ +function upgrade_130() { + global $wpdb; + + // Remove extraneous backslashes. + $posts = $wpdb->get_results("SELECT ID, post_title, post_content, post_excerpt, guid, post_date, post_name, post_status, post_author FROM $wpdb->posts"); + if ($posts) { + foreach($posts as $post) { + $post_content = addslashes(deslash($post->post_content)); + $post_title = addslashes(deslash($post->post_title)); + $post_excerpt = addslashes(deslash($post->post_excerpt)); + if ( empty($post->guid) ) + $guid = get_permalink($post->ID); + else + $guid = $post->guid; + + $wpdb->update( $wpdb->posts, compact('post_title', 'post_content', 'post_excerpt', 'guid'), array('ID' => $post->ID) ); + + } + } + + // Remove extraneous backslashes. + $comments = $wpdb->get_results("SELECT comment_ID, comment_author, comment_content FROM $wpdb->comments"); + if ($comments) { + foreach($comments as $comment) { + $comment_content = deslash($comment->comment_content); + $comment_author = deslash($comment->comment_author); + + $wpdb->update($wpdb->comments, compact('comment_content', 'comment_author'), array('comment_ID' => $comment->comment_ID) ); + } + } + + // Remove extraneous backslashes. + $links = $wpdb->get_results("SELECT link_id, link_name, link_description FROM $wpdb->links"); + if ($links) { + foreach($links as $link) { + $link_name = deslash($link->link_name); + $link_description = deslash($link->link_description); + + $wpdb->update( $wpdb->links, compact('link_name', 'link_description'), array('link_id' => $link->link_id) ); + } + } + + $active_plugins = __get_option('active_plugins'); + + // If plugins are not stored in an array, they're stored in the old + // newline separated format. Convert to new format. + if ( !is_array( $active_plugins ) ) { + $active_plugins = explode("\n", trim($active_plugins)); + update_option('active_plugins', $active_plugins); + } + + // Obsolete tables + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optionvalues'); + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiontypes'); + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroups'); + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroup_options'); + + // Update comments table to use comment_type + $wpdb->query("UPDATE $wpdb->comments SET comment_type='trackback', comment_content = REPLACE(comment_content, '', '') WHERE comment_content LIKE '%'"); + $wpdb->query("UPDATE $wpdb->comments SET comment_type='pingback', comment_content = REPLACE(comment_content, '', '') WHERE comment_content LIKE '%'"); + + // Some versions have multiple duplicate option_name rows with the same values + $options = $wpdb->get_results("SELECT option_name, COUNT(option_name) AS dupes FROM `$wpdb->options` GROUP BY option_name"); + foreach ( $options as $option ) { + if ( 1 != $option->dupes ) { // Could this be done in the query? + $limit = $option->dupes - 1; + $dupe_ids = $wpdb->get_col( $wpdb->prepare("SELECT option_id FROM $wpdb->options WHERE option_name = %s LIMIT %d", $option->option_name, $limit) ); + if ( $dupe_ids ) { + $dupe_ids = join($dupe_ids, ','); + $wpdb->query("DELETE FROM $wpdb->options WHERE option_id IN ($dupe_ids)"); + } + } + } + + make_site_theme(); +} + +/** + * Execute changes made in WordPress 2.0. + * + * @since 2.0.0 + */ +function upgrade_160() { + global $wpdb, $wp_current_db_version; + + populate_roles_160(); + + $users = $wpdb->get_results("SELECT * FROM $wpdb->users"); + foreach ( $users as $user ) : + if ( !empty( $user->user_firstname ) ) + update_user_meta( $user->ID, 'first_name', wp_slash($user->user_firstname) ); + if ( !empty( $user->user_lastname ) ) + update_user_meta( $user->ID, 'last_name', wp_slash($user->user_lastname) ); + if ( !empty( $user->user_nickname ) ) + update_user_meta( $user->ID, 'nickname', wp_slash($user->user_nickname) ); + if ( !empty( $user->user_level ) ) + update_user_meta( $user->ID, $wpdb->prefix . 'user_level', $user->user_level ); + if ( !empty( $user->user_icq ) ) + update_user_meta( $user->ID, 'icq', wp_slash($user->user_icq) ); + if ( !empty( $user->user_aim ) ) + update_user_meta( $user->ID, 'aim', wp_slash($user->user_aim) ); + if ( !empty( $user->user_msn ) ) + update_user_meta( $user->ID, 'msn', wp_slash($user->user_msn) ); + if ( !empty( $user->user_yim ) ) + update_user_meta( $user->ID, 'yim', wp_slash($user->user_icq) ); + if ( !empty( $user->user_description ) ) + update_user_meta( $user->ID, 'description', wp_slash($user->user_description) ); + + if ( isset( $user->user_idmode ) ): + $idmode = $user->user_idmode; + if ($idmode == 'nickname') $id = $user->user_nickname; + if ($idmode == 'login') $id = $user->user_login; + if ($idmode == 'firstname') $id = $user->user_firstname; + if ($idmode == 'lastname') $id = $user->user_lastname; + if ($idmode == 'namefl') $id = $user->user_firstname.' '.$user->user_lastname; + if ($idmode == 'namelf') $id = $user->user_lastname.' '.$user->user_firstname; + if (!$idmode) $id = $user->user_nickname; + $wpdb->update( $wpdb->users, array('display_name' => $id), array('ID' => $user->ID) ); + endif; + + // FIXME: RESET_CAPS is temporary code to reset roles and caps if flag is set. + $caps = get_user_meta( $user->ID, $wpdb->prefix . 'capabilities'); + if ( empty($caps) || defined('RESET_CAPS') ) { + $level = get_user_meta($user->ID, $wpdb->prefix . 'user_level', true); + $role = translate_level_to_role($level); + update_user_meta( $user->ID, $wpdb->prefix . 'capabilities', array($role => true) ); + } + + endforeach; + $old_user_fields = array( 'user_firstname', 'user_lastname', 'user_icq', 'user_aim', 'user_msn', 'user_yim', 'user_idmode', 'user_ip', 'user_domain', 'user_browser', 'user_description', 'user_nickname', 'user_level' ); + $wpdb->hide_errors(); + foreach ( $old_user_fields as $old ) + $wpdb->query("ALTER TABLE $wpdb->users DROP $old"); + $wpdb->show_errors(); + + // populate comment_count field of posts table + $comments = $wpdb->get_results( "SELECT comment_post_ID, COUNT(*) as c FROM $wpdb->comments WHERE comment_approved = '1' GROUP BY comment_post_ID" ); + if ( is_array( $comments ) ) + foreach ($comments as $comment) + $wpdb->update( $wpdb->posts, array('comment_count' => $comment->c), array('ID' => $comment->comment_post_ID) ); + + // Some alpha versions used a post status of object instead of attachment and put + // the mime type in post_type instead of post_mime_type. + if ( $wp_current_db_version > 2541 && $wp_current_db_version <= 3091 ) { + $objects = $wpdb->get_results("SELECT ID, post_type FROM $wpdb->posts WHERE post_status = 'object'"); + foreach ($objects as $object) { + $wpdb->update( $wpdb->posts, array( 'post_status' => 'attachment', + 'post_mime_type' => $object->post_type, + 'post_type' => ''), + array( 'ID' => $object->ID ) ); + + $meta = get_post_meta($object->ID, 'imagedata', true); + if ( ! empty($meta['file']) ) + update_attached_file( $object->ID, $meta['file'] ); + } + } +} + +/** + * Execute changes made in WordPress 2.1. + * + * @since 2.1.0 + */ +function upgrade_210() { + global $wpdb, $wp_current_db_version; + + if ( $wp_current_db_version < 3506 ) { + // Update status and type. + $posts = $wpdb->get_results("SELECT ID, post_status FROM $wpdb->posts"); + + if ( ! empty($posts) ) foreach ($posts as $post) { + $status = $post->post_status; + $type = 'post'; + + if ( 'static' == $status ) { + $status = 'publish'; + $type = 'page'; + } else if ( 'attachment' == $status ) { + $status = 'inherit'; + $type = 'attachment'; + } + + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_status = %s, post_type = %s WHERE ID = %d", $status, $type, $post->ID) ); + } + } + + if ( $wp_current_db_version < 3845 ) { + populate_roles_210(); + } + + if ( $wp_current_db_version < 3531 ) { + // Give future posts a post_status of future. + $now = gmdate('Y-m-d H:i:59'); + $wpdb->query ("UPDATE $wpdb->posts SET post_status = 'future' WHERE post_status = 'publish' AND post_date_gmt > '$now'"); + + $posts = $wpdb->get_results("SELECT ID, post_date FROM $wpdb->posts WHERE post_status ='future'"); + if ( !empty($posts) ) + foreach ( $posts as $post ) + wp_schedule_single_event(mysql2date('U', $post->post_date, false), 'publish_future_post', array($post->ID)); + } +} + +/** + * Execute changes made in WordPress 2.3. + * + * @since 2.3.0 + */ +function upgrade_230() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version < 5200 ) { + populate_roles_230(); + } + + // Convert categories to terms. + $tt_ids = array(); + $have_tags = false; + $categories = $wpdb->get_results("SELECT * FROM $wpdb->categories ORDER BY cat_ID"); + foreach ($categories as $category) { + $term_id = (int) $category->cat_ID; + $name = $category->cat_name; + $description = $category->category_description; + $slug = $category->category_nicename; + $parent = $category->category_parent; + $term_group = 0; + + // Associate terms with the same slug in a term group and make slugs unique. + if ( $exists = $wpdb->get_results( $wpdb->prepare("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug) ) ) { + $term_group = $exists[0]->term_group; + $id = $exists[0]->term_id; + $num = 2; + do { + $alt_slug = $slug . "-$num"; + $num++; + $slug_check = $wpdb->get_var( $wpdb->prepare("SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug) ); + } while ( $slug_check ); + + $slug = $alt_slug; + + if ( empty( $term_group ) ) { + $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM $wpdb->terms GROUP BY term_group") + 1; + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->terms SET term_group = %d WHERE term_id = %d", $term_group, $id) ); + } + } + + $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES + (%d, %s, %s, %d)", $term_id, $name, $slug, $term_group) ); + + $count = 0; + if ( !empty($category->category_count) ) { + $count = (int) $category->category_count; + $taxonomy = 'category'; + $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ( %d, %s, %s, %d, %d)", $term_id, $taxonomy, $description, $parent, $count) ); + $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id; + } + + if ( !empty($category->link_count) ) { + $count = (int) $category->link_count; + $taxonomy = 'link_category'; + $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ( %d, %s, %s, %d, %d)", $term_id, $taxonomy, $description, $parent, $count) ); + $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id; + } + + if ( !empty($category->tag_count) ) { + $have_tags = true; + $count = (int) $category->tag_count; + $taxonomy = 'post_tag'; + $wpdb->insert( $wpdb->term_taxonomy, compact('term_id', 'taxonomy', 'description', 'parent', 'count') ); + $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id; + } + + if ( empty($count) ) { + $count = 0; + $taxonomy = 'category'; + $wpdb->insert( $wpdb->term_taxonomy, compact('term_id', 'taxonomy', 'description', 'parent', 'count') ); + $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id; + } + } + + $select = 'post_id, category_id'; + if ( $have_tags ) + $select .= ', rel_type'; + + $posts = $wpdb->get_results("SELECT $select FROM $wpdb->post2cat GROUP BY post_id, category_id"); + foreach ( $posts as $post ) { + $post_id = (int) $post->post_id; + $term_id = (int) $post->category_id; + $taxonomy = 'category'; + if ( !empty($post->rel_type) && 'tag' == $post->rel_type) + $taxonomy = 'tag'; + $tt_id = $tt_ids[$term_id][$taxonomy]; + if ( empty($tt_id) ) + continue; + + $wpdb->insert( $wpdb->term_relationships, array('object_id' => $post_id, 'term_taxonomy_id' => $tt_id) ); + } + + // < 3570 we used linkcategories. >= 3570 we used categories and link2cat. + if ( $wp_current_db_version < 3570 ) { + // Create link_category terms for link categories. Create a map of link cat IDs + // to link_category terms. + $link_cat_id_map = array(); + $default_link_cat = 0; + $tt_ids = array(); + $link_cats = $wpdb->get_results("SELECT cat_id, cat_name FROM " . $wpdb->prefix . 'linkcategories'); + foreach ( $link_cats as $category) { + $cat_id = (int) $category->cat_id; + $term_id = 0; + $name = wp_slash($category->cat_name); + $slug = sanitize_title($name); + $term_group = 0; + + // Associate terms with the same slug in a term group and make slugs unique. + if ( $exists = $wpdb->get_results( $wpdb->prepare("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug) ) ) { + $term_group = $exists[0]->term_group; + $term_id = $exists[0]->term_id; + } + + if ( empty($term_id) ) { + $wpdb->insert( $wpdb->terms, compact('name', 'slug', 'term_group') ); + $term_id = (int) $wpdb->insert_id; + } + + $link_cat_id_map[$cat_id] = $term_id; + $default_link_cat = $term_id; + + $wpdb->insert( $wpdb->term_taxonomy, array('term_id' => $term_id, 'taxonomy' => 'link_category', 'description' => '', 'parent' => 0, 'count' => 0) ); + $tt_ids[$term_id] = (int) $wpdb->insert_id; + } + + // Associate links to cats. + $links = $wpdb->get_results("SELECT link_id, link_category FROM $wpdb->links"); + if ( !empty($links) ) foreach ( $links as $link ) { + if ( 0 == $link->link_category ) + continue; + if ( ! isset($link_cat_id_map[$link->link_category]) ) + continue; + $term_id = $link_cat_id_map[$link->link_category]; + $tt_id = $tt_ids[$term_id]; + if ( empty($tt_id) ) + continue; + + $wpdb->insert( $wpdb->term_relationships, array('object_id' => $link->link_id, 'term_taxonomy_id' => $tt_id) ); + } + + // Set default to the last category we grabbed during the upgrade loop. + update_option('default_link_category', $default_link_cat); + } else { + $links = $wpdb->get_results("SELECT link_id, category_id FROM $wpdb->link2cat GROUP BY link_id, category_id"); + foreach ( $links as $link ) { + $link_id = (int) $link->link_id; + $term_id = (int) $link->category_id; + $taxonomy = 'link_category'; + $tt_id = $tt_ids[$term_id][$taxonomy]; + if ( empty($tt_id) ) + continue; + $wpdb->insert( $wpdb->term_relationships, array('object_id' => $link_id, 'term_taxonomy_id' => $tt_id) ); + } + } + + if ( $wp_current_db_version < 4772 ) { + // Obsolete linkcategories table + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'linkcategories'); + } + + // Recalculate all counts + $terms = $wpdb->get_results("SELECT term_taxonomy_id, taxonomy FROM $wpdb->term_taxonomy"); + foreach ( (array) $terms as $term ) { + if ( ('post_tag' == $term->taxonomy) || ('category' == $term->taxonomy) ) + $count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type = 'post' AND term_taxonomy_id = %d", $term->term_taxonomy_id) ); + else + $count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term->term_taxonomy_id) ); + $wpdb->update( $wpdb->term_taxonomy, array('count' => $count), array('term_taxonomy_id' => $term->term_taxonomy_id) ); + } +} + +/** + * Remove old options from the database. + * + * @since 2.3.0 + */ +function upgrade_230_options_table() { + global $wpdb; + $old_options_fields = array( 'option_can_override', 'option_type', 'option_width', 'option_height', 'option_description', 'option_admin_level' ); + $wpdb->hide_errors(); + foreach ( $old_options_fields as $old ) + $wpdb->query("ALTER TABLE $wpdb->options DROP $old"); + $wpdb->show_errors(); +} + +/** + * Remove old categories, link2cat, and post2cat database tables. + * + * @since 2.3.0 + */ +function upgrade_230_old_tables() { + global $wpdb; + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'categories'); + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'link2cat'); + $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'post2cat'); +} + +/** + * Upgrade old slugs made in version 2.2. + * + * @since 2.2.0 + */ +function upgrade_old_slugs() { + // upgrade people who were using the Redirect Old Slugs plugin + global $wpdb; + $wpdb->query("UPDATE $wpdb->postmeta SET meta_key = '_wp_old_slug' WHERE meta_key = 'old_slug'"); +} + +/** + * Execute changes made in WordPress 2.5.0. + * + * @since 2.5.0 + */ +function upgrade_250() { + global $wp_current_db_version; + + if ( $wp_current_db_version < 6689 ) { + populate_roles_250(); + } + +} + +/** + * Execute changes made in WordPress 2.5.2. + * + * @since 2.5.2 + */ +function upgrade_252() { + global $wpdb; + + $wpdb->query("UPDATE $wpdb->users SET user_activation_key = ''"); +} + +/** + * Execute changes made in WordPress 2.6. + * + * @since 2.6.0 + */ +function upgrade_260() { + global $wp_current_db_version; + + if ( $wp_current_db_version < 8000 ) + populate_roles_260(); +} + +/** + * Execute changes made in WordPress 2.7. + * + * @since 2.7.0 + */ +function upgrade_270() { + global $wpdb, $wp_current_db_version; + + if ( $wp_current_db_version < 8980 ) + populate_roles_270(); + + // Update post_date for unpublished posts with empty timestamp + if ( $wp_current_db_version < 8921 ) + $wpdb->query( "UPDATE $wpdb->posts SET post_date = post_modified WHERE post_date = '0000-00-00 00:00:00'" ); +} + +/** + * Execute changes made in WordPress 2.8. + * + * @since 2.8.0 + */ +function upgrade_280() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version < 10360 ) + populate_roles_280(); + if ( is_multisite() ) { + $start = 0; + while( $rows = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options ORDER BY option_id LIMIT $start, 20" ) ) { + foreach( $rows as $row ) { + $value = $row->option_value; + if ( !@unserialize( $value ) ) + $value = stripslashes( $value ); + if ( $value !== $row->option_value ) { + update_option( $row->option_name, $value ); + } + } + $start += 20; + } + refresh_blog_details( $wpdb->blogid ); + } +} + +/** + * Execute changes made in WordPress 2.9. + * + * @since 2.9.0 + */ +function upgrade_290() { + global $wp_current_db_version; + + if ( $wp_current_db_version < 11958 ) { + // Previously, setting depth to 1 would redundantly disable threading, but now 2 is the minimum depth to avoid confusion + if ( get_option( 'thread_comments_depth' ) == '1' ) { + update_option( 'thread_comments_depth', 2 ); + update_option( 'thread_comments', 0 ); + } + } +} + +/** + * Execute changes made in WordPress 3.0. + * + * @since 3.0.0 + */ +function upgrade_300() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version < 15093 ) + populate_roles_300(); + + if ( $wp_current_db_version < 14139 && is_multisite() && is_main_site() && ! defined( 'MULTISITE' ) && get_site_option( 'siteurl' ) === false ) + add_site_option( 'siteurl', '' ); + + // 3.0 screen options key name changes. + if ( is_main_site() && !defined('DO_NOT_UPGRADE_GLOBAL_TABLES') ) { + $prefix = like_escape($wpdb->base_prefix); + $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key LIKE '{$prefix}%meta-box-hidden%' OR meta_key LIKE '{$prefix}%closedpostboxes%' OR meta_key LIKE '{$prefix}%manage-%-columns-hidden%' OR meta_key LIKE '{$prefix}%meta-box-order%' OR meta_key LIKE '{$prefix}%metaboxorder%' OR meta_key LIKE '{$prefix}%screen_layout%' + OR meta_key = 'manageedittagscolumnshidden' OR meta_key='managecategoriescolumnshidden' OR meta_key = 'manageedit-tagscolumnshidden' OR meta_key = 'manageeditcolumnshidden' OR meta_key = 'categories_per_page' OR meta_key = 'edit_tags_per_page'" ); + } + +} + +/** + * Execute changes made in WordPress 3.3. + * + * @since 3.3.0 + */ +function upgrade_330() { + global $wp_current_db_version, $wpdb, $wp_registered_widgets, $sidebars_widgets; + + if ( $wp_current_db_version < 19061 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) { + $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('show_admin_bar_admin', 'plugins_last_view')" ); + } + + if ( $wp_current_db_version >= 11548 ) + return; + + $sidebars_widgets = get_option( 'sidebars_widgets', array() ); + $_sidebars_widgets = array(); + + if ( isset($sidebars_widgets['wp_inactive_widgets']) || empty($sidebars_widgets) ) + $sidebars_widgets['array_version'] = 3; + elseif ( !isset($sidebars_widgets['array_version']) ) + $sidebars_widgets['array_version'] = 1; + + switch ( $sidebars_widgets['array_version'] ) { + case 1 : + foreach ( (array) $sidebars_widgets as $index => $sidebar ) + if ( is_array($sidebar) ) + foreach ( (array) $sidebar as $i => $name ) { + $id = strtolower($name); + if ( isset($wp_registered_widgets[$id]) ) { + $_sidebars_widgets[$index][$i] = $id; + continue; + } + $id = sanitize_title($name); + if ( isset($wp_registered_widgets[$id]) ) { + $_sidebars_widgets[$index][$i] = $id; + continue; + } + + $found = false; + + foreach ( $wp_registered_widgets as $widget_id => $widget ) { + if ( strtolower($widget['name']) == strtolower($name) ) { + $_sidebars_widgets[$index][$i] = $widget['id']; + $found = true; + break; + } elseif ( sanitize_title($widget['name']) == sanitize_title($name) ) { + $_sidebars_widgets[$index][$i] = $widget['id']; + $found = true; + break; + } + } + + if ( $found ) + continue; + + unset($_sidebars_widgets[$index][$i]); + } + $_sidebars_widgets['array_version'] = 2; + $sidebars_widgets = $_sidebars_widgets; + unset($_sidebars_widgets); + + case 2 : + $sidebars_widgets = retrieve_widgets(); + $sidebars_widgets['array_version'] = 3; + update_option( 'sidebars_widgets', $sidebars_widgets ); + } +} + +/** + * Execute changes made in WordPress 3.4. + * + * @since 3.4.0 + */ +function upgrade_340() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version < 19798 ) { + $wpdb->hide_errors(); + $wpdb->query( "ALTER TABLE $wpdb->options DROP COLUMN blog_id" ); + $wpdb->show_errors(); + } + + if ( $wp_current_db_version < 19799 ) { + $wpdb->hide_errors(); + $wpdb->query("ALTER TABLE $wpdb->comments DROP INDEX comment_approved"); + $wpdb->show_errors(); + } + + if ( $wp_current_db_version < 20022 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) { + $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'themes_last_view'" ); + } + + if ( $wp_current_db_version < 20080 ) { + if ( 'yes' == $wpdb->get_var( "SELECT autoload FROM $wpdb->options WHERE option_name = 'uninstall_plugins'" ) ) { + $uninstall_plugins = get_option( 'uninstall_plugins' ); + delete_option( 'uninstall_plugins' ); + add_option( 'uninstall_plugins', $uninstall_plugins, null, 'no' ); + } + } +} + +/** + * Execute changes made in WordPress 3.5. + * + * @since 3.5.0 + */ +function upgrade_350() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version < 22006 && $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) ) + update_option( 'link_manager_enabled', 1 ); // Previously set to 0 by populate_options() + + if ( $wp_current_db_version < 21811 && is_main_site() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) { + $meta_keys = array(); + foreach ( array_merge( get_post_types(), get_taxonomies() ) as $name ) { + if ( false !== strpos( $name, '-' ) ) + $meta_keys[] = 'edit_' . str_replace( '-', '_', $name ) . '_per_page'; + } + if ( $meta_keys ) { + $meta_keys = implode( "', '", $meta_keys ); + $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('$meta_keys')" ); + } + } + + if ( $wp_current_db_version < 22422 && $term = get_term_by( 'slug', 'post-format-standard', 'post_format' ) ) + wp_delete_term( $term->term_id, 'post_format' ); +} + +/** + * Execute changes made in WordPress 3.7. + * + * @since 3.7.0 + */ +function upgrade_370() { + global $wp_current_db_version; + if ( $wp_current_db_version < 25824 ) + wp_clear_scheduled_hook( 'wp_auto_updates_maybe_update' ); +} + +/** + * Execute network level changes + * + * @since 3.0.0 + */ +function upgrade_network() { + global $wp_current_db_version, $wpdb; + + // Always + if ( is_main_network() ) { + // Deletes all expired transients. + // The multi-table delete syntax is used to delete the transient record from table a, + // and the corresponding transient_timeout record from table b. + $time = time(); + $wpdb->query("DELETE a, b FROM $wpdb->sitemeta a, $wpdb->sitemeta b WHERE + a.meta_key LIKE '\_site\_transient\_%' AND + a.meta_key NOT LIKE '\_site\_transient\_timeout\_%' AND + b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) ) + AND b.meta_value < $time"); + } + + // 2.8 + if ( $wp_current_db_version < 11549 ) { + $wpmu_sitewide_plugins = get_site_option( 'wpmu_sitewide_plugins' ); + $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' ); + if ( $wpmu_sitewide_plugins ) { + if ( !$active_sitewide_plugins ) + $sitewide_plugins = (array) $wpmu_sitewide_plugins; + else + $sitewide_plugins = array_merge( (array) $active_sitewide_plugins, (array) $wpmu_sitewide_plugins ); + + update_site_option( 'active_sitewide_plugins', $sitewide_plugins ); + } + delete_site_option( 'wpmu_sitewide_plugins' ); + delete_site_option( 'deactivated_sitewide_plugins' ); + + $start = 0; + while( $rows = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} ORDER BY meta_id LIMIT $start, 20" ) ) { + foreach( $rows as $row ) { + $value = $row->meta_value; + if ( !@unserialize( $value ) ) + $value = stripslashes( $value ); + if ( $value !== $row->meta_value ) { + update_site_option( $row->meta_key, $value ); + } + } + $start += 20; + } + } + + // 3.0 + if ( $wp_current_db_version < 13576 ) + update_site_option( 'global_terms_enabled', '1' ); + + // 3.3 + if ( $wp_current_db_version < 19390 ) + update_site_option( 'initial_db_version', $wp_current_db_version ); + + if ( $wp_current_db_version < 19470 ) { + if ( false === get_site_option( 'active_sitewide_plugins' ) ) + update_site_option( 'active_sitewide_plugins', array() ); + } + + // 3.4 + if ( $wp_current_db_version < 20148 ) { + // 'allowedthemes' keys things by stylesheet. 'allowed_themes' keyed things by name. + $allowedthemes = get_site_option( 'allowedthemes' ); + $allowed_themes = get_site_option( 'allowed_themes' ); + if ( false === $allowedthemes && is_array( $allowed_themes ) && $allowed_themes ) { + $converted = array(); + $themes = wp_get_themes(); + foreach ( $themes as $stylesheet => $theme_data ) { + if ( isset( $allowed_themes[ $theme_data->get('Name') ] ) ) + $converted[ $stylesheet ] = true; + } + update_site_option( 'allowedthemes', $converted ); + delete_site_option( 'allowed_themes' ); + } + } + + // 3.5 + if ( $wp_current_db_version < 21823 ) + update_site_option( 'ms_files_rewriting', '1' ); + + // 3.5.2 + if ( $wp_current_db_version < 24448 ) { + $illegal_names = get_site_option( 'illegal_names' ); + if ( is_array( $illegal_names ) && count( $illegal_names ) === 1 ) { + $illegal_name = reset( $illegal_names ); + $illegal_names = explode( ' ', $illegal_name ); + update_site_option( 'illegal_names', $illegal_names ); + } + } +} + +// The functions we use to actually do stuff + +// General + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.0.0 + * + * @param string $table_name Database table name to create. + * @param string $create_ddl SQL statement to create table. + * @return bool If table already exists or was created by function. + */ +function maybe_create_table($table_name, $create_ddl) { + global $wpdb; + if ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name ) + return true; + //didn't find it try to create it. + $q = $wpdb->query($create_ddl); + // we cannot directly tell that whether this succeeded! + if ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name ) + return true; + return false; +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.0.1 + * + * @param string $table Database table name. + * @param string $index Index name to drop. + * @return bool True, when finished. + */ +function drop_index($table, $index) { + global $wpdb; + $wpdb->hide_errors(); + $wpdb->query("ALTER TABLE `$table` DROP INDEX `$index`"); + // Now we need to take out all the extra ones we may have created + for ($i = 0; $i < 25; $i++) { + $wpdb->query("ALTER TABLE `$table` DROP INDEX `{$index}_$i`"); + } + $wpdb->show_errors(); + return true; +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.0.1 + * + * @param string $table Database table name. + * @param string $index Database table index column. + * @return bool True, when done with execution. + */ +function add_clean_index($table, $index) { + global $wpdb; + drop_index($table, $index); + $wpdb->query("ALTER TABLE `$table` ADD INDEX ( `$index` )"); + return true; +} + +/** + ** maybe_add_column() + ** Add column to db table if it doesn't exist. + ** Returns: true if already exists or on successful completion + ** false on error + */ +function maybe_add_column($table_name, $column_name, $create_ddl) { + global $wpdb; + foreach ($wpdb->get_col("DESC $table_name", 0) as $column ) { + if ($column == $column_name) { + return true; + } + } + //didn't find it try to create it. + $q = $wpdb->query($create_ddl); + // we cannot directly tell that whether this succeeded! + foreach ($wpdb->get_col("DESC $table_name", 0) as $column ) { + if ($column == $column_name) { + return true; + } + } + return false; +} + +/** + * Retrieve all options as it was for 1.2. + * + * @since 1.2.0 + * + * @return array List of options. + */ +function get_alloptions_110() { + global $wpdb; + $all_options = new stdClass; + if ( $options = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" ) ) { + foreach ( $options as $option ) { + if ( 'siteurl' == $option->option_name || 'home' == $option->option_name || 'category_base' == $option->option_name ) + $option->option_value = untrailingslashit( $option->option_value ); + $all_options->{$option->option_name} = stripslashes( $option->option_value ); + } + } + return $all_options; +} + +/** + * Version of get_option that is private to install/upgrade. + * + * @since 1.5.1 + * @access private + * + * @param string $setting Option name. + * @return mixed + */ +function __get_option($setting) { + global $wpdb; + + if ( $setting == 'home' && defined( 'WP_HOME' ) ) + return untrailingslashit( WP_HOME ); + + if ( $setting == 'siteurl' && defined( 'WP_SITEURL' ) ) + return untrailingslashit( WP_SITEURL ); + + $option = $wpdb->get_var( $wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s", $setting ) ); + + if ( 'home' == $setting && '' == $option ) + return __get_option( 'siteurl' ); + + if ( 'siteurl' == $setting || 'home' == $setting || 'category_base' == $setting || 'tag_base' == $setting ) + $option = untrailingslashit( $option ); + + return maybe_unserialize( $option ); +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @param string $content + * @return string + */ +function deslash($content) { + // Note: \\\ inside a regex denotes a single backslash. + + // Replace one or more backslashes followed by a single quote with + // a single quote. + $content = preg_replace("/\\\+'/", "'", $content); + + // Replace one or more backslashes followed by a double quote with + // a double quote. + $content = preg_replace('/\\\+"/', '"', $content); + + // Replace one or more backslashes with one backslash. + $content = preg_replace("/\\\+/", "\\", $content); + + return $content; +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @param unknown_type $queries + * @param unknown_type $execute + * @return unknown + */ +function dbDelta( $queries = '', $execute = true ) { + global $wpdb; + + if ( in_array( $queries, array( '', 'all', 'blog', 'global', 'ms_global' ), true ) ) + $queries = wp_get_db_schema( $queries ); + + // Separate individual queries into an array + if ( !is_array($queries) ) { + $queries = explode( ';', $queries ); + $queries = array_filter( $queries ); + } + $queries = apply_filters( 'dbdelta_queries', $queries ); + + $cqueries = array(); // Creation Queries + $iqueries = array(); // Insertion Queries + $for_update = array(); + + // Create a tablename index for an array ($cqueries) of queries + foreach($queries as $qry) { + if (preg_match("|CREATE TABLE ([^ ]*)|", $qry, $matches)) { + $cqueries[ trim( $matches[1], '`' ) ] = $qry; + $for_update[$matches[1]] = 'Created table '.$matches[1]; + } else if (preg_match("|CREATE DATABASE ([^ ]*)|", $qry, $matches)) { + array_unshift($cqueries, $qry); + } else if (preg_match("|INSERT INTO ([^ ]*)|", $qry, $matches)) { + $iqueries[] = $qry; + } else if (preg_match("|UPDATE ([^ ]*)|", $qry, $matches)) { + $iqueries[] = $qry; + } else { + // Unrecognized query type + } + } + $cqueries = apply_filters( 'dbdelta_create_queries', $cqueries ); + $iqueries = apply_filters( 'dbdelta_insert_queries', $iqueries ); + + $global_tables = $wpdb->tables( 'global' ); + foreach ( $cqueries as $table => $qry ) { + // Upgrade global tables only for the main site. Don't upgrade at all if DO_NOT_UPGRADE_GLOBAL_TABLES is defined. + if ( in_array( $table, $global_tables ) && ( !is_main_site() || defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) ) + continue; + + // Fetch the table column structure from the database + $wpdb->suppress_errors(); + $tablefields = $wpdb->get_results("DESCRIBE {$table};"); + $wpdb->suppress_errors( false ); + + if ( ! $tablefields ) + continue; + + // Clear the field and index arrays + $cfields = $indices = array(); + // Get all of the field names in the query from between the parens + preg_match("|\((.*)\)|ms", $qry, $match2); + $qryline = trim($match2[1]); + + // Separate field lines into an array + $flds = explode("\n", $qryline); + + //echo "
    \n".print_r(strtolower($table), true).":\n".print_r($cqueries, true)."

    "; + + // For every field line specified in the query + foreach ($flds as $fld) { + // Extract the field name + preg_match("|^([^ ]*)|", trim($fld), $fvals); + $fieldname = trim( $fvals[1], '`' ); + + // Verify the found field name + $validfield = true; + switch (strtolower($fieldname)) { + case '': + case 'primary': + case 'index': + case 'fulltext': + case 'unique': + case 'key': + $validfield = false; + $indices[] = trim(trim($fld), ", \n"); + break; + } + $fld = trim($fld); + + // If it's a valid field, add it to the field array + if ($validfield) { + $cfields[strtolower($fieldname)] = trim($fld, ", \n"); + } + } + + // For every field in the table + foreach ($tablefields as $tablefield) { + // If the table field exists in the field array... + if (array_key_exists(strtolower($tablefield->Field), $cfields)) { + // Get the field type from the query + preg_match("|".$tablefield->Field." ([^ ]*( unsigned)?)|i", $cfields[strtolower($tablefield->Field)], $matches); + $fieldtype = $matches[1]; + + // Is actual field type different from the field type in query? + if ($tablefield->Type != $fieldtype) { + // Add a query to change the column type + $cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN {$tablefield->Field} " . $cfields[strtolower($tablefield->Field)]; + $for_update[$table.'.'.$tablefield->Field] = "Changed type of {$table}.{$tablefield->Field} from {$tablefield->Type} to {$fieldtype}"; + } + + // Get the default value from the array + //echo "{$cfields[strtolower($tablefield->Field)]}
    "; + if (preg_match("| DEFAULT '(.*?)'|i", $cfields[strtolower($tablefield->Field)], $matches)) { + $default_value = $matches[1]; + if ($tablefield->Default != $default_value) { + // Add a query to change the column's default value + $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN {$tablefield->Field} SET DEFAULT '{$default_value}'"; + $for_update[$table.'.'.$tablefield->Field] = "Changed default value of {$table}.{$tablefield->Field} from {$tablefield->Default} to {$default_value}"; + } + } + + // Remove the field from the array (so it's not added) + unset($cfields[strtolower($tablefield->Field)]); + } else { + // This field exists in the table, but not in the creation queries? + } + } + + // For every remaining field specified for the table + foreach ($cfields as $fieldname => $fielddef) { + // Push a query line into $cqueries that adds the field to that table + $cqueries[] = "ALTER TABLE {$table} ADD COLUMN $fielddef"; + $for_update[$table.'.'.$fieldname] = 'Added column '.$table.'.'.$fieldname; + } + + // Index stuff goes here + // Fetch the table index structure from the database + $tableindices = $wpdb->get_results("SHOW INDEX FROM {$table};"); + + if ($tableindices) { + // Clear the index array + unset($index_ary); + + // For every index in the table + foreach ($tableindices as $tableindex) { + // Add the index to the index data array + $keyname = $tableindex->Key_name; + $index_ary[$keyname]['columns'][] = array('fieldname' => $tableindex->Column_name, 'subpart' => $tableindex->Sub_part); + $index_ary[$keyname]['unique'] = ($tableindex->Non_unique == 0)?true:false; + } + + // For each actual index in the index array + foreach ($index_ary as $index_name => $index_data) { + // Build a create string to compare to the query + $index_string = ''; + if ($index_name == 'PRIMARY') { + $index_string .= 'PRIMARY '; + } else if($index_data['unique']) { + $index_string .= 'UNIQUE '; + } + $index_string .= 'KEY '; + if ($index_name != 'PRIMARY') { + $index_string .= $index_name; + } + $index_columns = ''; + // For each column in the index + foreach ($index_data['columns'] as $column_data) { + if ($index_columns != '') $index_columns .= ','; + // Add the field to the column list string + $index_columns .= $column_data['fieldname']; + if ($column_data['subpart'] != '') { + $index_columns .= '('.$column_data['subpart'].')'; + } + } + // Add the column list to the index create string + $index_string .= ' ('.$index_columns.')'; + if (!(($aindex = array_search($index_string, $indices)) === false)) { + unset($indices[$aindex]); + //echo "
    {$table}:
    Found index:".$index_string."
    \n"; + } + //else echo "
    {$table}:
    Did not find index:".$index_string."
    ".print_r($indices, true)."
    \n"; + } + } + + // For every remaining index specified for the table + foreach ( (array) $indices as $index ) { + // Push a query line into $cqueries that adds the index to that table + $cqueries[] = "ALTER TABLE {$table} ADD $index"; + $for_update[] = 'Added index ' . $table . ' ' . $index; + } + + // Remove the original table creation query from processing + unset( $cqueries[ $table ], $for_update[ $table ] ); + } + + $allqueries = array_merge($cqueries, $iqueries); + if ($execute) { + foreach ($allqueries as $query) { + //echo "
    ".print_r($query, true)."
    \n"; + $wpdb->query($query); + } + } + + return $for_update; +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + */ +function make_db_current( $tables = 'all' ) { + $alterations = dbDelta( $tables ); + echo "
      \n"; + foreach($alterations as $alteration) echo "
    1. $alteration
    2. \n"; + echo "
    \n"; +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + */ +function make_db_current_silent( $tables = 'all' ) { + $alterations = dbDelta( $tables ); +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @param unknown_type $theme_name + * @param unknown_type $template + * @return unknown + */ +function make_site_theme_from_oldschool($theme_name, $template) { + $home_path = get_home_path(); + $site_dir = WP_CONTENT_DIR . "/themes/$template"; + + if (! file_exists("$home_path/index.php")) + return false; + + // Copy files from the old locations to the site theme. + // TODO: This does not copy arbitrary include dependencies. Only the + // standard WP files are copied. + $files = array('index.php' => 'index.php', 'wp-layout.css' => 'style.css', 'wp-comments.php' => 'comments.php', 'wp-comments-popup.php' => 'comments-popup.php'); + + foreach ($files as $oldfile => $newfile) { + if ($oldfile == 'index.php') + $oldpath = $home_path; + else + $oldpath = ABSPATH; + + if ($oldfile == 'index.php') { // Check to make sure it's not a new index + $index = implode('', file("$oldpath/$oldfile")); + if (strpos($index, 'WP_USE_THEMES') !== false) { + if (! @copy(WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME . '/index.php', "$site_dir/$newfile")) + return false; + continue; // Don't copy anything + } + } + + if (! @copy("$oldpath/$oldfile", "$site_dir/$newfile")) + return false; + + chmod("$site_dir/$newfile", 0777); + + // Update the blog header include in each file. + $lines = explode("\n", implode('', file("$site_dir/$newfile"))); + if ($lines) { + $f = fopen("$site_dir/$newfile", 'w'); + + foreach ($lines as $line) { + if (preg_match('/require.*wp-blog-header/', $line)) + $line = '//' . $line; + + // Update stylesheet references. + $line = str_replace("/wp-layout.css", "", $line); + + // Update comments template inclusion. + $line = str_replace("", "", $line); + + fwrite($f, "{$line}\n"); + } + fclose($f); + } + } + + // Add a theme header. + $header = "/*\nTheme Name: $theme_name\nTheme URI: " . __get_option('siteurl') . "\nDescription: A theme automatically created by the update.\nVersion: 1.0\nAuthor: Moi\n*/\n"; + + $stylelines = file_get_contents("$site_dir/style.css"); + if ($stylelines) { + $f = fopen("$site_dir/style.css", 'w'); + + fwrite($f, $header); + fwrite($f, $stylelines); + fclose($f); + } + + return true; +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @param unknown_type $theme_name + * @param unknown_type $template + * @return unknown + */ +function make_site_theme_from_default($theme_name, $template) { + $site_dir = WP_CONTENT_DIR . "/themes/$template"; + $default_dir = WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME; + + // Copy files from the default theme to the site theme. + //$files = array('index.php', 'comments.php', 'comments-popup.php', 'footer.php', 'header.php', 'sidebar.php', 'style.css'); + + $theme_dir = @ opendir($default_dir); + if ($theme_dir) { + while(($theme_file = readdir( $theme_dir )) !== false) { + if (is_dir("$default_dir/$theme_file")) + continue; + if (! @copy("$default_dir/$theme_file", "$site_dir/$theme_file")) + return; + chmod("$site_dir/$theme_file", 0777); + } + } + @closedir($theme_dir); + + // Rewrite the theme header. + $stylelines = explode("\n", implode('', file("$site_dir/style.css"))); + if ($stylelines) { + $f = fopen("$site_dir/style.css", 'w'); + + foreach ($stylelines as $line) { + if (strpos($line, 'Theme Name:') !== false) $line = 'Theme Name: ' . $theme_name; + elseif (strpos($line, 'Theme URI:') !== false) $line = 'Theme URI: ' . __get_option('url'); + elseif (strpos($line, 'Description:') !== false) $line = 'Description: Your theme.'; + elseif (strpos($line, 'Version:') !== false) $line = 'Version: 1'; + elseif (strpos($line, 'Author:') !== false) $line = 'Author: You'; + fwrite($f, $line . "\n"); + } + fclose($f); + } + + // Copy the images. + umask(0); + if (! mkdir("$site_dir/images", 0777)) { + return false; + } + + $images_dir = @ opendir("$default_dir/images"); + if ($images_dir) { + while(($image = readdir($images_dir)) !== false) { + if (is_dir("$default_dir/images/$image")) + continue; + if (! @copy("$default_dir/images/$image", "$site_dir/images/$image")) + return; + chmod("$site_dir/images/$image", 0777); + } + } + @closedir($images_dir); +} + +// Create a site theme from the default theme. +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 1.5.0 + * + * @return unknown + */ +function make_site_theme() { + // Name the theme after the blog. + $theme_name = __get_option('blogname'); + $template = sanitize_title($theme_name); + $site_dir = WP_CONTENT_DIR . "/themes/$template"; + + // If the theme already exists, nothing to do. + if ( is_dir($site_dir)) { + return false; + } + + // We must be able to write to the themes dir. + if (! is_writable(WP_CONTENT_DIR . "/themes")) { + return false; + } + + umask(0); + if (! mkdir($site_dir, 0777)) { + return false; + } + + if (file_exists(ABSPATH . 'wp-layout.css')) { + if (! make_site_theme_from_oldschool($theme_name, $template)) { + // TODO: rm -rf the site theme directory. + return false; + } + } else { + if (! make_site_theme_from_default($theme_name, $template)) + // TODO: rm -rf the site theme directory. + return false; + } + + // Make the new site theme active. + $current_template = __get_option('template'); + if ($current_template == WP_DEFAULT_THEME) { + update_option('template', $template); + update_option('stylesheet', $template); + } + return $template; +} + +/** + * Translate user level to user role name. + * + * @since 2.0.0 + * + * @param int $level User level. + * @return string User role name. + */ +function translate_level_to_role($level) { + switch ($level) { + case 10: + case 9: + case 8: + return 'administrator'; + case 7: + case 6: + case 5: + return 'editor'; + case 4: + case 3: + case 2: + return 'author'; + case 1: + return 'contributor'; + case 0: + return 'subscriber'; + } +} + +/** + * {@internal Missing Short Description}} + * + * {@internal Missing Long Description}} + * + * @since 2.1.0 + */ +function wp_check_mysql_version() { + global $wpdb; + $result = $wpdb->check_database_version(); + if ( is_wp_error( $result ) ) + die( $result->get_error_message() ); +} + +/** + * Disables the Automattic widgets plugin, which was merged into core. + * + * @since 2.2.0 + */ +function maybe_disable_automattic_widgets() { + $plugins = __get_option( 'active_plugins' ); + + foreach ( (array) $plugins as $plugin ) { + if ( basename( $plugin ) == 'widgets.php' ) { + array_splice( $plugins, array_search( $plugin, $plugins ), 1 ); + update_option( 'active_plugins', $plugins ); + break; + } + } +} + +/** + * Disables the Link Manager on upgrade, if at the time of upgrade, no links exist in the DB. + * + * @since 3.5.0 + */ +function maybe_disable_link_manager() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version >= 22006 && get_option( 'link_manager_enabled' ) && ! $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) ) + update_option( 'link_manager_enabled', 0 ); +} + +/** + * Runs before the schema is upgraded. + * + * @since 2.9.0 + */ +function pre_schema_upgrade() { + global $wp_current_db_version, $wp_db_version, $wpdb; + + // Upgrade versions prior to 2.9 + if ( $wp_current_db_version < 11557 ) { + // Delete duplicate options. Keep the option with the highest option_id. + $wpdb->query("DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2 USING (`option_name`) WHERE o2.option_id > o1.option_id"); + + // Drop the old primary key and add the new. + $wpdb->query("ALTER TABLE $wpdb->options DROP PRIMARY KEY, ADD PRIMARY KEY(option_id)"); + + // Drop the old option_name index. dbDelta() doesn't do the drop. + $wpdb->query("ALTER TABLE $wpdb->options DROP INDEX option_name"); + } + + // Multisite schema upgrades. + if ( $wp_current_db_version < 25448 && is_multisite() && ! defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) && is_main_network() ) { + + // Upgrade verions prior to 3.7 + if ( $wp_current_db_version < 25179 ) { + // New primary key for signups. + $wpdb->query( "ALTER TABLE $wpdb->signups ADD signup_id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST" ); + $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain" ); + } + + if ( $wp_current_db_version < 25448 ) { + // Convert archived from enum to tinyint. + $wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived varchar(1) NOT NULL default '0'" ); + $wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived tinyint(2) NOT NULL default 0" ); + } + } +} + +/** + * Install global terms. + * + * @since 3.0.0 + * + */ +if ( !function_exists( 'install_global_terms' ) ) : +function install_global_terms() { + global $wpdb, $charset_collate; + $ms_queries = " +CREATE TABLE $wpdb->sitecategories ( + cat_ID bigint(20) NOT NULL auto_increment, + cat_name varchar(55) NOT NULL default '', + category_nicename varchar(200) NOT NULL default '', + last_updated timestamp NOT NULL, + PRIMARY KEY (cat_ID), + KEY category_nicename (category_nicename), + KEY last_updated (last_updated) +) $charset_collate; +"; +// now create tables + dbDelta( $ms_queries ); +} +endif; diff --git a/sources/wp-admin/includes/user.php b/sources/wp-admin/includes/user.php new file mode 100644 index 0000000..b61cb7a --- /dev/null +++ b/sources/wp-admin/includes/user.php @@ -0,0 +1,373 @@ +ID = (int) $user_id; + $userdata = get_userdata( $user_id ); + $user->user_login = wp_slash( $userdata->user_login ); + } else { + $update = false; + } + + if ( !$update && isset( $_POST['user_login'] ) ) + $user->user_login = sanitize_user($_POST['user_login'], true); + + $pass1 = $pass2 = ''; + if ( isset( $_POST['pass1'] ) ) + $pass1 = $_POST['pass1']; + if ( isset( $_POST['pass2'] ) ) + $pass2 = $_POST['pass2']; + + if ( isset( $_POST['role'] ) && current_user_can( 'edit_users' ) ) { + $new_role = sanitize_text_field( $_POST['role'] ); + $potential_role = isset($wp_roles->role_objects[$new_role]) ? $wp_roles->role_objects[$new_role] : false; + // Don't let anyone with 'edit_users' (admins) edit their own role to something without it. + // Multisite super admins can freely edit their blog roles -- they possess all caps. + if ( ( is_multisite() && current_user_can( 'manage_sites' ) ) || $user_id != get_current_user_id() || ($potential_role && $potential_role->has_cap( 'edit_users' ) ) ) + $user->role = $new_role; + + // If the new role isn't editable by the logged-in user die with error + $editable_roles = get_editable_roles(); + if ( ! empty( $new_role ) && empty( $editable_roles[$new_role] ) ) + wp_die(__('You can’t give users that role.')); + } + + if ( isset( $_POST['email'] )) + $user->user_email = sanitize_text_field( $_POST['email'] ); + if ( isset( $_POST['url'] ) ) { + if ( empty ( $_POST['url'] ) || $_POST['url'] == 'http://' ) { + $user->user_url = ''; + } else { + $user->user_url = esc_url_raw( $_POST['url'] ); + $protocols = implode( '|', array_map( 'preg_quote', wp_allowed_protocols() ) ); + $user->user_url = preg_match('/^(' . $protocols . '):/is', $user->user_url) ? $user->user_url : 'http://'.$user->user_url; + } + } + if ( isset( $_POST['first_name'] ) ) + $user->first_name = sanitize_text_field( $_POST['first_name'] ); + if ( isset( $_POST['last_name'] ) ) + $user->last_name = sanitize_text_field( $_POST['last_name'] ); + if ( isset( $_POST['nickname'] ) ) + $user->nickname = sanitize_text_field( $_POST['nickname'] ); + if ( isset( $_POST['display_name'] ) ) + $user->display_name = sanitize_text_field( $_POST['display_name'] ); + + if ( isset( $_POST['description'] ) ) + $user->description = trim( $_POST['description'] ); + + foreach ( wp_get_user_contact_methods( $user ) as $method => $name ) { + if ( isset( $_POST[$method] )) + $user->$method = sanitize_text_field( $_POST[$method] ); + } + + if ( $update ) { + $user->rich_editing = isset( $_POST['rich_editing'] ) && 'false' == $_POST['rich_editing'] ? 'false' : 'true'; + $user->admin_color = isset( $_POST['admin_color'] ) ? sanitize_text_field( $_POST['admin_color'] ) : 'fresh'; + $user->show_admin_bar_front = isset( $_POST['admin_bar_front'] ) ? 'true' : 'false'; + } + + $user->comment_shortcuts = isset( $_POST['comment_shortcuts'] ) && 'true' == $_POST['comment_shortcuts'] ? 'true' : ''; + + $user->use_ssl = 0; + if ( !empty($_POST['use_ssl']) ) + $user->use_ssl = 1; + + $errors = new WP_Error(); + + /* checking that username has been typed */ + if ( $user->user_login == '' ) + $errors->add( 'user_login', __( 'ERROR: Please enter a username.' ) ); + + /* checking the password has been typed twice */ + do_action_ref_array( 'check_passwords', array( $user->user_login, &$pass1, &$pass2 ) ); + + if ( $update ) { + if ( empty($pass1) && !empty($pass2) ) + $errors->add( 'pass', __( 'ERROR: You entered your new password only once.' ), array( 'form-field' => 'pass1' ) ); + elseif ( !empty($pass1) && empty($pass2) ) + $errors->add( 'pass', __( 'ERROR: You entered your new password only once.' ), array( 'form-field' => 'pass2' ) ); + } else { + if ( empty($pass1) ) + $errors->add( 'pass', __( 'ERROR: Please enter your password.' ), array( 'form-field' => 'pass1' ) ); + elseif ( empty($pass2) ) + $errors->add( 'pass', __( 'ERROR: Please enter your password twice.' ), array( 'form-field' => 'pass2' ) ); + } + + /* Check for "\" in password */ + if ( false !== strpos( wp_unslash( $pass1 ), "\\" ) ) + $errors->add( 'pass', __( 'ERROR: Passwords may not contain the character "\\".' ), array( 'form-field' => 'pass1' ) ); + + /* checking the password has been typed twice the same */ + if ( $pass1 != $pass2 ) + $errors->add( 'pass', __( 'ERROR: Please enter the same password in the two password fields.' ), array( 'form-field' => 'pass1' ) ); + + if ( !empty( $pass1 ) ) + $user->user_pass = $pass1; + + if ( !$update && isset( $_POST['user_login'] ) && !validate_username( $_POST['user_login'] ) ) + $errors->add( 'user_login', __( 'ERROR: This username is invalid because it uses illegal characters. Please enter a valid username.' )); + + if ( !$update && username_exists( $user->user_login ) ) + $errors->add( 'user_login', __( 'ERROR: This username is already registered. Please choose another one.' )); + + /* checking e-mail address */ + if ( empty( $user->user_email ) ) { + $errors->add( 'empty_email', __( 'ERROR: Please enter an e-mail address.' ), array( 'form-field' => 'email' ) ); + } elseif ( !is_email( $user->user_email ) ) { + $errors->add( 'invalid_email', __( 'ERROR: The email address isn’t correct.' ), array( 'form-field' => 'email' ) ); + } elseif ( ( $owner_id = email_exists($user->user_email) ) && ( !$update || ( $owner_id != $user->ID ) ) ) { + $errors->add( 'email_exists', __('ERROR: This email is already registered, please choose another one.'), array( 'form-field' => 'email' ) ); + } + + // Allow plugins to return their own errors. + do_action_ref_array( 'user_profile_update_errors', array( &$errors, $update, &$user ) ); + + if ( $errors->get_error_codes() ) + return $errors; + + if ( $update ) { + $user_id = wp_update_user( $user ); + } else { + $user_id = wp_insert_user( $user ); + wp_new_user_notification( $user_id, isset( $_POST['send_password'] ) ? wp_unslash( $pass1 ) : '' ); + } + return $user_id; +} + +/** + * Fetch a filtered list of user roles that the current user is + * allowed to edit. + * + * Simple function who's main purpose is to allow filtering of the + * list of roles in the $wp_roles object so that plugins can remove + * inappropriate ones depending on the situation or user making edits. + * Specifically because without filtering anyone with the edit_users + * capability can edit others to be administrators, even if they are + * only editors or authors. This filter allows admins to delegate + * user management. + * + * @since 2.8 + * + * @return unknown + */ +function get_editable_roles() { + global $wp_roles; + + $all_roles = $wp_roles->roles; + $editable_roles = apply_filters('editable_roles', $all_roles); + + return $editable_roles; +} + +/** + * Retrieve user data and filter it. + * + * @since 2.0.5 + * + * @param int $user_id User ID. + * @return WP_User|bool WP_User object on success, false on failure. + */ +function get_user_to_edit( $user_id ) { + $user = get_userdata( $user_id ); + + if ( $user ) + $user->filter = 'edit'; + + return $user; +} + +/** + * Retrieve the user's drafts. + * + * @since 2.0.0 + * + * @param int $user_id User ID. + * @return array + */ +function get_users_drafts( $user_id ) { + global $wpdb; + $query = $wpdb->prepare("SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'draft' AND post_author = %d ORDER BY post_modified DESC", $user_id); + $query = apply_filters('get_users_drafts', $query); + return $wpdb->get_results( $query ); +} + +/** + * Remove user and optionally reassign posts and links to another user. + * + * If the $reassign parameter is not assigned to an User ID, then all posts will + * be deleted of that user. The action 'delete_user' that is passed the User ID + * being deleted will be run after the posts are either reassigned or deleted. + * The user meta will also be deleted that are for that User ID. + * + * @since 2.0.0 + * + * @param int $id User ID. + * @param int $reassign Optional. Reassign posts and links to new User ID. + * @return bool True when finished. + */ +function wp_delete_user( $id, $reassign = 'novalue' ) { + global $wpdb; + + $id = (int) $id; + $user = new WP_User( $id ); + + if ( !$user->exists() ) + return false; + + // allow for transaction statement + do_action('delete_user', $id); + + if ( 'novalue' === $reassign || null === $reassign ) { + $post_types_to_delete = array(); + foreach ( get_post_types( array(), 'objects' ) as $post_type ) { + if ( $post_type->delete_with_user ) { + $post_types_to_delete[] = $post_type->name; + } elseif ( null === $post_type->delete_with_user && post_type_supports( $post_type->name, 'author' ) ) { + $post_types_to_delete[] = $post_type->name; + } + } + + $post_types_to_delete = apply_filters( 'post_types_to_delete_with_user', $post_types_to_delete, $id ); + $post_types_to_delete = implode( "', '", $post_types_to_delete ); + $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d AND post_type IN ('$post_types_to_delete')", $id ) ); + if ( $post_ids ) { + foreach ( $post_ids as $post_id ) + wp_delete_post( $post_id ); + } + + // Clean links + $link_ids = $wpdb->get_col( $wpdb->prepare("SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id) ); + + if ( $link_ids ) { + foreach ( $link_ids as $link_id ) + wp_delete_link($link_id); + } + } else { + $reassign = (int) $reassign; + $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) ); + $wpdb->update( $wpdb->posts, array('post_author' => $reassign), array('post_author' => $id) ); + if ( ! empty( $post_ids ) ) { + foreach ( $post_ids as $post_id ) + clean_post_cache( $post_id ); + } + $link_ids = $wpdb->get_col( $wpdb->prepare("SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id) ); + $wpdb->update( $wpdb->links, array('link_owner' => $reassign), array('link_owner' => $id) ); + if ( ! empty( $link_ids ) ) { + foreach ( $link_ids as $link_id ) + clean_bookmark_cache( $link_id ); + } + } + + // FINALLY, delete user + if ( is_multisite() ) { + remove_user_from_blog( $id, get_current_blog_id() ); + } else { + $meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) ); + foreach ( $meta as $mid ) + delete_metadata_by_mid( 'user', $mid ); + + $wpdb->delete( $wpdb->users, array( 'ID' => $id ) ); + } + + clean_user_cache( $user ); + + // allow for commit transaction + do_action('deleted_user', $id); + + return true; +} + +/** + * Remove all capabilities from user. + * + * @since 2.1.0 + * + * @param int $id User ID. + */ +function wp_revoke_user($id) { + $id = (int) $id; + + $user = new WP_User($id); + $user->remove_all_caps(); +} + +add_action('admin_init', 'default_password_nag_handler'); +/** + * @since 2.8.0 + */ +function default_password_nag_handler($errors = false) { + global $user_ID; + if ( ! get_user_option('default_password_nag') ) //Short circuit it. + return; + + //get_user_setting = JS saved UI setting. else no-js-fallback code. + if ( 'hide' == get_user_setting('default_password_nag') || isset($_GET['default_password_nag']) && '0' == $_GET['default_password_nag'] ) { + delete_user_setting('default_password_nag'); + update_user_option($user_ID, 'default_password_nag', false, true); + } +} + +add_action('profile_update', 'default_password_nag_edit_user', 10, 2); +/** + * @since 2.8.0 + */ +function default_password_nag_edit_user($user_ID, $old_data) { + if ( ! get_user_option('default_password_nag', $user_ID) ) //Short circuit it. + return; + + $new_data = get_userdata($user_ID); + + if ( $new_data->user_pass != $old_data->user_pass ) { //Remove the nag if the password has been changed. + delete_user_setting('default_password_nag'); + update_user_option($user_ID, 'default_password_nag', false, true); + } +} + +add_action('admin_notices', 'default_password_nag'); +/** + * @since 2.8.0 + */ +function default_password_nag() { + global $pagenow; + if ( 'profile.php' == $pagenow || ! get_user_option('default_password_nag') ) //Short circuit it. + return; + + echo '
    '; + echo '

    '; + echo '' . __('Notice:') . ' '; + _e('You’re using the auto-generated password for your account. Would you like to change it to something easier to remember?'); + echo '

    '; + printf( '' . __('Yes, take me to my profile page') . ' | ', get_edit_profile_url( get_current_user_id() ) . '#password' ); + printf( '' . __('No thanks, do not remind me again') . '', '?default_password_nag=0' ); + echo '

    '; +} diff --git a/sources/wp-admin/includes/widgets.php b/sources/wp-admin/includes/widgets.php new file mode 100644 index 0000000..dae9550 --- /dev/null +++ b/sources/wp-admin/includes/widgets.php @@ -0,0 +1,228 @@ + $widget['id'], 'widget_name' => $widget['name'], '_display' => 'template' ); + + if ( isset($wp_registered_widget_controls[$widget['id']]['id_base']) && isset($widget['params'][0]['number']) ) { + $id_base = $wp_registered_widget_controls[$widget['id']]['id_base']; + $args['_temp_id'] = "$id_base-__i__"; + $args['_multi_num'] = next_widget_id_number($id_base); + $args['_add'] = 'multi'; + } else { + $args['_add'] = 'single'; + if ( $sidebar ) + $args['_hide'] = '1'; + } + + $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); + call_user_func_array( 'wp_widget_control', $args ); + } +} + +/** + * Callback to sort array by a 'name' key. + * + * @since 3.1.0 + * @access private + */ +function _sort_name_callback( $a, $b ) { + return strnatcasecmp( $a['name'], $b['name'] ); +} + +/** + * Show the widgets and their settings for a sidebar. + * Used in the admin widget config screen. + * + * @since 2.5.0 + * + * @param string $sidebar id slug of the sidebar + */ +function wp_list_widget_controls( $sidebar ) { + add_filter( 'dynamic_sidebar_params', 'wp_list_widget_controls_dynamic_sidebar' ); + + echo "
    \n"; + + $description = wp_sidebar_description( $sidebar ); + + if ( !empty( $description ) ) { + echo "\n"; + } + + dynamic_sidebar( $sidebar ); + echo "
    \n"; +} + +/** + * {@internal Missing Short Description}} + * + * @since 2.5.0 + * + * @param array $params + * @return array + */ +function wp_list_widget_controls_dynamic_sidebar( $params ) { + global $wp_registered_widgets; + static $i = 0; + $i++; + + $widget_id = $params[0]['widget_id']; + $id = isset($params[0]['_temp_id']) ? $params[0]['_temp_id'] : $widget_id; + $hidden = isset($params[0]['_hide']) ? ' style="display:none;"' : ''; + + $params[0]['before_widget'] = "
    "; + $params[0]['after_widget'] = "
    "; + $params[0]['before_title'] = "%BEG_OF_TITLE%"; // deprecated + $params[0]['after_title'] = "%END_OF_TITLE%"; // deprecated + if ( is_callable( $wp_registered_widgets[$widget_id]['callback'] ) ) { + $wp_registered_widgets[$widget_id]['_callback'] = $wp_registered_widgets[$widget_id]['callback']; + $wp_registered_widgets[$widget_id]['callback'] = 'wp_widget_control'; + } + + return $params; +} + +function next_widget_id_number($id_base) { + global $wp_registered_widgets; + $number = 1; + + foreach ( $wp_registered_widgets as $widget_id => $widget ) { + if ( preg_match( '/' . $id_base . '-([0-9]+)$/', $widget_id, $matches ) ) + $number = max($number, $matches[1]); + } + $number++; + + return $number; +} + +/** + * Meta widget used to display the control form for a widget. + * + * Called from dynamic_sidebar(). + * + * @since 2.5.0 + * + * @param array $sidebar_args + * @return array + */ +function wp_widget_control( $sidebar_args ) { + global $wp_registered_widgets, $wp_registered_widget_controls, $sidebars_widgets; + + $widget_id = $sidebar_args['widget_id']; + $sidebar_id = isset($sidebar_args['id']) ? $sidebar_args['id'] : false; + $key = $sidebar_id ? array_search( $widget_id, $sidebars_widgets[$sidebar_id] ) : '-1'; // position of widget in sidebar + $control = isset($wp_registered_widget_controls[$widget_id]) ? $wp_registered_widget_controls[$widget_id] : array(); + $widget = $wp_registered_widgets[$widget_id]; + + $id_format = $widget['id']; + $widget_number = isset($control['params'][0]['number']) ? $control['params'][0]['number'] : ''; + $id_base = isset($control['id_base']) ? $control['id_base'] : $widget_id; + $multi_number = isset($sidebar_args['_multi_num']) ? $sidebar_args['_multi_num'] : ''; + $add_new = isset($sidebar_args['_add']) ? $sidebar_args['_add'] : ''; + + $query_arg = array( 'editwidget' => $widget['id'] ); + if ( $add_new ) { + $query_arg['addnew'] = 1; + if ( $multi_number ) { + $query_arg['num'] = $multi_number; + $query_arg['base'] = $id_base; + } + } else { + $query_arg['sidebar'] = $sidebar_id; + $query_arg['key'] = $key; + } + + // We aren't showing a widget control, we're outputting a template for a multi-widget control + if ( isset($sidebar_args['_display']) && 'template' == $sidebar_args['_display'] && $widget_number ) { + // number == -1 implies a template where id numbers are replaced by a generic '__i__' + $control['params'][0]['number'] = -1; + // with id_base widget id's are constructed like {$id_base}-{$id_number} + if ( isset($control['id_base']) ) + $id_format = $control['id_base'] . '-__i__'; + } + + $wp_registered_widgets[$widget_id]['callback'] = $wp_registered_widgets[$widget_id]['_callback']; + unset($wp_registered_widgets[$widget_id]['_callback']); + + $widget_title = esc_html( strip_tags( $sidebar_args['widget_name'] ) ); + $has_form = 'noform'; + + echo $sidebar_args['before_widget']; ?> +
    +
    + + + + + + +
    +

    +
    + +
    +
    +
    +" . __('There are no options for this widget.') . "

    \n"; ?> +
    + + + + + + + + +
    +
    + | + +
    +
    + 'widget-' . esc_attr( $id_format ) . '-savewidget' ) ); ?> + +
    +
    +
    +
    +
    + +
    + +
    + 4, 'default' => 1) ); +else + add_screen_option('layout_columns', array('max' => 4, 'default' => 2) ); + +$help = '

    ' . __( 'Welcome to your WordPress Dashboard! This is the screen you will see when you log in to your site, and gives you access to all the site management features of WordPress. You can get help for any screen by clicking the Help tab in the upper corner.' ) . '

    '; + +// Not using chaining here, so as to be parseable by PHP4. +$screen = get_current_screen(); + +$screen->add_help_tab( array( + 'id' => 'overview', + 'title' => __( 'Overview' ), + 'content' => $help, +) ); + +// Help tabs + +$help = '

    ' . __('The left-hand navigation menu provides links to all of the WordPress administration screens, with submenu items displayed on hover. You can minimize this menu to a narrow icon strip by clicking on the Collapse Menu arrow at the bottom.') . '

    '; +$help .= '

    ' . __('Links in the Toolbar at the top of the screen connect your dashboard and the front end of your site, and provide access to your profile and helpful WordPress information.') . '

    '; + +$screen->add_help_tab( array( + 'id' => 'help-navigation', + 'title' => __('Navigation'), + 'content' => $help, +) ); + +$help = '

    ' . __('You can use the following controls to arrange your Dashboard screen to suit your workflow. This is true on most other administration screens as well.') . '

    '; +$help .= '

    ' . __('Screen Options - Use the Screen Options tab to choose which Dashboard boxes to show, and how many columns to display.') . '

    '; +$help .= '

    ' . __('Drag and Drop - To rearrange the boxes, drag and drop by clicking on the title bar of the selected box and releasing when you see a gray dotted-line rectangle appear in the location you want to place the box.') . '

    '; +$help .= '

    ' . __('Box Controls - Click the title bar of the box to expand or collapse it. In addition, some boxes have configurable content, and will show a “Configure” link in the title bar if you hover over it.') . '

    '; + +$screen->add_help_tab( array( + 'id' => 'help-layout', + 'title' => __('Layout'), + 'content' => $help, +) ); + +$help = '

    ' . __('The boxes on your Dashboard screen are:') . '

    '; +if ( current_user_can( 'edit_posts' ) ) + $help .= '

    ' . __('Right Now - Displays a summary of the content on your site and identifies which theme and version of WordPress you are using.') . '

    '; +if ( current_user_can( 'moderate_comments' ) ) + $help .= '

    ' . __('Recent Comments - Shows the most recent comments on your posts (configurable, up to 30) and allows you to moderate them.') . '

    '; +if ( current_user_can( 'publish_posts' ) ) + $help .= '

    ' . __('Incoming Links - Shows links to your site found by Google Blog Search.') . '

    '; +if ( current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) { + $help .= '

    ' . __('QuickPress - Allows you to create a new post and either publish it or save it as a draft.') . '

    '; + $help .= '

    ' . __('Recent Drafts - Displays links to the 5 most recent draft posts you’ve started.') . '

    '; +} +$help .= '

    ' . __('WordPress Blog - Latest news from the official WordPress project.') . '

    '; +$help .= '

    ' . __('Other WordPress News - Shows the WordPress Planet feed. You can configure it to show a different feed of your choosing.') . '

    '; +if ( ! is_multisite() && current_user_can( 'install_plugins' ) ) + $help .= '

    ' . __('Plugins - Features the most popular, newest, and recently updated plugins from the WordPress.org Plugin Directory.') . '

    '; +if ( current_user_can( 'edit_theme_options' ) ) + $help .= '

    ' . __('Welcome - Shows links for some of the most common tasks when setting up a new site.') . '

    '; + +$screen->add_help_tab( array( + 'id' => 'help-content', + 'title' => __('Content'), + 'content' => $help, +) ); + +unset( $help ); + +$screen->set_help_sidebar( + '

    ' . __( 'For more information:' ) . '

    ' . + '

    ' . __( 'Documentation on Dashboard' ) . '

    ' . + '

    ' . __( 'Support Forums' ) . '

    ' +); + +include (ABSPATH . 'wp-admin/admin-header.php'); + +$today = current_time('mysql', 1); +?> + +
    + +

    + +user_email != get_option( 'admin_email' ) ); + if ( $hide ) + $classes .= ' hidden'; ?> + +
    + + + remove_action( 'welcome_panel', 'wp_welcome_panel' ); + * + * @since 3.5.0 + */ + do_action( 'welcome_panel' ); + ?> +
    + + +
    + + + +
    +
    + +
    + + diff --git a/sources/wp-admin/install-helper.php b/sources/wp-admin/install-helper.php new file mode 100644 index 0000000..c98b28c --- /dev/null +++ b/sources/wp-admin/install-helper.php @@ -0,0 +1,198 @@ + + * check_column('wp_links', 'link_description', 'mediumtext'); + * if (check_column($wpdb->comments, 'comment_author', 'tinytext')) + * echo "ok\n"; + * + * $error_count = 0; + * $tablename = $wpdb->links; + * // check the column + * if (!check_column($wpdb->links, 'link_description', 'varchar(255)')) { + * $ddl = "ALTER TABLE $wpdb->links MODIFY COLUMN link_description varchar(255) NOT NULL DEFAULT '' "; + * $q = $wpdb->query($ddl); + * } + * + * if (check_column($wpdb->links, 'link_description', 'varchar(255)')) { + * $res .= $tablename . ' - ok
    '; + * } else { + * $res .= 'There was a problem with ' . $tablename . '
    '; + * ++$error_count; + * } + * + * + * @package WordPress + * @subpackage Plugin + */ + +/** Load WordPress Bootstrap */ +require_once(dirname(dirname(__FILE__)).'/wp-load.php'); + +if ( ! function_exists('maybe_create_table') ) : +/** + * Create database table, if it doesn't already exist. + * + * @since 1.0.0 + * @package WordPress + * @subpackage Plugin + * @uses $wpdb + * + * @param string $table_name Database table name. + * @param string $create_ddl Create database table SQL. + * @return bool False on error, true if already exists or success. + */ +function maybe_create_table($table_name, $create_ddl) { + global $wpdb; + foreach ($wpdb->get_col("SHOW TABLES",0) as $table ) { + if ($table == $table_name) { + return true; + } + } + //didn't find it try to create it. + $wpdb->query($create_ddl); + // we cannot directly tell that whether this succeeded! + foreach ($wpdb->get_col("SHOW TABLES",0) as $table ) { + if ($table == $table_name) { + return true; + } + } + return false; +} +endif; + +if ( ! function_exists('maybe_add_column') ) : +/** + * Add column to database table, if column doesn't already exist in table. + * + * @since 1.0.0 + * @package WordPress + * @subpackage Plugin + * @uses $wpdb + * + * @param string $table_name Database table name + * @param string $column_name Table column name + * @param string $create_ddl SQL to add column to table. + * @return bool False on failure. True, if already exists or was successful. + */ +function maybe_add_column($table_name, $column_name, $create_ddl) { + global $wpdb; + foreach ($wpdb->get_col("DESC $table_name",0) as $column ) { + + if ($column == $column_name) { + return true; + } + } + //didn't find it try to create it. + $wpdb->query($create_ddl); + // we cannot directly tell that whether this succeeded! + foreach ($wpdb->get_col("DESC $table_name",0) as $column ) { + if ($column == $column_name) { + return true; + } + } + return false; +} +endif; + +/** + * Drop column from database table, if it exists. + * + * @since 1.0.0 + * @package WordPress + * @subpackage Plugin + * @uses $wpdb + * + * @param string $table_name Table name + * @param string $column_name Column name + * @param string $drop_ddl SQL statement to drop column. + * @return bool False on failure, true on success or doesn't exist. + */ +function maybe_drop_column($table_name, $column_name, $drop_ddl) { + global $wpdb; + foreach ($wpdb->get_col("DESC $table_name",0) as $column ) { + if ($column == $column_name) { + //found it try to drop it. + $wpdb->query($drop_ddl); + // we cannot directly tell that whether this succeeded! + foreach ($wpdb->get_col("DESC $table_name",0) as $column ) { + if ($column == $column_name) { + return false; + } + } + } + } + // else didn't find it + return true; +} + +/** + * Check column matches criteria. + * + * Uses the SQL DESC for retrieving the table info for the column. It will help + * understand the parameters, if you do more research on what column information + * is returned by the SQL statement. Pass in null to skip checking that + * criteria. + * + * Column names returned from DESC table are case sensitive and are listed: + * Field + * Type + * Null + * Key + * Default + * Extra + * + * @since 1.0.0 + * @package WordPress + * @subpackage Plugin + * + * @param string $table_name Table name + * @param string $col_name Column name + * @param string $col_type Column type + * @param bool $is_null Optional. Check is null. + * @param mixed $key Optional. Key info. + * @param mixed $default Optional. Default value. + * @param mixed $extra Optional. Extra value. + * @return bool True, if matches. False, if not matching. + */ +function check_column($table_name, $col_name, $col_type, $is_null = null, $key = null, $default = null, $extra = null) { + global $wpdb; + $diffs = 0; + $results = $wpdb->get_results("DESC $table_name"); + + foreach ($results as $row ) { + + if ($row->Field == $col_name) { + // got our column, check the params + if (($col_type != null) && ($row->Type != $col_type)) { + ++$diffs; + } + if (($is_null != null) && ($row->Null != $is_null)) { + ++$diffs; + } + if (($key != null) && ($row->Key != $key)) { + ++$diffs; + } + if (($default != null) && ($row->Default != $default)) { + ++$diffs; + } + if (($extra != null) && ($row->Extra != $extra)) { + ++$diffs; + } + if ($diffs > 0) { + return false; + } + return true; + } // end if found our column + } + return false; +} diff --git a/sources/wp-admin/install.php b/sources/wp-admin/install.php new file mode 100644 index 0000000..0b6ac2e --- /dev/null +++ b/sources/wp-admin/install.php @@ -0,0 +1,256 @@ + + + + + + Error: PHP is not running + + +

    WordPress

    +

    Error: PHP is not running

    +

    WordPress requires that your web server is running PHP. Your server does not have PHP installed, or PHP is turned off.

    + + + + +> + + + <?php _e( 'WordPress › Installation' ); ?> + + + +

    + +get_var("SHOW TABLES LIKE '$wpdb->users'") != null ); + + // Ensure that Blogs appear in search engines by default + $blog_public = 1; + if ( ! empty( $_POST ) ) + $blog_public = isset( $_POST['blog_public'] ); + + $weblog_title = isset( $_POST['weblog_title'] ) ? trim( wp_unslash( $_POST['weblog_title'] ) ) : ''; + $user_name = isset($_POST['user_name']) ? trim( wp_unslash( $_POST['user_name'] ) ) : ''; + $admin_password = isset($_POST['admin_password']) ? trim( wp_unslash( $_POST['admin_password'] ) ) : ''; + $admin_email = isset( $_POST['admin_email'] ) ? trim( wp_unslash( $_POST['admin_email'] ) ) : ''; + + if ( ! is_null( $error ) ) { +?> +

    + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    + +

    + +
    + +

    +
    + +

    +
    +

    +
    +

    +

    +
    +' . __( 'Already Installed' ) . '

    ' . __( 'You appear to have already installed WordPress. To reinstall please clear your old database tables first.' ) . '

    ' . __( 'Log In' ) . '

    ' ); +} + +$php_version = phpversion(); +$mysql_version = $wpdb->db_version(); +$php_compat = version_compare( $php_version, $required_php_version, '>=' ); +$mysql_compat = version_compare( $mysql_version, $required_mysql_version, '>=' ) || file_exists( WP_CONTENT_DIR . '/db.php' ); + +if ( !$mysql_compat && !$php_compat ) + $compat = sprintf( __( 'You cannot install because WordPress %1$s requires PHP version %2$s or higher and MySQL version %3$s or higher. You are running PHP version %4$s and MySQL version %5$s.' ), $wp_version, $required_php_version, $required_mysql_version, $php_version, $mysql_version ); +elseif ( !$php_compat ) + $compat = sprintf( __( 'You cannot install because WordPress %1$s requires PHP version %2$s or higher. You are running version %3$s.' ), $wp_version, $required_php_version, $php_version ); +elseif ( !$mysql_compat ) + $compat = sprintf( __( 'You cannot install because WordPress %1$s requires MySQL version %2$s or higher. You are running version %3$s.' ), $wp_version, $required_mysql_version, $mysql_version ); + +if ( !$mysql_compat || !$php_compat ) { + display_header(); + die( '

    ' . __( 'Insufficient Requirements' ) . '

    ' . $compat . '

    ' ); +} + +if ( ! is_string( $wpdb->base_prefix ) || '' === $wpdb->base_prefix ) { + display_header(); + die( '

    ' . __( 'Configuration Error' ) . '

    ' . __( 'Your wp-config.php file has an empty database table prefix, which is not supported.' ) . '

    ' ); +} + +switch($step) { + case 0: // Step 1 + case 1: // Step 1, direct link. + display_header(); +?> +

    +

    ReadMe documentation at your leisure. Otherwise, just fill in the information below and you’ll be on your way to using the most extendable and powerful personal publishing platform in the world.' ), '../readme.html' ); ?>

    + +

    +

    + +error ) ) + wp_die( $wpdb->error->get_error_message() ); + + display_header(); + // Fill in the data we gathered + $weblog_title = isset( $_POST['weblog_title'] ) ? trim( wp_unslash( $_POST['weblog_title'] ) ) : ''; + $user_name = isset($_POST['user_name']) ? trim( wp_unslash( $_POST['user_name'] ) ) : ''; + $admin_password = isset($_POST['admin_password']) ? wp_unslash( $_POST['admin_password'] ) : ''; + $admin_password_check = isset($_POST['admin_password2']) ? wp_unslash( $_POST['admin_password2'] ) : ''; + $admin_email = isset( $_POST['admin_email'] ) ?trim( wp_unslash( $_POST['admin_email'] ) ) : ''; + $public = isset( $_POST['blog_public'] ) ? (int) $_POST['blog_public'] : 0; + // check e-mail address + $error = false; + if ( empty( $user_name ) ) { + // TODO: poka-yoke + display_setup_form( __( 'Please provide a valid username.' ) ); + $error = true; + } elseif ( $user_name != sanitize_user( $user_name, true ) ) { + display_setup_form( __( 'The username you provided has invalid characters.' ) ); + $error = true; + } elseif ( $admin_password != $admin_password_check ) { + // TODO: poka-yoke + display_setup_form( __( 'Your passwords do not match. Please try again.' ) ); + $error = true; + } else if ( empty( $admin_email ) ) { + // TODO: poka-yoke + display_setup_form( __( 'You must provide an email address.' ) ); + $error = true; + } elseif ( ! is_email( $admin_email ) ) { + // TODO: poka-yoke + display_setup_form( __( 'Sorry, that isn’t a valid email address. Email addresses look like username@example.com.' ) ); + $error = true; + } + + if ( $error === false ) { + $wpdb->show_errors(); + $result = wp_install($weblog_title, $user_name, $admin_email, $public, '', $admin_password); + extract( $result, EXTR_SKIP ); +?> + +

    + +

    + + + + + + + + + + +
    '. esc_html($password) .'
    '; + echo "

    $password_message

    "; ?> +
    + +

    + + + + + + diff --git a/sources/wp-admin/js/about.js b/sources/wp-admin/js/about.js new file mode 100644 index 0000000..3aaa66d --- /dev/null +++ b/sources/wp-admin/js/about.js @@ -0,0 +1,80 @@ +(function($){ + var password = 'Gosh, WordPress is grand.', + $input = $('#pass'), + shouldAnimate = true, + timesForAnimation = [280, 300, 305, 310, 315, 325, 330, 345, 360, 370, 380, 400, 450, 500, 600], + resultsCache = {}, + indicatorString = $('#pass-strength-result').text(); + + function updateResult(){ + var strength; + + if ( typeof( resultsCache[ $input.val() ]) === 'undefined') { + strength = wp.passwordStrength.meter($input.val(), [], $input.val()); + resultsCache[ $input.val() ] = strength; + } else { + strength = resultsCache[ $input.val() ]; + } + + $('#pass-strength-result').removeClass('short bad good strong'); + switch ( strength ) { + case 2: + $('#pass-strength-result').addClass('bad').html( pwsL10n['bad'] ); + break; + case 3: + $('#pass-strength-result').addClass('good').html( pwsL10n['good'] ); + break; + case 4: + $('#pass-strength-result').addClass('strong').html( pwsL10n['strong'] ); + break; + default: + $('#pass-strength-result').addClass('short').html( pwsL10n['short'] ); + } + } + function resetMeter(){ + $input.val(''); + $('#pass-strength-result').text(indicatorString); + $('#pass-strength-result').removeClass('short bad good strong'); + } + + function animate(){ + if (shouldAnimate === false) + return; + if ($input.val().length < password.length){ + $input.val( password.substr(0, $input.val().length + 1) ); + updateResult(); + + // Look like real typing by changing the speed new letters are added each time + setTimeout( animate, ( timesForAnimation[ Math.floor( Math.random() * timesForAnimation.length ) ] ) ); + } else { + resetMeter(); + + // When we reset, let's wait a bit longer than normal to start again + setTimeout(animate, 700); + } + + } + + function begin(){ + // we async load zxcvbn, so we need to make sure it's loaded before starting + if (typeof(zxcvbn) !== 'undefined') + animate(); + else + setTimeout(begin,800); + } + + // Turn off the animation on focus + $input.on('focus', function(){ + shouldAnimate = false; + resetMeter(); + }); + + // Act like a normal password strength meter + $input.on('keyup', function(){ + updateResult(); + }); + + // Start the animation + begin(); + +})(jQuery); diff --git a/sources/wp-admin/js/about.min.js b/sources/wp-admin/js/about.min.js new file mode 100644 index 0000000..4720562 --- /dev/null +++ b/sources/wp-admin/js/about.min.js @@ -0,0 +1 @@ +!function(a){function b(){var b;switch("undefined"==typeof j[g.val()]?(b=wp.passwordStrength.meter(g.val(),[],g.val()),j[g.val()]=b):b=j[g.val()],a("#pass-strength-result").removeClass("short bad good strong"),b){case 2:a("#pass-strength-result").addClass("bad").html(pwsL10n.bad);break;case 3:a("#pass-strength-result").addClass("good").html(pwsL10n.good);break;case 4:a("#pass-strength-result").addClass("strong").html(pwsL10n.strong);break;default:a("#pass-strength-result").addClass("short").html(pwsL10n["short"])}}function c(){g.val(""),a("#pass-strength-result").text(k),a("#pass-strength-result").removeClass("short bad good strong")}function d(){h!==!1&&(g.val().length').after(self.button); + + el.iris( { + target: self.pickerContainer, + hide: true, + width: 255, + mode: 'hsv', + palettes: self.options.palettes, + change: function( event, ui ) { + self.toggler.css( { backgroundColor: ui.color.toString() } ); + // check for a custom cb + if ( $.isFunction( self.options.change ) ) + self.options.change.call( this, event, ui ); + } + } ); + el.val( self.initialValue ); + self._addListeners(); + if ( ! self.options.hide ) + self.toggler.click(); + }, + _addListeners: function() { + var self = this; + + self.toggler.click( function( event ){ + event.stopPropagation(); + self.element.toggle().iris( 'toggle' ); + self.button.toggleClass('hidden'); + self.toggler.toggleClass( 'wp-picker-open' ); + + // close picker when you click outside it + if ( self.toggler.hasClass( 'wp-picker-open' ) ) + $( "body" ).on( 'click', { wrap: self.wrap, toggler: self.toggler }, self._bodyListener ); + else + $( "body" ).off( 'click', self._bodyListener ); + }); + + self.element.change(function( event ) { + var me = $(this), + val = me.val(); + // Empty = clear + if ( val === '' || val === '#' ) { + self.toggler.css('backgroundColor', ''); + // fire clear callback if we have one + if ( $.isFunction( self.options.clear ) ) + self.options.clear.call( this, event ); + } + }); + + // open a keyboard-focused closed picker with space or enter + self.toggler.on('keyup', function( e ) { + if ( e.keyCode === 13 || e.keyCode === 32 ) { + e.preventDefault(); + self.toggler.trigger('click').next().focus(); + } + }); + + self.button.click( function( event ) { + var me = $(this); + if ( me.hasClass( 'wp-picker-clear' ) ) { + self.element.val( '' ); + self.toggler.css('backgroundColor', ''); + if ( $.isFunction( self.options.clear ) ) + self.options.clear.call( this, event ); + } else if ( me.hasClass( 'wp-picker-default' ) ) { + self.element.val( self.options.defaultColor ).change(); + } + }); + }, + _bodyListener: function( event ) { + if ( ! event.data.wrap.find( event.target ).length ) + event.data.toggler.click(); + }, + // $("#input").wpColorPicker('color') returns the current color + // $("#input").wpColorPicker('color', '#bada55') to set + color: function( newColor ) { + if ( newColor === undef ) + return this.element.iris( "option", "color" ); + + this.element.iris( "option", "color", newColor ); + }, + //$("#input").wpColorPicker('defaultColor') returns the current default color + //$("#input").wpColorPicker('defaultColor', newDefaultColor) to set + defaultColor: function( newDefaultColor ) { + if ( newDefaultColor === undef ) + return this.options.defaultColor; + + this.options.defaultColor = newDefaultColor; + } + } + + $.widget( 'wp.wpColorPicker', ColorPicker ); +}( jQuery ) ); \ No newline at end of file diff --git a/sources/wp-admin/js/color-picker.min.js b/sources/wp-admin/js/color-picker.min.js new file mode 100644 index 0000000..2a37457 --- /dev/null +++ b/sources/wp-admin/js/color-picker.min.js @@ -0,0 +1 @@ +!function(a,b){var c='',d='
    ',e='
    ',f='',g={options:{defaultColor:!1,change:!1,clear:!1,hide:!0,palettes:!0},_create:function(){if(a.support.iris){var b=this,g=b.element;a.extend(b.options,g.data()),b.initialValue=g.val(),g.addClass("wp-color-picker").hide().wrap(e),b.wrap=g.parent(),b.toggler=a(c).insertBefore(g).css({backgroundColor:b.initialValue}).attr("title",wpColorPickerL10n.pick).attr("data-current",wpColorPickerL10n.current),b.pickerContainer=a(d).insertAfter(g),b.button=a(f),b.options.defaultColor?b.button.addClass("wp-picker-default").val(wpColorPickerL10n.defaultString):b.button.addClass("wp-picker-clear").val(wpColorPickerL10n.clear),g.wrap('').after(b.button),g.iris({target:b.pickerContainer,hide:!0,width:255,mode:"hsv",palettes:b.options.palettes,change:function(c,d){b.toggler.css({backgroundColor:d.color.toString()}),a.isFunction(b.options.change)&&b.options.change.call(this,c,d)}}),g.val(b.initialValue),b._addListeners(),b.options.hide||b.toggler.click()}},_addListeners:function(){var b=this;b.toggler.click(function(c){c.stopPropagation(),b.element.toggle().iris("toggle"),b.button.toggleClass("hidden"),b.toggler.toggleClass("wp-picker-open"),b.toggler.hasClass("wp-picker-open")?a("body").on("click",{wrap:b.wrap,toggler:b.toggler},b._bodyListener):a("body").off("click",b._bodyListener)}),b.element.change(function(c){var d=a(this),e=d.val();(""===e||"#"===e)&&(b.toggler.css("backgroundColor",""),a.isFunction(b.options.clear)&&b.options.clear.call(this,c))}),b.toggler.on("keyup",function(a){(13===a.keyCode||32===a.keyCode)&&(a.preventDefault(),b.toggler.trigger("click").next().focus())}),b.button.click(function(c){var d=a(this);d.hasClass("wp-picker-clear")?(b.element.val(""),b.toggler.css("backgroundColor",""),a.isFunction(b.options.clear)&&b.options.clear.call(this,c)):d.hasClass("wp-picker-default")&&b.element.val(b.options.defaultColor).change()})},_bodyListener:function(a){a.data.wrap.find(a.target).length||a.data.toggler.click()},color:function(a){return a===b?this.element.iris("option","color"):(this.element.iris("option","color",a),void 0)},defaultColor:function(a){return a===b?this.options.defaultColor:(this.options.defaultColor=a,void 0)}};a.widget("wp.wpColorPicker",g)}(jQuery); \ No newline at end of file diff --git a/sources/wp-admin/js/comment.js b/sources/wp-admin/js/comment.js new file mode 100644 index 0000000..f9d93bf --- /dev/null +++ b/sources/wp-admin/js/comment.js @@ -0,0 +1,49 @@ +jQuery(document).ready( function($) { + + postboxes.add_postbox_toggles('comment'); + + var stamp = $('#timestamp').html(); + $('.edit-timestamp').click(function () { + if ($('#timestampdiv').is(":hidden")) { + $('#timestampdiv').slideDown("normal"); + $('.edit-timestamp').hide(); + } + return false; + }); + + $('.cancel-timestamp').click(function() { + $('#timestampdiv').slideUp("normal"); + $('#mm').val($('#hidden_mm').val()); + $('#jj').val($('#hidden_jj').val()); + $('#aa').val($('#hidden_aa').val()); + $('#hh').val($('#hidden_hh').val()); + $('#mn').val($('#hidden_mn').val()); + $('#timestamp').html(stamp); + $('.edit-timestamp').show(); + return false; + }); + + $('.save-timestamp').click(function () { // crazyhorse - multiple ok cancels + var aa = $('#aa').val(), mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(), + newD = new Date( aa, mm - 1, jj, hh, mn ); + + if ( newD.getFullYear() != aa || (1 + newD.getMonth()) != mm || newD.getDate() != jj || newD.getMinutes() != mn ) { + $('.timestamp-wrap', '#timestampdiv').addClass('form-invalid'); + return false; + } else { + $('.timestamp-wrap', '#timestampdiv').removeClass('form-invalid'); + } + + $('#timestampdiv').slideUp("normal"); + $('.edit-timestamp').show(); + $('#timestamp').html( + commentL10n.submittedOn + ' ' + + $( '#mm option[value="' + mm + '"]' ).text() + ' ' + + jj + ', ' + + aa + ' @ ' + + hh + ':' + + mn + ' ' + ); + return false; + }); +}); diff --git a/sources/wp-admin/js/comment.min.js b/sources/wp-admin/js/comment.min.js new file mode 100644 index 0000000..fbfa877 --- /dev/null +++ b/sources/wp-admin/js/comment.min.js @@ -0,0 +1 @@ +jQuery(document).ready(function(a){postboxes.add_postbox_toggles("comment");var b=a("#timestamp").html();a(".edit-timestamp").click(function(){return a("#timestampdiv").is(":hidden")&&(a("#timestampdiv").slideDown("normal"),a(".edit-timestamp").hide()),!1}),a(".cancel-timestamp").click(function(){return a("#timestampdiv").slideUp("normal"),a("#mm").val(a("#hidden_mm").val()),a("#jj").val(a("#hidden_jj").val()),a("#aa").val(a("#hidden_aa").val()),a("#hh").val(a("#hidden_hh").val()),a("#mn").val(a("#hidden_mn").val()),a("#timestamp").html(b),a(".edit-timestamp").show(),!1}),a(".save-timestamp").click(function(){var b=a("#aa").val(),c=a("#mm").val(),d=a("#jj").val(),e=a("#hh").val(),f=a("#mn").val(),g=new Date(b,c-1,d,e,f);return g.getFullYear()!=b||1+g.getMonth()!=c||g.getDate()!=d||g.getMinutes()!=f?(a(".timestamp-wrap","#timestampdiv").addClass("form-invalid"),!1):(a(".timestamp-wrap","#timestampdiv").removeClass("form-invalid"),a("#timestampdiv").slideUp("normal"),a(".edit-timestamp").show(),a("#timestamp").html(commentL10n.submittedOn+" "+a('#mm option[value="'+c+'"]').text()+" "+d+", "+b+" @ "+e+":"+f+" "),!1)})}); \ No newline at end of file diff --git a/sources/wp-admin/js/common.js b/sources/wp-admin/js/common.js new file mode 100644 index 0000000..822af97 --- /dev/null +++ b/sources/wp-admin/js/common.js @@ -0,0 +1,452 @@ +var showNotice, adminMenu, columns, validateForm, screenMeta; +(function($){ +// Removed in 3.3. +// (perhaps) needed for back-compat +adminMenu = { + init : function() {}, + fold : function() {}, + restoreMenuState : function() {}, + toggle : function() {}, + favorites : function() {} +}; + +// show/hide/save table columns +columns = { + init : function() { + var that = this; + $('.hide-column-tog', '#adv-settings').click( function() { + var $t = $(this), column = $t.val(); + if ( $t.prop('checked') ) + that.checked(column); + else + that.unchecked(column); + + columns.saveManageColumnsState(); + }); + }, + + saveManageColumnsState : function() { + var hidden = this.hidden(); + $.post(ajaxurl, { + action: 'hidden-columns', + hidden: hidden, + screenoptionnonce: $('#screenoptionnonce').val(), + page: pagenow + }); + }, + + checked : function(column) { + $('.column-' + column).show(); + this.colSpanChange(+1); + }, + + unchecked : function(column) { + $('.column-' + column).hide(); + this.colSpanChange(-1); + }, + + hidden : function() { + return $('.manage-column').filter(':hidden').map(function() { return this.id; }).get().join(','); + }, + + useCheckboxesForHidden : function() { + this.hidden = function(){ + return $('.hide-column-tog').not(':checked').map(function() { + var id = this.id; + return id.substring( id, id.length - 5 ); + }).get().join(','); + }; + }, + + colSpanChange : function(diff) { + var $t = $('table').find('.colspanchange'), n; + if ( !$t.length ) + return; + n = parseInt( $t.attr('colspan'), 10 ) + diff; + $t.attr('colspan', n.toString()); + } +} + +$(document).ready(function(){columns.init();}); + +validateForm = function( form ) { + return !$( form ).find('.form-required').filter( function() { return $('input:visible', this).val() == ''; } ).addClass( 'form-invalid' ).find('input:visible').change( function() { $(this).closest('.form-invalid').removeClass( 'form-invalid' ); } ).size(); +} + +// stub for doing better warnings +showNotice = { + warn : function() { + var msg = commonL10n.warnDelete || ''; + if ( confirm(msg) ) { + return true; + } + + return false; + }, + + note : function(text) { + alert(text); + } +}; + +screenMeta = { + element: null, // #screen-meta + toggles: null, // .screen-meta-toggle + page: null, // #wpcontent + + init: function() { + this.element = $('#screen-meta'); + this.toggles = $('.screen-meta-toggle a'); + this.page = $('#wpcontent'); + + this.toggles.click( this.toggleEvent ); + }, + + toggleEvent: function( e ) { + var panel = $( this.href.replace(/.+#/, '#') ); + e.preventDefault(); + + if ( !panel.length ) + return; + + if ( panel.is(':visible') ) + screenMeta.close( panel, $(this) ); + else + screenMeta.open( panel, $(this) ); + }, + + open: function( panel, link ) { + + $('.screen-meta-toggle').not( link.parent() ).css('visibility', 'hidden'); + + panel.parent().show(); + panel.slideDown( 'fast', function() { + panel.focus(); + link.addClass('screen-meta-active').attr('aria-expanded', true); + }); + }, + + close: function( panel, link ) { + panel.slideUp( 'fast', function() { + link.removeClass('screen-meta-active').attr('aria-expanded', false); + $('.screen-meta-toggle').css('visibility', ''); + panel.parent().hide(); + }); + } +}; + +/** + * Help tabs. + */ +$('.contextual-help-tabs').delegate('a', 'click focus', function(e) { + var link = $(this), + panel; + + e.preventDefault(); + + // Don't do anything if the click is for the tab already showing. + if ( link.is('.active a') ) + return false; + + // Links + $('.contextual-help-tabs .active').removeClass('active'); + link.parent('li').addClass('active'); + + panel = $( link.attr('href') ); + + // Panels + $('.help-tab-content').not( panel ).removeClass('active').hide(); + panel.addClass('active').show(); +}); + +$(document).ready( function() { + var lastClicked = false, checks, first, last, checked, sliced, menu = $('#adminmenu'), mobileEvent, + pageInput = $('input.current-page'), currentPage = pageInput.val(); + + // when the menu is folded, make the fly-out submenu header clickable + menu.on('click.wp-submenu-head', '.wp-submenu-head', function(e){ + $(e.target).parent().siblings('a').get(0).click(); + }); + + $('#collapse-menu').on('click.collapse-menu', function(e){ + var body = $( document.body ), respWidth; + + // reset any compensation for submenus near the bottom of the screen + $('#adminmenu div.wp-submenu').css('margin-top', ''); + + // WebKit excludes the width of the vertical scrollbar when applying the CSS "@media screen and (max-width: ...)" + // and matches $(window).width(). + // Firefox and IE > 8 include the scrollbar width, so after the jQuery normalization + // $(window).width() is 884px but window.innerWidth is 900px. + // (using window.innerWidth also excludes IE < 9) + respWidth = navigator.userAgent.indexOf('AppleWebKit/') > -1 ? $(window).width() : window.innerWidth; + + if ( respWidth && respWidth < 900 ) { + if ( body.hasClass('auto-fold') ) { + body.removeClass('auto-fold').removeClass('folded'); + setUserSetting('unfold', 1); + setUserSetting('mfold', 'o'); + } else { + body.addClass('auto-fold'); + setUserSetting('unfold', 0); + } + } else { + if ( body.hasClass('folded') ) { + body.removeClass('folded'); + setUserSetting('mfold', 'o'); + } else { + body.addClass('folded'); + setUserSetting('mfold', 'f'); + } + } + }); + + if ( 'ontouchstart' in window || /IEMobile\/[1-9]/.test(navigator.userAgent) ) { // touch screen device + // iOS Safari works with touchstart, the rest work with click + mobileEvent = /Mobile\/.+Safari/.test(navigator.userAgent) ? 'touchstart' : 'click'; + + // close any open submenus when touch/click is not on the menu + $(document.body).on( mobileEvent+'.wp-mobile-hover', function(e) { + if ( !$(e.target).closest('#adminmenu').length ) + menu.find('li.wp-has-submenu.opensub').removeClass('opensub'); + }); + + menu.find('a.wp-has-submenu').on( mobileEvent+'.wp-mobile-hover', function(e) { + var el = $(this), parent = el.parent(); + + // Show the sub instead of following the link if: + // - the submenu is not open + // - the submenu is not shown inline or the menu is not folded + if ( !parent.hasClass('opensub') && ( !parent.hasClass('wp-menu-open') || parent.width() < 40 ) ) { + e.preventDefault(); + menu.find('li.opensub').removeClass('opensub'); + parent.addClass('opensub'); + } + }); + } + + menu.find('li.wp-has-submenu').hoverIntent({ + over: function(e){ + var b, h, o, f, m = $(this).find('.wp-submenu'), menutop, wintop, maxtop, top = parseInt( m.css('top'), 10 ); + + if ( isNaN(top) || top > -5 ) // meaning the submenu is visible + return; + + menutop = $(this).offset().top; + wintop = $(window).scrollTop(); + maxtop = menutop - wintop - 30; // max = make the top of the sub almost touch admin bar + + b = menutop + m.height() + 1; // Bottom offset of the menu + h = $('#wpwrap').height(); // Height of the entire page + o = 60 + b - h; + f = $(window).height() + wintop - 15; // The fold + + if ( f < (b - o) ) + o = b - f; + + if ( o > maxtop ) + o = maxtop; + + if ( o > 1 ) + m.css('margin-top', '-'+o+'px'); + else + m.css('margin-top', ''); + + menu.find('li.menu-top').removeClass('opensub'); + $(this).addClass('opensub'); + }, + out: function(){ + $(this).removeClass('opensub').find('.wp-submenu').css('margin-top', ''); + }, + timeout: 200, + sensitivity: 7, + interval: 90 + }); + + menu.on('focus.adminmenu', '.wp-submenu a', function(e){ + $(e.target).closest('li.menu-top').addClass('opensub'); + }).on('blur.adminmenu', '.wp-submenu a', function(e){ + $(e.target).closest('li.menu-top').removeClass('opensub'); + }); + + // Move .updated and .error alert boxes. Don't move boxes designed to be inline. + $('div.wrap h2:first').nextAll('div.updated, div.error').addClass('below-h2'); + $('div.updated, div.error').not('.below-h2, .inline').insertAfter( $('div.wrap h2:first') ); + + // Init screen meta + screenMeta.init(); + + // check all checkboxes + $('tbody').children().children('.check-column').find(':checkbox').click( function(e) { + if ( 'undefined' == e.shiftKey ) { return true; } + if ( e.shiftKey ) { + if ( !lastClicked ) { return true; } + checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' ); + first = checks.index( lastClicked ); + last = checks.index( this ); + checked = $(this).prop('checked'); + if ( 0 < first && 0 < last && first != last ) { + sliced = ( last > first ) ? checks.slice( first, last ) : checks.slice( last, first ); + sliced.prop( 'checked', function() { + if ( $(this).closest('tr').is(':visible') ) + return checked; + + return false; + }); + } + } + lastClicked = this; + + // toggle "check all" checkboxes + var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible').not(':checked'); + $(this).closest('table').children('thead, tfoot').find(':checkbox').prop('checked', function() { + return ( 0 == unchecked.length ); + }); + + return true; + }); + + $('thead, tfoot').find('.check-column :checkbox').click( function(e) { + var c = $(this).prop('checked'), + kbtoggle = 'undefined' == typeof toggleWithKeyboard ? false : toggleWithKeyboard, + toggle = e.shiftKey || kbtoggle; + + $(this).closest( 'table' ).children( 'tbody' ).filter(':visible') + .children().children('.check-column').find(':checkbox') + .prop('checked', function() { + if ( $(this).is(':hidden') ) + return false; + if ( toggle ) + return $(this).prop( 'checked' ); + else if (c) + return true; + return false; + }); + + $(this).closest('table').children('thead, tfoot').filter(':visible') + .children().children('.check-column').find(':checkbox') + .prop('checked', function() { + if ( toggle ) + return false; + else if (c) + return true; + return false; + }); + }); + + // Show row actions on keyboard focus of its parent container element or any other elements contained within + var transitionTimeout, focusedRowActions; + $( 'td.post-title, td.title, td.comment, .bookmarks td.column-name, td.blogname, td.username, .dashboard-comment-wrap' ).focusin(function(){ + clearTimeout( transitionTimeout ); + focusedRowActions = $(this).find( '.row-actions' ); + focusedRowActions.addClass( 'visible' ); + }).focusout(function(){ + // Tabbing between post title and .row-actions links needs a brief pause, otherwise + // the .row-actions div gets hidden in transit in some browsers (ahem, Firefox). + transitionTimeout = setTimeout(function(){ + focusedRowActions.removeClass( 'visible' ); + }, 30); + }); + + $('#default-password-nag-no').click( function() { + setUserSetting('default_password_nag', 'hide'); + $('div.default-password-nag').hide(); + return false; + }); + + // tab in textareas + $('#newcontent').bind('keydown.wpevent_InsertTab', function(e) { + var el = e.target, selStart, selEnd, val, scroll, sel; + + if ( e.keyCode == 27 ) { // escape key + $(el).data('tab-out', true); + return; + } + + if ( e.keyCode != 9 || e.ctrlKey || e.altKey || e.shiftKey ) // tab key + return; + + if ( $(el).data('tab-out') ) { + $(el).data('tab-out', false); + return; + } + + selStart = el.selectionStart; + selEnd = el.selectionEnd; + val = el.value; + + try { + this.lastKey = 9; // not a standard DOM property, lastKey is to help stop Opera tab event. See blur handler below. + } catch(err) {} + + if ( document.selection ) { + el.focus(); + sel = document.selection.createRange(); + sel.text = '\t'; + } else if ( selStart >= 0 ) { + scroll = this.scrollTop; + el.value = val.substring(0, selStart).concat('\t', val.substring(selEnd) ); + el.selectionStart = el.selectionEnd = selStart + 1; + this.scrollTop = scroll; + } + + if ( e.stopPropagation ) + e.stopPropagation(); + if ( e.preventDefault ) + e.preventDefault(); + }); + + $('#newcontent').bind('blur.wpevent_InsertTab', function(e) { + if ( this.lastKey && 9 == this.lastKey ) + this.focus(); + }); + + if ( pageInput.length ) { + pageInput.closest('form').submit( function(e){ + + // Reset paging var for new filters/searches but not for bulk actions. See #17685. + if ( $('select[name="action"]').val() == -1 && $('select[name="action2"]').val() == -1 && pageInput.val() == currentPage ) + pageInput.val('1'); + }); + } + + $('.search-box input[type="search"], .search-box input[type="submit"]').mousedown(function () { + $('select[name^="action"]').val('-1'); + }); + + // Scroll into view when focused + $('#contextual-help-link, #show-settings-link').on( 'focus.scroll-into-view', function(e){ + if ( e.target.scrollIntoView ) + e.target.scrollIntoView(false); + }); + + // Disable upload buttons until files are selected + (function(){ + var button, input, form = $('form.wp-upload-form'); + if ( ! form.length ) + return; + button = form.find('input[type="submit"]'); + input = form.find('input[type="file"]'); + + function toggleUploadButton() { + button.prop('disabled', '' === input.map( function() { + return $(this).val(); + }).get().join('')); + } + toggleUploadButton(); + input.on('change', toggleUploadButton); + })(); +}); + +// internal use +$(document).bind( 'wp_CloseOnEscape', function( e, data ) { + if ( typeof(data.cb) != 'function' ) + return; + + if ( typeof(data.condition) != 'function' || data.condition() ) + data.cb(); + + return true; +}); + +})(jQuery); diff --git a/sources/wp-admin/js/common.min.js b/sources/wp-admin/js/common.min.js new file mode 100644 index 0000000..430e0c2 --- /dev/null +++ b/sources/wp-admin/js/common.min.js @@ -0,0 +1 @@ +var showNotice,adminMenu,columns,validateForm,screenMeta;!function(a){adminMenu={init:function(){},fold:function(){},restoreMenuState:function(){},toggle:function(){},favorites:function(){}},columns={init:function(){var b=this;a(".hide-column-tog","#adv-settings").click(function(){var c=a(this),d=c.val();c.prop("checked")?b.checked(d):b.unchecked(d),columns.saveManageColumnsState()})},saveManageColumnsState:function(){var b=this.hidden();a.post(ajaxurl,{action:"hidden-columns",hidden:b,screenoptionnonce:a("#screenoptionnonce").val(),page:pagenow})},checked:function(b){a(".column-"+b).show(),this.colSpanChange(1)},unchecked:function(b){a(".column-"+b).hide(),this.colSpanChange(-1)},hidden:function(){return a(".manage-column").filter(":hidden").map(function(){return this.id}).get().join(",")},useCheckboxesForHidden:function(){this.hidden=function(){return a(".hide-column-tog").not(":checked").map(function(){var a=this.id;return a.substring(a,a.length-5)}).get().join(",")}},colSpanChange:function(b){var c,d=a("table").find(".colspanchange");d.length&&(c=parseInt(d.attr("colspan"),10)+b,d.attr("colspan",c.toString()))}},a(document).ready(function(){columns.init()}),validateForm=function(b){return!a(b).find(".form-required").filter(function(){return""==a("input:visible",this).val()}).addClass("form-invalid").find("input:visible").change(function(){a(this).closest(".form-invalid").removeClass("form-invalid")}).size()},showNotice={warn:function(){var a=commonL10n.warnDelete||"";return confirm(a)?!0:!1},note:function(a){alert(a)}},screenMeta={element:null,toggles:null,page:null,init:function(){this.element=a("#screen-meta"),this.toggles=a(".screen-meta-toggle a"),this.page=a("#wpcontent"),this.toggles.click(this.toggleEvent)},toggleEvent:function(b){var c=a(this.href.replace(/.+#/,"#"));b.preventDefault(),c.length&&(c.is(":visible")?screenMeta.close(c,a(this)):screenMeta.open(c,a(this)))},open:function(b,c){a(".screen-meta-toggle").not(c.parent()).css("visibility","hidden"),b.parent().show(),b.slideDown("fast",function(){b.focus(),c.addClass("screen-meta-active").attr("aria-expanded",!0)})},close:function(b,c){b.slideUp("fast",function(){c.removeClass("screen-meta-active").attr("aria-expanded",!1),a(".screen-meta-toggle").css("visibility",""),b.parent().hide()})}},a(".contextual-help-tabs").delegate("a","click focus",function(b){var c,d=a(this);return b.preventDefault(),d.is(".active a")?!1:(a(".contextual-help-tabs .active").removeClass("active"),d.parent("li").addClass("active"),c=a(d.attr("href")),a(".help-tab-content").not(c).removeClass("active").hide(),c.addClass("active").show(),void 0)}),a(document).ready(function(){var b,c,d,e,f,g,h=!1,i=a("#adminmenu"),j=a("input.current-page"),k=j.val();i.on("click.wp-submenu-head",".wp-submenu-head",function(b){a(b.target).parent().siblings("a").get(0).click()}),a("#collapse-menu").on("click.collapse-menu",function(){var b,c=a(document.body);a("#adminmenu div.wp-submenu").css("margin-top",""),b=navigator.userAgent.indexOf("AppleWebKit/")>-1?a(window).width():window.innerWidth,b&&900>b?c.hasClass("auto-fold")?(c.removeClass("auto-fold").removeClass("folded"),setUserSetting("unfold",1),setUserSetting("mfold","o")):(c.addClass("auto-fold"),setUserSetting("unfold",0)):c.hasClass("folded")?(c.removeClass("folded"),setUserSetting("mfold","o")):(c.addClass("folded"),setUserSetting("mfold","f"))}),("ontouchstart"in window||/IEMobile\/[1-9]/.test(navigator.userAgent))&&(g=/Mobile\/.+Safari/.test(navigator.userAgent)?"touchstart":"click",a(document.body).on(g+".wp-mobile-hover",function(b){a(b.target).closest("#adminmenu").length||i.find("li.wp-has-submenu.opensub").removeClass("opensub")}),i.find("a.wp-has-submenu").on(g+".wp-mobile-hover",function(b){var c=a(this),d=c.parent();d.hasClass("opensub")||d.hasClass("wp-menu-open")&&!(d.width()<40)||(b.preventDefault(),i.find("li.opensub").removeClass("opensub"),d.addClass("opensub"))})),i.find("li.wp-has-submenu").hoverIntent({over:function(){var b,c,d,e,f,g,h,j=a(this).find(".wp-submenu"),k=parseInt(j.css("top"),10);isNaN(k)||k>-5||(f=a(this).offset().top,g=a(window).scrollTop(),h=f-g-30,b=f+j.height()+1,c=a("#wpwrap").height(),d=60+b-c,e=a(window).height()+g-15,b-d>e&&(d=b-e),d>h&&(d=h),d>1?j.css("margin-top","-"+d+"px"):j.css("margin-top",""),i.find("li.menu-top").removeClass("opensub"),a(this).addClass("opensub"))},out:function(){a(this).removeClass("opensub").find(".wp-submenu").css("margin-top","")},timeout:200,sensitivity:7,interval:90}),i.on("focus.adminmenu",".wp-submenu a",function(b){a(b.target).closest("li.menu-top").addClass("opensub")}).on("blur.adminmenu",".wp-submenu a",function(b){a(b.target).closest("li.menu-top").removeClass("opensub")}),a("div.wrap h2:first").nextAll("div.updated, div.error").addClass("below-h2"),a("div.updated, div.error").not(".below-h2, .inline").insertAfter(a("div.wrap h2:first")),screenMeta.init(),a("tbody").children().children(".check-column").find(":checkbox").click(function(g){if("undefined"==g.shiftKey)return!0;if(g.shiftKey){if(!h)return!0;b=a(h).closest("form").find(":checkbox"),c=b.index(h),d=b.index(this),e=a(this).prop("checked"),c>0&&d>0&&c!=d&&(f=d>c?b.slice(c,d):b.slice(d,c),f.prop("checked",function(){return a(this).closest("tr").is(":visible")?e:!1}))}h=this;var i=a(this).closest("tbody").find(":checkbox").filter(":visible").not(":checked");return a(this).closest("table").children("thead, tfoot").find(":checkbox").prop("checked",function(){return 0==i.length}),!0}),a("thead, tfoot").find(".check-column :checkbox").click(function(b){var c=a(this).prop("checked"),d="undefined"==typeof toggleWithKeyboard?!1:toggleWithKeyboard,e=b.shiftKey||d;a(this).closest("table").children("tbody").filter(":visible").children().children(".check-column").find(":checkbox").prop("checked",function(){return a(this).is(":hidden")?!1:e?a(this).prop("checked"):c?!0:!1}),a(this).closest("table").children("thead, tfoot").filter(":visible").children().children(".check-column").find(":checkbox").prop("checked",function(){return e?!1:c?!0:!1})});var l,m;a("td.post-title, td.title, td.comment, .bookmarks td.column-name, td.blogname, td.username, .dashboard-comment-wrap").focusin(function(){clearTimeout(l),m=a(this).find(".row-actions"),m.addClass("visible")}).focusout(function(){l=setTimeout(function(){m.removeClass("visible")},30)}),a("#default-password-nag-no").click(function(){return setUserSetting("default_password_nag","hide"),a("div.default-password-nag").hide(),!1}),a("#newcontent").bind("keydown.wpevent_InsertTab",function(b){var c,d,e,f,g,h=b.target;if(27==b.keyCode)return a(h).data("tab-out",!0),void 0;if(!(9!=b.keyCode||b.ctrlKey||b.altKey||b.shiftKey)){if(a(h).data("tab-out"))return a(h).data("tab-out",!1),void 0;c=h.selectionStart,d=h.selectionEnd,e=h.value;try{this.lastKey=9}catch(i){}document.selection?(h.focus(),g=document.selection.createRange(),g.text=" "):c>=0&&(f=this.scrollTop,h.value=e.substring(0,c).concat(" ",e.substring(d)),h.selectionStart=h.selectionEnd=c+1,this.scrollTop=f),b.stopPropagation&&b.stopPropagation(),b.preventDefault&&b.preventDefault()}}),a("#newcontent").bind("blur.wpevent_InsertTab",function(){this.lastKey&&9==this.lastKey&&this.focus()}),j.length&&j.closest("form").submit(function(){-1==a('select[name="action"]').val()&&-1==a('select[name="action2"]').val()&&j.val()==k&&j.val("1")}),a('.search-box input[type="search"], .search-box input[type="submit"]').mousedown(function(){a('select[name^="action"]').val("-1")}),a("#contextual-help-link, #show-settings-link").on("focus.scroll-into-view",function(a){a.target.scrollIntoView&&a.target.scrollIntoView(!1)}),function(){function b(){c.prop("disabled",""===d.map(function(){return a(this).val()}).get().join(""))}var c,d,e=a("form.wp-upload-form");e.length&&(c=e.find('input[type="submit"]'),d=e.find('input[type="file"]'),b(),d.on("change",b))}()}),a(document).bind("wp_CloseOnEscape",function(a,b){return"function"==typeof b.cb?(("function"!=typeof b.condition||b.condition())&&b.cb(),!0):void 0})}(jQuery); \ No newline at end of file diff --git a/sources/wp-admin/js/custom-background.js b/sources/wp-admin/js/custom-background.js new file mode 100644 index 0000000..c41ca6b --- /dev/null +++ b/sources/wp-admin/js/custom-background.js @@ -0,0 +1,74 @@ +(function($) { + $(document).ready(function() { + var bgImage = $("#custom-background-image"), + frame; + + $('#background-color').wpColorPicker({ + change: function( event, ui ) { + bgImage.css('background-color', ui.color.toString()); + }, + clear: function() { + bgImage.css('background-color', ''); + } + }); + + $('input[name="background-position-x"]').change(function() { + bgImage.css('background-position', $(this).val() + ' top'); + }); + + $('input[name="background-repeat"]').change(function() { + bgImage.css('background-repeat', $(this).val()); + }); + + $('#choose-from-library-link').click( function( event ) { + var $el = $(this); + + event.preventDefault(); + + // If the media frame already exists, reopen it. + if ( frame ) { + frame.open(); + return; + } + + // Create the media frame. + frame = wp.media.frames.customBackground = wp.media({ + // Set the title of the modal. + title: $el.data('choose'), + + // Tell the modal to show only images. + library: { + type: 'image' + }, + + // Customize the submit button. + button: { + // Set the text of the button. + text: $el.data('update'), + // Tell the button not to close the modal, since we're + // going to refresh the page when the image is selected. + close: false + } + }); + + // When an image is selected, run a callback. + frame.on( 'select', function() { + // Grab the selected attachment. + var attachment = frame.state().get('selection').first(); + + // Run an AJAX request to set the background image. + $.post( ajaxurl, { + action: 'set-background-image', + attachment_id: attachment.id, + size: 'full' + }).done( function() { + // When the request completes, reload the window. + window.location.reload(); + }); + }); + + // Finally, open the modal. + frame.open(); + }); + }); +})(jQuery); \ No newline at end of file diff --git a/sources/wp-admin/js/custom-background.min.js b/sources/wp-admin/js/custom-background.min.js new file mode 100644 index 0000000..669d281 --- /dev/null +++ b/sources/wp-admin/js/custom-background.min.js @@ -0,0 +1 @@ +!function(a){a(document).ready(function(){var b,c=a("#custom-background-image");a("#background-color").wpColorPicker({change:function(a,b){c.css("background-color",b.color.toString())},clear:function(){c.css("background-color","")}}),a('input[name="background-position-x"]').change(function(){c.css("background-position",a(this).val()+" top")}),a('input[name="background-repeat"]').change(function(){c.css("background-repeat",a(this).val())}),a("#choose-from-library-link").click(function(c){var d=a(this);return c.preventDefault(),b?(b.open(),void 0):(b=wp.media.frames.customBackground=wp.media({title:d.data("choose"),library:{type:"image"},button:{text:d.data("update"),close:!1}}),b.on("select",function(){var c=b.state().get("selection").first();a.post(ajaxurl,{action:"set-background-image",attachment_id:c.id,size:"full"}).done(function(){window.location.reload()})}),b.open(),void 0)})})}(jQuery); \ No newline at end of file diff --git a/sources/wp-admin/js/custom-header.js b/sources/wp-admin/js/custom-header.js new file mode 100644 index 0000000..d93ac38 --- /dev/null +++ b/sources/wp-admin/js/custom-header.js @@ -0,0 +1,60 @@ +(function($) { + var frame; + + $( function() { + // Fetch available headers and apply jQuery.masonry + // once the images have loaded. + var $headers = $('.available-headers'); + + $headers.imagesLoaded( function() { + $headers.masonry({ + itemSelector: '.default-header', + isRTL: !! ( 'undefined' != typeof isRtl && isRtl ) + }); + }); + + // Build the choose from library frame. + $('#choose-from-library-link').click( function( event ) { + var $el = $(this); + event.preventDefault(); + + // If the media frame already exists, reopen it. + if ( frame ) { + frame.open(); + return; + } + + // Create the media frame. + frame = wp.media.frames.customHeader = wp.media({ + // Set the title of the modal. + title: $el.data('choose'), + + // Tell the modal to show only images. + library: { + type: 'image' + }, + + // Customize the submit button. + button: { + // Set the text of the button. + text: $el.data('update'), + // Tell the button not to close the modal, since we're + // going to refresh the page when the image is selected. + close: false + } + }); + + // When an image is selected, run a callback. + frame.on( 'select', function() { + // Grab the selected attachment. + var attachment = frame.state().get('selection').first(), + link = $el.data('updateLink'); + + // Tell the browser to navigate to the crop step. + window.location = link + '&file=' + attachment.id; + }); + + frame.open(); + }); + }); +}(jQuery)); diff --git a/sources/wp-admin/js/customize-controls.js b/sources/wp-admin/js/customize-controls.js new file mode 100644 index 0000000..f780db7 --- /dev/null +++ b/sources/wp-admin/js/customize-controls.js @@ -0,0 +1,1009 @@ +(function( exports, $ ){ + var api = wp.customize; + + /* + * @param options + * - previewer - The Previewer instance to sync with. + * - transport - The transport to use for previewing. Supports 'refresh' and 'postMessage'. + */ + api.Setting = api.Value.extend({ + initialize: function( id, value, options ) { + var element; + + api.Value.prototype.initialize.call( this, value, options ); + + this.id = id; + this.transport = this.transport || 'refresh'; + + this.bind( this.preview ); + }, + preview: function() { + switch ( this.transport ) { + case 'refresh': + return this.previewer.refresh(); + case 'postMessage': + return this.previewer.send( 'setting', [ this.id, this() ] ); + } + } + }); + + api.Control = api.Class.extend({ + initialize: function( id, options ) { + var control = this, + nodes, radios, settings; + + this.params = {}; + $.extend( this, options || {} ); + + this.id = id; + this.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' ); + this.container = $( this.selector ); + + settings = $.map( this.params.settings, function( value ) { + return value; + }); + + api.apply( api, settings.concat( function() { + var key; + + control.settings = {}; + for ( key in control.params.settings ) { + control.settings[ key ] = api( control.params.settings[ key ] ); + } + + control.setting = control.settings['default'] || null; + control.ready(); + }) ); + + control.elements = []; + + nodes = this.container.find('[data-customize-setting-link]'); + radios = {}; + + nodes.each( function() { + var node = $(this), + name; + + if ( node.is(':radio') ) { + name = node.prop('name'); + if ( radios[ name ] ) + return; + + radios[ name ] = true; + node = nodes.filter( '[name="' + name + '"]' ); + } + + api( node.data('customizeSettingLink'), function( setting ) { + var element = new api.Element( node ); + control.elements.push( element ); + element.sync( setting ); + element.set( setting() ); + }); + }); + }, + + ready: function() {}, + + dropdownInit: function() { + var control = this, + statuses = this.container.find('.dropdown-status'), + params = this.params, + update = function( to ) { + if ( typeof to === 'string' && params.statuses && params.statuses[ to ] ) + statuses.html( params.statuses[ to ] ).show(); + else + statuses.hide(); + }; + + var toggleFreeze = false; + + // Support the .dropdown class to open/close complex elements + this.container.on( 'click keydown', '.dropdown', function( event ) { + if ( event.type === 'keydown' && 13 !== event.which ) // enter + return; + + event.preventDefault(); + + if (!toggleFreeze) + control.container.toggleClass('open'); + + if ( control.container.hasClass('open') ) + control.container.parent().parent().find('li.library-selected').focus(); + + // Don't want to fire focus and click at same time + toggleFreeze = true; + setTimeout(function () { + toggleFreeze = false; + }, 400); + }); + + this.setting.bind( update ); + update( this.setting() ); + } + }); + + api.ColorControl = api.Control.extend({ + ready: function() { + var control = this, + picker = this.container.find('.color-picker-hex'); + + picker.val( control.setting() ).wpColorPicker({ + change: function( event, options ) { + control.setting.set( picker.wpColorPicker('color') ); + }, + clear: function() { + control.setting.set( false ); + } + }); + } + }); + + api.UploadControl = api.Control.extend({ + ready: function() { + var control = this; + + this.params.removed = this.params.removed || ''; + + this.success = $.proxy( this.success, this ); + + this.uploader = $.extend({ + container: this.container, + browser: this.container.find('.upload'), + dropzone: this.container.find('.upload-dropzone'), + success: this.success, + plupload: {}, + params: {} + }, this.uploader || {} ); + + if ( control.params.extensions ) { + control.uploader.plupload.filters = [{ + title: api.l10n.allowedFiles, + extensions: control.params.extensions + }]; + } + + if ( control.params.context ) + control.uploader.params['post_data[context]'] = this.params.context; + + if ( api.settings.theme.stylesheet ) + control.uploader.params['post_data[theme]'] = api.settings.theme.stylesheet; + + this.uploader = new wp.Uploader( this.uploader ); + + this.remover = this.container.find('.remove'); + this.remover.on( 'click keydown', function( event ) { + if ( event.type === 'keydown' && 13 !== event.which ) // enter + return; + + control.setting.set( control.params.removed ); + event.preventDefault(); + }); + + this.removerVisibility = $.proxy( this.removerVisibility, this ); + this.setting.bind( this.removerVisibility ); + this.removerVisibility( this.setting.get() ); + }, + success: function( attachment ) { + this.setting.set( attachment.get('url') ); + }, + removerVisibility: function( to ) { + this.remover.toggle( to != this.params.removed ); + } + }); + + api.ImageControl = api.UploadControl.extend({ + ready: function() { + var control = this, + panels; + + this.uploader = { + init: function( up ) { + var fallback, button; + + if ( this.supports.dragdrop ) + return; + + // Maintain references while wrapping the fallback button. + fallback = control.container.find( '.upload-fallback' ); + button = fallback.children().detach(); + + this.browser.detach().empty().append( button ); + fallback.append( this.browser ).show(); + } + }; + + api.UploadControl.prototype.ready.call( this ); + + this.thumbnail = this.container.find('.preview-thumbnail img'); + this.thumbnailSrc = $.proxy( this.thumbnailSrc, this ); + this.setting.bind( this.thumbnailSrc ); + + this.library = this.container.find('.library'); + + // Generate tab objects + this.tabs = {}; + panels = this.library.find('.library-content'); + + this.library.children('ul').children('li').each( function() { + var link = $(this), + id = link.data('customizeTab'), + panel = panels.filter('[data-customize-tab="' + id + '"]'); + + control.tabs[ id ] = { + both: link.add( panel ), + link: link, + panel: panel + }; + }); + + // Bind tab switch events + this.library.children('ul').on( 'click keydown', 'li', function( event ) { + if ( event.type === 'keydown' && 13 !== event.which ) // enter + return; + + var id = $(this).data('customizeTab'), + tab = control.tabs[ id ]; + + event.preventDefault(); + + if ( tab.link.hasClass('library-selected') ) + return; + + control.selected.both.removeClass('library-selected'); + control.selected = tab; + control.selected.both.addClass('library-selected'); + }); + + // Bind events to switch image urls. + this.library.on( 'click keydown', 'a', function( event ) { + if ( event.type === 'keydown' && 13 !== event.which ) // enter + return; + + var value = $(this).data('customizeImageValue'); + + if ( value ) { + control.setting.set( value ); + event.preventDefault(); + } + }); + + if ( this.tabs.uploaded ) { + this.tabs.uploaded.target = this.library.find('.uploaded-target'); + if ( ! this.tabs.uploaded.panel.find('.thumbnail').length ) + this.tabs.uploaded.both.addClass('hidden'); + } + + // Select a tab + panels.each( function() { + var tab = control.tabs[ $(this).data('customizeTab') ]; + + // Select the first visible tab. + if ( ! tab.link.hasClass('hidden') ) { + control.selected = tab; + tab.both.addClass('library-selected'); + return false; + } + }); + + this.dropdownInit(); + }, + success: function( attachment ) { + api.UploadControl.prototype.success.call( this, attachment ); + + // Add the uploaded image to the uploaded tab. + if ( this.tabs.uploaded && this.tabs.uploaded.target.length ) { + this.tabs.uploaded.both.removeClass('hidden'); + + // @todo: Do NOT store this on the attachment model. That is bad. + attachment.element = $( '' ) + .data( 'customizeImageValue', attachment.get('url') ) + .append( '' ) + .appendTo( this.tabs.uploaded.target ); + } + }, + thumbnailSrc: function( to ) { + if ( /^(https?:)?\/\//.test( to ) ) + this.thumbnail.prop( 'src', to ).show(); + else + this.thumbnail.hide(); + } + }); + + // Change objects contained within the main customize object to Settings. + api.defaultConstructor = api.Setting; + + // Create the collection of Control objects. + api.control = new api.Values({ defaultConstructor: api.Control }); + + api.PreviewFrame = api.Messenger.extend({ + sensitivity: 2000, + + initialize: function( params, options ) { + var deferred = $.Deferred(), + self = this; + + // This is the promise object. + deferred.promise( this ); + + this.container = params.container; + this.signature = params.signature; + + $.extend( params, { channel: api.PreviewFrame.uuid() }); + + api.Messenger.prototype.initialize.call( this, params, options ); + + this.add( 'previewUrl', params.previewUrl ); + + this.query = $.extend( params.query || {}, { customize_messenger_channel: this.channel() }); + + this.run( deferred ); + }, + + run: function( deferred ) { + var self = this, + loaded = false, + ready = false; + + if ( this._ready ) + this.unbind( 'ready', this._ready ); + + this._ready = function() { + ready = true; + + if ( loaded ) + deferred.resolveWith( self ); + }; + + this.bind( 'ready', this._ready ); + + this.request = $.ajax( this.previewUrl(), { + type: 'POST', + data: this.query, + xhrFields: { + withCredentials: true + } + } ); + + this.request.fail( function() { + deferred.rejectWith( self, [ 'request failure' ] ); + }); + + this.request.done( function( response ) { + var location = self.request.getResponseHeader('Location'), + signature = self.signature, + index; + + // Check if the location response header differs from the current URL. + // If so, the request was redirected; try loading the requested page. + if ( location && location != self.previewUrl() ) { + deferred.rejectWith( self, [ 'redirect', location ] ); + return; + } + + // Check if the user is not logged in. + if ( '0' === response ) { + self.login( deferred ); + return; + } + + // Check for cheaters. + if ( '-1' === response ) { + deferred.rejectWith( self, [ 'cheatin' ] ); + return; + } + + // Check for a signature in the request. + index = response.lastIndexOf( signature ); + if ( -1 === index || index < response.lastIndexOf('') ) { + deferred.rejectWith( self, [ 'unsigned' ] ); + return; + } + + // Strip the signature from the request. + response = response.slice( 0, index ) + response.slice( index + signature.length ); + + // Create the iframe and inject the html content. + self.iframe = $('"; + echo '
    '; + require_once(ABSPATH . 'wp-admin/admin-footer.php'); + exit; + break; + case 'delete-selected': + if ( ! current_user_can( 'delete_themes' ) ) + wp_die( __('You do not have sufficient permissions to delete themes for this site.') ); + check_admin_referer( 'bulk-themes' ); + + $themes = isset( $_REQUEST['checked'] ) ? (array) $_REQUEST['checked'] : array(); + + unset( $themes[ get_option( 'stylesheet' ) ], $themes[ get_option( 'template' ) ] ); + + if ( empty( $themes ) ) { + wp_safe_redirect( add_query_arg( 'error', 'none', $referer ) ); + exit; + } + + $files_to_delete = $theme_info = array(); + foreach ( $themes as $key => $theme ) { + $theme_info[ $theme ] = wp_get_theme( $theme ); + $files_to_delete = array_merge( $files_to_delete, list_files( $theme_info[ $theme ]->get_stylesheet_directory() ) ); + } + + if ( empty( $themes ) ) { + wp_safe_redirect( add_query_arg( 'error', 'main', $referer ) ); + exit; + } + + include(ABSPATH . 'wp-admin/update.php'); + + $parent_file = 'themes.php'; + + if ( ! isset( $_REQUEST['verify-delete'] ) ) { + wp_enqueue_script( 'jquery' ); + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + ?> +
    + ' . _n( 'Delete Theme', 'Delete Themes', $themes_to_delete ) . ''; + ?> +

    +

    +
      + ', sprintf( __('%1$s by %2$s' ), $theme->display('Name'), $theme->display('Author') ), ''; /* translators: 1: theme name, 2: theme author */ ?> +
    +

    +
    + + + '; + ?> + + +
    +
    + +
    + +

    + +
    + 1, + 'action' => 'delete-selected', + 'checked' => $_REQUEST['checked'], + '_wpnonce' => $_REQUEST['_wpnonce'] + ), network_admin_url( 'themes.php' ) ) ) ); + } + + $paged = ( $_REQUEST['paged'] ) ? $_REQUEST['paged'] : 1; + wp_redirect( add_query_arg( array( + 'deleted' => count( $themes ), + 'paged' => $paged, + 's' => $s + ), network_admin_url( 'themes.php' ) ) ); + exit; + break; + } +} + +$wp_list_table->prepare_items(); + +add_thickbox(); + +add_screen_option( 'per_page', array('label' => _x( 'Themes', 'themes per page (screen options)' )) ); + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

    ' . __('This screen enables and disables the inclusion of themes available to choose in the Appearance menu for each site. It does not activate or deactivate which theme a site is currently using.') . '

    ' . + '

    ' . __('If the network admin disables a theme that is in use, it can still remain selected on that site. If another theme is chosen, the disabled theme will not appear in the site’s Appearance > Themes screen.') . '

    ' . + '

    ' . __('Themes can be enabled on a site by site basis by the network admin on the Edit Site screen (which has a Themes tab); get there via the Edit action link on the All Sites screen. Only network admins are able to install or edit themes.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Network Themes') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +$title = __('Themes'); +$parent_file = 'themes.php'; + +wp_enqueue_script( 'theme' ); + +require_once(ABSPATH . 'wp-admin/admin-header.php'); + +?> + +
    + +

    ' . __('Search results for “%s”') . '', esc_html( $s ) ); ?> +

    + +

    ' . sprintf( _n( 'Theme enabled.', '%s themes enabled.', $_GET['enabled'] ), number_format_i18n( $_GET['enabled'] ) ) . '

    '; +} elseif ( isset( $_GET['disabled'] ) ) { + $_GET['disabled'] = absint( $_GET['disabled'] ); + echo '

    ' . sprintf( _n( 'Theme disabled.', '%s themes disabled.', $_GET['disabled'] ), number_format_i18n( $_GET['disabled'] ) ) . '

    '; +} elseif ( isset( $_GET['deleted'] ) ) { + $_GET['deleted'] = absint( $_GET['deleted'] ); + echo '

    ' . sprintf( _nx( 'Theme deleted.', '%s themes deleted.', $_GET['deleted'], 'network' ), number_format_i18n( $_GET['deleted'] ) ) . '

    '; +} elseif ( isset( $_GET['error'] ) && 'none' == $_GET['error'] ) { + echo '

    ' . __( 'No theme selected.' ) . '

    '; +} elseif ( isset( $_GET['error'] ) && 'main' == $_GET['error'] ) { + echo '

    ' . __( 'You cannot delete a theme while it is active on the main site.' ) . '

    '; +} + +?> + +
    +search_box( __( 'Search Installed Themes' ), 'theme' ); ?> +
    + +views(); + +if ( 'broken' == $status ) + echo '

    ' . __('The following themes are installed but incomplete. Themes must have a stylesheet and a template.') . '

    '; +?> + +
    + + + +display(); ?> +
    + +
    + +add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

    ' . __('Only use this screen once you have updated to a new version of WordPress through Updates/Available Updates (via the Network Administration navigation menu or the Toolbar). Clicking the Upgrade Network button will step through each site in the network, five at a time, and make sure any database updates are applied.') . '

    ' . + '

    ' . __('If a version update to core has not happened, clicking this button won’t affect anything.') . '

    ' . + '

    ' . __('If this process fails for any reason, users logging in to their sites will force the same update.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Upgrade Network') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +if ( ! current_user_can( 'manage_network' ) ) + wp_die( __( 'You do not have permission to access this page.' ) ); + +echo '
    '; +screen_icon('tools'); +echo '

    ' . __( 'Upgrade Network' ) . '

    '; + +$action = isset($_GET['action']) ? $_GET['action'] : 'show'; + +switch ( $action ) { + case "upgrade": + $n = ( isset($_GET['n']) ) ? intval($_GET['n']) : 0; + + if ( $n < 5 ) { + global $wp_db_version; + update_site_option( 'wpmu_upgrade_site', $wp_db_version ); + } + + $blogs = $wpdb->get_results( "SELECT * FROM {$wpdb->blogs} WHERE site_id = '{$wpdb->siteid}' AND spam = '0' AND deleted = '0' AND archived = '0' ORDER BY registered DESC LIMIT {$n}, 5", ARRAY_A ); + if ( empty( $blogs ) ) { + echo '

    ' . __( 'All done!' ) . '

    '; + break; + } + echo "
      "; + foreach ( (array) $blogs as $details ) { + switch_to_blog( $details['blog_id'] ); + $siteurl = site_url(); + $upgrade_url = admin_url( 'upgrade.php?step=upgrade_db' ); + restore_current_blog(); + echo "
    • $siteurl
    • "; + $response = wp_remote_get( $upgrade_url, array( 'timeout' => 120, 'httpversion' => '1.1' ) ); + if ( is_wp_error( $response ) ) + wp_die( sprintf( __( 'Warning! Problem updating %1$s. Your server may not be able to connect to sites running on it. Error message: %2$s' ), $siteurl, $response->get_error_message() ) ); + do_action( 'after_mu_upgrade', $response ); + do_action( 'wpmu_upgrade_site', $details[ 'blog_id' ] ); + } + echo "
    "; + ?>

    + +

    +

    + + +

    +

    + +
    + + diff --git a/sources/wp-admin/network/user-edit.php b/sources/wp-admin/network/user-edit.php new file mode 100644 index 0000000..effaaf8 --- /dev/null +++ b/sources/wp-admin/network/user-edit.php @@ -0,0 +1,16 @@ +add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

    ' . __('Add User will set up a new user account on the network and send that person an email with username and password.') . '

    ' . + '

    ' . __('Users who are signed up to the network without a site are added as subscribers to the main or primary dashboard site, giving them profile pages to manage their accounts. These users will only see Dashboard and My Sites in the main navigation until a site is created for them.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Network Users') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +if ( isset($_REQUEST['action']) && 'add-user' == $_REQUEST['action'] ) { + check_admin_referer( 'add-user', '_wpnonce_add-user' ); + if ( ! current_user_can( 'manage_network_users' ) ) + wp_die( __( 'You do not have permission to access this page.' ) ); + + if ( ! is_array( $_POST['user'] ) ) + wp_die( __( 'Cannot create an empty user.' ) ); + + $user = $_POST['user']; + + $user_details = wpmu_validate_user_signup( $user['username'], $user['email'] ); + if ( is_wp_error( $user_details[ 'errors' ] ) && ! empty( $user_details[ 'errors' ]->errors ) ) { + $add_user_errors = $user_details[ 'errors' ]; + } else { + $password = wp_generate_password( 12, false); + $user_id = wpmu_create_user( esc_html( strtolower( $user['username'] ) ), $password, esc_html( $user['email'] ) ); + + if ( ! $user_id ) { + $add_user_errors = new WP_Error( 'add_user_fail', __( 'Cannot add user.' ) ); + } else { + wp_new_user_notification( $user_id, $password ); + wp_redirect( add_query_arg( array('update' => 'added'), 'user-new.php' ) ); + exit; + } + } +} + +if ( isset($_GET['update']) ) { + $messages = array(); + if ( 'added' == $_GET['update'] ) + $messages[] = __('User added.'); +} + +$title = __('Add New User'); +$parent_file = 'users.php'; + +require( ABSPATH . 'wp-admin/admin-header.php' ); ?> + +
    + +

    +

    ' . $msg . '

    '; +} + +if ( isset( $add_user_errors ) && is_wp_error( $add_user_errors ) ) { ?> +
    + get_error_messages() as $message ) + echo "

    $message

    "; + ?> +
    + +
    + + + + + + + + + + + + +
    + + +
    + + +

    +

    +
    + + ID'>$current_user->user_login"; + + foreach ( ( $allusers = (array) $_POST['allusers'] ) as $key => $val ) { + if ( $val != '' && $val != '0' ) { + $delete_user = get_userdata( $val ); + + if ( ! current_user_can( 'delete_user', $delete_user->ID ) ) + wp_die( sprintf( __( 'Warning! User %s cannot be deleted.' ), $delete_user->user_login ) ); + + if ( in_array( $delete_user->user_login, $site_admins ) ) + wp_die( sprintf( __( 'Warning! User cannot be deleted. The user %s is a network administrator.' ), $delete_user->user_login ) ); + + echo "\n"; + $blogs = get_blogs_of_user( $val, true ); + + if ( !empty( $blogs ) ) { + ?> +

    %s?" ), $delete_user->user_login ); ?>

    + $details ) { + $blog_users = get_users( array( 'blog_id' => $details->userblog_id ) ); + if ( is_array( $blog_users ) && !empty( $blog_users ) ) { + $user_site = "{$details->blogname}"; + $user_dropdown = "\n"; + ?> +
      +
    • +
    • +
    • +
    + "; + } + } + } + + submit_button( __('Confirm Deletion'), 'delete' ); + ?> + + '; + confirm_delete_users( $_POST['allusers'] ); + echo ''; + require_once( ABSPATH . 'wp-admin/admin-footer.php' ); + } else { + wp_redirect( network_admin_url( 'users.php' ) ); + } + exit(); + break; + + case 'allusers': + if ( !current_user_can( 'manage_network_users' ) ) + wp_die( __( 'You do not have permission to access this page.' ) ); + + if ( ( isset( $_POST['action']) || isset($_POST['action2'] ) ) && isset( $_POST['allusers'] ) ) { + check_admin_referer( 'bulk-users-network' ); + + $doaction = $_POST['action'] != -1 ? $_POST['action'] : $_POST['action2']; + $userfunction = ''; + + foreach ( (array) $_POST['allusers'] as $key => $val ) { + if ( !empty( $val ) ) { + switch ( $doaction ) { + case 'delete': + if ( ! current_user_can( 'delete_users' ) ) + wp_die( __( 'You do not have permission to access this page.' ) ); + $title = __( 'Users' ); + $parent_file = 'users.php'; + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + echo '
    '; + confirm_delete_users( $_POST['allusers'] ); + echo '
    '; + require_once( ABSPATH . 'wp-admin/admin-footer.php' ); + exit(); + break; + + case 'spam': + $user = get_userdata( $val ); + if ( is_super_admin( $user->ID ) ) + wp_die( sprintf( __( 'Warning! User cannot be modified. The user %s is a network administrator.' ), esc_html( $user->user_login ) ) ); + + $userfunction = 'all_spam'; + $blogs = get_blogs_of_user( $val, true ); + foreach ( (array) $blogs as $key => $details ) { + if ( $details->userblog_id != $current_site->blog_id ) // main blog not a spam ! + update_blog_status( $details->userblog_id, 'spam', '1' ); + } + update_user_status( $val, 'spam', '1' ); + break; + + case 'notspam': + $userfunction = 'all_notspam'; + $blogs = get_blogs_of_user( $val, true ); + foreach ( (array) $blogs as $key => $details ) + update_blog_status( $details->userblog_id, 'spam', '0' ); + + update_user_status( $val, 'spam', '0' ); + break; + } + } + } + + wp_safe_redirect( add_query_arg( array( 'updated' => 'true', 'action' => $userfunction ), wp_get_referer() ) ); + } else { + $location = network_admin_url( 'users.php' ); + + if ( ! empty( $_REQUEST['paged'] ) ) + $location = add_query_arg( 'paged', (int) $_REQUEST['paged'], $location ); + wp_redirect( $location ); + } + exit(); + break; + + case 'dodelete': + check_admin_referer( 'ms-users-delete' ); + if ( ! ( current_user_can( 'manage_network_users' ) && current_user_can( 'delete_users' ) ) ) + wp_die( __( 'You do not have permission to access this page.' ) ); + + if ( ! empty( $_POST['blog'] ) && is_array( $_POST['blog'] ) ) { + foreach ( $_POST['blog'] as $id => $users ) { + foreach ( $users as $blogid => $user_id ) { + if ( ! current_user_can( 'delete_user', $id ) ) + continue; + + if ( ! empty( $_POST['delete'] ) && 'reassign' == $_POST['delete'][$blogid][$id] ) + remove_user_from_blog( $id, $blogid, $user_id ); + else + remove_user_from_blog( $id, $blogid ); + } + } + } + $i = 0; + if ( is_array( $_POST['user'] ) && ! empty( $_POST['user'] ) ) + foreach( $_POST['user'] as $id ) { + if ( ! current_user_can( 'delete_user', $id ) ) + continue; + wpmu_delete_user( $id ); + $i++; + } + + if ( $i == 1 ) + $deletefunction = 'delete'; + else + $deletefunction = 'all_delete'; + + wp_redirect( add_query_arg( array( 'updated' => 'true', 'action' => $deletefunction ), network_admin_url( 'users.php' ) ) ); + exit(); + break; + } +} + +$wp_list_table = _get_list_table('WP_MS_Users_List_Table'); +$pagenum = $wp_list_table->get_pagenum(); +$wp_list_table->prepare_items(); +$total_pages = $wp_list_table->get_pagination_arg( 'total_pages' ); + +if ( $pagenum > $total_pages && $total_pages > 0 ) { + wp_redirect( add_query_arg( 'paged', $total_pages ) ); + exit; +} +$title = __( 'Users' ); +$parent_file = 'users.php'; + +add_screen_option( 'per_page', array('label' => _x( 'Users', 'users per page (screen options)' )) ); + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

    ' . __('This table shows all users across the network and the sites to which they are assigned.') . '

    ' . + '

    ' . __('Hover over any user on the list to make the edit links appear. The Edit link on the left will take you to his or her Edit User profile page; the Edit link on the right by any site name goes to an Edit Site screen for that site.') . '

    ' . + '

    ' . __('You can also go to the user’s profile page by clicking on the individual username.') . '

    ' . + '

    ' . __('You can sort the table by clicking on any of the bold headings and switch between list and excerpt views by using the icons in the upper right.') . '

    ' . + '

    ' . __('The bulk action will permanently delete selected users, or mark/unmark those selected as spam. Spam users will have posts removed and will be unable to sign up again with the same email addresses.') . '

    ' . + '

    ' . __('You can make an existing user an additional super admin by going to the Edit User profile page and checking the box to grant that privilege.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Network Users') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +if ( isset( $_REQUEST['updated'] ) && $_REQUEST['updated'] == 'true' && ! empty( $_REQUEST['action'] ) ) { + ?> +

    + +

    + +
    + +

    + ' . __( 'Search results for “%s”' ) . '', esc_html( $usersearch ) ); + ?> +

    + + views(); ?> + +
    + search_box( __( 'Search Users' ), 'all-user' ); ?> +
    + +
    + display(); ?> +
    +
    + + diff --git a/sources/wp-admin/options-discussion.php b/sources/wp-admin/options-discussion.php new file mode 100644 index 0000000..76f6b32 --- /dev/null +++ b/sources/wp-admin/options-discussion.php @@ -0,0 +1,274 @@ +add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

    ' . __('This screen provides many options for controlling the management and display of comments and links to your posts/pages. So many, in fact, they won’t all fit here! :) Use the documentation links to get information on what each discussion setting does.') . '

    ' . + '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    ', +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Discussion Settings') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +include( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
    + +

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    +

    + +

    +

    + +

    +
    +

    +

    + +

    +
    + +

    + +

    + + + + + + + + + + + + + + + + + +
    + +
    + + __('G — Suitable for all audiences'), + /* translators: Content suitability rating: http://bit.ly/89QxZA */ + 'PG' => __('PG — Possibly offensive, usually for audiences 13 and above'), + /* translators: Content suitability rating: http://bit.ly/89QxZA */ + 'R' => __('R — Intended for adult audiences above 17'), + /* translators: Content suitability rating: http://bit.ly/89QxZA */ + 'X' => __('X — Even more mature than above') +); +foreach ($ratings as $key => $rating) : + $selected = (get_option('avatar_rating') == $key) ? 'checked="checked"' : ''; + echo "\n\t
    "; +endforeach; +?> + +
    + +
    + + __('Mystery Man'), + 'blank' => __('Blank'), + 'gravatar_default' => __('Gravatar Logo'), + 'identicon' => __('Identicon (Generated)'), + 'wavatar' => __('Wavatar (Generated)'), + 'monsterid' => __('MonsterID (Generated)'), + 'retro' => __('Retro (Generated)') +); +/** + * Filter the default avatars. + * + * Avatars are stored in key/value pairs, where the key is option value, + * and the name is the displayed avatar name. + * + * @since 2.6.0 + * + * @param array $avatar_defaults Array of default avatars. + */ +$avatar_defaults = apply_filters( 'avatar_defaults', $avatar_defaults ); +$default = get_option('avatar_default'); +if ( empty($default) ) + $default = 'mystery'; +$size = 32; +$avatar_list = ''; +foreach ( $avatar_defaults as $default_key => $default_name ) { + $selected = ($default == $default_key) ? 'checked="checked" ' : ''; + $avatar_list .= "\n\t'; + $avatar_list .= '
    '; +} +/** + * Filter the HTML output of the default avatar list. + * + * @since 2.6.0 + * + * @param string $avatar_list HTML markup of the avatar list. + */ +echo apply_filters( 'default_avatar_select', $avatar_list ); +?> + +
    + + + + +
    +
    + + diff --git a/sources/wp-admin/options-general.php b/sources/wp-admin/options-general.php new file mode 100644 index 0000000..5f2bf21 --- /dev/null +++ b/sources/wp-admin/options-general.php @@ -0,0 +1,330 @@ + + +' . __('The fields on this screen determine some of the basics of your site setup.') . '

    ' . + '

    ' . __('Most themes display the site title at the top of every page, in the title bar of the browser, and as the identifying name for syndicated feeds. The tagline is also displayed by many themes.') . '

    '; + +if ( ! is_multisite() ) { + $options_help .= '

    ' . __('The WordPress URL and the Site URL can be the same (example.com) or different; for example, having the WordPress core files (example.com/wordpress) in a subdirectory instead of the root directory.') . '

    ' . + '

    ' . __('If you want site visitors to be able to register themselves, as opposed to by the site administrator, check the membership box. A default user role can be set for all new users, whether self-registered or registered by the site admin.') . '

    '; +} + +$options_help .= '

    ' . __('UTC means Coordinated Universal Time.') . '

    ' . + '

    ' . __( 'You must click the Save Changes button at the bottom of the screen for new settings to take effect.' ) . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $options_help, +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on General Settings') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +include( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
    + +

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    class="regular-text code" />
    class="regular-text code" /> +

    to be different from the directory you installed WordPress.'); ?>

    +

    +
    + +
    +

    The new address will not become active until confirmed.') ?>

    + +
    +

    %1$s. Cancel'), esc_html( $new_admin_email ), esc_url( admin_url( 'options.php?dismiss=new_admin_email' ) ) ); ?>

    +
    + +
    + + + + UTC time is %s'), date_i18n($timezone_format, false, 'gmt')); ?> + + %1$s'), date_i18n($timezone_format)); ?> + +

    + +
    + + +
    + $right_now ) { + $found = true; + break; + } + } + + if ( $found ) { + echo ' '; + $message = $tr['isdst'] ? + __('Daylight saving time begins on: %s.') : + __('Standard time begins on: %s.'); + // Add the difference between the current offset and the new offset to ts to get the correct transition time from date_i18n(). + printf( $message, date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $tr['ts'] + ($tz_offset - $tr['offset']) ) ); + } else { + _e('This timezone does not observe daylight saving time.'); + } + } + // Set back to UTC. + date_default_timezone_set('UTC'); + ?> +
    + +
    +
    + ' . date_i18n( $format ) . "
    \n"; + } + + echo ' ' . date_i18n( get_option('date_format') ) . " \n"; + + echo "\t

    " . __('Documentation on date and time formatting.') . "

    \n"; +?> +
    +
    +
    + ' . date_i18n( $format ) . "
    \n"; + } + + echo ' ' . date_i18n( get_option('time_format') ) . " \n"; + ; +?> +
    +
    + +
    + + + + +
    + +
    + + diff --git a/sources/wp-admin/options-head.php b/sources/wp-admin/options-head.php new file mode 100644 index 0000000..1c706c8 --- /dev/null +++ b/sources/wp-admin/options-head.php @@ -0,0 +1,18 @@ +' . __('You can set maximum sizes for images inserted into your written content; you can also insert an image as Full Size.') . '

    '; + +if ( ! is_multisite() && ( get_option('upload_url_path') || ( get_option('upload_path') != 'wp-content/uploads' && get_option('upload_path') ) ) ) { + $media_options_help .= '

    ' . __('Uploading Files allows you to choose the folder and path for storing your uploaded files.') . '

    '; +} + +$media_options_help .= '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $media_options_help, +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Media Settings') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +include( ABSPATH . 'wp-admin/admin-header.php' ); + +?> + +
    + +

    + +
    + + +

    +

    + + + + + + + + + + + + + + + + + + +
    + + + +
    +/> + +
    + + + + +
    + + + + +
    + + +

    + + +
    + + + +

    + + + + + + + + + + + + + + + + + +
    +

    wp-content/uploads'); ?>

    +
    +

    +
    + +
    + + + + + + +
    + +
    + + diff --git a/sources/wp-admin/options-permalink.php b/sources/wp-admin/options-permalink.php new file mode 100644 index 0000000..738a0c3 --- /dev/null +++ b/sources/wp-admin/options-permalink.php @@ -0,0 +1,289 @@ +add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

    ' . __('Permalinks are the permanent URLs to your individual pages and blog posts, as well as your category and tag archives. A permalink is the web address used to link to your content. The URL to each post should be permanent, and never change — hence the name permalink.') . '

    ' . + '

    ' . __('This screen allows you to choose your default permalink structure. You can choose from common settings or create custom URL structures.') . '

    ' . + '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    ', +) ); + +get_current_screen()->add_help_tab( array( + 'id' => 'common-settings', + 'title' => __('Common Settings'), + 'content' => '

    ' . __('Many people choose to use “pretty permalinks,” URLs that contain useful information such as the post title rather than generic post ID numbers. You can choose from any of the permalink formats under Common Settings, or can craft your own if you select Custom Structure.') . '

    ' . + '

    ' . __('If you pick an option other than Default, your general URL path with structure tags, terms surrounded by %, will also appear in the custom structure field and your path can be further modified there.') . '

    ' . + '

    ' . __('When you assign multiple categories or tags to a post, only one can show up in the permalink: the lowest numbered category. This applies if your custom structure includes %category% or %tag%.') . '

    ' . + '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    ', +) ); + +get_current_screen()->add_help_tab( array( + 'id' => 'custom-structures', + 'title' => __('Custom Structures'), + 'content' => '

    ' . __('The Optional fields let you customize the “category” and “tag” base names that will appear in archive URLs. For example, the page listing all posts in the “Uncategorized” category could be /topics/uncategorized instead of /category/uncategorized.') . '

    ' . + '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    ', +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Permalinks Settings') . '

    ' . + '

    ' . __('Documentation on Using Permalinks') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +/** + * Display JavaScript on the page. + * + * @since 3.5.0 + */ +function options_permalink_add_js() { + ?> + +set_permalink_structure( $permalink_structure ); + } + + if ( isset( $_POST['category_base'] ) ) { + $category_base = $_POST['category_base']; + if ( ! empty( $category_base ) ) + $category_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace( '#', '', $category_base ) ); + $wp_rewrite->set_category_base( $category_base ); + } + + if ( isset( $_POST['tag_base'] ) ) { + $tag_base = $_POST['tag_base']; + if ( ! empty( $tag_base ) ) + $tag_base = $blog_prefix . preg_replace('#/+#', '/', '/' . str_replace( '#', '', $tag_base ) ); + $wp_rewrite->set_tag_base( $tag_base ); + } + + wp_redirect( admin_url( 'options-permalink.php?settings-updated=true' ) ); + exit; +} + +$permalink_structure = get_option('permalink_structure'); +$category_base = get_option('category_base'); +$tag_base = get_option( 'tag_base' ); + +if ( $iis7_permalinks ) { + if ( ( ! file_exists($home_path . 'web.config') && win_is_writable($home_path) ) || win_is_writable($home_path . 'web.config') ) + $writable = true; + else + $writable = false; +} elseif ( $is_nginx ) { + $writable = false; +} else { + if ( ( ! file_exists($home_path . '.htaccess') && is_writable($home_path) ) || is_writable($home_path . '.htaccess') ) + $writable = true; + else + $writable = false; +} + +if ( $wp_rewrite->using_index_permalinks() ) + $usingpi = true; +else + $usingpi = false; + +flush_rewrite_rules(); + +require( ABSPATH . 'wp-admin/admin-header.php' ); + +if ( ! empty( $_GET['settings-updated'] ) ) : ?> +

    +

    + + +
    + +

    + +
    + + +

    URLs which have question marks and lots of numbers in them; however, WordPress offers you the ability to create a custom URL structure for your permalinks and archives. This can improve the aesthetics, usability, and forward-compatibility of your links. A number of tags are available, and here are some examples to get you started.'); ?>

    + + '', + 1 => $prefix . '/%year%/%monthnum%/%day%/%postname%/', + 2 => $prefix . '/%year%/%monthnum%/%postname%/', + 3 => $prefix . '/' . _x( 'archives', 'sample permalink base' ) . '/%post_id%', + 4 => $prefix . '/%postname%/', +); +?> +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + +

    URLs here. For example, using topics as your category base would make your category links like http://example.org/%stopics/uncategorized/. If you leave these blank the defaults will be used.'), $suffix ); ?>

    + + + + + + + + + + + +
    + + + + +
    + + +

    web.config file were writable, we could do this automatically, but it isn’t so this is the url rewrite rule you should have in your web.config file. Click in the field and press CTRL + a to select all. Then insert this rule inside of the /<configuration>/<system.webServer>/<rewrite>/<rules> element in web.config file.') ?>

    +
    + +

    +
    +

    web.config file writable for us to generate rewrite rules automatically, do not forget to revert the permissions after rule has been saved.') ?>

    + +

    writable, we could do this automatically, but it isn’t so this is the url rewrite rule you should have in your web.config file. Create a new file, called web.config in the root directory of your site. Click in the field and press CTRL + a to select all. Then insert this code into the web.config file.') ?>

    +
    + +

    +
    +

    web.config file automatically, do not forget to revert the permissions after the file has been created.') ?>

    + + + +

    .htaccess file were writable, we could do this automatically, but it isn’t so these are the mod_rewrite rules you should have in your .htaccess file. Click in the field and press CTRL + a to select all.') ?>

    +
    + +

    +
    + + + + +
    + + diff --git a/sources/wp-admin/options-reading.php b/sources/wp-admin/options-reading.php new file mode 100644 index 0000000..e928b2e --- /dev/null +++ b/sources/wp-admin/options-reading.php @@ -0,0 +1,185 @@ + + +'; + echo '

    ' . __( 'The character encoding of your site (UTF-8 is recommended)' ) . '

    '; +} + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

    ' . __('This screen contains the settings that affect the display of your content.') . '

    ' . + '

    ' . sprintf(__('You can choose what’s displayed on the front page of your site. It can be posts in reverse chronological order (classic blog), or a fixed/static page. To set a static home page, you first need to create two Pages. One will become the front page, and the other will be where your posts are displayed.'), 'post-new.php?post_type=page') . '

    ' . + '

    ' . __('You can also control the display of your content in RSS feeds, including the maximum numbers of posts to display and whether to show full text or a summary.') . '

    ' . + '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    ', +) ); + +get_current_screen()->add_help_tab( array( + 'id' => 'site-visibility', + 'title' => has_action( 'blog_privacy_selector' ) ? __( 'Site Visibility' ) : __( 'Search Engine Visibility' ), + 'content' => '

    ' . __( 'You can choose whether or not your site will be crawled by robots, ping services, and spiders. If you want those services to ignore your site, click the checkbox next to “Discourage search engines from indexing this site” and click the Save Changes button at the bottom of the screen. Note that your privacy is not complete; your site is still visible on the web.' ) . '

    ' . + '

    ' . __( 'When this setting is in effect, a reminder is shown in the Right Now box of the Dashboard that says, “Search Engines Discouraged,” to remind you that your site is not being crawled.' ) . '

    ', +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Reading Settings') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +include( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
    + +

    + +
    + 'blog_charset' ) ); +?> + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    +

    +

    +

    +
      +
    • +
    • +
    + +

    Warning: these pages should not be the same!' ); ?>

    + +
    + +
    +


    +

    +
    + + /> +
    + /> + +

    + + + +

    + +
    + + + + +
    +
    + diff --git a/sources/wp-admin/options-writing.php b/sources/wp-admin/options-writing.php new file mode 100644 index 0000000..cad326a --- /dev/null +++ b/sources/wp-admin/options-writing.php @@ -0,0 +1,195 @@ +add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

    ' . __('You can submit content in several different ways; this screen holds the settings for all of them. The top section controls the editor within the dashboard, while the rest control external publishing methods. For more information on any of these methods, use the documentation links.') . '

    ' . + '

    ' . __('You must click the Save Changes button at the bottom of the screen for new settings to take effect.') . '

    ', +) ); + +get_current_screen()->add_help_tab( array( + 'id' => 'options-press', + 'title' => __('Press This'), + 'content' => '

    ' . __('Press This is a bookmarklet that makes it easy to blog about something you come across on the web. You can use it to just grab a link, or to post an excerpt. Press This will even allow you to choose from images included on the page and use them in your post. Just drag the Press This link on this screen to your bookmarks bar in your browser, and you’ll be on your way to easier content creation. Clicking on it while on another website opens a popup window with all these options.') . '

    ', +) ); + +/** This filter is documented in wp-admin/options.php */ +if ( apply_filters( 'enable_post_by_email_configuration', true ) ) { + get_current_screen()->add_help_tab( array( + 'id' => 'options-postemail', + 'title' => __( 'Post Via Email' ), + 'content' => '

    ' . __( 'Post via email settings allow you to send your WordPress install an email with the content of your post. You must set up a secret e-mail account with POP3 access to use this, and any mail received at this address will be posted, so it’s a good idea to keep this address very secret.' ) . '

    ', + ) ); +} + +/** +* Toggle site update services configuration functionality. +* +* @since 3.0.0 +* +* @param bool True or false, based on whether update services configuration is enabled or not. +*/ +if ( apply_filters( 'enable_update_services_configuration', true ) ) { + get_current_screen()->add_help_tab( array( + 'id' => 'options-services', + 'title' => __( 'Update Services' ), + 'content' => '

    ' . __( 'If desired, WordPress will automatically alert various services of your new posts.' ) . '

    ', + ) ); +} + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Writing Settings') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +include( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
    + +

    + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    + 0, 'name' => 'default_category', 'orderby' => 'name', 'selected' => get_option('default_category'), 'hierarchical' => true)); +?> +
    + +
    + 0, 'name' => 'default_link_category', 'orderby' => 'name', 'selected' => get_option('default_link_category'), 'hierarchical' => true, 'taxonomy' => 'link_category')); +?> +
    + +

    +

    +

    +

    +

    + + + +

    +

    %s, %s, %s.'), wp_generate_password(8, false), wp_generate_password(8, false), wp_generate_password(8, false)) ?>

    + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    + 0, 'name' => 'default_email_category', 'orderby' => 'name', 'selected' => get_option('default_email_category'), 'hierarchical' => true)); +?> +
    + + + +

    + + + +

    + + + + + +

    Update Services because of your site’s visibility settings.'), 'options-reading.php'); ?>

    + + + + + + + +
    +
    + + diff --git a/sources/wp-admin/options.php b/sources/wp-admin/options.php new file mode 100644 index 0000000..00fb3c0 --- /dev/null +++ b/sources/wp-admin/options.php @@ -0,0 +1,256 @@ + array( 'blogname', 'blogdescription', 'gmt_offset', 'date_format', 'time_format', 'start_of_week', 'timezone_string' ), + 'discussion' => array( 'default_pingback_flag', 'default_ping_status', 'default_comment_status', 'comments_notify', 'moderation_notify', 'comment_moderation', 'require_name_email', 'comment_whitelist', 'comment_max_links', 'moderation_keys', 'blacklist_keys', 'show_avatars', 'avatar_rating', 'avatar_default', 'close_comments_for_old_posts', 'close_comments_days_old', 'thread_comments', 'thread_comments_depth', 'page_comments', 'comments_per_page', 'default_comments_page', 'comment_order', 'comment_registration' ), + 'media' => array( 'thumbnail_size_w', 'thumbnail_size_h', 'thumbnail_crop', 'medium_size_w', 'medium_size_h', 'large_size_w', 'large_size_h', 'image_default_size', 'image_default_align', 'image_default_link_type' ), + 'reading' => array( 'posts_per_page', 'posts_per_rss', 'rss_use_excerpt', 'show_on_front', 'page_on_front', 'page_for_posts', 'blog_public' ), + 'writing' => array( 'use_smilies', 'default_category', 'default_email_category', 'use_balanceTags', 'default_link_category', 'default_post_format' ) +); +$whitelist_options['misc'] = $whitelist_options['options'] = $whitelist_options['privacy'] = array(); + +$mail_options = array('mailserver_url', 'mailserver_port', 'mailserver_login', 'mailserver_pass'); + +if ( ! in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) + $whitelist_options['reading'][] = 'blog_charset'; + +if ( !is_multisite() ) { + if ( !defined( 'WP_SITEURL' ) ) + $whitelist_options['general'][] = 'siteurl'; + if ( !defined( 'WP_HOME' ) ) + $whitelist_options['general'][] = 'home'; + + $whitelist_options['general'][] = 'admin_email'; + $whitelist_options['general'][] = 'users_can_register'; + $whitelist_options['general'][] = 'default_role'; + + $whitelist_options['writing'] = array_merge($whitelist_options['writing'], $mail_options); + $whitelist_options['writing'][] = 'ping_sites'; + + $whitelist_options['media'][] = 'uploads_use_yearmonth_folders'; + + // If upload_url_path and upload_path are both default values, they're locked. + if ( get_option( 'upload_url_path' ) || ( get_option('upload_path') != 'wp-content/uploads' && get_option('upload_path') ) ) { + $whitelist_options['media'][] = 'upload_path'; + $whitelist_options['media'][] = 'upload_url_path'; + } +} else { + $whitelist_options['general'][] = 'new_admin_email'; + $whitelist_options['general'][] = 'WPLANG'; + + /** + * Toggle post-by-email functionality. + * + * @since 3.0.0 + * + * @param bool True or false, based on whether post-by-email configuration is enabled or not. + */ + if ( apply_filters( 'enable_post_by_email_configuration', true ) ) + $whitelist_options['writing'] = array_merge($whitelist_options['writing'], $mail_options); +} + +/** + * Filter the options white list. + * + * @since 2.7.0 + * + * @param array White list options. + */ +$whitelist_options = apply_filters( 'whitelist_options', $whitelist_options ); + +/* + * If $_GET['action'] == 'update' we are saving settings sent from a settings page + */ +if ( 'update' == $action ) { + if ( 'options' == $option_page && !isset( $_POST['option_page'] ) ) { // This is for back compat and will eventually be removed. + $unregistered = true; + check_admin_referer( 'update-options' ); + } else { + $unregistered = false; + check_admin_referer( $option_page . '-options' ); + } + + if ( !isset( $whitelist_options[ $option_page ] ) ) + wp_die( __( 'ERROR: options page not found.' ) ); + + if ( 'options' == $option_page ) { + if ( is_multisite() && ! is_super_admin() ) + wp_die( __( 'You do not have sufficient permissions to modify unregistered settings for this site.' ) ); + $options = explode( ',', wp_unslash( $_POST[ 'page_options' ] ) ); + } else { + $options = $whitelist_options[ $option_page ]; + } + + // Handle custom date/time formats + if ( 'general' == $option_page ) { + if ( !empty($_POST['date_format']) && isset($_POST['date_format_custom']) && '\c\u\s\t\o\m' == wp_unslash( $_POST['date_format'] ) ) + $_POST['date_format'] = $_POST['date_format_custom']; + if ( !empty($_POST['time_format']) && isset($_POST['time_format_custom']) && '\c\u\s\t\o\m' == wp_unslash( $_POST['time_format'] ) ) + $_POST['time_format'] = $_POST['time_format_custom']; + // Map UTC+- timezones to gmt_offsets and set timezone_string to empty. + if ( !empty($_POST['timezone_string']) && preg_match('/^UTC[+-]/', $_POST['timezone_string']) ) { + $_POST['gmt_offset'] = $_POST['timezone_string']; + $_POST['gmt_offset'] = preg_replace('/UTC\+?/', '', $_POST['gmt_offset']); + $_POST['timezone_string'] = ''; + } + } + + if ( $options ) { + foreach ( $options as $option ) { + if ( $unregistered ) + _deprecated_argument( 'options.php', '2.7', sprintf( __( 'The %1$s setting is unregistered. Unregistered settings are deprecated. See http://codex.wordpress.org/Settings_API' ), $option, $option_page ) ); + + $option = trim( $option ); + $value = null; + if ( isset( $_POST[ $option ] ) ) { + $value = $_POST[ $option ]; + if ( ! is_array( $value ) ) + $value = trim( $value ); + $value = wp_unslash( $value ); + } + update_option( $option, $value ); + } + } + + /** + * Handle settings errors and return to options page + */ + // If no settings errors were registered add a general 'updated' message. + if ( !count( get_settings_errors() ) ) + add_settings_error('general', 'settings_updated', __('Settings saved.'), 'updated'); + set_transient('settings_errors', get_settings_errors(), 30); + + /** + * Redirect back to the settings page that was submitted + */ + $goback = add_query_arg( 'settings-updated', 'true', wp_get_referer() ); + wp_redirect( $goback ); + exit; +} + +include( ABSPATH . 'wp-admin/admin-header.php' ); ?> + +
    + +

    +
    + + + + +get_results( "SELECT * FROM $wpdb->options ORDER BY option_name" ); + +foreach ( (array) $options as $option ) : + $disabled = false; + if ( $option->option_name == '' ) + continue; + if ( is_serialized( $option->option_value ) ) { + if ( is_serialized_string( $option->option_value ) ) { + // this is a serialized string, so we should display it + $value = maybe_unserialize( $option->option_value ); + $options_to_update[] = $option->option_name; + $class = 'all-options'; + } else { + $value = 'SERIALIZED DATA'; + $disabled = true; + $class = 'all-options disabled'; + } + } else { + $value = $option->option_value; + $options_to_update[] = $option->option_name; + $class = 'all-options'; + } + $name = esc_attr( $option->option_name ); + echo " + + + +"; +endforeach; +?> +
    "; + if ( strpos( $value, "\n" ) !== false ) + echo ""; + else + echo ""; + echo "
    + + + + + +
    +
    + + time() ) + (array) get_option( 'recently_activated' ) ); + + wp_redirect(add_query_arg('_wpnonce', wp_create_nonce('edit-plugin-test_' . $file), "plugin-editor.php?file=$file&liveupdate=1&scrollto=$scrollto&networkwide=" . $network_wide)); + exit; + } + wp_redirect( self_admin_url("plugin-editor.php?file=$file&a=te&scrollto=$scrollto") ); + } else { + wp_redirect( self_admin_url("plugin-editor.php?file=$file&scrollto=$scrollto") ); + } + exit; + +break; + +default: + + if ( isset($_GET['liveupdate']) ) { + check_admin_referer('edit-plugin-test_' . $file); + + $error = validate_plugin($file); + if ( is_wp_error($error) ) + wp_die( $error ); + + if ( ( ! empty( $_GET['networkwide'] ) && ! is_plugin_active_for_network($file) ) || ! is_plugin_active($file) ) + activate_plugin($file, "plugin-editor.php?file=$file&phperror=1", ! empty( $_GET['networkwide'] ) ); // we'll override this later if the plugin can be included without fatal error + + wp_redirect( self_admin_url("plugin-editor.php?file=$file&a=te&scrollto=$scrollto") ); + exit; + } + + // List of allowable extensions + $editable_extensions = array('php', 'txt', 'text', 'js', 'css', 'html', 'htm', 'xml', 'inc', 'include'); + + /** + * Filter file type extensions editable in the plugin editor. + * + * @since 2.8.0 + * + * @param array $editable_extensions An array of editable plugin file extensions. + */ + $editable_extensions = (array) apply_filters( 'editable_extensions', $editable_extensions ); + + if ( ! is_file($real_file) ) { + wp_die(sprintf('

    %s

    ', __('No such file exists! Double check the name and try again.'))); + } else { + // Get the extension of the file + if ( preg_match('/\.([^.]+)$/', $real_file, $matches) ) { + $ext = strtolower($matches[1]); + // If extension is not in the acceptable list, skip it + if ( !in_array( $ext, $editable_extensions) ) + wp_die(sprintf('

    %s

    ', __('Files of this type are not editable.'))); + } + } + + get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => + '

    ' . __('You can use the editor to make changes to any of your plugins’ individual PHP files. Be aware that if you make changes, plugins updates will overwrite your customizations.') . '

    ' . + '

    ' . __('Choose a plugin to edit from the menu in the upper right and click the Select button. Click once on any file name to load it in the editor, and make your changes. Don’t forget to save your changes (Update File) when you’re finished.') . '

    ' . + '

    ' . __('The Documentation menu below the editor lists the PHP functions recognized in the plugin file. Clicking Look Up takes you to a web page about that particular function.') . '

    ' . + '

    ' . __('In the editing area the Tab key enters a tab character. To move below this area by pressing Tab, press the Esc key followed by the Tab key.') . '

    ' . + '

    ' . __('If you want to make changes but don’t want them to be overwritten when the plugin is updated, you may be ready to think about writing your own plugin. For information on how to edit plugins, write your own from scratch, or just better understand their anatomy, check out the links below.') . '

    ' . + ( is_network_admin() ? '

    ' . __('Any edits to files from this screen will be reflected on all sites in the network.') . '

    ' : '' ) + ) ); + + get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Editing Plugins') . '

    ' . + '

    ' . __('Documentation on Writing Plugins') . '

    ' . + '

    ' . __('Support Forums') . '

    ' + ); + + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + update_recently_edited(WP_PLUGIN_DIR . '/' . $file); + + $content = file_get_contents( $real_file ); + + if ( '.php' == substr( $real_file, strrpos( $real_file, '.' ) ) ) { + $functions = wp_doc_link_parse( $content ); + + if ( !empty($functions) ) { + $docs_select = ''; + } + } + + $content = esc_textarea( $content ); + ?> + +

    + +

    fatal error.') ?>

    + + + +
    + +
    + +

    + +
    +
    +%s (active)'), $file); + else + echo sprintf(__('Browsing %s (active)'), $file); + } else { + if ( is_writeable($real_file) ) + echo sprintf(__('Editing %s (inactive)'), $file); + else + echo sprintf(__('Browsing %s (inactive)'), $file); + } + ?> +
    +
    +
    + + + +
    +
    +
    +
    + +
    +

    + +
      + + > + +
    +
    +
    + +
    + + + + +
    + +
    + + + +

    Warning: Making changes to active plugins is not recommended. If your changes cause a fatal error, the plugin will be automatically deactivated.'); ?>

    + +

    + "; + submit_button( __( 'Update File and Attempt to Reactivate' ), 'primary', 'submit', false ); + } else { + submit_button( __( 'Update File' ), 'primary', 'submit', false ); + } + ?> +

    + +

    the Codex for more information.'); ?>

    + +
    +
    +
    + +get_pagenum(); +$wp_list_table->prepare_items(); + +$title = __('Install Plugins'); +$parent_file = 'plugins.php'; + +wp_enqueue_script( 'plugin-install' ); +if ( 'plugin-information' != $tab ) + add_thickbox(); + +$body_id = $tab; + +/** + * Fires before each tab on the Install Plugins screen is loaded. + * + * The dynamic portion of the action hook, $tab, allows for targeting + * individual tabs, for instance 'install_plugins_pre_plugin-information'. + * + * @since 2.7.0 + */ +do_action( "install_plugins_pre_$tab" ); + +get_current_screen()->add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

    ' . sprintf(__('Plugins hook into WordPress to extend its functionality with custom features. Plugins are developed independently from the core WordPress application by thousands of developers all over the world. All plugins in the official WordPress.org Plugin Directory are compatible with the license WordPress uses. You can find new plugins to install by searching or browsing the Directory right here in your own Plugins section.'), 'http://wordpress.org/plugins/') . '

    ' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'adding-plugins', +'title' => __('Adding Plugins'), +'content' => + '

    ' . __('If you know what you’re looking for, Search is your best bet. The Search screen has options to search the WordPress.org Plugin Directory for a particular Term, Author, or Tag. You can also search the directory by selecting popular tags. Tags in larger type mean more plugins have been labeled with that tag.') . '

    ' . + '

    ' . __('If you just want to get an idea of what’s available, you can browse Featured, Popular, and Newest plugins by using the links in the upper left of the screen. These sections rotate regularly.') . '

    ' . + '

    ' . __('You can also browse a user’s favorite plugins, by using the Favorites link in the upper left of the screen and entering their WordPress.org username.') . '

    ' . + '

    ' . __('If you want to install a plugin that you’ve downloaded elsewhere, click the Upload link in the upper left. You will be prompted to upload the .zip package, and once uploaded, you can activate the new plugin.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Installing Plugins') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +/** + * WordPress Administration Template Header. + */ +include(ABSPATH . 'wp-admin/admin-header.php'); +?> +
    + +

    + +views(); ?> + +
    + + +
    +get_pagenum(); + +$action = $wp_list_table->current_action(); + +$plugin = isset($_REQUEST['plugin']) ? $_REQUEST['plugin'] : ''; +$s = isset($_REQUEST['s']) ? urlencode($_REQUEST['s']) : ''; + +// Clean up request URI from temporary args for screen options/paging uri's to work as expected. +$_SERVER['REQUEST_URI'] = remove_query_arg(array('error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce'), $_SERVER['REQUEST_URI']); + +if ( $action ) { + + switch ( $action ) { + case 'activate': + if ( ! current_user_can('activate_plugins') ) + wp_die(__('You do not have sufficient permissions to activate plugins for this site.')); + + if ( is_multisite() && ! is_network_admin() && is_network_only_plugin( $plugin ) ) { + wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") ); + exit; + } + + check_admin_referer('activate-plugin_' . $plugin); + + $result = activate_plugin($plugin, self_admin_url('plugins.php?error=true&plugin=' . $plugin), is_network_admin() ); + if ( is_wp_error( $result ) ) { + if ( 'unexpected_output' == $result->get_error_code() ) { + $redirect = self_admin_url('plugins.php?error=true&charsout=' . strlen($result->get_error_data()) . '&plugin=' . $plugin . "&plugin_status=$status&paged=$page&s=$s"); + wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect)); + exit; + } else { + wp_die($result); + } + } + + if ( ! is_network_admin() ) { + $recent = (array) get_option( 'recently_activated' ); + unset( $recent[ $plugin ] ); + update_option( 'recently_activated', $recent ); + } + + if ( isset($_GET['from']) && 'import' == $_GET['from'] ) { + wp_redirect( self_admin_url("import.php?import=" . str_replace('-importer', '', dirname($plugin))) ); // overrides the ?error=true one above and redirects to the Imports page, stripping the -importer suffix + } else { + wp_redirect( self_admin_url("plugins.php?activate=true&plugin_status=$status&paged=$page&s=$s") ); // overrides the ?error=true one above + } + exit; + break; + case 'activate-selected': + if ( ! current_user_can('activate_plugins') ) + wp_die(__('You do not have sufficient permissions to activate plugins for this site.')); + + check_admin_referer('bulk-plugins'); + + $plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array(); + + // Only activate plugins which are not already active. + if ( is_network_admin() ) { + foreach ( $plugins as $i => $plugin ) { + if ( is_plugin_active_for_network( $plugin ) ) + unset( $plugins[ $i ] ); + } + } else { + foreach ( $plugins as $i => $plugin ) { + if ( is_plugin_active( $plugin ) || is_network_only_plugin( $plugin ) ) + unset( $plugins[ $i ] ); + } + } + + if ( empty($plugins) ) { + wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") ); + exit; + } + + activate_plugins($plugins, self_admin_url('plugins.php?error=true'), is_network_admin() ); + + if ( ! is_network_admin() ) { + $recent = (array) get_option('recently_activated' ); + foreach ( $plugins as $plugin ) + unset( $recent[ $plugin ] ); + update_option( 'recently_activated', $recent ); + } + + wp_redirect( self_admin_url("plugins.php?activate-multi=true&plugin_status=$status&paged=$page&s=$s") ); + exit; + break; + case 'update-selected' : + + check_admin_referer( 'bulk-plugins' ); + + if ( isset( $_GET['plugins'] ) ) + $plugins = explode( ',', $_GET['plugins'] ); + elseif ( isset( $_POST['checked'] ) ) + $plugins = (array) $_POST['checked']; + else + $plugins = array(); + + $title = __( 'Update Plugins' ); + $parent_file = 'plugins.php'; + + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + echo '
    '; + screen_icon(); + echo '

    ' . esc_html( $title ) . '

    '; + + $url = self_admin_url('update.php?action=update-selected&plugins=' . urlencode( join(',', $plugins) )); + $url = wp_nonce_url($url, 'bulk-update-plugins'); + + echo ""; + echo '
    '; + require_once(ABSPATH . 'wp-admin/admin-footer.php'); + exit; + break; + case 'error_scrape': + if ( ! current_user_can('activate_plugins') ) + wp_die(__('You do not have sufficient permissions to activate plugins for this site.')); + + check_admin_referer('plugin-activation-error_' . $plugin); + + $valid = validate_plugin($plugin); + if ( is_wp_error($valid) ) + wp_die($valid); + + if ( ! WP_DEBUG ) { + error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR ); + } + + @ini_set('display_errors', true); //Ensure that Fatal errors are displayed. + // Go back to "sandbox" scope so we get the same errors as before + function plugin_sandbox_scrape( $plugin ) { + include( WP_PLUGIN_DIR . '/' . $plugin ); + } + plugin_sandbox_scrape( $plugin ); + do_action('activate_' . $plugin); + exit; + break; + case 'deactivate': + if ( ! current_user_can('activate_plugins') ) + wp_die(__('You do not have sufficient permissions to deactivate plugins for this site.')); + + check_admin_referer('deactivate-plugin_' . $plugin); + + if ( ! is_network_admin() && is_plugin_active_for_network( $plugin ) ) { + wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") ); + exit; + } + + deactivate_plugins( $plugin, false, is_network_admin() ); + if ( ! is_network_admin() ) + update_option( 'recently_activated', array( $plugin => time() ) + (array) get_option( 'recently_activated' ) ); + if ( headers_sent() ) + echo ""; + else + wp_redirect( self_admin_url("plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s") ); + exit; + break; + case 'deactivate-selected': + if ( ! current_user_can('activate_plugins') ) + wp_die(__('You do not have sufficient permissions to deactivate plugins for this site.')); + + check_admin_referer('bulk-plugins'); + + $plugins = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array(); + // Do not deactivate plugins which are already deactivated. + if ( is_network_admin() ) { + $plugins = array_filter( $plugins, 'is_plugin_active_for_network' ); + } else { + $plugins = array_filter( $plugins, 'is_plugin_active' ); + $plugins = array_diff( $plugins, array_filter( $plugins, 'is_plugin_active_for_network' ) ); + } + if ( empty($plugins) ) { + wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") ); + exit; + } + + deactivate_plugins( $plugins, false, is_network_admin() ); + + if ( ! is_network_admin() ) { + $deactivated = array(); + foreach ( $plugins as $plugin ) + $deactivated[ $plugin ] = time(); + update_option( 'recently_activated', $deactivated + (array) get_option( 'recently_activated' ) ); + } + + wp_redirect( self_admin_url("plugins.php?deactivate-multi=true&plugin_status=$status&paged=$page&s=$s") ); + exit; + break; + case 'delete-selected': + if ( ! current_user_can('delete_plugins') ) + wp_die(__('You do not have sufficient permissions to delete plugins for this site.')); + + check_admin_referer('bulk-plugins'); + + //$_POST = from the plugin form; $_GET = from the FTP details screen. + $plugins = isset( $_REQUEST['checked'] ) ? (array) $_REQUEST['checked'] : array(); + if ( empty( $plugins ) ) { + wp_redirect( self_admin_url("plugins.php?plugin_status=$status&paged=$page&s=$s") ); + exit; + } + + $plugins = array_filter($plugins, 'is_plugin_inactive'); // Do not allow to delete Activated plugins. + if ( empty( $plugins ) ) { + wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) ); + exit; + } + + include(ABSPATH . 'wp-admin/update.php'); + + $parent_file = 'plugins.php'; + + if ( ! isset($_REQUEST['verify-delete']) ) { + wp_enqueue_script('jquery'); + require_once(ABSPATH . 'wp-admin/admin-header.php'); + ?> +
    + $data ) { + $plugin_info[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $data ); + $plugin_info[ $plugin_file ]['is_uninstallable'] = is_uninstallable_plugin( $plugin ); + if ( ! $plugin_info[ $plugin_file ]['Network'] ) + $have_non_network_plugins = true; + } + } + } + } + screen_icon(); + $plugins_to_delete = count( $plugin_info ); + echo '

    ' . _n( 'Delete Plugin', 'Delete Plugins', $plugins_to_delete ) . '

    '; + ?> + +

    + +

    +
      + ', sprintf( __( '%1$s by %2$s (will also delete its data)' ), esc_html($plugin['Name']), esc_html($plugin['AuthorName']) ), ''; + $data_to_delete = true; + } else { + /* translators: 1: plugin name, 2: plugin author */ + echo '
    • ', sprintf( __('%1$s by %2$s' ), esc_html($plugin['Name']), esc_html($plugin['AuthorName']) ), '
    • '; + } + } + ?> +
    +

    +
    + + + '; + ?> + + +
    +
    + +
    + +

    + +
    + prepare_items(); + +wp_enqueue_script('plugin-install'); +add_thickbox(); + +add_screen_option( 'per_page', array('label' => _x( 'Plugins', 'plugins per page (screen options)' ), 'default' => 999 ) ); + +get_current_screen()->add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

    ' . __('Plugins extend and expand the functionality of WordPress. Once a plugin is installed, you may activate it or deactivate it here.') . '

    ' . + '

    ' . sprintf(__('You can find additional plugins for your site by using the Plugin Browser/Installer functionality or by browsing the WordPress Plugin Directory directly and installing new plugins manually. To manually install a plugin you generally just need to upload the plugin file into your /wp-content/plugins directory. Once a plugin has been installed, you can activate it here.'), 'plugin-install.php', 'http://wordpress.org/plugins/') . '

    ' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'compatibility-problems', +'title' => __('Troubleshooting'), +'content' => + '

    ' . __('Most of the time, plugins play nicely with the core of WordPress and with other plugins. Sometimes, though, a plugin’s code will get in the way of another plugin, causing compatibility issues. If your site starts doing strange things, this may be the problem. Try deactivating all your plugins and re-activating them in various combinations until you isolate which one(s) caused the issue.') . '

    ' . + '

    ' . sprintf( __('If something goes wrong with a plugin and you can’t use WordPress, delete or rename that file in the %s directory and it will be automatically deactivated.'), WP_PLUGIN_DIR) . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Managing Plugins') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +$title = __('Plugins'); +$parent_file = 'plugins.php'; + +require_once(ABSPATH . 'wp-admin/admin-header.php'); + +$invalid = validate_active_plugins(); +if ( !empty($invalid) ) + foreach ( $invalid as $plugin_file => $error ) + echo '

    ' . sprintf(__('The plugin %s has been deactivated due to an error: %s'), esc_html($plugin_file), $error->get_error_message()) . '

    '; +?> + +unexpected output during activation. If you notice “headers already sent” messages, problems with syndication feeds or other issues, try deactivating or removing this plugin.'), $_GET['charsout']); + else + $errmsg = __('Plugin could not be activated because it triggered a fatal error.'); + ?> +

    + + + +
    + +

    get_error_message() ); ?>

    + +

    deleted.'); ?>

    + + +

    activated.') ?>

    + +

    activated.'); ?>

    + +

    deactivated.') ?>

    + +

    deactivated.'); ?>

    + +

    + + +
    + +

    + +' . __('Search results for “%s”') . '', esc_html( $s ) ); ?> +

    + + + +views(); ?> + +
    +search_box( __( 'Search Installed Plugins' ), 'plugin' ); ?> +
    + +
    + + + + +display(); ?> +
    + +
    + + true ) ) ) ) + $post_type = $_GET['post_type']; +else + wp_die( __('Invalid post type') ); + +$post_type_object = get_post_type_object( $post_type ); + +if ( 'post' == $post_type ) { + $parent_file = 'edit.php'; + $submenu_file = 'post-new.php'; +} elseif ( 'attachment' == $post_type ) { + if ( wp_redirect( admin_url( 'media-new.php' ) ) ) + exit; +} else { + $submenu_file = "post-new.php?post_type=$post_type"; + if ( isset( $post_type_object ) && $post_type_object->show_in_menu && $post_type_object->show_in_menu !== true ) { + $parent_file = $post_type_object->show_in_menu; + if ( ! isset( $_registered_pages[ get_plugin_page_hookname( "post-new.php?post_type=$post_type", $post_type_object->show_in_menu ) ] ) ) + $submenu_file = $parent_file; + } else { + $parent_file = "edit.php?post_type=$post_type"; + } +} + +$title = $post_type_object->labels->add_new_item; + +$editing = true; + +if ( ! current_user_can( $post_type_object->cap->edit_posts ) || ! current_user_can( $post_type_object->cap->create_posts ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + +// Schedule auto-draft cleanup +if ( ! wp_next_scheduled( 'wp_scheduled_auto_draft_delete' ) ) + wp_schedule_event( time(), 'daily', 'wp_scheduled_auto_draft_delete' ); + +wp_enqueue_script( 'autosave' ); + +if ( is_multisite() ) { + add_action( 'admin_footer', '_admin_notice_post_locked' ); +} else { + $check_users = get_users( array( 'fields' => 'ID', 'number' => 2 ) ); + + if ( count( $check_users ) > 1 ) + add_action( 'admin_footer', '_admin_notice_post_locked' ); + + unset( $check_users ); +} + +// Show post form. +$post = get_default_post_to_edit( $post_type, true ); +$post_ID = $post->ID; +include( ABSPATH . 'wp-admin/edit-form-advanced.php' ); +include( ABSPATH . 'wp-admin/admin-footer.php' ); diff --git a/sources/wp-admin/post.php b/sources/wp-admin/post.php new file mode 100644 index 0000000..b832004 --- /dev/null +++ b/sources/wp-admin/post.php @@ -0,0 +1,312 @@ +post_type; + $post_type_object = get_post_type_object( $post_type ); +} + +/** + * Redirect to previous page. + * + * @param int $post_id Optional. Post ID. + */ +function redirect_post($post_id = '') { + if ( isset($_POST['save']) || isset($_POST['publish']) ) { + $status = get_post_status( $post_id ); + + if ( isset( $_POST['publish'] ) ) { + switch ( $status ) { + case 'pending': + $message = 8; + break; + case 'future': + $message = 9; + break; + default: + $message = 6; + } + } else { + $message = 'draft' == $status ? 10 : 1; + } + + $location = add_query_arg( 'message', $message, get_edit_post_link( $post_id, 'url' ) ); + } elseif ( isset($_POST['addmeta']) && $_POST['addmeta'] ) { + $location = add_query_arg( 'message', 2, wp_get_referer() ); + $location = explode('#', $location); + $location = $location[0] . '#postcustom'; + } elseif ( isset($_POST['deletemeta']) && $_POST['deletemeta'] ) { + $location = add_query_arg( 'message', 3, wp_get_referer() ); + $location = explode('#', $location); + $location = $location[0] . '#postcustom'; + } elseif ( 'post-quickpress-save-cont' == $_POST['action'] ) { + $location = "post.php?action=edit&post=$post_id&message=7"; + } else { + $location = add_query_arg( 'message', 4, get_edit_post_link( $post_id, 'url' ) ); + } + + wp_redirect( apply_filters( 'redirect_post_location', $location, $post_id ) ); + exit; +} + +if ( isset( $_POST['deletepost'] ) ) + $action = 'delete'; +elseif ( isset($_POST['wp-preview']) && 'dopreview' == $_POST['wp-preview'] ) + $action = 'preview'; + +$sendback = wp_get_referer(); +if ( ! $sendback || + strpos( $sendback, 'post.php' ) !== false || + strpos( $sendback, 'post-new.php' ) !== false ) { + if ( 'attachment' == $post_type ) { + $sendback = admin_url( 'upload.php' ); + } else { + $sendback = admin_url( 'edit.php' ); + $sendback .= ( ! empty( $post_type ) ) ? '?post_type=' . $post_type : ''; + } +} else { + $sendback = remove_query_arg( array('trashed', 'untrashed', 'deleted', 'ids'), $sendback ); +} + +switch($action) { +case 'postajaxpost': +case 'post': +case 'post-quickpress-publish': +case 'post-quickpress-save': + check_admin_referer('add-' . $post_type); + + if ( 'post-quickpress-publish' == $action ) + $_POST['publish'] = 'publish'; // tell write_post() to publish + + if ( 'post-quickpress-publish' == $action || 'post-quickpress-save' == $action ) { + $_POST['comment_status'] = get_option('default_comment_status'); + $_POST['ping_status'] = get_option('default_ping_status'); + $post_id = edit_post(); + } else { + $post_id = 'postajaxpost' == $action ? edit_post() : write_post(); + } + + if ( 0 === strpos( $action, 'post-quickpress' ) ) { + $_POST['post_ID'] = $post_id; + // output the quickpress dashboard widget + require_once(ABSPATH . 'wp-admin/includes/dashboard.php'); + wp_dashboard_quick_press(); + exit; + } + + redirect_post($post_id); + exit(); + break; + +case 'edit': + $editing = true; + + if ( empty( $post_id ) ) { + wp_redirect( admin_url('post.php') ); + exit(); + } + + if ( ! $post ) + wp_die( __( 'You attempted to edit an item that doesn’t exist. Perhaps it was deleted?' ) ); + + if ( ! $post_type_object ) + wp_die( __( 'Unknown post type.' ) ); + + if ( ! current_user_can( 'edit_post', $post_id ) ) + wp_die( __( 'You are not allowed to edit this item.' ) ); + + if ( 'trash' == $post->post_status ) + wp_die( __( 'You can’t edit this item because it is in the Trash. Please restore it and try again.' ) ); + + if ( ! empty( $_GET['get-post-lock'] ) ) { + wp_set_post_lock( $post_id ); + wp_redirect( get_edit_post_link( $post_id, 'url' ) ); + exit(); + } + + $post_type = $post->post_type; + if ( 'post' == $post_type ) { + $parent_file = "edit.php"; + $submenu_file = "edit.php"; + $post_new_file = "post-new.php"; + } elseif ( 'attachment' == $post_type ) { + $parent_file = 'upload.php'; + $submenu_file = 'upload.php'; + $post_new_file = 'media-new.php'; + } else { + if ( isset( $post_type_object ) && $post_type_object->show_in_menu && $post_type_object->show_in_menu !== true ) + $parent_file = $post_type_object->show_in_menu; + else + $parent_file = "edit.php?post_type=$post_type"; + $submenu_file = "edit.php?post_type=$post_type"; + $post_new_file = "post-new.php?post_type=$post_type"; + } + + if ( ! wp_check_post_lock( $post->ID ) ) { + $active_post_lock = wp_set_post_lock( $post->ID ); + + if ( 'attachment' !== $post_type ) + wp_enqueue_script('autosave'); + } + + if ( is_multisite() ) { + add_action( 'admin_footer', '_admin_notice_post_locked' ); + } else { + $check_users = get_users( array( 'fields' => 'ID', 'number' => 2 ) ); + + if ( count( $check_users ) > 1 ) + add_action( 'admin_footer', '_admin_notice_post_locked' ); + + unset( $check_users ); + } + + $title = $post_type_object->labels->edit_item; + $post = get_post($post_id, OBJECT, 'edit'); + + if ( post_type_supports($post_type, 'comments') ) { + wp_enqueue_script('admin-comments'); + enqueue_comment_hotkeys_js(); + } + + include( ABSPATH . 'wp-admin/edit-form-advanced.php' ); + + break; + +case 'editattachment': + check_admin_referer('update-post_' . $post_id); + + // Don't let these be changed + unset($_POST['guid']); + $_POST['post_type'] = 'attachment'; + + // Update the thumbnail filename + $newmeta = wp_get_attachment_metadata( $post_id, true ); + $newmeta['thumb'] = $_POST['thumb']; + + wp_update_attachment_metadata( $post_id, $newmeta ); + +case 'editpost': + check_admin_referer('update-post_' . $post_id); + + $post_id = edit_post(); + + // Session cookie flag that the post was saved + if ( isset( $_COOKIE['wp-saving-post-' . $post_id] ) ) + setcookie( 'wp-saving-post-' . $post_id, 'saved' ); + + redirect_post($post_id); // Send user on their way while we keep working + + exit(); + break; + +case 'trash': + check_admin_referer('trash-post_' . $post_id); + + if ( ! $post ) + wp_die( __( 'The item you are trying to move to the Trash no longer exists.' ) ); + + if ( ! $post_type_object ) + wp_die( __( 'Unknown post type.' ) ); + + if ( ! current_user_can( 'delete_post', $post_id ) ) + wp_die( __( 'You are not allowed to move this item to the Trash.' ) ); + + if ( $user_id = wp_check_post_lock( $post_id ) ) { + $user = get_userdata( $user_id ); + wp_die( sprintf( __( 'You cannot move this item to the Trash. %s is currently editing.' ), $user->display_name ) ); + } + + if ( ! wp_trash_post( $post_id ) ) + wp_die( __( 'Error in moving to Trash.' ) ); + + wp_redirect( add_query_arg( array('trashed' => 1, 'ids' => $post_id), $sendback ) ); + exit(); + break; + +case 'untrash': + check_admin_referer('untrash-post_' . $post_id); + + if ( ! $post ) + wp_die( __( 'The item you are trying to restore from the Trash no longer exists.' ) ); + + if ( ! $post_type_object ) + wp_die( __( 'Unknown post type.' ) ); + + if ( ! current_user_can( 'delete_post', $post_id ) ) + wp_die( __( 'You are not allowed to move this item out of the Trash.' ) ); + + if ( ! wp_untrash_post( $post_id ) ) + wp_die( __( 'Error in restoring from Trash.' ) ); + + wp_redirect( add_query_arg('untrashed', 1, $sendback) ); + exit(); + break; + +case 'delete': + check_admin_referer('delete-post_' . $post_id); + + if ( ! $post ) + wp_die( __( 'This item has already been deleted.' ) ); + + if ( ! $post_type_object ) + wp_die( __( 'Unknown post type.' ) ); + + if ( ! current_user_can( 'delete_post', $post_id ) ) + wp_die( __( 'You are not allowed to delete this item.' ) ); + + $force = ! EMPTY_TRASH_DAYS; + if ( $post->post_type == 'attachment' ) { + $force = ( $force || ! MEDIA_TRASH ); + if ( ! wp_delete_attachment( $post_id, $force ) ) + wp_die( __( 'Error in deleting.' ) ); + } else { + if ( ! wp_delete_post( $post_id, $force ) ) + wp_die( __( 'Error in deleting.' ) ); + } + + wp_redirect( add_query_arg('deleted', 1, $sendback) ); + exit(); + break; + +case 'preview': + check_admin_referer( 'autosave', 'autosavenonce' ); + + $url = post_preview(); + + wp_redirect($url); + exit(); + break; + +default: + wp_redirect( admin_url('edit.php') ); + exit(); + break; +} // end switch +include( ABSPATH . 'wp-admin/admin-footer.php' ); diff --git a/sources/wp-admin/press-this.php b/sources/wp-admin/press-this.php new file mode 100644 index 0000000..5e9e259 --- /dev/null +++ b/sources/wp-admin/press-this.php @@ -0,0 +1,657 @@ +cap->create_posts ) ) + wp_die( __( 'Cheatin’ uh?' ) ); + +/** + * Press It form handler. + * + * @package WordPress + * @subpackage Press_This + * @since 2.6.0 + * + * @return int Post ID + */ +function press_it() { + + $post = get_default_post_to_edit(); + $post = get_object_vars($post); + $post_ID = $post['ID'] = (int) $_POST['post_id']; + + if ( !current_user_can('edit_post', $post_ID) ) + wp_die(__('You are not allowed to edit this post.')); + + $post['post_category'] = isset($_POST['post_category']) ? $_POST['post_category'] : ''; + $post['tax_input'] = isset($_POST['tax_input']) ? $_POST['tax_input'] : ''; + $post['post_title'] = isset($_POST['title']) ? $_POST['title'] : ''; + $content = isset($_POST['content']) ? $_POST['content'] : ''; + + $upload = false; + if ( !empty($_POST['photo_src']) && current_user_can('upload_files') ) { + foreach( (array) $_POST['photo_src'] as $key => $image) { + // see if files exist in content - we don't want to upload non-used selected files. + if ( strpos($_POST['content'], htmlspecialchars($image)) !== false ) { + $desc = isset($_POST['photo_description'][$key]) ? $_POST['photo_description'][$key] : ''; + $upload = media_sideload_image($image, $post_ID, $desc); + + // Replace the POSTED content with correct uploaded ones. Regex contains fix for Magic Quotes + if ( !is_wp_error($upload) ) + $content = preg_replace('/]*)src=\\\?(\"|\')'.preg_quote(htmlspecialchars($image), '/').'\\\?(\2)([^>\/]*)\/*>/is', $upload, $content); + } + } + } + // set the post_content and status + $post['post_content'] = $content; + if ( isset( $_POST['publish'] ) && current_user_can( 'publish_posts' ) ) + $post['post_status'] = 'publish'; + elseif ( isset( $_POST['review'] ) ) + $post['post_status'] = 'pending'; + else + $post['post_status'] = 'draft'; + + // error handling for media_sideload + if ( is_wp_error($upload) ) { + wp_delete_post($post_ID); + wp_die($upload); + } else { + // Post formats + if ( isset( $_POST['post_format'] ) ) { + if ( current_theme_supports( 'post-formats', $_POST['post_format'] ) ) + set_post_format( $post_ID, $_POST['post_format'] ); + elseif ( '0' == $_POST['post_format'] ) + set_post_format( $post_ID, false ); + } + + $post_ID = wp_update_post($post); + } + + return $post_ID; +} + +// For submitted posts. +if ( isset($_REQUEST['action']) && 'post' == $_REQUEST['action'] ) { + check_admin_referer('press-this'); + $posted = $post_ID = press_it(); +} else { + $post = get_default_post_to_edit('post', true); + $post_ID = $post->ID; +} + +// Set Variables +$title = isset( $_GET['t'] ) ? trim( strip_tags( html_entity_decode( wp_unslash( $_GET['t'] ) , ENT_QUOTES) ) ) : ''; + +$selection = ''; +if ( !empty($_GET['s']) ) { + $selection = str_replace(''', "'", wp_unslash($_GET['s'])); + $selection = trim( htmlspecialchars( html_entity_decode($selection, ENT_QUOTES) ) ); +} + +if ( ! empty($selection) ) { + $selection = preg_replace('/(\r?\n|\r)/', '

    ', $selection); + $selection = '

    ' . str_replace('

    ', '', $selection) . '

    '; +} + +$url = isset($_GET['u']) ? esc_url($_GET['u']) : ''; +$image = isset($_GET['i']) ? $_GET['i'] : ''; + +if ( !empty($_REQUEST['ajax']) ) { + switch ($_REQUEST['ajax']) { + case 'video': ?> + +
    +

    +
    + +

    +
    +
    + + +

    +
    +
    + +
    +
    + +

    + + + <?php echo esc_attr(__('Click to insert.')); ?> + +

    + +

    + ]*)src=(\"|\')([^<>\'\"]+)(\2)([^>]*)\/*>/i'; + $content = str_replace(array("\n","\t","\r"), '', $content); + preg_match_all($pattern, $content, $matches); + if ( empty($matches[0]) ) + return ''; + $sources = array(); + foreach ($matches[3] as $src) { + // if no http in url + if (strpos($src, 'http') === false) + // if it doesn't have a relative uri + if ( strpos($src, '../') === false && strpos($src, './') === false && strpos($src, '/') === 0) + $src = 'http://'.str_replace('//','/', $host['host'].'/'.$src); + else + $src = 'http://'.str_replace('//','/', $host['host'].'/'.dirname($host['path']).'/'.$src); + $sources[] = esc_url($src); + } + return "'" . implode("','", $sources) . "'"; + } + $url = wp_kses(urldecode($url), null); + echo 'new Array('.get_images_from_uri($url).')'; + break; + + case 'photo_js': ?> + // gather images and load some default JS + var last = null + var img, img_tag, aspect, w, h, skip, i, strtoappend = ""; + if(photostorage == false) { + var my_src = eval( + jQuery.ajax({ + type: "GET", + url: "", + cache : false, + async : false, + data: "ajax=photo_images&u=", + dataType : "script" + }).responseText + ); + if(my_src.length == 0) { + var my_src = eval( + jQuery.ajax({ + type: "GET", + url: "", + cache : false, + async : false, + data: "ajax=photo_images&u=", + dataType : "script" + }).responseText + ); + if(my_src.length == 0) { + strtoappend = ''; + } + } + } + for (i = 0; i < my_src.length; i++) { + img = new Image(); + img.src = my_src[i]; + img_attr = 'id="img' + i + '"'; + skip = false; + + maybeappend = ''; + + if (img.width && img.height) { + if (img.width >= 30 && img.height >= 30) { + aspect = img.width / img.height; + scale = (aspect > 1) ? (71 / img.width) : (71 / img.height); + + w = img.width; + h = img.height; + + if (scale < 1) { + w = parseInt(img.width * scale); + h = parseInt(img.height * scale); + } + img_attr += ' style="width: ' + w + 'px; height: ' + h + 'px;"'; + strtoappend += maybeappend; + } + } else { + strtoappend += maybeappend; + } + } + + function pick(img, desc) { + if (img) { + if('object' == typeof jQuery('.photolist input') && jQuery('.photolist input').length != 0) length = jQuery('.photolist input').length; + if(length == 0) length = 1; + jQuery('.photolist').append(''); + jQuery('.photolist').append(''); + insert_editor( "\n\n" + encodeURI('

    ' + desc + '

    ')); + } + return false; + } + + function image_selector(el) { + var desc, src, parent = jQuery(el).closest('#photo-add-url-div'); + + if ( parent.length ) { + desc = parent.find('input.tb_this_photo_description').val() || ''; + src = parent.find('input.tb_this_photo').val() || '' + } else { + desc = jQuery('#tb_this_photo_description').val() || ''; + src = jQuery('#tb_this_photo').val() || '' + } + + tb_remove(); + pick(src, desc); + jQuery('#extra-fields').hide(); + jQuery('#extra-fields').html(''); + return false; + } + + jQuery('#extra-fields').html('

    ()

    '); + jQuery('#img_container').html(strtoappend); + +<?php _e('Press This') ?> + + + + + + + +
    +
    +
    +
    + + + + + + + + +
    + +
    +

    +

    +
    +

    + 'save' ) ); + if ( current_user_can('publish_posts') ) { + submit_button( __( 'Publish' ), 'primary', 'publish', false ); + } else { + echo '

    '; + submit_button( __( 'Submit for Review' ), 'primary', 'review', false ); + } ?> + +

    + +

    + +

    + +
    +
    + + +
    +

    +

    +
    +
    + + + + + +
    +
      + 'category', 'popular_cats' => $popular_ids ) ) ?> +
    +
    + + cap->assign_terms) ) : ?> +

    + + cap->edit_terms) ) : ?> +
    +

    + + labels->add_new_item ); ?> + +

    +

    + + + + 'category', 'hide_empty' => 0, 'name' => 'newcategory_parent', 'orderby' => 'name', 'hierarchical' => 1, 'show_option_none' => '— ' . $tax->labels->parent_item . ' —' ) ); ?> + + + +

    +
    + +
    +
    +
    + +
    +

    +

    +
    +
    +
    + + +
    + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + +
    +

    + + | + |

    +
    + + +
    +
    + +
    +
    + + + + + +
    + true, + 'textarea_rows' => '15' + ); + + $content = ''; + if ( $selection ) + $content .= $selection; + + if ( $url ) { + $content .= '

    '; + + if ( $selection ) + $content .= __('via '); + + $content .= sprintf( "%s.

    ", esc_url( $url ), esc_html( $title ) ); + } + + remove_action( 'media_buttons', 'media_buttons' ); + add_action( 'media_buttons', 'press_this_media_buttons' ); + function press_this_media_buttons() { + _e( 'Add:' ); + + if ( current_user_can('upload_files') ) { + ?> + + <?php esc_attr_e('Insert an Image'); ?> + + <?php esc_attr_e('Embed a Video'); ?> + +
    +
    +
    +
    + + + + + diff --git a/sources/wp-admin/profile.php b/sources/wp-admin/profile.php new file mode 100644 index 0000000..0f33eb2 --- /dev/null +++ b/sources/wp-admin/profile.php @@ -0,0 +1,18 @@ +post_parent ) ) + break; + + if ( ! $post = get_post( $revision->post_parent ) ) + break; + + // Revisions disabled (previously checked autosaves && ! wp_is_post_autosave( $revision )) + if ( ! wp_revisions_enabled( $post ) ) { + $redirect = 'edit.php?post_type=' . $post->post_type; + break; + } + + // Don't allow revision restore when post is locked + if ( wp_check_post_lock( $post->ID ) ) + break; + + check_admin_referer( "restore-post_{$revision->ID}" ); + + wp_restore_post_revision( $revision->ID ); + $redirect = add_query_arg( array( 'message' => 5, 'revision' => $revision->ID ), get_edit_post_link( $post->ID, 'url' ) ); + break; +case 'view' : +case 'edit' : +default : + if ( ! $revision = wp_get_post_revision( $revision_id ) ) + break; + if ( ! $post = get_post( $revision->post_parent ) ) + break; + + if ( ! current_user_can( 'read_post', $revision->ID ) || ! current_user_can( 'read_post', $post->ID ) ) + break; + + // Revisions disabled and we're not looking at an autosave + if ( ! wp_revisions_enabled( $post ) && ! wp_is_post_autosave( $revision ) ) { + $redirect = 'edit.php?post_type=' . $post->post_type; + break; + } + + $post_title = '' . _draft_or_post_title() . ''; + $h2 = sprintf( __( 'Compare Revisions of “%1$s”' ), $post_title ); + $title = __( 'Revisions' ); + + $redirect = false; + break; +endswitch; + +// Empty post_type means either malformed object found, or no valid parent was found. +if ( ! $redirect && empty( $post->post_type ) ) + $redirect = 'edit.php'; + +if ( ! empty( $redirect ) ) { + wp_redirect( $redirect ); + exit; +} + +// This is so that the correct "Edit" menu item is selected. +if ( ! empty( $post->post_type ) && 'post' != $post->post_type ) + $parent_file = $submenu_file = 'edit.php?post_type=' . $post->post_type; +else + $parent_file = $submenu_file = 'edit.php'; + +wp_enqueue_script( 'revisions' ); +wp_localize_script( 'revisions', '_wpRevisionsSettings', wp_prepare_revisions_for_js( $post, $revision_id, $from ) ); + +/* Revisions Help Tab */ + +$revisions_overview = '

    ' . __( 'This screen is used for managing your content revisions.' ) . '

    '; +$revisions_overview .= '

    ' . __( 'Revisions are saved copies of your post or page, which are periodically created as you update your content. The red text on the left shows the content that was removed. The green text on the right shows the content that was added.' ) . '

    '; +$revisions_overview .= '

    ' . __( 'From this screen you can review, compare, and restore revisions:' ) . '

    '; +$revisions_overview .= '
    • ' . __( 'To navigate between revisions, drag the slider handle left or right or use the Previous or Next buttons.' ) . '
    • '; +$revisions_overview .= '
    • ' . __( 'Compare two different revisions by selecting the “Compare any two revisions” box to the side.' ) . '
    • '; +$revisions_overview .= '
    • ' . __( 'To restore a revision, click Restore This Revision.' ) . '
    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'revisions-overview', + 'title' => __( 'Overview' ), + 'content' => $revisions_overview +) ); + +$revisions_sidebar = '

    ' . __( 'For more information:' ) . '

    '; +$revisions_sidebar .= '

    ' . __( 'Revisions Management' ) . '

    '; +$revisions_sidebar .= '

    ' . __( 'Support Forums' ) . '

    '; + +get_current_screen()->set_help_sidebar( $revisions_sidebar ); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +?> + +
    + +

    +
    + + + + + + + + + + + + +' . sprintf( __( "The file 'wp-config.php' already exists. If you need to reset any of the configuration items in this file, please delete it first. You may try installing now." ), 'install.php' ) . '

    ' ); + +// Check if wp-config.php exists above the root directory but is not part of another install +if ( file_exists(ABSPATH . '../wp-config.php' ) && ! file_exists( ABSPATH . '../wp-settings.php' ) ) + wp_die( '

    ' . sprintf( __( "The file 'wp-config.php' already exists one level above your WordPress installation. If you need to reset any of the configuration items in this file, please delete it first. You may try installing now."), 'install.php' ) . '

    ' ); + +$step = isset( $_GET['step'] ) ? (int) $_GET['step'] : 0; + +/** + * Display setup wp-config.php file header. + * + * @ignore + * @since 2.3.0 + * @package WordPress + * @subpackage Installer_WP_Config + */ +function setup_config_display_header() { + global $wp_version; + + header( 'Content-Type: text/html; charset=utf-8' ); +?> + +> + + +<?php _e( 'WordPress › Setup Configuration File' ); ?> + + + + + +

    + + +

    +
      +
    1. +
    2. +
    3. +
    4. +
    5. +
    +

    wp-config-sample.php in a text editor, fill in your information, and save it as wp-config.php." ); ?>

    +

    + +

    + +
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    localhost does not work.' ); ?>
    + +

    +
    +

    ' . __( 'Try again' ) . ''; + + if ( empty( $prefix ) ) + wp_die( __( 'ERROR: "Table Prefix" must not be empty.' . $tryagain_link ) ); + + // Validate $prefix: it can only contain letters, numbers and underscores. + if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) + wp_die( __( 'ERROR: "Table Prefix" can only contain numbers, letters, and underscores.' . $tryagain_link ) ); + + // Test the db connection. + /**#@+ + * @ignore + */ + define('DB_NAME', $dbname); + define('DB_USER', $uname); + define('DB_PASSWORD', $pwd); + define('DB_HOST', $dbhost); + /**#@-*/ + + // We'll fail here if the values are no good. + require_wp_db(); + if ( ! empty( $wpdb->error ) ) + wp_die( $wpdb->error->get_error_message() . $tryagain_link ); + + // Fetch or generate keys and salts. + $no_api = isset( $_POST['noapi'] ); + if ( ! $no_api ) { + require_once( ABSPATH . WPINC . '/class-http.php' ); + require_once( ABSPATH . WPINC . '/http.php' ); + /**#@+ + * @ignore + */ + function get_bloginfo() { + return wp_guess_url(); + } + /**#@-*/ + $secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' ); + } + + if ( $no_api || is_wp_error( $secret_keys ) ) { + $secret_keys = array(); + require_once( ABSPATH . WPINC . '/pluggable.php' ); + for ( $i = 0; $i < 8; $i++ ) { + $secret_keys[] = wp_generate_password( 64, true, true ); + } + } else { + $secret_keys = explode( "\n", wp_remote_retrieve_body( $secret_keys ) ); + foreach ( $secret_keys as $k => $v ) { + $secret_keys[$k] = substr( $v, 28, 64 ); + } + } + + $key = 0; + // Not a PHP5-style by-reference foreach, as this file must be parseable by PHP4. + foreach ( $config_file as $line_num => $line ) { + if ( '$table_prefix =' == substr( $line, 0, 16 ) ) { + $config_file[ $line_num ] = '$table_prefix = \'' . addcslashes( $prefix, "\\'" ) . "';\r\n"; + continue; + } + + if ( ! preg_match( '/^define\(\'([A-Z_]+)\',([ ]+)/', $line, $match ) ) + continue; + + $constant = $match[1]; + $padding = $match[2]; + + switch ( $constant ) { + case 'DB_NAME' : + case 'DB_USER' : + case 'DB_PASSWORD' : + case 'DB_HOST' : + $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n"; + break; + case 'AUTH_KEY' : + case 'SECURE_AUTH_KEY' : + case 'LOGGED_IN_KEY' : + case 'NONCE_KEY' : + case 'AUTH_SALT' : + case 'SECURE_AUTH_SALT' : + case 'LOGGED_IN_SALT' : + case 'NONCE_SALT' : + $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . $secret_keys[$key++] . "');\r\n"; + break; + } + } + unset( $line ); + + if ( ! is_writable(ABSPATH) ) : + setup_config_display_header(); +?> +

    wp-config.php file." ); ?>

    +

    wp-config.php manually and paste the following text into it.' ); ?>

    + +

    +

    + + +

    + +

    + + + diff --git a/sources/wp-admin/theme-editor.php b/sources/wp-admin/theme-editor.php new file mode 100644 index 0000000..7d1c618 --- /dev/null +++ b/sources/wp-admin/theme-editor.php @@ -0,0 +1,246 @@ +'.__('You do not have sufficient permissions to edit templates for this site.').'

    '); + +$title = __("Edit Themes"); +$parent_file = 'themes.php'; + +get_current_screen()->add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

    ' . __('You can use the Theme Editor to edit the individual CSS and PHP files which make up your theme.') . '

    +

    ' . __('Begin by choosing a theme to edit from the dropdown menu and clicking Select. A list then appears of all the template files. Clicking once on any file name causes the file to appear in the large Editor box.') . '

    +

    ' . __('For PHP files, you can use the Documentation dropdown to select from functions recognized in that file. Look Up takes you to a web page with reference material about that particular function.') . '

    +

    ' . __('In the editing area the Tab key enters a tab character. To move below this area by pressing Tab, press the Esc key followed by the Tab key.') . '

    +

    ' . __('After typing in your edits, click Update File.') . '

    +

    ' . __('Advice: think very carefully about your site crashing if you are live-editing the theme currently in use.') . '

    +

    ' . sprintf( __('Upgrading to a newer version of the same theme will override changes made here. To avoid this, consider creating a child theme instead.'), __('http://codex.wordpress.org/Child_Themes') ) . '

    ' . + ( is_network_admin() ? '

    ' . __('Any edits to files from this screen will be reflected on all sites in the network.') . '

    ' : '' ) +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Theme Development') . '

    ' . + '

    ' . __('Documentation on Using Themes') . '

    ' . + '

    ' . __('Documentation on Editing Files') . '

    ' . + '

    ' . __('Documentation on Template Tags') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +wp_reset_vars( array( 'action', 'error', 'file', 'theme' ) ); + +if ( $theme ) + $stylesheet = $theme; +else + $stylesheet = get_stylesheet(); + +$theme = wp_get_theme( $stylesheet ); + +if ( ! $theme->exists() ) + wp_die( __( 'The requested theme does not exist.' ) ); + +if ( $theme->errors() && 'theme_no_stylesheet' == $theme->errors()->get_error_code() ) + wp_die( __( 'The requested theme does not exist.' ) . ' ' . $theme->errors()->get_error_message() ); + +$allowed_files = $theme->get_files( 'php', 1 ); +$has_templates = ! empty( $allowed_files ); +$style_files = $theme->get_files( 'css' ); +$allowed_files['style.css'] = $style_files['style.css']; +$allowed_files += $style_files; + +if ( empty( $file ) ) { + $relative_file = 'style.css'; + $file = $allowed_files['style.css']; +} else { + $relative_file = $file; + $file = $theme->get_stylesheet_directory() . '/' . $relative_file; +} + +validate_file_to_edit( $file, $allowed_files ); +$scrollto = isset( $_REQUEST['scrollto'] ) ? (int) $_REQUEST['scrollto'] : 0; + +switch( $action ) { +case 'update': + check_admin_referer( 'edit-theme_' . $file . $stylesheet ); + $newcontent = wp_unslash( $_POST['newcontent'] ); + $location = 'theme-editor.php?file=' . urlencode( $relative_file ) . '&theme=' . urlencode( $stylesheet ) . '&scrollto=' . $scrollto; + if ( is_writeable( $file ) ) { + //is_writable() not always reliable, check return value. see comments @ http://uk.php.net/is_writable + $f = fopen( $file, 'w+' ); + if ( $f !== false ) { + fwrite( $f, $newcontent ); + fclose( $f ); + $location .= '&updated=true'; + $theme->cache_delete(); + } + } + wp_redirect( $location ); + exit; +break; + +default: + + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + + update_recently_edited( $file ); + + if ( ! is_file( $file ) ) + $error = true; + + $content = ''; + if ( ! $error && filesize( $file ) > 0 ) { + $f = fopen($file, 'r'); + $content = fread($f, filesize($file)); + + if ( '.php' == substr( $file, strrpos( $file, '.' ) ) ) { + $functions = wp_doc_link_parse( $content ); + + $docs_select = ''; + } + + $content = esc_textarea( $content ); + } + + ?> + +

    +(' . $file_show . ')'; +?> +
    + +

    + +
    +
    +

    display('Name'); if ( $description ) echo ': ' . $description; ?>

    +
    +
    +
    + + + +
    +
    +
    +
    +errors() ) + echo '

    ' . __( 'This theme is broken.' ) . ' ' . $theme->errors()->get_error_message() . '

    '; +?> +
    +parent() ) : +?> +

    + parent() ) : ?> +

    get_template() ) ) . '">' . $theme->parent()->display('Name') . '' ); ?>

    + +
      + $absolute_filename ) : + if ( 'style.css' == $filename ) + echo "\t
    \n\t

    " . _x( 'Styles', 'Theme stylesheets in theme editor' ) . "

    \n\t
      \n"; + + $file_description = get_file_description( $absolute_filename ); + if ( $file_description != basename( $filename ) ) + $file_description .= '
      (' . $filename . ')'; + + if ( $absolute_filename == $file ) + $file_description = '' . $file_description . ''; +?> +
    • + +
    + +
    +

    ' . __('Oops, no such file exists! Double check the name and try again, merci.') . '

    '; +else : ?> +
    + +
    + + + + +
    + +
    + + + +
    + + +
    + get_stylesheet() == get_template() ) : ?> +

    +

    + + +

    the Codex for more information.'); ?>

    + +
    +
    + +
    +
    + +get_pagenum(); +$wp_list_table->prepare_items(); + +$title = __('Install Themes'); +$parent_file = 'themes.php'; +if ( !is_network_admin() ) + $submenu_file = 'themes.php'; + +wp_enqueue_script( 'theme-install' ); +wp_enqueue_script( 'theme' ); + +$body_id = $tab; + +do_action('install_themes_pre_' . $tab); //Used to override the general interface, Eg, install or theme information. + +$help_overview = + '

    ' . sprintf(__('You can find additional themes for your site by using the Theme Browser/Installer on this screen, which will display themes from the WordPress.org Theme Directory. These themes are designed and developed by third parties, are available free of charge, and are compatible with the license WordPress uses.'), 'http://wordpress.org/themes/') . '

    ' . + '

    ' . __('You can Search for themes by keyword, author, or tag, or can get more specific and search by criteria listed in the feature filter. Alternately, you can browse the themes that are Featured, Newest, or Recently Updated. When you find a theme you like, you can preview it or install it.') . '

    ' . + '

    ' . __('You can Upload a theme manually if you have already downloaded its ZIP archive onto your computer (make sure it is from a trusted and original source). You can also do it the old-fashioned way and copy a downloaded theme’s folder via FTP into your /wp-content/themes directory.') . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $help_overview +) ); + +$help_installing = + '

    ' . __('Once you have generated a list of themes, you can preview and install any of them. Click on the thumbnail of the theme you’re interested in previewing. It will open up in a full-screen Preview page to give you a better idea of how that theme will look.') . '

    ' . + '

    ' . __('To install the theme so you can preview it with your site’s content and customize its theme options, click the "Install" button at the top of the left-hand pane. The theme files will be downloaded to your website automatically. When this is complete, the theme is now available for activation, which you can do by clicking the "Activate" link, or by navigating to your Manage Themes screen and clicking the "Live Preview" link under any installed theme’s thumbnail image.') . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'installing', + 'title' => __('Previewing and Installing'), + 'content' => $help_installing +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Adding New Themes') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +include(ABSPATH . 'wp-admin/admin-header.php'); +?> +
    + +

    + + + +views(); ?> + +
    + +
    +exists() || ! $theme->is_allowed() ) + wp_die( __( 'Cheatin’ uh?' ) ); + switch_theme( $theme->get_stylesheet() ); + wp_redirect( admin_url('themes.php?activated=true') ); + exit; + } elseif ( 'delete' == $_GET['action'] ) { + check_admin_referer('delete-theme_' . $_GET['stylesheet']); + $theme = wp_get_theme( $_GET['stylesheet'] ); + if ( !current_user_can('delete_themes') || ! $theme->exists() ) + wp_die( __( 'Cheatin’ uh?' ) ); + delete_theme($_GET['stylesheet']); + wp_redirect( admin_url('themes.php?deleted=true') ); + exit; + } +} + +$wp_list_table->prepare_items(); + +$title = __('Manage Themes'); +$parent_file = 'themes.php'; + +if ( current_user_can( 'switch_themes' ) ) : + +$help_manage = '

    ' . __('Aside from the default theme included with your WordPress installation, themes are designed and developed by third parties.') . '

    ' . + '

    ' . __('You can see your active theme at the top of the screen. Below are the other themes you have installed that are not currently in use. You can see what your site would look like with one of these themes by clicking the Live Preview link (see "Previewing and Customizing" help tab). To change themes, click the Activate link.') . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $help_manage +) ); + +if ( current_user_can( 'install_themes' ) ) { + if ( is_multisite() ) { + $help_install = '

    ' . __('Installing themes on Multisite can only be done from the Network Admin section.') . '

    '; + } else { + $help_install = '

    ' . sprintf( __('If you would like to see more themes to choose from, click on the “Install Themes” tab and you will be able to browse or search for additional themes from the WordPress.org Theme Directory. Themes in the WordPress.org Theme Directory are designed and developed by third parties, and are compatible with the license WordPress uses. Oh, and they’re free!'), 'http://wordpress.org/themes/' ) . '

    '; + } + + get_current_screen()->add_help_tab( array( + 'id' => 'adding-themes', + 'title' => __('Adding Themes'), + 'content' => $help_install + ) ); +} + +add_thickbox(); + +endif; // switch_themes + +if ( current_user_can( 'edit_theme_options' ) ) { + $help_customize = + '

    ' . __('Click on the "Live Preview" link under any theme to preview that theme and change theme options in a separate, full-screen view. Any installed theme can be previewed and customized in this way.') . '

    '. + '

    ' . __('The theme being previewed is fully interactive — navigate to different pages to see how the theme handles posts, archives, and other page templates.') . '

    ' . + '

    ' . __('In the left-hand pane you can edit the theme settings. The settings will differ, depending on what theme features the theme being previewed supports. To accept the new settings and activate the theme all in one step, click the "Save & Activate" button at the top of the left-hand pane.') . '

    ' . + '

    ' . __('When previewing on smaller monitors, you can use the "Collapse" icon at the bottom of the left-hand pane. This will hide the pane, giving you more room to preview your site in the new theme. To bring the pane back, click on the Collapse icon again.') . '

    '; + + get_current_screen()->add_help_tab( array( + 'id' => 'customize-preview-themes', + 'title' => __('Previewing and Customizing'), + 'content' => $help_customize + ) ); +} + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Using Themes') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +wp_enqueue_script( 'theme' ); +wp_enqueue_script( 'customize-loader' ); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
    +

    + +

    + +

    + +

    Visit site' ), home_url( '/' ) ); ?>

    + +

    Visit site' ), home_url( '/' ) ); ?>

    +

    +get_screenshot(); +$class = $screenshot ? 'has-screenshot' : ''; + +$customize_title = sprintf( __( 'Customize “%s”' ), $ct->display('Name') ); + +?> +
    + + + + <?php esc_attr_e( 'Current theme preview' ); ?> + + + <?php esc_attr_e( 'Current theme preview' ); ?> + + +

    +

    + display('Name'); ?> +

    + +errors() && ( ! is_multisite() || current_user_can( 'manage_network_themes' ) ) ) { + echo '

    ' . sprintf( __( 'ERROR: %s' ), $ct->errors()->get_error_message() ) . '

    '; +} + +// Certain error codes are less fatal than others. We can still display theme information in most cases. +if ( ! $ct->errors() || ( 1 == count( $ct->errors()->get_error_codes() ) + && in_array( $ct->errors()->get_error_code(), array( 'theme_no_parent', 'theme_parent_invalid', 'theme_no_index' ) ) ) ) : ?> + +
    +
      +
    • display('Author') ); ?>
    • +
    • display('Version') ); ?>
    • +
    +

    display('Description'); ?>

    + parent() ) { + printf( '

    ' . __( 'This child theme requires its parent theme, %2$s.' ) . '

    ', + __( 'http://codex.wordpress.org/Child_Themes' ), + $ct->parent()->display( 'Name' ) ); + } ?> + +
    + + {$item[0]}"; + else + $options[] = "{$item[0]}"; + } else if ( current_user_can($item[1]) ) { + $menu_file = $item[2]; + if ( false !== ( $pos = strpos( $menu_file, '?' ) ) ) + $menu_file = substr( $menu_file, 0, $pos ); + if ( file_exists( ABSPATH . "wp-admin/$menu_file" ) ) { + $options[] = "{$item[0]}"; + } else { + $options[] = "{$item[0]}"; + } + } + } + } + + if ( $options || current_user_can( 'edit_theme_options' ) ) : + ?> +
    + + + + +
      + +
    • + +
    + +
    + + + + +
    + +
    +'; + require( ABSPATH . 'wp-admin/admin-footer.php' ); + exit; +} +?> + +
    + +

    + +has_items() ) : ?> + + + +
    + +
    +

    + + + + $features ) : + $feature_name = esc_html( $feature_name ); ?> + +
    +
    + +
      + $feature ) : + $feature_name = $feature; + $feature_name = esc_html( $feature_name ); + $feature = esc_attr( $feature ); + ?> +
    1. + features ) ); ?>/> + +
    2. + +
    +
    + + +
    + 'filter-submit' ) ); ?> +   + +
    +
    +
    +
    +
    + + + +
    + +display(); ?> + +
    +
    + + true ) ) ) { +?> + +

    +

    + + + + + + + + + + "; + } +?> +
    " . $broken_theme->get('Name') ."" . $broken_theme->errors()->get_error_message() . "
    + +
    + + diff --git a/sources/wp-admin/tools.php b/sources/wp-admin/tools.php new file mode 100644 index 0000000..4fab0bd --- /dev/null +++ b/sources/wp-admin/tools.php @@ -0,0 +1,71 @@ +add_help_tab( array( + 'id' => 'press-this', + 'title' => __('Press This'), + 'content' => '

    ' . __('Press This is a bookmarklet that makes it easy to blog about something you come across on the web. You can use it to just grab a link, or to post an excerpt. Press This will even allow you to choose from images included on the page and use them in your post. Just drag the Press This link on this screen to your bookmarks bar in your browser, and you’ll be on your way to easier content creation. Clicking on it while on another website opens a popup window with all these options.') . '

    ', +) ); +get_current_screen()->add_help_tab( array( + 'id' => 'converter', + 'title' => __('Categories and Tags Converter'), + 'content' => '

    ' . __('Categories have hierarchy, meaning that you can nest sub-categories. Tags do not have hierarchy and cannot be nested. Sometimes people start out using one on their posts, then later realize that the other would work better for their content.' ) . '

    ' . + '

    ' . __( 'The Categories and Tags Converter link on this screen will take you to the Import screen, where that Converter is one of the plugins you can install. Once that plugin is installed, the Activate Plugin & Run Importer link will take you to a screen where you can choose to convert tags into categories or vice versa.' ) . '

    ', +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Tools') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +?> +
    + +

    + + +
    +

    +

    + +

    +

    +

    + +
    +cap->manage_terms) || current_user_can($tags->cap->manage_terms) ) : ?> +
    +

    +

    Categories and Tags Converter available from the Import screen.'), 'import.php' ); ?>

    +
    + +
    +locale && 'en_US' == get_locale() ) + $version_string = $update->current; + // If the only available update is a partial builds, it doesn't need a language-specific version string. + elseif ( 'en_US' == $update->locale && $update->packages->partial && $wp_version == $update->partial_version && ( $updates = get_core_updates() ) && 1 == count( $updates ) ) + $version_string = $update->current; + else + $version_string = sprintf( "%s–%s", $update->current, $update->locale ); + + $current = false; + if ( !isset($update->response) || 'latest' == $update->response ) + $current = true; + $submit = __('Update Now'); + $form_action = 'update-core.php?action=do-core-upgrade'; + $php_version = phpversion(); + $mysql_version = $wpdb->db_version(); + $show_buttons = true; + if ( 'development' == $update->response ) { + $message = __('You are using a development version of WordPress. You can update to the latest nightly build automatically or download the nightly build and install it manually:'); + $download = __('Download nightly build'); + } else { + if ( $current ) { + $message = sprintf( __( 'If you need to re-install version %s, you can do so here or download the package and re-install manually:' ), $version_string ); + $submit = __('Re-install Now'); + $form_action = 'update-core.php?action=do-core-reinstall'; + } else { + $php_compat = version_compare( $php_version, $update->php_version, '>=' ); + if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) + $mysql_compat = true; + else + $mysql_compat = version_compare( $mysql_version, $update->mysql_version, '>=' ); + + if ( !$mysql_compat && !$php_compat ) + $message = sprintf( __('You cannot update because WordPress %1$s requires PHP version %2$s or higher and MySQL version %3$s or higher. You are running PHP version %4$s and MySQL version %5$s.'), $update->current, $update->php_version, $update->mysql_version, $php_version, $mysql_version ); + elseif ( !$php_compat ) + $message = sprintf( __('You cannot update because WordPress %1$s requires PHP version %2$s or higher. You are running version %3$s.'), $update->current, $update->php_version, $php_version ); + elseif ( !$mysql_compat ) + $message = sprintf( __('You cannot update because WordPress %1$s requires MySQL version %2$s or higher. You are running version %3$s.'), $update->current, $update->mysql_version, $mysql_version ); + else + $message = sprintf(__('You can update to WordPress %2$s automatically or download the package and install it manually:'), $update->current, $version_string); + if ( !$mysql_compat || !$php_compat ) + $show_buttons = false; + } + $download = sprintf(__('Download %s'), $version_string); + } + + echo '

    '; + echo $message; + echo '

    '; + echo '
    '; + wp_nonce_field('upgrade-core'); + echo '

    '; + echo ''; + echo ''; + if ( $show_buttons ) { + if ( $first_pass ) { + submit_button( $submit, $current ? 'button' : 'primary regular', 'upgrade', false ); + $first_pass = false; + } else { + submit_button( $submit, 'button', 'upgrade', false ); + } + echo ' ' . $download . ' '; + } + if ( 'en_US' != $update->locale ) + if ( !isset( $update->dismissed ) || !$update->dismissed ) + submit_button( __('Hide this update'), 'button', 'dismiss', false ); + else + submit_button( __('Bring back this update'), 'button', 'undismiss', false ); + echo '

    '; + if ( 'en_US' != $update->locale && ( !isset($wp_local_package) || $wp_local_package != $update->locale ) ) + echo '

    '.__('This localized version contains both the translation and various other localization fixes. You can skip upgrading if you want to keep your current translation.').'

    '; + // Partial builds don't need language-specific warnings. + elseif ( 'en_US' == $update->locale && get_locale() != 'en_US' && ( ! $update->packages->partial && $wp_version == $update->partial_version ) ) { + echo '

    '.sprintf( __('You are about to install WordPress %s in English (US). There is a chance this update will break your translation. You may prefer to wait for the localized version to be released.'), $update->response != 'development' ? $update->current : '' ).'

    '; + } + echo '
    '; + +} + +function dismissed_updates() { + $dismissed = get_core_updates( array( 'dismissed' => true, 'available' => false ) ); + if ( $dismissed ) { + + $show_text = esc_js(__('Show hidden updates')); + $hide_text = esc_js(__('Hide hidden updates')); + ?> + + '.__('Show hidden updates').'

    '; + echo '
      '; + foreach( (array) $dismissed as $update) { + echo '
    • '; + list_core_update( $update ); + echo '
    • '; + } + echo '
    '; + } +} + +/** + * Display upgrade WordPress for downloading latest or upgrading automatically form. + * + * @since 2.7 + * + * @return null + */ +function core_upgrade_preamble() { + global $wp_version, $required_php_version, $required_mysql_version; + + $updates = get_core_updates(); + + if ( !isset($updates[0]->response) || 'latest' == $updates[0]->response ) { + echo '

    '; + _e('You have the latest version of WordPress.'); + + if ( wp_http_supports( array( 'ssl' ) ) ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + $upgrader = new WP_Automatic_Updater; + $future_minor_update = (object) array( + 'current' => $wp_version . '.1.next.minor', + 'version' => $wp_version . '.1.next.minor', + 'php_version' => $required_php_version, + 'mysql_version' => $required_mysql_version, + ); + $should_auto_update = $upgrader->should_update( 'core', $future_minor_update, ABSPATH ); + if ( $should_auto_update ) + echo ' ' . __( 'Future security updates will be applied automatically.' ); + } + echo '

    '; + } else { + echo '

    '; + _e('Important: before updating, please back up your database and files. For help with updates, visit the Updating WordPress Codex page.'); + echo '

    '; + + echo '

    '; + _e( 'An updated version of WordPress is available.' ); + echo '

    '; + } + + if ( isset( $updates[0] ) && $updates[0]->response == 'development' ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + $upgrader = new WP_Automatic_Updater; + if ( wp_http_supports( 'ssl' ) && $upgrader->should_update( 'core', $updates[0], ABSPATH ) ) + echo '

    BETA TESTERS: This site is set up to install updates of future beta versions automatically.

    '; + } + + echo '
      '; + $alternate = true; + foreach( (array) $updates as $update ) { + echo '
    • '; + list_core_update( $update ); + echo '
    • '; + } + echo '
    '; + // Don't show the maintenance mode notice when we are only showing a single re-install option. + if ( $updates && ( count( $updates ) > 1 || $updates[0]->response != 'latest' ) ) { + echo '

    ' . __( 'While your site is being updated, it will be in maintenance mode. As soon as your updates are complete, your site will return to normal.' ) . '

    '; + } elseif ( ! $updates ) { + list( $normalized_version ) = explode( '-', $wp_version ); + echo '

    ' . sprintf( __( 'Learn more about WordPress %s.' ), esc_url( self_admin_url( 'about.php' ) ), $normalized_version ) . '

    '; + } + dismissed_updates(); +} + +function list_plugin_updates() { + global $wp_version; + + $cur_wp_version = preg_replace('/-.*$/', '', $wp_version); + + require_once(ABSPATH . 'wp-admin/includes/plugin-install.php'); + $plugins = get_plugin_updates(); + if ( empty( $plugins ) ) { + echo '

    ' . __( 'Plugins' ) . '

    '; + echo '

    ' . __( 'Your plugins are all up to date.' ) . '

    '; + return; + } + $form_action = 'update-core.php?action=do-plugin-upgrade'; + + $core_updates = get_core_updates(); + if ( !isset($core_updates[0]->response) || 'latest' == $core_updates[0]->response || 'development' == $core_updates[0]->response || version_compare( $core_updates[0]->current, $cur_wp_version, '=') ) + $core_update_version = false; + else + $core_update_version = $core_updates[0]->current; + ?> +

    +

    +
    + +

    + + + + + + + + + + + + + + + + $plugin_data) { + $info = plugins_api('plugin_information', array('slug' => $plugin_data->update->slug )); + // Get plugin compat for running version of WordPress. + if ( isset($info->tested) && version_compare($info->tested, $cur_wp_version, '>=') ) { + $compat = '
    ' . sprintf(__('Compatibility with WordPress %1$s: 100%% (according to its author)'), $cur_wp_version); + } elseif ( isset($info->compatibility[$cur_wp_version][$plugin_data->update->new_version]) ) { + $compat = $info->compatibility[$cur_wp_version][$plugin_data->update->new_version]; + $compat = '
    ' . sprintf(__('Compatibility with WordPress %1$s: %2$d%% (%3$d "works" votes out of %4$d total)'), $cur_wp_version, $compat[0], $compat[2], $compat[1]); + } else { + $compat = '
    ' . sprintf(__('Compatibility with WordPress %1$s: Unknown'), $cur_wp_version); + } + // Get plugin compat for updated version of WordPress. + if ( $core_update_version ) { + if ( isset($info->compatibility[$core_update_version][$plugin_data->update->new_version]) ) { + $update_compat = $info->compatibility[$core_update_version][$plugin_data->update->new_version]; + $compat .= '
    ' . sprintf(__('Compatibility with WordPress %1$s: %2$d%% (%3$d "works" votes out of %4$d total)'), $core_update_version, $update_compat[0], $update_compat[2], $update_compat[1]); + } else { + $compat .= '
    ' . sprintf(__('Compatibility with WordPress %1$s: Unknown'), $core_update_version); + } + } + // Get the upgrade notice for the new plugin version. + if ( isset($plugin_data->update->upgrade_notice) ) { + $upgrade_notice = '
    ' . strip_tags($plugin_data->update->upgrade_notice); + } else { + $upgrade_notice = ''; + } + + $details_url = self_admin_url('plugin-install.php?tab=plugin-information&plugin=' . $plugin_data->update->slug . '§ion=changelog&TB_iframe=true&width=640&height=662'); + $details_text = sprintf(__('View version %1$s details'), $plugin_data->update->new_version); + $details = sprintf('%3$s.', esc_url($details_url), esc_attr($plugin_data->Name), $details_text); + + echo " + + + + "; + } +?> + +

    {$plugin_data->Name}
    " . sprintf(__('You have version %1$s installed. Update to %2$s.'), $plugin_data->Version, $plugin_data->update->new_version) . ' ' . $details . $compat . $upgrade_notice . "

    +

    +
    +' . __( 'Themes' ) . ''; + echo '

    ' . __( 'Your themes are all up to date.' ) . '

    '; + return; + } + + $form_action = 'update-core.php?action=do-theme-upgrade'; + +?> +

    +

    +

    Please Note: Any customizations you have made to theme files will be lost. Please consider using child themes for modifications.' ), __( 'http://codex.wordpress.org/Child_Themes' ) ); ?>

    +
    + +

    + + + + + + + + + + + + + + + + $theme ) { + echo " + + + + "; + } +?> + +
    " . $theme->display('Name') . ' ' . sprintf( __( 'You have version %1$s installed. Update to %2$s.' ), $theme->display('Version'), $theme->update['new_version'] ) . "
    +

    +
    +' . __( 'Translations' ) . ''; + echo '

    ' . __( 'Your translations are all up to date.' ) . '

    '; + } + return; + } + + $form_action = 'update-core.php?action=do-translation-upgrade'; + ?> +

    +
    +

    + +

    +
    + +
    + +

    +'; + return; + } + + if ( ! WP_Filesystem( $credentials, ABSPATH ) ) { + // Failed to connect, Error and request again + request_filesystem_credentials( $url, '', true, ABSPATH ); + echo '
    '; + return; + } + + if ( $wp_filesystem->errors->get_error_code() ) { + foreach ( $wp_filesystem->errors->get_error_messages() as $message ) + show_message($message); + echo ''; + return; + } + + if ( $reinstall ) + $update->response = 'reinstall'; + + add_filter( 'update_feedback', 'show_message' ); + + $upgrader = new Core_Upgrader(); + $result = $upgrader->upgrade( $update ); + + if ( is_wp_error($result) ) { + show_message($result); + if ('up_to_date' != $result->get_error_code() ) + show_message( __('Installation Failed') ); + echo ''; + return; + } + + show_message( __('WordPress updated successfully') ); + show_message( '' . sprintf( __( 'Welcome to WordPress %1$s. You will be redirected to the About WordPress screen. If not, click here.' ), $result, esc_url( self_admin_url( 'about.php?updated' ) ) ) . '' ); + show_message( '' . sprintf( __( 'Welcome to WordPress %1$s. Learn more.' ), $result, esc_url( self_admin_url( 'about.php?updated' ) ) ) . '' ); + ?> + + + add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

    ' . __('This screen lets you update to the latest version of WordPress as well as update your themes and plugins from the WordPress.org repository. When updates are available, the number of available updates will appear in a bubble on the left hand menu as a notification.') . '

    ' . + '

    ' . __('It is very important to keep your WordPress installation up to date for security reasons, so when you see a number appear, make sure you take the time to update, which is an easy process.') . '

    ' +) ); + +get_current_screen()->add_help_tab( array( +'id' => 'how-to-update', +'title' => __('How to Update'), +'content' => + '

    ' . __('Updating your WordPress installation is a simple one-click procedure; just click on the Update button when it says a new version is available.') . '

    ' . + '

    ' . __('To update themes or plugins from this screen, use the checkboxes to make your selection and click on the appropriate Update button. Check the box at the top of the Themes or Plugins section to select all and update them all at once.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Updating WordPress') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +if ( 'upgrade-core' == $action ) { + + wp_version_check(); + require_once(ABSPATH . 'wp-admin/admin-header.php'); + ?> +
    + +

    +

    '; + if ( $upgrade_error == 'themes' ) + _e('Please select one or more themes to update.'); + else + _e('Please select one or more plugins to update.'); + echo '

    '; + } + + echo '

    '; + /* translators: %1 date, %2 time. */ + printf( __('Last checked on %1$s at %2$s.'), date_i18n( get_option( 'date_format' ) ), date_i18n( get_option( 'time_format' ) ) ); + echo '   ' . __( 'Check Again' ) . ''; + echo '

    '; + + if ( $core = current_user_can( 'update_core' ) ) + core_upgrade_preamble(); + if ( $plugins = current_user_can( 'update_plugins' ) ) + list_plugin_updates(); + if ( $themes = current_user_can( 'update_themes' ) ) + list_theme_updates(); + if ( $core || $plugins || $themes ) + list_translation_updates(); + unset( $core, $plugins, $themes ); + do_action('core_upgrade_preamble'); + echo ''; + include(ABSPATH . 'wp-admin/admin-footer.php'); + +} elseif ( 'do-core-upgrade' == $action || 'do-core-reinstall' == $action ) { + + if ( ! current_user_can( 'update_core' ) ) + wp_die( __( 'You do not have sufficient permissions to update this site.' ) ); + + check_admin_referer('upgrade-core'); + + // do the (un)dismiss actions before headers, + // so that they can redirect + if ( isset( $_POST['dismiss'] ) ) + do_dismiss_core_update(); + elseif ( isset( $_POST['undismiss'] ) ) + do_undismiss_core_update(); + + require_once(ABSPATH . 'wp-admin/admin-header.php'); + if ( 'do-core-reinstall' == $action ) + $reinstall = true; + else + $reinstall = false; + + if ( isset( $_POST['upgrade'] ) ) + do_core_upgrade($reinstall); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + +} elseif ( 'do-plugin-upgrade' == $action ) { + + if ( ! current_user_can( 'update_plugins' ) ) + wp_die( __( 'You do not have sufficient permissions to update this site.' ) ); + + check_admin_referer('upgrade-core'); + + if ( isset( $_GET['plugins'] ) ) { + $plugins = explode( ',', $_GET['plugins'] ); + } elseif ( isset( $_POST['checked'] ) ) { + $plugins = (array) $_POST['checked']; + } else { + wp_redirect( admin_url('update-core.php') ); + exit; + } + + $url = 'update.php?action=update-selected&plugins=' . urlencode(implode(',', $plugins)); + $url = wp_nonce_url($url, 'bulk-update-plugins'); + + $title = __('Update Plugins'); + + require_once(ABSPATH . 'wp-admin/admin-header.php'); + echo '
    '; + screen_icon('plugins'); + echo '

    ' . esc_html__('Update Plugins') . '

    '; + echo ""; + echo '
    '; + include(ABSPATH . 'wp-admin/admin-footer.php'); + +} elseif ( 'do-theme-upgrade' == $action ) { + + if ( ! current_user_can( 'update_themes' ) ) + wp_die( __( 'You do not have sufficient permissions to update this site.' ) ); + + check_admin_referer('upgrade-core'); + + if ( isset( $_GET['themes'] ) ) { + $themes = explode( ',', $_GET['themes'] ); + } elseif ( isset( $_POST['checked'] ) ) { + $themes = (array) $_POST['checked']; + } else { + wp_redirect( admin_url('update-core.php') ); + exit; + } + + $url = 'update.php?action=update-selected-themes&themes=' . urlencode(implode(',', $themes)); + $url = wp_nonce_url($url, 'bulk-update-themes'); + + $title = __('Update Themes'); + + require_once(ABSPATH . 'wp-admin/admin-header.php'); + echo '
    '; + screen_icon('themes'); + echo '

    ' . esc_html__('Update Themes') . '

    '; + echo ""; + echo '
    '; + include(ABSPATH . 'wp-admin/admin-footer.php'); + +} elseif ( 'do-translation-upgrade' == $action ) { + + if ( ! current_user_can( 'update_core' ) && ! current_user_can( 'update_plugins' ) && ! current_user_can( 'update_themes' ) ) + wp_die( __( 'You do not have sufficient permissions to update this site.' ) ); + + check_admin_referer( 'upgrade-translations' ); + + require_once( ABSPATH . 'wp-admin/admin-header.php' ); + include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); + + $url = 'update-core.php?action=do-translation-upgrade'; + $nonce = 'upgrade-translations'; + $title = __( 'Update Translations' ); + $context = WP_LANG_DIR; + + $upgrader = new Language_Pack_Upgrader( new Language_Pack_Upgrader_Skin( compact( 'url', 'nonce', 'title', 'context' ) ) ); + $result = $upgrader->bulk_upgrade(); + + require_once( ABSPATH . 'wp-admin/admin-footer.php' ); + +} else { + do_action('update-core-custom_' . $action); +} diff --git a/sources/wp-admin/update.php b/sources/wp-admin/update.php new file mode 100644 index 0000000..b89ada2 --- /dev/null +++ b/sources/wp-admin/update.php @@ -0,0 +1,257 @@ +bulk_upgrade( $plugins ); + + iframe_footer(); + + } elseif ( 'upgrade-plugin' == $action ) { + if ( ! current_user_can('update_plugins') ) + wp_die(__('You do not have sufficient permissions to update plugins for this site.')); + + check_admin_referer('upgrade-plugin_' . $plugin); + + $title = __('Update Plugin'); + $parent_file = 'plugins.php'; + $submenu_file = 'plugins.php'; + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + $nonce = 'upgrade-plugin_' . $plugin; + $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin ); + + $upgrader = new Plugin_Upgrader( new Plugin_Upgrader_Skin( compact('title', 'nonce', 'url', 'plugin') ) ); + $upgrader->upgrade($plugin); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + } elseif ('activate-plugin' == $action ) { + if ( ! current_user_can('update_plugins') ) + wp_die(__('You do not have sufficient permissions to update plugins for this site.')); + + check_admin_referer('activate-plugin_' . $plugin); + if ( ! isset($_GET['failure']) && ! isset($_GET['success']) ) { + wp_redirect( admin_url('update.php?action=activate-plugin&failure=true&plugin=' . urlencode( $plugin ) . '&_wpnonce=' . $_GET['_wpnonce']) ); + activate_plugin( $plugin, '', ! empty( $_GET['networkwide'] ), true ); + wp_redirect( admin_url('update.php?action=activate-plugin&success=true&plugin=' . urlencode( $plugin ) . '&_wpnonce=' . $_GET['_wpnonce']) ); + die(); + } + iframe_header( __('Plugin Reactivation'), true ); + if ( isset($_GET['success']) ) + echo '

    ' . __('Plugin reactivated successfully.') . '

    '; + + if ( isset($_GET['failure']) ){ + echo '

    ' . __('Plugin failed to reactivate due to a fatal error.') . '

    '; + + error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR ); + @ini_set('display_errors', true); //Ensure that Fatal errors are displayed. + include(WP_PLUGIN_DIR . '/' . $plugin); + } + iframe_footer(); + } elseif ( 'install-plugin' == $action ) { + + if ( ! current_user_can('install_plugins') ) + wp_die( __( 'You do not have sufficient permissions to install plugins on this site.' ) ); + + include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; //for plugins_api.. + + check_admin_referer('install-plugin_' . $plugin); + $api = plugins_api('plugin_information', array('slug' => $plugin, 'fields' => array('sections' => false) ) ); //Save on a bit of bandwidth. + + if ( is_wp_error($api) ) + wp_die($api); + + $title = __('Plugin Install'); + $parent_file = 'plugins.php'; + $submenu_file = 'plugin-install.php'; + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + $title = sprintf( __('Installing Plugin: %s'), $api->name . ' ' . $api->version ); + $nonce = 'install-plugin_' . $plugin; + $url = 'update.php?action=install-plugin&plugin=' . urlencode( $plugin ); + if ( isset($_GET['from']) ) + $url .= '&from=' . urlencode(stripslashes($_GET['from'])); + + $type = 'web'; //Install plugin type, From Web or an Upload. + + $upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact('title', 'url', 'nonce', 'plugin', 'api') ) ); + $upgrader->install($api->download_link); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + } elseif ( 'upload-plugin' == $action ) { + + if ( ! current_user_can('install_plugins') ) + wp_die( __( 'You do not have sufficient permissions to install plugins on this site.' ) ); + + check_admin_referer('plugin-upload'); + + $file_upload = new File_Upload_Upgrader('pluginzip', 'package'); + + $title = __('Upload Plugin'); + $parent_file = 'plugins.php'; + $submenu_file = 'plugin-install.php'; + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + $title = sprintf( __('Installing Plugin from uploaded file: %s'), esc_html( basename( $file_upload->filename ) ) ); + $nonce = 'plugin-upload'; + $url = add_query_arg(array('package' => $file_upload->id), 'update.php?action=upload-plugin'); + $type = 'upload'; //Install plugin type, From Web or an Upload. + + $upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact('type', 'title', 'nonce', 'url') ) ); + $result = $upgrader->install( $file_upload->package ); + + if ( $result || is_wp_error($result) ) + $file_upload->cleanup(); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + } elseif ( 'upgrade-theme' == $action ) { + + if ( ! current_user_can('update_themes') ) + wp_die(__('You do not have sufficient permissions to update themes for this site.')); + + check_admin_referer('upgrade-theme_' . $theme); + + wp_enqueue_script( 'customize-loader' ); + + $title = __('Update Theme'); + $parent_file = 'themes.php'; + $submenu_file = 'themes.php'; + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + $nonce = 'upgrade-theme_' . $theme; + $url = 'update.php?action=upgrade-theme&theme=' . urlencode( $theme ); + + $upgrader = new Theme_Upgrader( new Theme_Upgrader_Skin( compact('title', 'nonce', 'url', 'theme') ) ); + $upgrader->upgrade($theme); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + } elseif ( 'update-selected-themes' == $action ) { + if ( ! current_user_can( 'update_themes' ) ) + wp_die( __( 'You do not have sufficient permissions to update themes for this site.' ) ); + + check_admin_referer( 'bulk-update-themes' ); + + if ( isset( $_GET['themes'] ) ) + $themes = explode( ',', stripslashes($_GET['themes']) ); + elseif ( isset( $_POST['checked'] ) ) + $themes = (array) $_POST['checked']; + else + $themes = array(); + + $themes = array_map('urldecode', $themes); + + $url = 'update.php?action=update-selected-themes&themes=' . urlencode(implode(',', $themes)); + $nonce = 'bulk-update-themes'; + + wp_enqueue_script('jquery'); + iframe_header(); + + $upgrader = new Theme_Upgrader( new Bulk_Theme_Upgrader_Skin( compact( 'nonce', 'url' ) ) ); + $upgrader->bulk_upgrade( $themes ); + + iframe_footer(); + } elseif ( 'install-theme' == $action ) { + + if ( ! current_user_can('install_themes') ) + wp_die( __( 'You do not have sufficient permissions to install themes on this site.' ) ); + + include_once ABSPATH . 'wp-admin/includes/theme-install.php'; //for themes_api.. + + check_admin_referer('install-theme_' . $theme); + $api = themes_api('theme_information', array('slug' => $theme, 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth. + + if ( is_wp_error($api) ) + wp_die($api); + + wp_enqueue_script( 'customize-loader' ); + + $title = __('Install Themes'); + $parent_file = 'themes.php'; + $submenu_file = 'themes.php'; + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + $title = sprintf( __('Installing Theme: %s'), $api->name . ' ' . $api->version ); + $nonce = 'install-theme_' . $theme; + $url = 'update.php?action=install-theme&theme=' . urlencode( $theme ); + $type = 'web'; //Install theme type, From Web or an Upload. + + $upgrader = new Theme_Upgrader( new Theme_Installer_Skin( compact('title', 'url', 'nonce', 'plugin', 'api') ) ); + $upgrader->install($api->download_link); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + } elseif ( 'upload-theme' == $action ) { + + if ( ! current_user_can('install_themes') ) + wp_die( __( 'You do not have sufficient permissions to install themes on this site.' ) ); + + check_admin_referer('theme-upload'); + + $file_upload = new File_Upload_Upgrader('themezip', 'package'); + + wp_enqueue_script( 'customize-loader' ); + + $title = __('Upload Theme'); + $parent_file = 'themes.php'; + $submenu_file = 'theme-install.php'; + + require_once(ABSPATH . 'wp-admin/admin-header.php'); + + $title = sprintf( __('Installing Theme from uploaded file: %s'), esc_html( basename( $file_upload->filename ) ) ); + $nonce = 'theme-upload'; + $url = add_query_arg(array('package' => $file_upload->id), 'update.php?action=upload-theme'); + $type = 'upload'; //Install plugin type, From Web or an Upload. + + $upgrader = new Theme_Upgrader( new Theme_Installer_Skin( compact('type', 'title', 'nonce', 'url') ) ); + $result = $upgrader->install( $file_upload->package ); + + if ( $result || is_wp_error($result) ) + $file_upload->cleanup(); + + include(ABSPATH . 'wp-admin/admin-footer.php'); + + } else { + do_action('update-custom_' . $action); + } +} diff --git a/sources/wp-admin/upgrade-functions.php b/sources/wp-admin/upgrade-functions.php new file mode 100644 index 0000000..080d74d --- /dev/null +++ b/sources/wp-admin/upgrade-functions.php @@ -0,0 +1,12 @@ +db_version(); +$php_compat = version_compare( $php_version, $required_php_version, '>=' ); +if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) + $mysql_compat = true; +else + $mysql_compat = version_compare( $mysql_version, $required_mysql_version, '>=' ); + +@header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) ); +?> + +> + + + <?php _e( 'WordPress › Update' ); ?> + + + +

    + + + +

    +

    +

    + +WordPress %1$s requires PHP version %2$s or higher and MySQL version %3$s or higher. You are running PHP version %4$s and MySQL version %5$s.'), $wp_version, $required_php_version, $required_mysql_version, $php_version, $mysql_version ); + elseif ( !$php_compat ) + printf( __('You cannot update because WordPress %1$s requires PHP version %2$s or higher. You are running version %3$s.'), $wp_version, $required_php_version, $php_version ); + elseif ( !$mysql_compat ) + printf( __('You cannot update because WordPress %1$s requires MySQL version %2$s or higher. You are running version %3$s.'), $wp_version, $required_mysql_version, $mysql_version ); +?> + +

    +

    +

    +

    + +

    +

    +

    + + + + + + diff --git a/sources/wp-admin/upload.php b/sources/wp-admin/upload.php new file mode 100644 index 0000000..64d0f84 --- /dev/null +++ b/sources/wp-admin/upload.php @@ -0,0 +1,250 @@ +get_pagenum(); + +// Handle bulk actions +$doaction = $wp_list_table->current_action(); + +if ( $doaction ) { + check_admin_referer('bulk-media'); + + if ( 'delete_all' == $doaction ) { + $post_ids = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_type='attachment' AND post_status = 'trash'" ); + $doaction = 'delete'; + } elseif ( isset( $_REQUEST['media'] ) ) { + $post_ids = $_REQUEST['media']; + } elseif ( isset( $_REQUEST['ids'] ) ) { + $post_ids = explode( ',', $_REQUEST['ids'] ); + } + + $location = 'upload.php'; + if ( $referer = wp_get_referer() ) { + if ( false !== strpos( $referer, 'upload.php' ) ) + $location = remove_query_arg( array( 'trashed', 'untrashed', 'deleted', 'message', 'ids', 'posted' ), $referer ); + } + + switch ( $doaction ) { + case 'find_detached': + if ( !current_user_can('edit_posts') ) + wp_die( __('You are not allowed to scan for lost attachments.') ); + + $lost = $wpdb->get_col( " + SELECT ID FROM $wpdb->posts + WHERE post_type = 'attachment' AND post_parent > '0' + AND post_parent NOT IN ( + SELECT ID FROM $wpdb->posts + WHERE post_type NOT IN ( 'attachment', '" . join( "', '", get_post_types( array( 'public' => false ) ) ) . "' ) + ) + " ); + + $_REQUEST['detached'] = 1; + break; + case 'attach': + $parent_id = (int) $_REQUEST['found_post_id']; + if ( !$parent_id ) + return; + + $parent = get_post( $parent_id ); + if ( !current_user_can( 'edit_post', $parent_id ) ) + wp_die( __( 'You are not allowed to edit this post.' ) ); + + $attach = array(); + foreach ( (array) $_REQUEST['media'] as $att_id ) { + $att_id = (int) $att_id; + + if ( !current_user_can( 'edit_post', $att_id ) ) + continue; + + $attach[] = $att_id; + } + + if ( ! empty( $attach ) ) { + $attach_string = implode( ',', $attach ); + $attached = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %d WHERE post_type = 'attachment' AND ID IN ( $attach_string )", $parent_id ) ); + foreach ( $attach as $att_id ) { + clean_attachment_cache( $att_id ); + } + } + + if ( isset( $attached ) ) { + $location = 'upload.php'; + if ( $referer = wp_get_referer() ) { + if ( false !== strpos( $referer, 'upload.php' ) ) + $location = $referer; + } + + $location = add_query_arg( array( 'attached' => $attached ) , $location ); + wp_redirect( $location ); + exit; + } + break; + case 'trash': + if ( !isset( $post_ids ) ) + break; + foreach ( (array) $post_ids as $post_id ) { + if ( !current_user_can( 'delete_post', $post_id ) ) + wp_die( __( 'You are not allowed to move this post to the trash.' ) ); + + if ( !wp_trash_post( $post_id ) ) + wp_die( __( 'Error in moving to trash.' ) ); + } + $location = add_query_arg( array( 'trashed' => count( $post_ids ), 'ids' => join( ',', $post_ids ) ), $location ); + break; + case 'untrash': + if ( !isset( $post_ids ) ) + break; + foreach ( (array) $post_ids as $post_id ) { + if ( !current_user_can( 'delete_post', $post_id ) ) + wp_die( __( 'You are not allowed to move this post out of the trash.' ) ); + + if ( !wp_untrash_post( $post_id ) ) + wp_die( __( 'Error in restoring from trash.' ) ); + } + $location = add_query_arg( 'untrashed', count( $post_ids ), $location ); + break; + case 'delete': + if ( !isset( $post_ids ) ) + break; + foreach ( (array) $post_ids as $post_id_del ) { + if ( !current_user_can( 'delete_post', $post_id_del ) ) + wp_die( __( 'You are not allowed to delete this post.' ) ); + + if ( !wp_delete_attachment( $post_id_del ) ) + wp_die( __( 'Error in deleting.' ) ); + } + $location = add_query_arg( 'deleted', count( $post_ids ), $location ); + break; + } + + wp_redirect( $location ); + exit; +} elseif ( ! empty( $_GET['_wp_http_referer'] ) ) { + wp_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); + exit; +} + +$wp_list_table->prepare_items(); + +$title = __('Media Library'); +$parent_file = 'upload.php'; + +wp_enqueue_script( 'wp-ajax-response' ); +wp_enqueue_script( 'jquery-ui-draggable' ); +wp_enqueue_script( 'media' ); + +add_screen_option( 'per_page', array('label' => _x( 'Media items', 'items per page (screen options)' )) ); + +get_current_screen()->add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

    ' . __( 'All the files you’ve uploaded are listed in the Media Library, with the most recent uploads listed first. You can use the Screen Options tab to customize the display of this screen.' ) . '

    ' . + '

    ' . __( 'You can narrow the list by file type/status using the text link filters at the top of the screen. You also can refine the list by date using the dropdown menu above the media table.' ) . '

    ' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'actions-links', +'title' => __('Available Actions'), +'content' => + '

    ' . __( 'Hovering over a row reveals action links: Edit, Delete Permanently, and View. Clicking Edit or on the media file’s name displays a simple screen to edit that individual file’s metadata. Clicking Delete Permanently will delete the file from the media library (as well as from any posts to which it is currently attached). View will take you to the display page for that file.' ) . '

    ' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'attaching-files', +'title' => __('Attaching Files'), +'content' => + '

    ' . __( 'If a media file has not been attached to any post, you will see that in the Attached To column, and can click on Attach File to launch a small popup that will allow you to search for a post and attach the file.' ) . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __( 'For more information:' ) . '

    ' . + '

    ' . __( 'Documentation on Media Library' ) . '

    ' . + '

    ' . __( 'Support Forums' ) . '

    ' +); + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); +?> + +
    + +

    + + ' . __('Search results for “%s”') . '', get_search_query() ); ?> +

    + +' . __('Undo') . ''; + $_SERVER['REQUEST_URI'] = remove_query_arg(array('trashed'), $_SERVER['REQUEST_URI']); +} + +if ( ! empty( $_GET['untrashed'] ) && $untrashed = absint( $_GET['untrashed'] ) ) { + $message = sprintf( _n( 'Media attachment restored from the trash.', '%d media attachments restored from the trash.', $untrashed ), number_format_i18n( $_GET['untrashed'] ) ); + $_SERVER['REQUEST_URI'] = remove_query_arg(array('untrashed'), $_SERVER['REQUEST_URI']); +} + +$messages[1] = __('Media attachment updated.'); +$messages[2] = __('Media permanently deleted.'); +$messages[3] = __('Error saving media attachment.'); +$messages[4] = __('Media moved to the trash.') . ' ' . __('Undo') . ''; +$messages[5] = __('Media restored from the trash.'); + +if ( ! empty( $_GET['message'] ) && isset( $messages[ $_GET['message'] ] ) ) { + $message = $messages[ $_GET['message'] ]; + $_SERVER['REQUEST_URI'] = remove_query_arg(array('message'), $_SERVER['REQUEST_URI']); +} + +if ( !empty($message) ) { ?> +

    + + +views(); ?> + +
    + +search_box( __( 'Search Media' ), 'media' ); ?> + +display(); ?> + +
    + +
    + +
    +
    + +ID ) ); + +if ( ! $user_id && IS_PROFILE_PAGE ) + $user_id = $current_user->ID; +elseif ( ! $user_id && ! IS_PROFILE_PAGE ) + wp_die(__( 'Invalid user ID.' ) ); +elseif ( ! get_userdata( $user_id ) ) + wp_die( __('Invalid user ID.') ); + +wp_enqueue_script('user-profile'); + +$title = IS_PROFILE_PAGE ? __('Profile') : __('Edit User'); +if ( current_user_can('edit_users') && !IS_PROFILE_PAGE ) + $submenu_file = 'users.php'; +else + $submenu_file = 'profile.php'; + +if ( current_user_can('edit_users') && !is_user_admin() ) + $parent_file = 'users.php'; +else + $parent_file = 'profile.php'; + +$profile_help = '

    ' . __('Your profile contains information about you (your “account”) as well as some personal options related to using WordPress.') . '

    ' . + '

    ' . __('You can change your password, turn on keyboard shortcuts, change the color scheme of your WordPress administration screens, and turn off the WYSIWYG (Visual) editor, among other things. You can hide the Toolbar (formerly called the Admin Bar) from the front end of your site, however it cannot be disabled on the admin screens.') . '

    ' . + '

    ' . __('Your username cannot be changed, but you can use other fields to enter your real name or a nickname, and change which name to display on your posts.') . '

    ' . + '

    ' . __('Required fields are indicated; the rest are optional. Profile information will only be displayed if your theme is set up to do so.') . '

    ' . + '

    ' . __('Remember to click the Update Profile button when you are finished.') . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $profile_help, +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on User Profiles') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +$wp_http_referer = remove_query_arg(array('update', 'delete_count'), $wp_http_referer ); + +$user_can_edit = current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ); + +/** + * Optional SSL preference that can be turned on by hooking to the 'personal_options' action. + * + * @since 2.7.0 + * + * @param object $user User data object + */ +function use_ssl_preference($user) { +?> + + + + +ID && ! apply_filters( 'enable_edit_any_user_configuration', true ) ) + wp_die( __( 'You do not have permission to edit this user.' ) ); + +// Execute confirmed email change. See send_confirmation_on_profile_email(). +if ( is_multisite() && IS_PROFILE_PAGE && isset( $_GET[ 'newuseremail' ] ) && $current_user->ID ) { + $new_email = get_option( $current_user->ID . '_new_email' ); + if ( $new_email[ 'hash' ] == $_GET[ 'newuseremail' ] ) { + $user = new stdClass; + $user->ID = $current_user->ID; + $user->user_email = esc_html( trim( $new_email[ 'newemail' ] ) ); + if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->signups} WHERE user_login = %s", $current_user->user_login ) ) ) + $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->signups} SET user_email = %s WHERE user_login = %s", $user->user_email, $current_user->user_login ) ); + wp_update_user( $user ); + delete_option( $current_user->ID . '_new_email' ); + wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) ); + die(); + } +} elseif ( is_multisite() && IS_PROFILE_PAGE && !empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' == $_GET['dismiss'] ) { + delete_option( $current_user->ID . '_new_email' ); + wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) ); + die(); +} + +switch ($action) { +case 'update': + +check_admin_referer('update-user_' . $user_id); + +if ( !current_user_can('edit_user', $user_id) ) + wp_die(__('You do not have permission to edit this user.')); + +if ( IS_PROFILE_PAGE ) + do_action('personal_options_update', $user_id); +else + do_action('edit_user_profile_update', $user_id); + +if ( !is_multisite() ) { + $errors = edit_user($user_id); +} else { + $user = get_userdata( $user_id ); + + // Update the email address in signups, if present. + if ( $user->user_login && isset( $_POST[ 'email' ] ) && is_email( $_POST[ 'email' ] ) && $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->signups} WHERE user_login = %s", $user->user_login ) ) ) + $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->signups} SET user_email = %s WHERE user_login = %s", $_POST[ 'email' ], $user_login ) ); + + // WPMU must delete the user from the current blog if WP added him after editing. + $delete_role = false; + $blog_prefix = $wpdb->get_blog_prefix(); + if ( $user_id != $current_user->ID ) { + $cap = $wpdb->get_var( "SELECT meta_value FROM {$wpdb->usermeta} WHERE user_id = '{$user_id}' AND meta_key = '{$blog_prefix}capabilities' AND meta_value = 'a:0:{}'" ); + if ( !is_network_admin() && null == $cap && $_POST[ 'role' ] == '' ) { + $_POST[ 'role' ] = 'contributor'; + $delete_role = true; + } + } + if ( !isset( $errors ) || ( isset( $errors ) && is_object( $errors ) && false == $errors->get_error_codes() ) ) + $errors = edit_user($user_id); + if ( $delete_role ) // stops users being added to current blog when they are edited + delete_user_meta( $user_id, $blog_prefix . 'capabilities' ); + + if ( is_multisite() && is_network_admin() && !IS_PROFILE_PAGE && current_user_can( 'manage_network_options' ) && !isset($super_admins) && empty( $_POST['super_admin'] ) == is_super_admin( $user_id ) ) + empty( $_POST['super_admin'] ) ? revoke_super_admin( $user_id ) : grant_super_admin( $user_id ); +} + +if ( !is_wp_error( $errors ) ) { + $redirect = add_query_arg( 'updated', true, get_edit_user_link( $user_id ) ); + if ( $wp_http_referer ) + $redirect = add_query_arg('wp_http_referer', urlencode($wp_http_referer), $redirect); + wp_redirect($redirect); + exit; +} + +default: +$profileuser = get_user_to_edit($user_id); + +if ( !current_user_can('edit_user', $user_id) ) + wp_die(__('You do not have permission to edit this user.')); + +include (ABSPATH . 'wp-admin/admin-header.php'); +?> + +ID ) && current_user_can( 'manage_network_options' ) ) { ?> +

    + + +
    + +

    + +

    + + +

    + +
    + + +

    \n

    ", $errors->get_error_messages() ); ?>

    + + +
    + +

    + + + + + +

    + +
    > + + + + +

    + + +

    + +

    + + + + + + + + + 1 && has_action('admin_color_scheme_picker') ) : ?> + + + + + + + + + + + + + + + +
    More information'); ?>
    +
    +
    +
    + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +user_email != get_site_option( 'admin_email' ) || ! is_super_admin( $profileuser->ID ) ) : ?> +

    + +

    + +
    + +
    + +

    + + + + + + + + + + + + + $desc ) { +?> + + + + + +
    + ID . '_new_email' ); + if ( $new_email && $new_email['newemail'] != $current_user->user_email && $profileuser->ID == $current_user->ID ) : ?> +
    +

    %1$s. Cancel'), $new_email['newemail'], esc_url( self_admin_url( 'profile.php?dismiss=' . $current_user->ID . '_new_email' ) ) ); ?>

    +
    + +
    + +

    + + + + + + + + + + + + + + + + + +

    +
    + + +
    + +
    +
    +

    +
    + + + +caps ) > count( $profileuser->roles ) && apply_filters( 'additional_capabilities_display', true, $profileuser ) ) : ?> +

    + + + + + +
    +caps as $cap => $value ) { + if ( ! $wp_roles->is_role( $cap ) ) { + if ( '' != $output ) + $output .= ', '; + $output .= $value ? $cap : sprintf( __( 'Denied: %s' ), $cap ); + } + } + echo $output; +?> +
    + + + + + + + +
    +
    + + + 'enter_email'), 'user-new.php' ) ); + die(); + } + } + + if ( !$user_details ) { + wp_redirect( add_query_arg( array('update' => 'does_not_exist'), 'user-new.php' ) ); + die(); + } + + if ( ! current_user_can('promote_user', $user_details->ID) ) + wp_die(__('Cheatin’ uh?')); + + // Adding an existing user to this blog + $new_user_email = $user_details->user_email; + $redirect = 'user-new.php'; + $username = $user_details->user_login; + $user_id = $user_details->ID; + if ( ( $username != null && !is_super_admin( $user_id ) ) && ( array_key_exists($blog_id, get_blogs_of_user($user_id)) ) ) { + $redirect = add_query_arg( array('update' => 'addexisting'), 'user-new.php' ); + } else { + if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) { + add_existing_user_to_blog( array( 'user_id' => $user_id, 'role' => $_REQUEST[ 'role' ] ) ); + $redirect = add_query_arg( array('update' => 'addnoconfirmation'), 'user-new.php' ); + } else { + $newuser_key = substr( md5( $user_id ), 0, 5 ); + add_option( 'new_user_' . $newuser_key, array( 'user_id' => $user_id, 'email' => $user_details->user_email, 'role' => $_REQUEST[ 'role' ] ) ); + + $roles = get_editable_roles(); + $role = $roles[ $_REQUEST['role'] ]; + /* translators: 1: Site name, 2: site URL, 3: role, 4: activation URL */ + $message = __( 'Hi, + +You\'ve been invited to join \'%1$s\' at +%2$s with the role of %3$s. + +Please click the following link to confirm the invite: +%4$s' ); + wp_mail( $new_user_email, sprintf( __( '[%s] Joining confirmation' ), get_option( 'blogname' ) ), sprintf( $message, get_option( 'blogname' ), home_url(), wp_specialchars_decode( translate_user_role( $role['name'] ) ), home_url( "/newbloguser/$newuser_key/" ) ) ); + $redirect = add_query_arg( array('update' => 'add'), 'user-new.php' ); + } + } + wp_redirect( $redirect ); + die(); +} elseif ( isset($_REQUEST['action']) && 'createuser' == $_REQUEST['action'] ) { + check_admin_referer( 'create-user', '_wpnonce_create-user' ); + + if ( ! current_user_can('create_users') ) + wp_die(__('Cheatin’ uh?')); + + if ( ! is_multisite() ) { + $user_id = edit_user(); + + if ( is_wp_error( $user_id ) ) { + $add_user_errors = $user_id; + } else { + if ( current_user_can( 'list_users' ) ) + $redirect = 'users.php?update=add&id=' . $user_id; + else + $redirect = add_query_arg( 'update', 'add', 'user-new.php' ); + wp_redirect( $redirect ); + die(); + } + } else { + // Adding a new user to this site + $user_details = wpmu_validate_user_signup( $_REQUEST[ 'user_login' ], $_REQUEST[ 'email' ] ); + if ( is_wp_error( $user_details[ 'errors' ] ) && !empty( $user_details[ 'errors' ]->errors ) ) { + $add_user_errors = $user_details[ 'errors' ]; + } else { + /** + * Filter the user_login, aka the username, before it is added to the site. + * + * @since 3.0.0 + * + * @param string $_REQUEST['user_login'] The sanitized username. + */ + $new_user_login = apply_filters( 'pre_user_login', sanitize_user( wp_unslash( $_REQUEST['user_login'] ), true ) ); + if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) { + add_filter( 'wpmu_signup_user_notification', '__return_false' ); // Disable confirmation email + } + wpmu_signup_user( $new_user_login, $_REQUEST[ 'email' ], array( 'add_to_blog' => $wpdb->blogid, 'new_role' => $_REQUEST[ 'role' ] ) ); + if ( isset( $_POST[ 'noconfirmation' ] ) && is_super_admin() ) { + $key = $wpdb->get_var( $wpdb->prepare( "SELECT activation_key FROM {$wpdb->signups} WHERE user_login = %s AND user_email = %s", $new_user_login, $_REQUEST[ 'email' ] ) ); + wpmu_activate_signup( $key ); + $redirect = add_query_arg( array('update' => 'addnoconfirmation'), 'user-new.php' ); + } else { + $redirect = add_query_arg( array('update' => 'newuserconfirmation'), 'user-new.php' ); + } + wp_redirect( $redirect ); + die(); + } + } +} + +$title = __('Add New User'); +$parent_file = 'users.php'; + +$do_both = false; +if ( is_multisite() && current_user_can('promote_users') && current_user_can('create_users') ) + $do_both = true; + +$help = '

    ' . __('To add a new user to your site, fill in the form on this screen and click the Add New User button at the bottom.') . '

    '; + +if ( is_multisite() ) { + $help .= '

    ' . __('Because this is a multisite installation, you may add accounts that already exist on the Network by specifying a username or email, and defining a role. For more options, such as specifying a password, you have to be a Network Administrator and use the hover link under an existing user’s name to Edit the user profile under Network Admin > All Users.') . '

    ' . + '

    ' . __('New users will receive an email letting them know they’ve been added as a user for your site. This email will also contain their password. Check the box if you don’t want the user to receive a welcome email.') . '

    '; +} else { + $help .= '

    ' . __('You must assign a password to the new user, which they can change after logging in. The username, however, cannot be changed.') . '

    ' . + '

    ' . __('New users will receive an email letting them know they’ve been added as a user for your site. By default, this email will also contain their password. Uncheck the box if you don’t want the password to be included in the welcome email.') . '

    '; +} + +$help .= '

    ' . __('Remember to click the Add New User button at the bottom of this screen when you are finished.') . '

    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => $help, +) ); + +get_current_screen()->add_help_tab( array( +'id' => 'user-roles', +'title' => __('User Roles'), +'content' => '

    ' . __('Here is a basic overview of the different user roles and the permissions associated with each one:') . '

    ' . + '
      ' . + '
    • ' . __('Administrators have access to all the administration features.') . '
    • ' . + '
    • ' . __('Editors can publish posts, manage posts as well as manage other people’s posts, etc.') . '
    • ' . + '
    • ' . __('Authors can publish and manage their own posts, and are able to upload files.') . '
    • ' . + '
    • ' . __('Contributors can write and manage their posts but not publish posts or upload media files.') . '
    • ' . + '
    • ' . __('Subscribers can read comments/comment/receive newsletters, etc. but cannot create regular site content.') . '
    • ' . + '
    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Adding New Users') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +wp_enqueue_script('wp-ajax-response'); +wp_enqueue_script('user-profile'); + +/** + * Allows you to enable user auto-complete for non-super admins in multisite. + * + * @since 3.4.0 + * + * @param bool True or false, based on if you enable auto-complete for non-super admins. Default is false. + */ +if ( is_multisite() && current_user_can( 'promote_users' ) && ! wp_is_large_network( 'users' ) + && ( is_super_admin() || apply_filters( 'autocomplete_users_for_site_admins', false ) ) +) { + wp_enqueue_script( 'user-suggest' ); +} + +require_once( ABSPATH . 'wp-admin/admin-header.php' ); + +if ( isset($_GET['update']) ) { + $messages = array(); + if ( is_multisite() ) { + switch ( $_GET['update'] ) { + case "newuserconfirmation": + $messages[] = __('Invitation email sent to new user. A confirmation link must be clicked before their account is created.'); + break; + case "add": + $messages[] = __('Invitation email sent to user. A confirmation link must be clicked for them to be added to your site.'); + break; + case "addnoconfirmation": + $messages[] = __('User has been added to your site.'); + break; + case "addexisting": + $messages[] = __('That user is already a member of this site.'); + break; + case "does_not_exist": + $messages[] = __('The requested user does not exist.'); + break; + case "enter_email": + $messages[] = __('Please enter a valid email address.'); + break; + } + } else { + if ( 'add' == $_GET['update'] ) + $messages[] = __('User added.'); + } +} +?> +
    + +

    +

    + + +
    +
      + get_error_messages() as $err ) + echo "
    • $err
    • \n"; + ?> +
    +
    +

    ' . $msg . '

    '; +} ?> + + +
    + get_error_messages() as $message ) + echo "

    $message

    "; + ?> +
    + +
    + +' . __('Add Existing User') . ''; + if ( !is_super_admin() ) { + _e( 'Enter the email address of an existing user on this network to invite them to this site. That person will be sent an email asking them to confirm the invite.' ); + $label = __('E-mail'); + } else { + _e( 'Enter the email address or username of an existing user on this network to invite them to this site. That person will be sent an email asking them to confirm the invite.' ); + $label = __('E-mail or Username'); + } +?> + +
    > + + + + + + + + + + + + + + + + + + +
    +
    + + 'addusersub' ) ); ?> +
    +' . __( 'Add New User' ) . ''; +?> +

    + +
    > + + + 'login', 'first_name' => 'firstname', 'last_name' => 'lastname', + 'email' => 'email', 'url' => 'uri', 'role' => 'role', 'send_password' => 'send_password', 'noconfirmation' => 'ignore_pass' ) as $post_field => $var ) { + $var = "new_user_$var"; + if( isset( $_POST['createuser'] ) ) { + if ( ! isset($$var) ) + $$var = isset( $_POST[$post_field] ) ? wp_unslash( $_POST[$post_field] ) : ''; + } else { + $$var = false; + } +} + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +

    +
    +
    + + + + 'createusersub' ) ); ?> + +
    + + +domain != $current_site->domain ) || ( $current_blog->path != $current_site->path ) ); +$redirect_user_admin_request = apply_filters( 'redirect_user_admin_request', $redirect_user_admin_request ); +if ( $redirect_user_admin_request ) { + wp_redirect( user_admin_url() ); + exit; +} +unset( $redirect_user_admin_request ); diff --git a/sources/wp-admin/user/credits.php b/sources/wp-admin/user/credits.php new file mode 100644 index 0000000..2b4021a --- /dev/null +++ b/sources/wp-admin/user/credits.php @@ -0,0 +1,13 @@ +get_pagenum(); +$title = __('Users'); +$parent_file = 'users.php'; + +add_screen_option( 'per_page', array('label' => _x( 'Users', 'users per page (screen options)' )) ); + +// contextual help - choose Help on the top right of admin panel to preview this. +get_current_screen()->add_help_tab( array( + 'id' => 'overview', + 'title' => __('Overview'), + 'content' => '

    ' . __('This screen lists all the existing users for your site. Each user has one of five defined roles as set by the site admin: Site Administrator, Editor, Author, Contributor, or Subscriber. Users with roles other than Administrator will see fewer options in the dashboard navigation when they are logged in, based on their role.') . '

    ' . + '

    ' . __('To add a new user for your site, click the Add New button at the top of the screen or Add New in the Users menu section.') . '

    ' +) ) ; + +get_current_screen()->add_help_tab( array( + 'id' => 'screen-display', + 'title' => __('Screen Display'), + 'content' => '

    ' . __('You can customize the display of this screen in a number of ways:') . '

    ' . + '
      ' . + '
    • ' . __('You can hide/display columns based on your needs and decide how many users to list per screen using the Screen Options tab.') . '
    • ' . + '
    • ' . __('You can filter the list of users by User Role using the text links in the upper left to show All, Administrator, Editor, Author, Contributor, or Subscriber. The default view is to show all users. Unused User Roles are not listed.') . '
    • ' . + '
    • ' . __('You can view all posts made by a user by clicking on the number under the Posts column.') . '
    • ' . + '
    ' +) ); + +$help = '

    ' . __('Hovering over a row in the users list will display action links that allow you to manage users. You can perform the following actions:') . '

    ' . + '
      ' . + '
    • ' . __('Edit takes you to the editable profile screen for that user. You can also reach that screen by clicking on the username.') . '
    • '; + +if ( is_multisite() ) + $help .= '
    • ' . __( 'Remove allows you to remove a user from your site. It does not delete their posts. You can also remove multiple users at once by using Bulk Actions.' ) . '
    • '; +else + $help .= '
    • ' . __( 'Delete brings you to the Delete Users screen for confirmation, where you can permanently remove a user from your site and delete their posts. You can also delete multiple users at once by using Bulk Actions.' ) . '
    • '; + +$help .= '
    '; + +get_current_screen()->add_help_tab( array( + 'id' => 'actions', + 'title' => __('Actions'), + 'content' => $help, +) ); +unset( $help ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Managing Users') . '

    ' . + '

    ' . __('Descriptions of Roles and Capabilities') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +if ( empty($_REQUEST) ) { + $referer = ''; +} elseif ( isset($_REQUEST['wp_http_referer']) ) { + $redirect = remove_query_arg(array('wp_http_referer', 'updated', 'delete_count'), wp_unslash( $_REQUEST['wp_http_referer'] ) ); + $referer = ''; +} else { + $redirect = 'users.php'; + $referer = ''; +} + +$update = ''; + +/** + * @since 3.5.0 + * @access private + */ +function delete_users_add_js() { ?> + +current_action() ) { + +/* Bulk Dropdown menu Role changes */ +case 'promote': + check_admin_referer('bulk-users'); + + if ( ! current_user_can( 'promote_users' ) ) + wp_die( __( 'You can’t edit that user.' ) ); + + if ( empty($_REQUEST['users']) ) { + wp_redirect($redirect); + exit(); + } + + $editable_roles = get_editable_roles(); + if ( empty( $editable_roles[$_REQUEST['new_role']] ) ) + wp_die(__('You can’t give users that role.')); + + $userids = $_REQUEST['users']; + $update = 'promote'; + foreach ( $userids as $id ) { + $id = (int) $id; + + if ( ! current_user_can('promote_user', $id) ) + wp_die(__('You can’t edit that user.')); + // The new role of the current user must also have the promote_users cap or be a multisite super admin + if ( $id == $current_user->ID && ! $wp_roles->role_objects[ $_REQUEST['new_role'] ]->has_cap('promote_users') + && ! ( is_multisite() && is_super_admin() ) ) { + $update = 'err_admin_role'; + continue; + } + + // If the user doesn't already belong to the blog, bail. + if ( is_multisite() && !is_user_member_of_blog( $id ) ) + wp_die(__('Cheatin’ uh?')); + + $user = get_userdata( $id ); + $user->set_role($_REQUEST['new_role']); + } + + wp_redirect(add_query_arg('update', $update, $redirect)); + exit(); + +break; + +case 'dodelete': + if ( is_multisite() ) + wp_die( __('User deletion is not allowed from this screen.') ); + + check_admin_referer('delete-users'); + + if ( empty($_REQUEST['users']) ) { + wp_redirect($redirect); + exit(); + } + + $userids = array_map( 'intval', (array) $_REQUEST['users'] ); + + if ( empty( $_REQUEST['delete_option'] ) ) { + $url = self_admin_url( 'users.php?action=delete&users[]=' . implode( '&users[]=', $userids ) . '&error=true' ); + $url = str_replace( '&', '&', wp_nonce_url( $url, 'bulk-users' ) ); + wp_redirect( $url ); + exit; + } + + if ( ! current_user_can( 'delete_users' ) ) + wp_die(__('You can’t delete users.')); + + $update = 'del'; + $delete_count = 0; + + foreach ( $userids as $id ) { + if ( ! current_user_can( 'delete_user', $id ) ) + wp_die(__( 'You can’t delete that user.' ) ); + + if ( $id == $current_user->ID ) { + $update = 'err_admin_del'; + continue; + } + switch ( $_REQUEST['delete_option'] ) { + case 'delete': + wp_delete_user( $id ); + break; + case 'reassign': + wp_delete_user( $id, $_REQUEST['reassign_user'] ); + break; + } + ++$delete_count; + } + + $redirect = add_query_arg( array('delete_count' => $delete_count, 'update' => $update), $redirect); + wp_redirect($redirect); + exit(); + +break; + +case 'delete': + if ( is_multisite() ) + wp_die( __('User deletion is not allowed from this screen.') ); + + check_admin_referer('bulk-users'); + + if ( empty($_REQUEST['users']) && empty($_REQUEST['user']) ) { + wp_redirect($redirect); + exit(); + } + + if ( ! current_user_can( 'delete_users' ) ) + $errors = new WP_Error( 'edit_users', __( 'You can’t delete users.' ) ); + + if ( empty($_REQUEST['users']) ) + $userids = array( intval( $_REQUEST['user'] ) ); + else + $userids = array_map( 'intval', (array) $_REQUEST['users'] ); + + add_action( 'admin_head', 'delete_users_add_js' ); + + include( ABSPATH . 'wp-admin/admin-header.php' ); +?> +
    + + + +
    + +

    + +
    +

    +
    + +

    +
      +ID ) { + echo "
    • " . sprintf(__('ID #%1$s: %2$s The current user will not be deleted.'), $id, $user->user_login) . "
    • \n"; + } else { + echo "
    • " . sprintf(__('ID #%1$s: %2$s'), $id, $user->user_login) . "
    • \n"; + $go_delete++; + } + } + ?> +
    + +

    +
      +
    • +
    • + ' . __( 'Attribute all posts to:' ) . ' '; + wp_dropdown_users( array( 'name' => 'reassign_user', 'exclude' => array_diff( $userids, array($current_user->ID) ) ) ); ?>
    • +
    + + + +

    + +
    +
    +ID && !is_super_admin() ) { + $update = 'err_admin_remove'; + continue; + } + if ( !current_user_can('remove_user', $id) ) { + $update = 'err_admin_remove'; + continue; + } + remove_user_from_blog($id, $blog_id); + } + + $redirect = add_query_arg( array('update' => $update), $redirect); + wp_redirect($redirect); + exit; + +break; + +case 'remove': + + check_admin_referer('bulk-users'); + + if ( ! is_multisite() ) + wp_die( __( 'You can’t remove users.' ) ); + + if ( empty($_REQUEST['users']) && empty($_REQUEST['user']) ) { + wp_redirect($redirect); + exit(); + } + + if ( !current_user_can('remove_users') ) + $error = new WP_Error('edit_users', __('You can’t remove users.')); + + if ( empty($_REQUEST['users']) ) + $userids = array(intval($_REQUEST['user'])); + else + $userids = $_REQUEST['users']; + + include( ABSPATH . 'wp-admin/admin-header.php' ); +?> +
    + + + +
    + +

    +

    +
      +ID && !is_super_admin() ) { + echo "
    • " . sprintf(__('ID #%1$s: %2$s The current user will not be removed.'), $id, $user->user_login) . "
    • \n"; + } elseif ( !current_user_can('remove_user', $id) ) { + echo "
    • " . sprintf(__('ID #%1$s: %2$s You don\'t have permission to remove this user.'), $id, $user->user_login) . "
    • \n"; + } else { + echo "
    • " . sprintf(__('ID #%1$s: %2$s'), $id, $user->user_login) . "
    • \n"; + $go_remove = true; + } + } + ?> + + + + +

      + +
    +
    +prepare_items(); + $total_pages = $wp_list_table->get_pagination_arg( 'total_pages' ); + if ( $pagenum > $total_pages && $total_pages > 0 ) { + wp_redirect( add_query_arg( 'paged', $total_pages ) ); + exit; + } + + include( ABSPATH . 'wp-admin/admin-header.php' ); + + $messages = array(); + if ( isset($_GET['update']) ) : + switch($_GET['update']) { + case 'del': + case 'del_many': + $delete_count = isset($_GET['delete_count']) ? (int) $_GET['delete_count'] : 0; + $messages[] = '

    ' . sprintf( _n( 'User deleted.', '%s users deleted.', $delete_count ), number_format_i18n( $delete_count ) ) . '

    '; + break; + case 'add': + if ( isset( $_GET['id'] ) && ( $user_id = $_GET['id'] ) && current_user_can( 'edit_user', $user_id ) ) { + $messages[] = '

    ' . sprintf( __( 'New user created. Edit user' ), + esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), + self_admin_url( 'user-edit.php?user_id=' . $user_id ) ) ) ) . '

    '; + } else { + $messages[] = '

    ' . __( 'New user created.' ) . '

    '; + } + break; + case 'promote': + $messages[] = '

    ' . __('Changed roles.') . '

    '; + break; + case 'err_admin_role': + $messages[] = '

    ' . __('The current user’s role must have user editing capabilities.') . '

    '; + $messages[] = '

    ' . __('Other user roles have been changed.') . '

    '; + break; + case 'err_admin_del': + $messages[] = '

    ' . __('You can’t delete the current user.') . '

    '; + $messages[] = '

    ' . __('Other users have been deleted.') . '

    '; + break; + case 'remove': + $messages[] = '

    ' . __('User removed from this site.') . '

    '; + break; + case 'err_admin_remove': + $messages[] = '

    ' . __("You can't remove the current user.") . '

    '; + $messages[] = '

    ' . __('Other users have been removed.') . '

    '; + break; + } + endif; ?> + + +
    +
      + get_error_messages() as $err ) + echo "
    • $err
    • \n"; + ?> +
    +
    + + +
    + +

    + + + + +' . __('Search results for “%s”') . '', esc_html( $usersearch ) ); ?> +

    + +views(); ?> + +
    + +search_box( __( 'Search Users' ), 'user' ); ?> + +display(); ?> +
    + +
    +
    +add_help_tab( array( +'id' => 'overview', +'title' => __('Overview'), +'content' => + '

    ' . __('Widgets are independent sections of content that can be placed into any widgetized area provided by your theme (commonly called sidebars). To populate your sidebars/widget areas with individual widgets, drag and drop the title bars into the desired area. By default, only the first widget area is expanded. To populate additional widget areas, click on their title bars to expand them.') . '

    +

    ' . __('The Available Widgets section contains all the widgets you can choose from. Once you drag a widget into a sidebar, it will open to allow you to configure its settings. When you are happy with the widget settings, click the Save button and the widget will go live on your site. If you click Delete, it will remove the widget.') . '

    ' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'removing-reusing', +'title' => __('Removing and Reusing'), +'content' => + '

    ' . __('If you want to remove the widget but save its setting for possible future use, just drag it into the Inactive Widgets area. You can add them back anytime from there. This is especially helpful when you switch to a theme with fewer or different widget areas.') . '

    +

    ' . __('Widgets may be used multiple times. You can give each widget a title, to display on your site, but it’s not required.') . '

    +

    ' . __('Enabling Accessibility Mode, via Screen Options, allows you to use Add and Edit buttons instead of using drag and drop.') . '

    ' +) ); +get_current_screen()->add_help_tab( array( +'id' => 'missing-widgets', +'title' => __('Missing Widgets'), +'content' => + '

    ' . __('Many themes show some sidebar widgets by default until you edit your sidebars, but they are not automatically displayed in your sidebar management tool. After you make your first widget change, you can re-add the default widgets by adding them from the Available Widgets area.') . '

    ' . + '

    ' . __('When changing themes, there is often some variation in the number and setup of widget areas/sidebars and sometimes these conflicts make the transition a bit less smooth. If you changed themes and seem to be missing widgets, scroll down on this screen to the Inactive Widgets area, where all of your widgets and their settings will have been saved.') . '

    ' +) ); + +get_current_screen()->set_help_sidebar( + '

    ' . __('For more information:') . '

    ' . + '

    ' . __('Documentation on Widgets') . '

    ' . + '

    ' . __('Support Forums') . '

    ' +); + +if ( ! current_theme_supports( 'widgets' ) ) { + wp_die( __( 'The theme you are currently using isn’t widget-aware, meaning that it has no sidebars that you are able to change. For information on making your theme widget-aware, please follow these instructions.' ) ); +} + +// These are the widgets grouped by sidebar +$sidebars_widgets = wp_get_sidebars_widgets(); + +if ( empty( $sidebars_widgets ) ) + $sidebars_widgets = wp_get_widget_defaults(); + +foreach ( $sidebars_widgets as $sidebar_id => $widgets ) { + if ( 'wp_inactive_widgets' == $sidebar_id ) + continue; + + if ( !isset( $wp_registered_sidebars[ $sidebar_id ] ) ) { + if ( ! empty( $widgets ) ) { // register the inactive_widgets area as sidebar + register_sidebar(array( + 'name' => __( 'Inactive Sidebar (not used)' ), + 'id' => $sidebar_id, + 'class' => 'inactive-sidebar orphan-sidebar', + 'description' => __( 'This sidebar is no longer available and does not show anywhere on your site. Remove each of the widgets below to fully remove this inactive sidebar.' ), + 'before_widget' => '', + 'after_widget' => '', + 'before_title' => '', + 'after_title' => '', + )); + } else { + unset( $sidebars_widgets[ $sidebar_id ] ); + } + } +} + +// register the inactive_widgets area as sidebar +register_sidebar(array( + 'name' => __('Inactive Widgets'), + 'id' => 'wp_inactive_widgets', + 'class' => 'inactive-sidebar', + 'description' => __( 'Drag widgets here to remove them from the sidebar but keep their settings.' ), + 'before_widget' => '', + 'after_widget' => '', + 'before_title' => '', + 'after_title' => '', +)); + +retrieve_widgets(); + +// We're saving a widget without js +if ( isset($_POST['savewidget']) || isset($_POST['removewidget']) ) { + $widget_id = $_POST['widget-id']; + check_admin_referer("save-delete-widget-$widget_id"); + + $number = isset($_POST['multi_number']) ? (int) $_POST['multi_number'] : ''; + if ( $number ) { + foreach ( $_POST as $key => $val ) { + if ( is_array($val) && preg_match('/__i__|%i%/', key($val)) ) { + $_POST[$key] = array( $number => array_shift($val) ); + break; + } + } + } + + $sidebar_id = $_POST['sidebar']; + $position = isset($_POST[$sidebar_id . '_position']) ? (int) $_POST[$sidebar_id . '_position'] - 1 : 0; + + $id_base = $_POST['id_base']; + $sidebar = isset($sidebars_widgets[$sidebar_id]) ? $sidebars_widgets[$sidebar_id] : array(); + + // delete + if ( isset($_POST['removewidget']) && $_POST['removewidget'] ) { + + if ( !in_array($widget_id, $sidebar, true) ) { + wp_redirect( admin_url('widgets.php?error=0') ); + exit; + } + + $sidebar = array_diff( $sidebar, array($widget_id) ); + $_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1'); + } + + $_POST['widget-id'] = $sidebar; + + foreach ( (array) $wp_registered_widget_updates as $name => $control ) { + if ( $name != $id_base || !is_callable($control['callback']) ) + continue; + + ob_start(); + call_user_func_array( $control['callback'], $control['params'] ); + ob_end_clean(); + + break; + } + + $sidebars_widgets[$sidebar_id] = $sidebar; + + // remove old position + if ( !isset($_POST['delete_widget']) ) { + foreach ( $sidebars_widgets as $key => $sb ) { + if ( is_array($sb) ) + $sidebars_widgets[$key] = array_diff( $sb, array($widget_id) ); + } + array_splice( $sidebars_widgets[$sidebar_id], $position, 0, $widget_id ); + } + + wp_set_sidebars_widgets($sidebars_widgets); + wp_redirect( admin_url('widgets.php?message=0') ); + exit; +} + +// Output the widget form without js +if ( isset($_GET['editwidget']) && $_GET['editwidget'] ) { + $widget_id = $_GET['editwidget']; + + if ( isset($_GET['addnew']) ) { + // Default to the first sidebar + $keys = array_keys( $wp_registered_sidebars ); + $sidebar = array_shift( $keys ); + + if ( isset($_GET['base']) && isset($_GET['num']) ) { // multi-widget + // Copy minimal info from an existing instance of this widget to a new instance + foreach ( $wp_registered_widget_controls as $control ) { + if ( $_GET['base'] === $control['id_base'] ) { + $control_callback = $control['callback']; + $multi_number = (int) $_GET['num']; + $control['params'][0]['number'] = -1; + $widget_id = $control['id'] = $control['id_base'] . '-' . $multi_number; + $wp_registered_widget_controls[$control['id']] = $control; + break; + } + } + } + } + + if ( isset($wp_registered_widget_controls[$widget_id]) && !isset($control) ) { + $control = $wp_registered_widget_controls[$widget_id]; + $control_callback = $control['callback']; + } elseif ( !isset($wp_registered_widget_controls[$widget_id]) && isset($wp_registered_widgets[$widget_id]) ) { + $name = esc_html( strip_tags($wp_registered_widgets[$widget_id]['name']) ); + } + + if ( !isset($name) ) + $name = esc_html( strip_tags($control['name']) ); + + if ( !isset($sidebar) ) + $sidebar = isset($_GET['sidebar']) ? $_GET['sidebar'] : 'wp_inactive_widgets'; + + if ( !isset($multi_number) ) + $multi_number = isset($control['params'][0]['number']) ? $control['params'][0]['number'] : ''; + + $id_base = isset($control['id_base']) ? $control['id_base'] : $control['id']; + + // show the widget form + $width = ' style="width:' . max($control['width'], 350) . 'px"'; + $key = isset($_GET['key']) ? (int) $_GET['key'] : 0; + + require_once( ABSPATH . 'wp-admin/admin-header.php' ); ?> +
    + +

    +
    > +

    + +
    +
    +' . __('There are no options for this widget.') . "

    \n"; ?> +
    + +

    +
    + + $sbvalue ) { + echo "\t\t\n"; + } ?> +
    "; + if ( 'wp_inactive_widgets' == $sbname || 'orphaned_widgets' == substr( $sbname, 0, 16 ) ) { + echo ' '; + } else { + if ( !isset($sidebars_widgets[$sbname]) || !is_array($sidebars_widgets[$sbname]) ) { + $j = 1; + $sidebars_widgets[$sbname] = array(); + } else { + $j = count($sidebars_widgets[$sbname]); + if ( isset($_GET['addnew']) || !in_array($widget_id, $sidebars_widgets[$sbname], true) ) + $j++; + } + $selected = ''; + echo "\t\t\n"; + } + echo "
    +
    + +
    + + + + + + + +
    +
    +
    +
    +
    + + +
    + +

    + + +

    + + +

    + + + + +
    +
    +
    + +
    +

    +
    + +
    +
    +
    +
    +
    + + $registered_sidebar ) { + if ( false !== strpos( $registered_sidebar['class'], 'inactive-sidebar' ) || 'orphaned_widgets' == substr( $sidebar, 0, 16 ) ) { + $wrap_class = 'widgets-holder-wrap'; + if ( !empty( $registered_sidebar['class'] ) ) + $wrap_class .= ' ' . $registered_sidebar['class']; + +?> + +
    + +
    + +
    +
    +
    + + +
    +
    + +
    +
    + $registered_sidebar ) { + if ( false !== strpos( $registered_sidebar['class'], 'inactive-sidebar' ) || 'orphaned_widgets' == substr( $sidebar, 0, 16 ) ) + continue; + + $wrap_class = 'widgets-holder-wrap'; + if ( !empty( $registered_sidebar['class'] ) ) + $wrap_class .= ' sidebar-' . $registered_sidebar['class']; + + if ( $i ) + $wrap_class .= ' closed'; ?> + +
    + + +
    + +
    +
    +
    + +
    +
    +
    + +comment_status ) ) { + /** + * Fires when a comment is attempted on a post that does not exist. + * + * @since unknown + * @param int $comment_post_ID Post ID. + */ + do_action( 'comment_id_not_found', $comment_post_ID ); + exit; +} + +// get_post_status() will get the parent status for attachments. +$status = get_post_status($post); + +$status_obj = get_post_status_object($status); + +if ( ! comments_open( $comment_post_ID ) ) { + /** + * Fires when a comment is attempted on a post that has comments closed. + * + * @since unknown + * @param int $comment_post_ID Post ID. + */ + do_action( 'comment_closed', $comment_post_ID ); + wp_die( __('Sorry, comments are closed for this item.') ); +} elseif ( 'trash' == $status ) { + /** + * Fires when a comment is attempted on a trashed post. + * + * @since 2.9.0 + * @param int $comment_post_ID Post ID. + */ + do_action( 'comment_on_trash', $comment_post_ID ); + exit; +} elseif ( ! $status_obj->public && ! $status_obj->private ) { + /** + * Fires when a comment is attempted on a post in draft mode. + * + * @since unknown + * @param int $comment_post_ID Post ID. + */ + do_action( 'comment_on_draft', $comment_post_ID ); + exit; +} elseif ( post_password_required( $comment_post_ID ) ) { + /** + * Fires when a comment is attempted on a password-protected post. + * + * @since unknown + * @param int $comment_post_ID Post ID. + */ + do_action( 'comment_on_password_protected', $comment_post_ID ); + exit; +} else { + /** + * Fires before a comment is posted. + * + * @since unknown + * @param int $comment_post_ID Post ID. + */ + do_action( 'pre_comment_on_post', $comment_post_ID ); +} + +$comment_author = ( isset($_POST['author']) ) ? trim(strip_tags($_POST['author'])) : null; +$comment_author_email = ( isset($_POST['email']) ) ? trim($_POST['email']) : null; +$comment_author_url = ( isset($_POST['url']) ) ? trim($_POST['url']) : null; +$comment_content = ( isset($_POST['comment']) ) ? trim($_POST['comment']) : null; + +// If the user is logged in +$user = wp_get_current_user(); +if ( $user->exists() ) { + if ( empty( $user->display_name ) ) + $user->display_name=$user->user_login; + $comment_author = wp_slash( $user->display_name ); + $comment_author_email = wp_slash( $user->user_email ); + $comment_author_url = wp_slash( $user->user_url ); + if ( current_user_can( 'unfiltered_html' ) ) { + if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) + || ! wp_verify_nonce( $_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment_post_ID ) + ) { + kses_remove_filters(); // start with a clean slate + kses_init_filters(); // set up the filters + } + } +} else { + if ( get_option('comment_registration') || 'private' == $status ) + wp_die( __('Sorry, you must be logged in to post a comment.') ); +} + +$comment_type = ''; + +if ( get_option('require_name_email') && !$user->exists() ) { + if ( 6 > strlen($comment_author_email) || '' == $comment_author ) + wp_die( __('ERROR: please fill the required fields (name, email).') ); + elseif ( !is_email($comment_author_email)) + wp_die( __('ERROR: please enter a valid email address.') ); +} + +if ( '' == $comment_content ) + wp_die( __('ERROR: please type a comment.') ); + +$comment_parent = isset($_POST['comment_parent']) ? absint($_POST['comment_parent']) : 0; + +$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID'); + +$comment_id = wp_new_comment( $commentdata ); +$comment = get_comment($comment_id); + +/** + * Perform other actions when comment cookies are set. + * + * @since 3.4.0 + * + * @param object $comment Comment object. + * @param WP_User $user User object. The user may not exist. + */ +do_action( 'set_comment_cookies', $comment, $user ); + +$location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id; + +/** + * The location URI to send commenter after posting. + * + * @since unknown + * + * @param string $location The 'redirect_to' URI sent via $_POST. + * @param object $comment Comment object. + */ +$location = apply_filters( 'comment_post_redirect', $location, $comment ); + +wp_safe_redirect( $location ); +exit; diff --git a/sources/wp-config-sample.php b/sources/wp-config-sample.php new file mode 100644 index 0000000..b70924b --- /dev/null +++ b/sources/wp-config-sample.php @@ -0,0 +1,99 @@ +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, 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: WordPress 3.7\n" +"Report-Msgid-Bugs-To: http://wppolyglots.wordpress.com\n" +"POT-Creation-Date: 2013-10-23 21:00:59+00:00\n" +"PO-Revision-Date: 2013-10-25 14:07+0100\n" +"Last-Translator: Xavier B. \n" +"Language-Team: WordPress Francophone \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-Bookmarks: -1,430,-1,-1,-1,-1,-1,-1,-1,-1\n" +"X-Generator: Poedit 1.5.7\n" + +#: wp-admin/about.php:22 wp-admin/credits.php:82 wp-admin/freedoms.php:20 +msgid "Welcome to WordPress %s" +msgstr "Bienvenue dans WordPress %s" + +#: wp-admin/about.php:24 wp-admin/credits.php:84 wp-admin/freedoms.php:22 +msgid "" +"Thank you for updating to WordPress 3.7! You might not notice a thing, and " +"we’re okay with that." +msgstr "" +"Merci d’être passé à WordPress 3.7 ! Vous remarquerez peut-être " +"que rien n’a vraiment changé, et c’est normal." + +#: wp-admin/about.php:26 wp-admin/credits.php:86 wp-admin/freedoms.php:24 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:329 +#: wp-admin/includes/class-wp-plugins-list-table.php:410 +#: wp-admin/includes/update.php:162 wp-admin/includes/update.php:188 +#: wp-admin/themes.php:156 +msgid "Version %s" +msgstr "Version %s" + +#: wp-admin/about.php:30 wp-admin/credits.php:90 wp-admin/freedoms.php:28 +msgid "What’s New" +msgstr "Nouveautés" + +#: wp-admin/about.php:32 wp-admin/credits.php:12 wp-admin/credits.php:92 +#: wp-admin/freedoms.php:30 +msgid "Credits" +msgstr "Crédits" + +#: wp-admin/about.php:34 wp-admin/credits.php:94 wp-admin/freedoms.php:12 +#: wp-admin/freedoms.php:32 +msgid "Freedoms" +msgstr "Libertés" + +#: wp-admin/about.php:39 +msgid "Background Updates" +msgstr "Mises à jour en tâche de fond" + +#: wp-admin/about.php:43 +msgid "Updates While You Sleep" +msgstr "Mise à jour sans avoir rien à faire" + +#: wp-admin/about.php:44 +msgid "" +"With WordPress 3.7, you don’t have to lift a finger to apply " +"maintenance and security updates. Most sites are now able to automatically " +"apply these updates in the background, though some configurations may not " +"allow it." +msgstr "" +"Avec WordPress 3.7, vous n’avez même plus à lever le petit doigt pour " +"appliquer une mise à jour de maintenance ou de sécurité. La plupart des " +"sites sont maintenant capables d’appliquer ces mises à jour " +"automatiquement en coulisse. Notez que certaines configurations ne le " +"permettent pas." + +#: wp-admin/about.php:50 +msgid "More Reliable Than Ever" +msgstr "Plus sûr que jamais" + +#: wp-admin/about.php:51 +msgid "" +"The update process has been made even more reliable and secure, with dozens " +"of new checks and safeguards." +msgstr "" +"Le processus de mise à jour a été rendu encore plus sûr et sécurisé, avec " +"des douzaines de nouvelles vérifications et de mesures de sauvegarde." + +#: wp-admin/about.php:52 +msgid "" +"You’ll still need to click “Update Now” once WordPress 3.8 " +"is released, but we’ve never had more confidence in that beautiful " +"blue button." +msgstr "" +"Il vous faudra toujours cliquer sur le bouton « Mettre à jour " +"maintenant » une fois que WordPress 3.8 sera sorti, mais nous " +"avons plus confiance en ce bouton que jamais." + +#: wp-admin/about.php:67 +msgid "" +"This site is able to apply these updates automatically. " +"Cool!" +msgstr "" +"Votre site est capable d’appliquer ces mises à jour " +"automatiquement. Super !" + +#: wp-admin/about.php:77 +msgid "" +"This site is not able to apply these updates automatically. " +"But we’ll email %s when there is a new security release." +msgstr "" +"Votre site n’est pas capable d’appliquer ces " +"mises à jour automatiquement. Mais nous vous enverrons un message à l’" +"adresse %s le jour il y aura une mise à jour de sécurité." + +#: wp-admin/about.php:79 +msgid "" +"This site is not able to apply these updates automatically." +msgstr "" +"Votre site n’est pas capable d’appliquer ces " +"mises à jour automatiquement." + +#: wp-admin/about.php:89 +msgid "Create Stronger Passwords" +msgstr "Créez des mots de passe plus sûrs" + +#: wp-admin/about.php:93 +msgid "" +"Your password is your site’s first line of defense. It’s best to " +"create passwords that are complex, long, and unique. To that end, our " +"password meter has been updated in WordPress 3.7 to recognize common " +"mistakes that can weaken your password: dates, names, keyboard patterns " +"(123456789), and even pop culture references." +msgstr "" +"Votre mot de passe est la première ligne de défense de votre site. Il vaut " +"mieux des mots de passe complexes, longs et uniques. Pour ce faire, notre " +"testeur de mot de passe a été mis à jour dans WordPress 3.7 pour reconnaître " +"les erreurs les plus courantes, celles qui peuvent affaiblir votre mot de " +"passe : dates, noms, parcours clavier (123456789), et même les " +"références de la culture populaire." + +#: wp-admin/about.php:94 +msgid "Try it out on the right." +msgstr "Essayez-le sur la droite." + +#: wp-admin/about.php:99 +msgid "Getting the urge to change your password?" +msgstr "Changer de mot de passe vous démange-t-il ?" + +#: wp-admin/about.php:107 +msgid "Improved Search Results" +msgstr "Amélioration des résultats de recherche" + +#: wp-admin/about.php:108 +msgid "" +"Search results are now ordered by how well the search query matches a post, " +"instead of ordered only by date. For example, when your search terms match a " +"post title, that result will be pushed to the top." +msgstr "" +"Les résultats de recherche sont maintenant triés par la pertinence de la " +"requête au sein de vos articles, plutôt que de n’être trié que par " +"date. Par exemple, lorsque votre recherche correspond au titre d’un " +"article, celui-ci sera placé en haut des résultats." + +#: wp-admin/about.php:111 +msgid "Better Global Support" +msgstr "Meilleur support global" + +#: wp-admin/about.php:112 +msgid "" +"Localized versions of WordPress will receive faster and more complete " +"translations. WordPress 3.7 adds support for automatically installing the " +"right language files and keeping them up to date." +msgstr "" +"Les versions locales de WordPress recevront des traductions plus rapides et " +"plus complètes. WordPress 3.7 ajoute la possibilité d’installer " +"automatiquement les bons fichiers de langue et de les garder à jour." + +#: wp-admin/about.php:118 +msgid "Under the Hood" +msgstr "Sous le capot" + +#: wp-admin/about.php:122 +msgid "More Background Updates (Experimental)" +msgstr "Autres aspects des mises à jour en tâche de fond (expérimental)" + +#: wp-admin/about.php:123 +msgid "" +"Want WordPress to always update automatically, even for major feature " +"releases? Want to always keep a certain plugin up to date in the background? " +"WordPress 3.7 comes with fine-grained update controls for developers and " +"systems administrators." +msgstr "" +"Vous voulez que WordPress fasse toujours une mise à jour automatique, même " +"pour les versions majeures ? Vous voulez qu’une extension soit " +"toujours mise à jour silencieusement ? WordPress 3.7 vous propose un " +"contrôle très précis des mises à jour pour les développeurs et les " +"administrateurs système." + +#: wp-admin/about.php:126 +msgid "Advanced Date Queries" +msgstr "Requêtes avancées de dates" + +#: wp-admin/about.php:127 +msgid "" +"Developers can now query for posts within a date range, or that are older " +"than or newer than a specific point in time. Or get really fancy: all posts " +"written on Friday afternoons? Not a problem." +msgstr "" +"Les développeurs peuvent maintenant chercher des articles dans un intervalle " +"de dates, ou en fonction de leur âge par rapport à une date précise. Pour " +"présenter cela de jolie manière : afficher tous vos articles écrits un " +"vendredi après-midi ? Aucun problème." + +#: wp-admin/about.php:130 +msgid "Multisite Improvements" +msgstr "Améliorations du multisite" + +#: wp-admin/about.php:131 +msgid "" +"wp_get_sites() allows developers to easily get an array of all " +"the sites on your network without resorting to a direct database query " +"— just one of many improvements to multisite in WordPress 3.7." +msgstr "" +"wp_get_sites() permet aux développeurs d’obtenir " +"facilement un tableau de tous les sites de votre réseau sans devoir faire " +"une requête directe sur la base de données — et ce n’est que " +"l’une des nombreuses améliorations du multisite dans WordPress 3.7." + +#: wp-admin/about.php:138 +msgid "Return to Updates" +msgstr "Retourner aux mises à jour" + +#: wp-admin/about.php:138 +msgid "Return to Dashboard → Updates" +msgstr "Retourner aux mises à jour" + +#: wp-admin/about.php:142 +msgid "Go to Dashboard → Home" +msgstr "Aller sur l’accueil" + +#: wp-admin/about.php:142 +msgid "Go to Dashboard" +msgstr "Aller sur le tableau de bord" + +#: wp-admin/about.php:153 +msgid "Maintenance Release" +msgid_plural "Maintenance Releases" +msgstr[0] "Mise à jour de maintenance" +msgstr[1] "Mises à jour de maintenance" + +#: wp-admin/about.php:154 +msgid "Security Release" +msgid_plural "Security Releases" +msgstr[0] "Mise à jour de sécurité" +msgstr[1] "Mises à jour de sécurité" + +#: wp-admin/about.php:155 +msgid "Maintenance and Security Release" +msgid_plural "Maintenance and Security Releases" +msgstr[0] "Mise à jour de maintenance et de sécurité" +msgstr[1] "Mises à jour de maintenance et de sécurité" + +#. translators: 1: WordPress version number. +#: wp-admin/about.php:158 +msgid "Version %1$s addressed a security issue." +msgid_plural "Version %1$s addressed some security issues." +msgstr[0] "" +"La version %1$s corrige une vulnérabilité de sécurité." +msgstr[1] "" +"La version %1$s corrige plusieurs vulnérabilités de " +"sécurité." + +#. translators: 1: WordPress version number, 2: plural number of bugs. +#: wp-admin/about.php:162 +msgid "Version %1$s addressed %2$s bug." +msgid_plural "Version %1$s addressed %2$s bugs." +msgstr[0] "La version %1$s corrige %2$s bug." +msgstr[1] "La version %1$s corrige %2$s bugs." + +#. translators: 1: WordPress version number, 2: plural number of bugs. Singular +#. security issue. +#: wp-admin/about.php:166 +msgid "" +"Version %1$s addressed a security issue and fixed %2$s bug." +msgid_plural "" +"Version %1$s addressed a security issue and fixed %2$s bugs." +msgstr[0] "" +"La version %1$s s’occupe d’un problème de " +"sécurité et corrige %2$s bug." +msgstr[1] "" +"Version %1$s s’occupe d’un problème de sécurité " +"et corrige %2$s bugs." + +#. translators: 1: WordPress version number, 2: plural number of bugs. More +#. than one security issue. +#: wp-admin/about.php:170 +msgid "" +"Version %1$s addressed some security issues and fixed %2$s " +"bug." +msgid_plural "" +"Version %1$s addressed some security issues and fixed %2$s " +"bugs." +msgstr[0] "" +"La version %1$s s’occupe de quelques problèmes de " +"sécurité et corrige %2$s bug." +msgstr[1] "" +"Version %1$s s’occupe de quelques problèmes de " +"sécurité et corrige %2$s bugs." + +#: wp-admin/about.php:173 +msgid "For more information, see the release notes." +msgstr "" +"Pour plus d’informations, consultez les notes de " +"publication." + +#: wp-admin/admin-footer.php:35 +msgid "" +"Thank you for creating with WordPress." +msgstr "" +"Merci de faire de WordPress " +"votre outil de création." + +#: wp-admin/admin-header.php:32 wp-admin/customize.php:76 +msgid "%1$s — WordPress" +msgstr "%1$s — WordPress" + +#: wp-admin/admin-header.php:34 +msgid "%1$s ‹ %2$s — WordPress" +msgstr "%1$s ‹ %2$s — WordPress" + +#: wp-admin/admin-header.php:177 +msgid "Skip to main content" +msgstr "Aller au contenu principal" + +#: wp-admin/admin-header.php:198 +msgid "Main content" +msgstr "Contenu principal" + +#: wp-admin/admin.php:220 +msgid "Invalid plugin page" +msgstr "Page d’extension non valide" + +#: wp-admin/admin.php:223 +msgid "Cannot load %s." +msgstr "Impossible de charger %s." + +#: wp-admin/admin.php:256 +msgid "You are not allowed to import." +msgstr "Vous n’avez pas l’autorisation d’importer." + +#: wp-admin/admin.php:279 wp-admin/import.php:17 wp-admin/menu.php:201 +msgid "Import" +msgstr "Importer" + +#: wp-admin/async-upload.php:49 wp-admin/post.php:140 wp-admin/post.php:236 +#: wp-admin/post.php:260 wp-admin/post.php:279 +msgid "Unknown post type." +msgstr "Type de contenu inconnu." + +#: wp-admin/async-upload.php:51 wp-admin/edit-tags.php:253 +#: wp-admin/post.php:143 +msgid "You are not allowed to edit this item." +msgstr "Vous n’avez pas l’autorisation de modifier ce contenu." + +#: wp-admin/async-upload.php:57 +msgctxt "media item" +msgid "Edit" +msgstr "Modifier" + +#: wp-admin/async-upload.php:86 +msgid "“%s” has failed to upload due to an error" +msgstr "« %s » n’a pas pu être mis en ligne suite à une erreur" + +#: wp-admin/comment.php:46 wp-admin/edit-form-comment.php:17 +msgid "Edit Comment" +msgstr "Modifier le commentaire" + +#: wp-admin/comment.php:50 wp-admin/custom-background.php:88 +#: wp-admin/custom-header.php:106 wp-admin/edit-comments.php:116 +#: wp-admin/edit-form-advanced.php:292 wp-admin/edit-link-form.php:47 +#: wp-admin/edit-tags.php:204 wp-admin/edit.php:161 wp-admin/edit.php:206 +#: wp-admin/export.php:48 wp-admin/import.php:21 +#: wp-admin/includes/screen.php:782 wp-admin/index.php:44 +#: wp-admin/link-manager.php:45 wp-admin/media-new.php:45 +#: wp-admin/media.php:73 wp-admin/my-sites.php:40 wp-admin/nav-menus.php:486 +#: wp-admin/nav-menus.php:521 wp-admin/options-discussion.php:19 +#: wp-admin/options-general.php:73 wp-admin/options-media.php:28 +#: wp-admin/options-permalink.php:20 wp-admin/options-reading.php:55 +#: wp-admin/options-writing.php:20 wp-admin/plugin-editor.php:121 +#: wp-admin/plugin-install.php:50 wp-admin/plugins.php:340 +#: wp-admin/revision.php:112 wp-admin/theme-editor.php:25 +#: wp-admin/theme-install.php:46 wp-admin/themes.php:51 +#: wp-admin/update-core.php:469 wp-admin/upload.php:152 +#: wp-admin/user-edit.php:47 wp-admin/user-new.php:165 wp-admin/users.php:25 +#: wp-admin/widgets.php:49 +msgid "Overview" +msgstr "Vue d’ensemble" + +#: wp-admin/comment.php:52 +msgid "" +"You can edit the information left in a comment if needed. This is often " +"useful when you notice that a commenter has made a typographical error." +msgstr "" +"Au besoin, vous pouvez modifier les informations laissées dans un " +"commentaire. Par exemple, si un commentateur a fait une faute d’" +"orthographe." + +#: wp-admin/comment.php:53 +msgid "" +"You can also moderate the comment from this screen using the Status box, " +"where you can also change the timestamp of the comment." +msgstr "" +"Vous pouvez également modérer le commentaire depuis cet écran, à l’" +"aide du bloc État, d’où vous pouvez également changer l’" +"horodatage du commentaire." + +#: wp-admin/comment.php:57 wp-admin/custom-background.php:97 +#: wp-admin/custom-header.php:132 wp-admin/edit-comments.php:132 +#: wp-admin/edit-form-advanced.php:269 wp-admin/edit-form-advanced.php:284 +#: wp-admin/edit-form-advanced.php:301 wp-admin/edit-link-form.php:55 +#: wp-admin/edit-tags.php:234 wp-admin/edit.php:198 wp-admin/edit.php:219 +#: wp-admin/export.php:54 wp-admin/import.php:27 wp-admin/index.php:97 +#: wp-admin/link-manager.php:59 wp-admin/media-new.php:55 +#: wp-admin/media.php:82 wp-admin/my-sites.php:47 wp-admin/nav-menus.php:527 +#: wp-admin/options-discussion.php:25 wp-admin/options-general.php:78 +#: wp-admin/options-media.php:33 wp-admin/options-permalink.php:43 +#: wp-admin/options-reading.php:70 wp-admin/options-writing.php:56 +#: wp-admin/plugin-editor.php:132 wp-admin/plugin-install.php:65 +#: wp-admin/plugins.php:354 wp-admin/revision.php:116 +#: wp-admin/theme-editor.php:38 wp-admin/theme-install.php:61 +#: wp-admin/themes.php:88 wp-admin/tools.php:27 wp-admin/update-core.php:484 +#: wp-admin/upload.php:171 wp-admin/user-edit.php:52 wp-admin/user-new.php:183 +#: wp-admin/users.php:60 wp-admin/widgets.php:71 +msgid "For more information:" +msgstr "Plus d’informations :" + +#: wp-admin/comment.php:58 wp-admin/edit-comments.php:133 +msgid "" +"Documentation on Comments" +msgstr "" +"Documentation sur les commentaires (en)" + +#: wp-admin/comment.php:59 wp-admin/custom-background.php:99 +#: wp-admin/custom-header.php:134 wp-admin/edit-comments.php:136 +#: wp-admin/edit-form-advanced.php:271 wp-admin/edit-form-advanced.php:287 +#: wp-admin/edit-form-advanced.php:303 wp-admin/edit-link-form.php:57 +#: wp-admin/edit-tags.php:243 wp-admin/edit.php:200 wp-admin/edit.php:221 +#: wp-admin/export.php:56 wp-admin/import.php:29 wp-admin/index.php:99 +#: wp-admin/link-manager.php:61 wp-admin/media-new.php:57 +#: wp-admin/media.php:84 wp-admin/my-sites.php:49 wp-admin/nav-menus.php:529 +#: wp-admin/options-discussion.php:27 wp-admin/options-general.php:80 +#: wp-admin/options-media.php:35 wp-admin/options-permalink.php:46 +#: wp-admin/options-reading.php:72 wp-admin/options-writing.php:58 +#: wp-admin/plugin-editor.php:135 wp-admin/plugin-install.php:67 +#: wp-admin/plugins.php:356 wp-admin/revision.php:118 +#: wp-admin/theme-editor.php:43 wp-admin/theme-install.php:63 +#: wp-admin/themes.php:90 wp-admin/tools.php:29 wp-admin/update-core.php:486 +#: wp-admin/upload.php:173 wp-admin/user-edit.php:54 wp-admin/user-new.php:185 +#: wp-admin/users.php:63 wp-admin/widgets.php:73 +msgid "" +"Support Forums" +msgstr "" +"Forums " +"d’entraide" + +#: wp-admin/comment.php:68 wp-admin/comment.php:222 +#: wp-admin/edit-comments.php:165 +msgid "Oops, no comment with this ID." +msgstr "Oups, aucun commentaire avec cet ID." + +#: wp-admin/comment.php:68 wp-admin/comment.php:222 +#: wp-admin/includes/post.php:1243 +msgid "Go back" +msgstr "Retour" + +#: wp-admin/comment.php:71 +msgid "You are not allowed to edit this comment." +msgstr "Vous n’avez pas l’autorisation de modifier ce commentaire." + +#: wp-admin/comment.php:74 +msgid "" +"This comment is in the Trash. Please move it out of the Trash if you want to " +"edit it." +msgstr "" +"Ce commentaire est dans la Corbeille. Veuillez l’en sortir avant de le " +"modifier." + +#: wp-admin/comment.php:87 +msgid "Moderate Comment" +msgstr "Modérer le commentaire" + +#: wp-admin/comment.php:124 +msgid "You are about to mark the following comment as spam:" +msgstr "" +"Vous êtes sur le point de marquer le commentaire suivant comme " +"indésirable :" + +#: wp-admin/comment.php:125 +msgid "Spam Comment" +msgstr "Marquer comme indésirable" + +#: wp-admin/comment.php:128 +msgid "You are about to move the following comment to the Trash:" +msgstr "" +"Vous êtes sur le point de déplacer le commentaire suivant dans la " +"Corbeille :" + +#: wp-admin/comment.php:129 +msgid "Trash Comment" +msgstr "Mettre le commentaire dans la Corbeille" + +#: wp-admin/comment.php:132 +msgid "You are about to delete the following comment:" +msgstr "Vous êtes sur le point de supprimer le commentaire suivant :" + +#: wp-admin/comment.php:133 +msgid "Permanently Delete Comment" +msgstr "Supprimer définitivement le commentaire" + +#: wp-admin/comment.php:136 +msgid "You are about to approve the following comment:" +msgstr "Vous êtes sur le point d’approuver le commentaire suivant :" + +#: wp-admin/comment.php:137 +msgid "Approve Comment" +msgstr "Approuver le commentaire" + +#: wp-admin/comment.php:145 +msgid "This comment is currently approved." +msgstr "Ce commentaire est actuellement approuvé." + +#: wp-admin/comment.php:148 +msgid "This comment is currently marked as spam." +msgstr "Ce commentaire est actuellement marqué comme indésirable." + +#: wp-admin/comment.php:151 +msgid "This comment is currently in the Trash." +msgstr "Ce commentaire est actuellement dans la Corbeille." + +#: wp-admin/comment.php:158 wp-admin/plugins.php:266 +#: wp-admin/theme-editor.php:218 +msgid "Caution:" +msgstr "Attention :" + +#: wp-admin/comment.php:224 wp-admin/edit-comments.php:168 +#: wp-admin/includes/comment.php:37 +msgid "You are not allowed to edit comments on this post." +msgstr "" +"Vous n’avez pas l’autorisation de modifier les commentaires de " +"cet article." + +#: wp-admin/comment.php:298 +msgid "Unknown action." +msgstr "Action inconnue." + +#: wp-admin/credits.php:103 +msgid "" +"WordPress is created by a worldwide team of passionate " +"individuals. Get involved in WordPress." +msgstr "" +"WordPress est créé par une équipe de personnes passionnées, répartie sur toute la planète. Participez au " +"développement de WordPress !" + +#. translators: Url to the codex documentation on contributing to WordPress +#. used on the credits page +#: wp-admin/credits.php:106 wp-admin/credits.php:163 +msgid "http://codex.wordpress.org/Contributing_to_WordPress" +msgstr "http://codex.wordpress.org/Contributing_to_WordPress" + +#: wp-admin/credits.php:111 +msgid "WordPress is created by a worldwide team of passionate individuals." +msgstr "" +"WordPress est créé par une équipe de personnes passionnées, réparties sur " +"toute la planète." + +#: wp-admin/credits.php:119 +msgctxt "" +"Translate this to be the equivalent of English Translators in your language " +"for the credits page Translators section" +msgid "Translators" +msgstr "Traducteurs" + +#: wp-admin/credits.php:161 +msgid "" +"Want to see your name in lights on this page? Get involved in " +"WordPress." +msgstr "" +"Vous voulez faire partie des noms listés sur cette page ? Participez au développement de WordPress !" + +#: wp-admin/credits.php:173 +msgid "Project Leaders" +msgstr "Chefs de projet" + +#: wp-admin/credits.php:174 +msgid "Extended Core Team" +msgstr "Équipe principale étendue" + +#: wp-admin/credits.php:175 +msgid "Core Developers" +msgstr "Développeurs principaux" + +#: wp-admin/credits.php:176 +msgid "Recent Rockstars" +msgstr "Étoiles montantes" + +#: wp-admin/credits.php:177 +msgid "Core Contributors to WordPress %s" +msgstr "Contributeurs au code de WordPress %s" + +#: wp-admin/credits.php:178 +msgid "Contributing Developers" +msgstr "Développeurs ayant contribué" + +#: wp-admin/credits.php:179 +msgid "Cofounder, Project Lead" +msgstr "Cofondateur, chef de projet" + +#: wp-admin/credits.php:180 +msgid "Lead Developer" +msgstr "Développeur principal" + +#: wp-admin/credits.php:181 +msgid "User Experience Lead" +msgstr "En charge de l’expérience utilisateur" + +#: wp-admin/credits.php:182 +msgid "Core Developer" +msgstr "Développeur cœur" + +#: wp-admin/credits.php:183 +msgid "Core Committer" +msgstr "Développeur principal" + +#: wp-admin/credits.php:184 +msgid "Guest Committer" +msgstr "Développeur invité" + +#: wp-admin/credits.php:185 +msgid "Developer" +msgstr "Développeur" + +#: wp-admin/credits.php:186 +msgid "Designer" +msgstr "Concepteur graphique" + +#: wp-admin/credits.php:187 +msgid "XML-RPC" +msgstr "XML-RPC" + +#: wp-admin/credits.php:188 +msgid "Internationalization" +msgstr "Internationalisation" + +#: wp-admin/credits.php:189 +msgid "External Libraries" +msgstr "Bibliothèques tierces" + +#: wp-admin/credits.php:190 +msgid "Icon Design" +msgstr "Conception des icônes" + +#: wp-admin/custom-background.php:90 +msgid "" +"You can customize the look of your site without touching any of your " +"theme’s code by using a custom background. Your background can be an " +"image or a color." +msgstr "" +"Vous pouvez personnaliser l’apparence de votre site sans jamais " +"toucher au code de votre thème, en utilisant un fond personnalisé. Votre " +"fond peut être une image ou juste une couleur." + +#: wp-admin/custom-background.php:91 +msgid "" +"To use a background image, simply upload it or choose an image that has " +"already been uploaded to your Media Library by clicking the “Choose " +"Image” button. You can display a single instance of your image, or " +"tile it to fill the screen. You can have your background fixed in place, so " +"your site content moves on top of it, or you can have it scroll with your " +"site." +msgstr "" +"Pour utiliser une image de fond, mettez-la simplement en ligne ou choisissez " +"une image déjà mise en ligne dans votre Bibliothèque de Médias en cliquant " +"sur le bouton « Choisir l’image ». Vous pouvez " +"n’afficher qu’une occurrence de l’image, ou la répéter " +"afin de remplir l’écran. Vous pouvez choisir de garder le fond en " +"place quand vous faites défiler le contenu, ou au contraire faire que le " +"fond défile en même temps." + +#: wp-admin/custom-background.php:92 +msgid "" +"You can also choose a background color by clicking the Select Color button " +"and either typing in a legitimate HTML hex value, e.g. “#ff0000” " +"for red, or by choosing a color using the color picker." +msgstr "" +"Vous pouvez également choisir une couleur pour ce texte en cliquant sur le " +"bouton « Sélecteur de couleur » et soit en saisissant " +"une valeur HTML valide (ex. : #ff0000 pour du rouge) ou en " +"cliquant sur le sélecteur de couleur." + +#: wp-admin/custom-background.php:93 +msgid "" +"Don’t forget to click on the Save Changes button when you are finished." +msgstr "" +"N’oubliez pas de cliquer sur « Enregistrer les " +"modifications » quand vous avez terminé." + +#: wp-admin/custom-background.php:98 +msgid "" +"Documentation on Custom Background" +msgstr "" +"Documentation sur le fond personnalisé (en)" + +#: wp-admin/custom-background.php:183 wp-admin/includes/theme.php:189 +msgid "Custom Background" +msgstr "Arrière-plan personnalisé" + +#: wp-admin/custom-background.php:186 +msgid "" +"Background updated. Visit your site to see how it looks." +msgstr "" +"L’arrière-plan a été mis à jour. Afficher votre site pour voir le rendu." + +#: wp-admin/custom-background.php:228 +msgid "Remove Background Image" +msgstr "Supprimer l’image d’arrière-plan" + +#: wp-admin/custom-background.php:229 +msgid "" +"This will remove the background image. You will not be able to restore any " +"customizations." +msgstr "" +"Ceci supprimera l’image d’arrière-plan. Il ne vous sera pas " +"possible de rétablir vos personnalisations." + +#: wp-admin/custom-background.php:238 wp-admin/custom-background.php:242 +#: wp-admin/includes/image-edit.php:100 +msgid "Restore Original Image" +msgstr "Rétablir l’image originale" + +#: wp-admin/custom-background.php:243 +msgid "" +"This will restore the original background image. You will not be able to " +"restore any customizations." +msgstr "" +"Ceci remettra en place l’image d’arrière-plan originale. Il ne " +"vous sera pas possible de récupérer vos personnalisations." + +#: wp-admin/custom-background.php:250 wp-admin/custom-header.php:498 +msgid "Select Image" +msgstr "Sélectionnez une image" + +#: wp-admin/custom-background.php:253 wp-admin/custom-header.php:520 +msgid "Choose an image from your computer:" +msgstr "Choisissez une image sur votre ordinateur :" + +#: wp-admin/custom-background.php:260 wp-admin/custom-header.php:534 +msgid "Or choose an image from your media library:" +msgstr "Ou choisissez une image dans votre bibliothèque de médias :" + +#: wp-admin/custom-background.php:262 +msgid "Choose a Background Image" +msgstr "Choisir une image d’arrière-plan" + +#: wp-admin/custom-background.php:263 +msgid "Set as background" +msgstr "Utiliser comme image de fond" + +#: wp-admin/custom-background.php:263 wp-admin/custom-header.php:538 +msgid "Choose Image" +msgstr "Choisissez une image" + +#: wp-admin/custom-background.php:271 +msgid "Display Options" +msgstr "Options d’affichage" + +#: wp-admin/custom-background.php:277 wp-admin/widgets.php:248 +msgid "Position" +msgstr "Position" + +#: wp-admin/custom-background.php:295 +msgid "Repeat" +msgstr "Répétition" + +#: wp-admin/custom-background.php:305 +msgctxt "Background Attachment" +msgid "Attachment" +msgstr "Attachement" + +#: wp-admin/custom-background.php:356 wp-admin/custom-header.php:773 +#: wp-admin/includes/ajax-actions.php:1669 +msgid "The uploaded file is not a valid image. Please try again." +msgstr "" +"Le fichier mis en ligne n’est pas une image valide. Veuillez réessayer." + +#: wp-admin/custom-header.php:108 +msgid "This screen is used to customize the header section of your theme." +msgstr "" +"Cet écran est utilisé pour personnaliser la section d’en-tête de votre " +"thème." + +#: wp-admin/custom-header.php:109 +msgid "" +"You can choose from the theme’s default header images, or use one of " +"your own. You can also customize how your Site Title and Tagline are " +"displayed." +msgstr "" +"Vous pouvez choisir à partir des images d’en-tête par défaut du thème, " +"ou utiliser l’une des vôtres. Vous pouvez également personnaliser la " +"manière dont s’affichent le titre de votre site et son slogan." + +#: wp-admin/custom-header.php:116 +msgid "" +"You can set a custom image header for your site. Simply upload the image and " +"crop it, and the new header will go live immediately. Alternatively, you can " +"use an image that has already been uploaded to your Media Library by " +"clicking the “Choose Image” button." +msgstr "" +"Vous pouvez utiliser une image d’en-tête personnalisée pour votre " +"site. Mettez simplement l’image en ligne, recadrez-la, et le nouvel en-" +"tête sera aussitôt en ligne. Autrement, vous pouvez utiliser une image qui a " +"déjà été mise en ligne dans votre Bibliothèque de Médias, en cliquant sur le " +"bouton « Choisissez une image »." + +#: wp-admin/custom-header.php:117 +msgid "" +"Some themes come with additional header images bundled. If you see multiple " +"images displayed, select the one you’d like and click the “Save " +"Changes” button." +msgstr "" +"Certains thèmes disposent d’une série d’images d’en-tête. " +"Si vous voyez plusieurs images affichées, sélectionnez celle que vous aimez " +"et cliquez sur le bouton « Enregistrer les modifications " +"»." + +#: wp-admin/custom-header.php:118 +msgid "" +"If your theme has more than one default header image, or you have uploaded " +"more than one custom header image, you have the option of having WordPress " +"display a randomly different image on each page of your site. Click the " +"“Random” radio button next to the Uploaded Images or Default " +"Images section to enable this feature." +msgstr "" +"Si votre thème a plus d’une image d’en-tête par défaut, ou si " +"vous avez mis en ligne plus d’une image d’en-tête personnalisée, " +"vous pouvez faire en sorte que WordPress affiche une image aléatoire " +"différente à chaque chargement de votre site. Sélectionnez l’option " +"« Au hasard » dans la section « Images par " +"défaut » ou « Images mises en ligne » pour " +"activer cette fonctionnalité." + +#: wp-admin/custom-header.php:119 +msgid "" +"If you don’t want a header image to be displayed on your site at all, " +"click the “Remove Header Image” button at the bottom of the " +"Header Image section of this page. If you want to re-enable the header image " +"later, you just have to select one of the other image options and click " +"“Save Changes”." +msgstr "" +"Si vous ne souhaitez pas que votre site utilise une image d’en-tête, " +"cliquez sur le bouton « Retirer l’image d’en-tête " +"» en bas de la section « Image d’en-tête » " +"de cette page. Si vous souhaitez réactiver l’image d’en-tête, il " +"vous suffit de sélectionner l’une des autres options d’images, " +"et de la valider en cliquant sur « Enregistrer les " +"modifications »." + +#: wp-admin/custom-header.php:124 wp-admin/custom-header.php:601 +#: wp-admin/custom-header.php:606 +msgid "Header Text" +msgstr "Texte de l’en-tête" + +#: wp-admin/custom-header.php:126 +msgid "" +"For most themes, the header text is your Site Title and Tagline, as defined " +"in the General Settings section." +msgstr "" +"Pour la plupart des thèmes, le texte d’en-tête est le titre de votre " +"site et son slogan, tels que définis dans la section Réglages généraux." + +#: wp-admin/custom-header.php:127 +msgid "" +"In the Header Text section of this page, you can choose whether to display " +"this text or hide it. You can also choose a color for the text by clicking " +"the Select Color button and either typing in a legitimate HTML hex value, e." +"g. “#ff0000” for red, or by choosing a color using the color " +"picker." +msgstr "" +"Dans la section « Texte d’en-tête » de cette " +"page, vous pouvez choisir d’afficher ce texte ou de le cacher. Vous " +"pouvez également choisir une couleur pour ce texte en cliquant sur le bouton " +"« Sélecteur de couleur » et soit en saisissant une " +"valeur HTML valide (ex. : #ff0000 pour du rouge) ou en " +"cliquant sur le sélecteur de couleur." + +#: wp-admin/custom-header.php:128 +msgid "" +"Don’t forget to click “Save Changes” when you’re " +"done!" +msgstr "" +"N’oubliez pas de cliquer sur « Enregistrer les " +"modifications » quand vous avez terminé !" + +#: wp-admin/custom-header.php:133 +msgid "" +"Documentation on Custom Header" +msgstr "" +"Documentation sur l’en-tête personnalisé" + +#: wp-admin/custom-header.php:280 +msgid "Random: Show a different image on each page." +msgstr "" +"Aléatoire  : affiche une image différente sur chaque " +"page." + +#: wp-admin/custom-header.php:454 wp-admin/includes/theme.php:191 +msgid "Custom Header" +msgstr "Personnalisation de l’en-tête" + +#: wp-admin/custom-header.php:458 +msgid "Header updated. Visit your site to see how it looks." +msgstr "" +"L’en-tête a été mis à jour. Visiter le site pour " +"voir son nouvel aspect." + +#: wp-admin/custom-header.php:500 +msgid "" +"You can select an image to be shown at the top of your site by uploading " +"from your computer or choosing from your media library. After selecting an " +"image you will be able to crop it." +msgstr "" +"Vous pouvez choisir une image d’en-tête personnalisée en la mettant en " +"ligne depuis votre ordinateur ou en la choisissant dans votre bibliothèque " +"de médias. Après avoir sélectionné l’image, vous pourrez la recadrer." + +#: wp-admin/custom-header.php:503 +msgid "" +"Images of exactly %1$d × %2$d pixels will be used as-" +"is." +msgstr "" +"Les images ayant pour taille exacte %1$d pixels par %2$d " +"seront utilisées telles quelles." + +#: wp-admin/custom-header.php:506 +msgid "Images should be at least %1$d pixels wide." +msgstr "" +"Les images devraient faire au moins %1$d pixels de large." + +#: wp-admin/custom-header.php:509 +msgid "Images should be at least %1$d pixels tall." +msgstr "" +"Les images devraient faire au moins %1$d pixels de haut." + +#: wp-admin/custom-header.php:513 +msgid "Suggested width is %1$d pixels." +msgstr "La largeur suggérée est de %1$d pixels." + +#: wp-admin/custom-header.php:515 +msgid "Suggested height is %1$d pixels." +msgstr "La hauteur suggérée est de %1$d pixels." + +#: wp-admin/custom-header.php:537 +msgid "Choose a Custom Header" +msgstr "Choisir un en-tête personnalisé" + +#: wp-admin/custom-header.php:538 +msgid "Set as header" +msgstr "Utiliser comme en-tête" + +#: wp-admin/custom-header.php:552 +msgid "Uploaded Images" +msgstr "Images mises en ligne" + +#: wp-admin/custom-header.php:554 +msgid "" +"You can choose one of your previously uploaded headers, or show a random one." +msgstr "" +"Vous pouvez choisir un en-tête parmi ceux que vous avez déjà mis en ligne, " +"ou en afficher un aléatoirement" + +# Ne pas mettre d'entité HTML ( ...) : chaîne affichée dans l'éditeur visuel. +#: wp-admin/custom-header.php:563 +msgid "Default Images" +msgstr "Images par défaut" + +#: wp-admin/custom-header.php:566 +msgid "" +"If you don‘t want to upload your own image, you can use one of these " +"cool headers, or show a random one." +msgstr "" +"Si vous ne voulez pas mettre en ligne d’image, vous pouvez utiliser " +"l’un de ces en-têtes, ou en afficher un aléatoirement." + +#: wp-admin/custom-header.php:568 +msgid "" +"You can use one of these cool headers or show a random one on each page." +msgstr "" +"Vous pouvez choisir parmi ces en-têtes, ou en afficher un aléatoirement à " +"chaque chargement de page." + +#: wp-admin/custom-header.php:580 +msgid "" +"This will remove the header image. You will not be able to restore any " +"customizations." +msgstr "" +"Ceci retirera l’image d’en-tête. Il ne vous sera pas possible de " +"rétablir vos personnalisations." + +#: wp-admin/custom-header.php:581 +msgid "Remove Header Image" +msgstr "Retirer l’image d’en-tête" + +#: wp-admin/custom-header.php:589 +msgid "Reset Image" +msgstr "Remettre l’image d’origine" + +#: wp-admin/custom-header.php:591 +msgid "" +"This will restore the original header image. You will not be able to restore " +"any customizations." +msgstr "" +"Ceci remettra en place l’image d’en-tête d’origine. Il ne " +"vous sera pas possible de récupérer vos personnalisations." + +#: wp-admin/custom-header.php:592 +msgid "Restore Original Header Image" +msgstr "Rétablir l’image d’en-tête d’origine" + +#: wp-admin/custom-header.php:609 +msgid "Show header text with your image." +msgstr "Afficher le texte d’en-tête avec l’image." + +#: wp-admin/custom-header.php:615 +msgid "Text Color" +msgstr "Couleur du texte" + +#: wp-admin/custom-header.php:626 +msgctxt "color" +msgid "Default: %s" +msgstr "Par défaut : %s" + +#: wp-admin/custom-header.php:713 wp-admin/custom-header.php:855 +msgid "Image could not be processed. Please go back and try again." +msgstr "" +"L’image n’a pas pu être traitée. Veuillez revenir en arrière en " +"réessayer." + +#: wp-admin/custom-header.php:713 wp-admin/custom-header.php:855 +msgid "Image Processing Error" +msgstr "Erreur lors du traitement de l’image" + +#: wp-admin/custom-header.php:728 +msgid "Crop Header Image" +msgstr "Recadrer l’image d’en-tête" + +#: wp-admin/custom-header.php:731 +msgid "Choose the part of the image you want to use as your header." +msgstr "" +"Choisissez la partie de l’image que vous voulez utiliser comme en-tête." + +#: wp-admin/custom-header.php:732 +msgid "You need Javascript to choose a part of the image." +msgstr "" +"Vous avez besoin de la fonctionnalité JavaScript de votre navigateur " +"internet pour choisir une partie de l’image." + +#: wp-admin/custom-header.php:750 +msgid "Crop and Publish" +msgstr "Recadrer et publier" + +#: wp-admin/custom-header.php:753 +msgid "Skip Cropping, Publish Image as Is" +msgstr "Pas de recadrage, utiliser l’image telle quelle" + +#: wp-admin/custom-header.php:778 +msgid "Image Upload Error" +msgstr "Erreur lors de l’envoi de l’image" + +#: wp-admin/custom-header.php:925 +msgid "You do not have permission to customize headers." +msgstr "" +"Vous n’avez pas l’autorisation de personnaliser les en-têtes." + +#: wp-admin/customize.php:76 +msgid "Customize %s" +msgstr "Personnaliser %s" + +#: wp-admin/customize.php:116 +msgid "Theme Customizer Options" +msgstr "Options de personnalisation du thème" + +#. translators: %s is the theme name in the Customize/Live Preview pane +#: wp-admin/customize.php:119 +msgid "You are previewing %s" +msgstr "Vous prévisualisez %s" + +#: wp-admin/customize.php:144 +#: wp-admin/includes/class-wp-theme-install-list-table.php:264 +msgid "Collapse Sidebar" +msgstr "Réduire la barre latérale" + +#: wp-admin/customize.php:146 +#: wp-admin/includes/class-wp-theme-install-list-table.php:265 +msgid "Collapse" +msgstr "Réduire" + +#: wp-admin/edit-comments.php:108 wp-admin/edit-comments.php:146 +msgid "Comments on “%s”" +msgstr "Commentaires sur « %s »" + +#: wp-admin/edit-comments.php:112 +msgctxt "comments per page (screen options)" +msgid "Comments" +msgstr "Commentaires" + +#: wp-admin/edit-comments.php:118 +msgid "" +"You can manage comments made on your site similar to the way you manage " +"posts and other content. This screen is customizable in the same ways as " +"other management screens, and you can act on comments using the on-hover " +"action links or the Bulk Actions." +msgstr "" +"Vous pouvez gérer les commentaires sur votre site de la même manière que " +"vous gérez les articles et autres contenus. Cet écran est personnalisable de " +"la même manière que les autres écrans de gestion, et vous pouvez agir sur " +"les commentaires par le biais des liens qui apparaissent au survol de la " +"souris, ou via le menu « Actions groupées »." + +#: wp-admin/edit-comments.php:122 +msgid "Moderating Comments" +msgstr "Modération des commentaires" + +#: wp-admin/edit-comments.php:124 +msgid "A yellow row means the comment is waiting for you to moderate it." +msgstr "" +"Une ligne jaune indique que le commentaire est en attente de modération." + +#: wp-admin/edit-comments.php:125 +msgid "" +"In the Author column, in addition to the author’s " +"name, email address, and blog URL, the commenter’s IP address is " +"shown. Clicking on this link will show you all the comments made from this " +"IP address." +msgstr "" +"Dans la colonne « Auteur », en plus de trouver le nom " +"de l’auteur, son adresse de messagerie et celle de son site, vous " +"trouverez son adresse IP. En cliquant dessus, vous obtiendrez une liste de " +"tous les commentaires faits depuis cette adresse IP." + +#: wp-admin/edit-comments.php:126 +msgid "" +"In the Comment column, above each comment it says “" +"Submitted on,” followed by the date and time the comment was left on " +"your site. Clicking on the date/time link will take you to that comment on " +"your live site. Hovering over any comment gives you options to approve, " +"reply (and approve), quick edit, edit, spam mark, or trash that comment." +msgstr "" +"Dans la colonne « Commentaire », vous trouverez au-" +"dessus de chaque commentaire la date et l’heure de son envoi. En " +"cliquant sur ce lien, vous irez à la page de votre site où le commentaire a " +"été publié. En survolant n’importe quel commentaire, des options " +"apparaîtront, vous permettant d’approuver un commentaire, y répondre " +"(et l’approuver), modifier ses détails, modifier son contenu, le " +"marquer comme indésirable, ou le jeter à la Corbeille." + +#: wp-admin/edit-comments.php:127 +msgid "" +"In the In Response To column, there are three elements. The " +"text is the name of the post that inspired the comment, and links to the " +"post editor for that entry. The View Post link leads to that post on your " +"live site. The small bubble with the number in it shows the number of " +"approved comments that post has received. If the bubble is gray, you have " +"moderated all comments for that post. If it is blue, there are pending " +"comments. Clicking the bubble will filter the comments screen to show only " +"comments on that post." +msgstr "" +"Dans la colonne « En réponse à » se " +"trouvent trois éléments. Le texte correspond au titre de l’article qui " +"a inspiré ce commentaire, et un clic sur ce lien vous permettra de modifier " +"cet article. Le lien « Afficher l’article » mène " +"à l’article sur le site. La petite bulle avec un nombre vous indique " +"le nombre de commentaires que l’article a reçus. Si la bulle est " +"grise, vous avez modéré tous les commentaires de cet article. Si elle est " +"bleue, il y a des commentaires en attente de modération. Un clic sur la " +"bulle filtrera la liste des commentaires pour ne plus afficher que ceux liés " +"à cet article." + +#: wp-admin/edit-comments.php:128 +msgid "" +"Many people take advantage of keyboard shortcuts to moderate their comments " +"more quickly. Use the link to the side to learn more." +msgstr "" +"De nombreux utilisateurs utilisent les raccourcis clavier pour modérer leurs " +"commentaires plus rapidement. Suivez le lien sur le côté pour en savoir plus." + +#: wp-admin/edit-comments.php:134 +msgid "" +"Documentation on Comment Spam" +msgstr "" +"Documentation sur les commentaires indésirables" + +#: wp-admin/edit-comments.php:135 +msgid "" +"Documentation on Keyboard Shortcuts" +msgstr "" +"Documentation sur les raccourcis clavier (en)" + +#: wp-admin/edit-comments.php:156 wp-admin/edit-tags.php:300 +#: wp-admin/edit.php:274 wp-admin/link-manager.php:75 wp-admin/plugins.php:415 +#: wp-admin/upload.php:188 wp-admin/users.php:439 +msgid "Search results for “%s”" +msgstr "Résultats de recherche pour « %s »" + +#: wp-admin/edit-comments.php:186 +msgid "%s comment approved" +msgid_plural "%s comments approved" +msgstr[0] "%s commentaire approuvé" +msgstr[1] "%s commentaires approuvés" + +#: wp-admin/edit-comments.php:190 +msgid "%s comment marked as spam." +msgid_plural "%s comments marked as spam." +msgstr[0] "%s commentaire marqué comme indésirable." +msgstr[1] "%s commentaires marqués comme indésirables." + +#: wp-admin/edit-comments.php:194 +msgid "%s comment restored from the spam" +msgid_plural "%s comments restored from the spam" +msgstr[0] "%s commentaire rétabli depuis les commentaires indésirables" +msgstr[1] "%s commentaires rétablis depuis les commentaires indésirables" + +#: wp-admin/edit-comments.php:198 +msgid "%s comment moved to the Trash." +msgid_plural "%s comments moved to the Trash." +msgstr[0] "%s commentaire déplacé dans la Corbeille." +msgstr[1] "%s commentaires déplacés dans la Corbeille." + +#: wp-admin/edit-comments.php:202 +msgid "%s comment restored from the Trash" +msgid_plural "%s comments restored from the Trash" +msgstr[0] "%s commentaire récupéré depuis la Corbeille" +msgstr[1] "%s commentaires récupérés depuis la Corbeille" + +#: wp-admin/edit-comments.php:205 +msgid "%s comment permanently deleted" +msgid_plural "%s comments permanently deleted" +msgstr[0] "%s commentaire supprimé définitivement" +msgstr[1] "%s commentaires supprimés définitivement" + +#: wp-admin/edit-comments.php:210 +msgid "This comment is already approved." +msgstr "Ce commentaire est déjà approuvé." + +#: wp-admin/edit-comments.php:210 wp-admin/edit-comments.php:216 +#: wp-admin/includes/class-wp-comments-list-table.php:421 +#: wp-admin/includes/dashboard.php:687 +msgid "Edit comment" +msgstr "Modifier le commentaire" + +#: wp-admin/edit-comments.php:213 +msgid "This comment is already in the Trash." +msgstr "Ce commentaire est déjà marqué comme indésirable." + +#: wp-admin/edit-comments.php:213 +msgid "View Trash" +msgstr "Voir la Corbeille" + +#: wp-admin/edit-comments.php:216 +msgid "This comment is already marked as spam." +msgstr "Ce commentaire est déjà marqué comme indésirable." + +#: wp-admin/edit-comments.php:230 +msgid "Search Comments" +msgstr "Chercher un commentaire" + +#: wp-admin/edit-form-advanced.php:41 +msgid "Post updated. View post" +msgstr "Article mis à jour. Afficher l’article" + +#: wp-admin/edit-form-advanced.php:42 wp-admin/edit-form-advanced.php:58 +msgid "Custom field updated." +msgstr "Champ personnalisé mis à jour." + +#: wp-admin/edit-form-advanced.php:43 wp-admin/edit-form-advanced.php:59 +msgid "Custom field deleted." +msgstr "Champ personnalisé supprimé." + +#: wp-admin/edit-form-advanced.php:44 +msgid "Post updated." +msgstr "Article mis à jour." + +#. translators: %s: date and time of the revision +#: wp-admin/edit-form-advanced.php:46 +msgid "Post restored to revision from %s" +msgstr "Article rétabli à partir de la révision du %s" + +#: wp-admin/edit-form-advanced.php:47 +msgid "Post published. View post" +msgstr "Article publié. Afficher l’article" + +#: wp-admin/edit-form-advanced.php:48 +msgid "Post saved." +msgstr "Article enregistré." + +#: wp-admin/edit-form-advanced.php:49 +msgid "Post submitted. Preview post" +msgstr "" +"Article proposé. Prévisualiser l’" +"article" + +#: wp-admin/edit-form-advanced.php:50 +msgid "" +"Post scheduled for: %1$s. Preview post" +msgstr "" +"Article prévu pour le : %1$s. Prévisualiser l’article" + +#. translators: Publish box date format, see http:php.net/date +#: wp-admin/edit-form-advanced.php:52 wp-admin/edit-form-advanced.php:65 +#: wp-admin/edit-form-comment.php:103 wp-admin/includes/meta-boxes.php:155 +#: wp-admin/includes/meta-boxes.php:277 wp-admin/includes/revision.php:170 +msgid "M j, Y @ G:i" +msgstr "j F Y \\à G \\h i \\m\\i\\n" + +#: wp-admin/edit-form-advanced.php:53 +msgid "Post draft updated. Preview post" +msgstr "" +"Brouillon d’article mis à jour. Prévisualiser l’article" + +#: wp-admin/edit-form-advanced.php:57 +msgid "Page updated. View page" +msgstr "Page mise à jour. Afficher la page" + +#: wp-admin/edit-form-advanced.php:60 +msgid "Page updated." +msgstr "Page mise à jour." + +#: wp-admin/edit-form-advanced.php:61 +msgid "Page restored to revision from %s" +msgstr "Page rétablie à partir de la révision du %s" + +#: wp-admin/edit-form-advanced.php:62 +msgid "Page published. View page" +msgstr "Page publiée. Afficher la page" + +#: wp-admin/edit-form-advanced.php:63 +msgid "Page saved." +msgstr "Page enregistrée." + +#: wp-admin/edit-form-advanced.php:64 +msgid "Page submitted. Preview page" +msgstr "" +"Page proposée. Prévisualiser la page" + +#: wp-admin/edit-form-advanced.php:65 +msgid "" +"Page scheduled for: %1$s. Preview page" +msgstr "" +"Page prévue pour le : %1$s. Afficher la page" + +#: wp-admin/edit-form-advanced.php:66 +msgid "Page draft updated. Preview page" +msgstr "" +"Brouillon de page mis à jour. Prévisualiser " +"la page" + +#: wp-admin/edit-form-advanced.php:68 wp-admin/media.php:95 +#: wp-admin/upload.php:194 wp-admin/upload.php:219 +msgid "Media attachment updated." +msgstr "Fichier attaché mis à jour." + +#: wp-admin/edit-form-advanced.php:107 +msgid "" +"There is an autosave of this post that is more recent than the version " +"below. View the autosave" +msgstr "" +"Une sauvegarde automatique existe pour cet article ; elle est plus " +"récente que la version affichée ci-dessous. Afficher cette " +"sauvegarde automatique." + +#: wp-admin/edit-form-advanced.php:164 wp-admin/edit-form-advanced.php:353 +msgid "Page Attributes" +msgstr "Attributs de la page" + +#: wp-admin/edit-form-advanced.php:164 +msgid "Attributes" +msgstr "Attributs" + +#: wp-admin/edit-form-advanced.php:174 +msgid "Featured Image" +msgstr "Image à la Une" + +#: wp-admin/edit-form-advanced.php:180 +msgid "Send Trackbacks" +msgstr "Envoyer des rétroliens" + +#: wp-admin/edit-form-advanced.php:183 +msgid "Custom Fields" +msgstr "Champs personnalisés" + +#: wp-admin/edit-form-advanced.php:196 wp-admin/includes/dashboard.php:310 +#: wp-admin/menu.php:212 +msgid "Discussion" +msgstr "Discussion" + +#: wp-admin/edit-form-advanced.php:202 +#: wp-admin/includes/class-wp-posts-list-table.php:793 +#: wp-admin/includes/class-wp-terms-list-table.php:101 +#: wp-admin/includes/class-wp-terms-list-table.php:344 +#: wp-admin/includes/meta-boxes.php:592 +msgid "Slug" +msgstr "Identifiant" + +#: wp-admin/edit-form-advanced.php:250 +msgid "" +"The title field and the big Post Editing Area are fixed in place, but you " +"can reposition all the other boxes using drag and drop. You can also " +"minimize or expand them by clicking the title bar of each box. Use the " +"Screen Options tab to unhide more boxes (Excerpt, Send Trackbacks, Custom " +"Fields, Discussion, Slug, Author) or to choose a 1- or 2-column layout for " +"this screen." +msgstr "" +"Le champ du titre et la zone d’édition de l’article sont " +"inamovibles, mais vous pouvez déplacer toutes les autres blocs par simple " +"glisser/déposer. Vous pouvez également les fermer/ouvrir en cliquant sur la " +"barre de titre de chaque boite. Utilisez l’onglet « Options " +"de l’écran » pour cacher d’autres boites (Extrait, " +"Envoyer des rétroliens, Champs personnalisés, Discussion, Identifiant, " +"Auteur) ou pour choisir un affichage sur une ou deux colonnes pour cet écran." + +#: wp-admin/edit-form-advanced.php:254 +msgid "Customizing This Display" +msgstr "Personnaliser cet écran" + +#: wp-admin/edit-form-advanced.php:258 +msgid "" +"Title - Enter a title for your post. After you enter a " +"title, you’ll see the permalink below, which you can edit." +msgstr "" +"Titre - Saisissez un titre pour votre article. Après avoir " +"saisi le titre, un permalien s’affichera en dessous, que vous pourrez " +"modifier à loisir." + +#: wp-admin/edit-form-advanced.php:259 +msgid "" +"Post editor - Enter the text for your post. There are two " +"modes of editing: Visual and Text. Choose the mode by clicking on the " +"appropriate tab. Visual mode gives you a WYSIWYG editor. Click the last icon " +"in the row to get a second row of controls. The Text mode allows you to " +"enter HTML along with your post text. Line breaks will be converted to " +"paragraphs automatically. You can insert media files by clicking the icons " +"above the post editor and following the directions. You can go to the " +"distraction-free writing screen via the Fullscreen icon in Visual mode " +"(second to last in the top row) or the Fullscreen button in Text mode (last " +"in the row). Once there, you can make buttons visible by hovering over the " +"top area. Exit Fullscreen back to the regular post editor." +msgstr "" +"Éditeur d’article - Saisissez-y le contenu de votre " +"article. Vous disposez pour ce faire de deux modes : Visuel ou Texte. " +"Choisissez un mode en cliquant sur l’onglet correspondant. Le mode " +"Visuel vous donne accès à un éditeur WYSIWYG ; cliquez sur la dernière " +"icône de la rangée pour afficher une seconde rangée d’icônes. Le mode " +"Texte vous permet de saisir directement du code HTML en même temps que le " +"contenu de votre article. Vous pouvez insérer des fichiers média en cliquant " +"sur les icônes situées au-dessus de l’éditeur, puis en suivant les " +"instructions. Vous pouvez passer en mode « aucune " +"distraction » grâce à l’icône « Plein Écran " +"» du mode Visuel (avant-dernier bouton de la première rangée), ou le " +"bouton « Plein Écran » du mode HTML (dernier bouton de " +"la rangée). Une fois dans ce mode, vous pouvez rendre les boutons visibles " +"en survolant la zone supérieure de la page. Quittez le mode Plein Écran pour " +"revenir en mode d’édition normal." + +#: wp-admin/edit-form-advanced.php:263 +msgid "Title and Post Editor" +msgstr "Titre et éditeur d’article" + +#: wp-admin/edit-form-advanced.php:268 +msgid "" +"You can also create posts with the Press This bookmarklet." +msgstr "" +"Vous pouvez également créer des articles avec le bookmarklet Publier un article." + +#: wp-admin/edit-form-advanced.php:270 +msgid "" +"Documentation on Writing and Editing Posts" +msgstr "" +"Documentation sur l’écriture et la modification des articles (en)" + +#: wp-admin/edit-form-advanced.php:274 +msgid "" +"Pages are similar to Posts in that they have a title, body text, and " +"associated metadata, but they are different in that they are not part of the " +"chronological blog stream, kind of like permanent posts. Pages are not " +"categorized or tagged, but can have a hierarchy. You can nest Pages under " +"other Pages by making one the “Parent” of the other, creating a " +"group of Pages." +msgstr "" +"Les pages sont comme des articles, en cela qu’elles ont un titre, un " +"contenu et des métadonnées associées ; mais elles diffèrent en cela " +"qu’elles ne font pas partie du flux chronologique du blog - un peu " +"comme des articles permanents. Les pages ne sont pas catégorisées et ne " +"reçoivent pas de mots-clés, mais peuvent disposer d’une hiérarchie. En " +"effet, vous pouvez imbriquer des pages sous d’autres pages, faisant de " +"ces dernières les « parentes » des premières, créant " +"ainsi un groupement de pages." + +#: wp-admin/edit-form-advanced.php:275 +msgid "" +"Creating a Page is very similar to creating a Post, and the screens can be " +"customized in the same way using drag and drop, the Screen Options tab, and " +"expanding/collapsing boxes as you choose. This screen also has the " +"distraction-free writing space, available in both the Visual and Text modes " +"via the Fullscreen buttons. The Page editor mostly works the same as the " +"Post editor, but there are some Page-specific features in the Page " +"Attributes box:" +msgstr "" +"Le processus de création d’une page reste très proche de celui d’" +"un article, et les écrans respectifs peuvent être personnalisés de la même " +"manière, par le biais de glisser/déposer, de l’onglet « " +"Option de l’Écran », et en ouvrant/fermant les blocs selon " +"vos besoins. Cet écran dispose également du mode « aucune " +"distraction », tant dans le mode Visuel que dans le mode Texte, " +"via les boutons « Plein Écran ». L’éditeur de " +"page fonctionne globalement comme celui des articles, mais dispose de " +"certaines spécificités, disponibles dans le bloc « Attributs de " +"Page » :" + +#: wp-admin/edit-form-advanced.php:279 +msgid "About Pages" +msgstr "À propos des pages" + +#: wp-admin/edit-form-advanced.php:285 +msgid "" +"Documentation on Adding New Pages" +msgstr "" +"Documentation sur l’ajout de nouvelles pages (en)" + +#: wp-admin/edit-form-advanced.php:286 +msgid "" +"Documentation on Editing Pages" +msgstr "" +"Documentation sur la modification des pages (en)" + +#: wp-admin/edit-form-advanced.php:294 +msgid "" +"This screen allows you to edit four fields for metadata in a file within the " +"media library." +msgstr "" +"Cet écran vous permet de modifier les quatre champs des métadonnées des " +"fichiers dans la bibliothèque des médias." + +#: wp-admin/edit-form-advanced.php:295 wp-admin/media.php:76 +msgid "" +"For images only, you can click on Edit Image under the thumbnail to expand " +"out an inline image editor with icons for cropping, rotating, or flipping " +"the image as well as for undoing and redoing. The boxes on the right give " +"you more options for scaling the image, for cropping it, and for cropping " +"the thumbnail in a different way than you crop the original image. You can " +"click on Help in those boxes to get more information." +msgstr "" +"Pour les images (et seulement elles), vous pouvez cliquer sur « " +"Modifier l’Image », sous la miniature, afin de faire " +"apparaître un éditeur d’image, vous permettant de recadrer, d’" +"appliquer une rotation ou d’inverser une image, ainsi que de défaire " +"et refaire vos modifications. Les blocs sur la droite vous donnent accès à " +"d’autres options pour le changement d’échelle, le recadrage et " +"même le recadrage de la miniature, qui peut être différent de celui de " +"l’image originale. Cliquez sur le bouton Aide de ces blocs pour " +"obtenir plus d’informations." + +#: wp-admin/edit-form-advanced.php:296 wp-admin/media.php:77 +msgid "" +"Note that you crop the image by clicking on it (the Crop icon is already " +"selected) and dragging the cropping frame to select the desired part. Then " +"click Save to retain the cropping." +msgstr "" +"Pour recadrer une image, cliquez sur l’icône Recadrer puis " +"sélectionnez la zone à conserver en cliquant sur l’image et en faisant " +"glisser le curseur de la souris. Ensuite, cliquez sur Enregistrer pour " +"conserver votre modification." + +#: wp-admin/edit-form-advanced.php:297 wp-admin/media.php:78 +msgid "Remember to click Update Media to save metadata entered or changed." +msgstr "" +"Pensez bien à cliquer sur le bouton « Mettre à jour le " +"fichier » afin de conserver les métadonnées ajoutées ou modifiées." + +#: wp-admin/edit-form-advanced.php:302 wp-admin/media.php:83 +msgid "" +"Documentation on Edit Media" +msgstr "" +"Documentation sur la modification des médias (en)" + +#: wp-admin/edit-form-advanced.php:308 +msgid "" +"You can upload and insert media (images, audio, documents, etc.) by clicking " +"the Add Media button. You can select from the images and files already " +"uploaded to the Media Library, or upload new media to add to your page or " +"post. To create an image gallery, select the images to add and click the " +"“Create a new gallery” button." +msgstr "" +"Vous pouvez mettre en ligne et insérer des fichiers média (images, sons, " +"documents, etc.) en cliquant sur le bouton » Ajouter un " +"média «. Vous pouvez sélectionner vos images et fichiers parmi " +"ceux déjà présents dans la bibliothèque de médias, ou en mettre en ligne de " +"nouveaux à ajouter à votre article/page. Pour créer une galerie d’" +"image, sélectionnez les images à ajouter et cliquez sur le bouton »" +" Créer une nouvelle galerie «." + +#: wp-admin/edit-form-advanced.php:309 +msgid "" +"You can also embed media from many popular websites including Twitter, " +"YouTube, Flickr and others by pasting the media URL on its own line into the " +"content of your post/page. Please refer to the Codex to learn more about embeds." +msgstr "" +"Vous pouvez également insérer des contenus en provenance de nombreux sites " +"populaires, comme Twitter, YouTube, Flickr et d’autres, simplement en " +"collant l’adresse web du contenu dans sa propre ligne dans le texte de " +"votre article/page. Référez-vous au Codex pour a href=\"http://codex." +"wordpress.org/Embeds\">en apprendre plus sur les contenu insérés." + +#: wp-admin/edit-form-advanced.php:313 +msgid "Inserting Media" +msgstr "Insertion du média" + +#: wp-admin/edit-form-advanced.php:319 +msgid "" +"Several boxes on this screen contain settings for how your content will be " +"published, including:" +msgstr "" +"Plusieurs sections de cet écran vous permettez de régler la manière dont " +"votre contenu sera publié, notamment :" + +#: wp-admin/edit-form-advanced.php:320 +msgid "" +"Publish - You can set the terms of publishing your post in " +"the Publish box. For Status, Visibility, and Publish (immediately), click on " +"the Edit link to reveal more options. Visibility includes options for " +"password-protecting a post or making it stay at the top of your blog " +"indefinitely (sticky). Publish (immediately) allows you to set a future or " +"past date and time, so you can schedule a post to be published in the future " +"or backdate a post." +msgstr "" +"Publier - Vous pouvez définir la manière dont votre article " +"est publié dans le bloc «&nsbp;Publier ». Pour « " +"État », « Visibilité », « " +"Format » et « Publier (immédiatement) », un " +"clic sur le lien « Modifier » affichera plus d’" +"options. « Visibilité » inclut des options pour " +"protéger l’article avec un mot de passe ou faire en sorte qu’il " +"reste en tête de page indéfiniment. « Publier (immédiatement)" +" » vous permet de programmer la publication de votre article à " +"une date précise, dans le futur ou le passé ; cela vous permet d’" +"écrire à l’avance des articles à publier, ou de les antidater." + +#: wp-admin/edit-form-advanced.php:323 +msgid "" +"Format - Post Formats designate how your theme will display " +"a specific post. For example, you could have a standard blog post " +"with a title and paragraphs, or a short aside that omits the title " +"and contains a short text blurb. Please refer to the Codex for descriptions " +"of each post format. Your theme could enable all or some of 10 possible " +"formats." +msgstr "" +"Format d’article - Désigne la manière dont votre " +"thème doit afficher un article donné. Par exemple, vous pourriez vouloir " +"utiliser le format par défaut pour afficher titre et contenu, ou le " +"format En passant pour ne pas utiliser le titre et n’afficher " +"qu’un court texte. Lisez la documentation du Codex pour obtenir une description de chaque format d’article (en). Il est possible " +"que votre thème ne reconnaisse qu’une partie des 10 formats possibles." + +#: wp-admin/edit-form-advanced.php:327 +msgid "" +"Featured Image - This allows you to associate an image with " +"your post without inserting it. This is usually useful only if your theme " +"makes use of the featured image as a post thumbnail on the home page, a " +"custom header, etc." +msgstr "" +"Image à la Une - Vous pouvez associer une image à votre " +"article, sans pour autant l’y insérer. Cela ne sert vraiment que si " +"votre thème fait usage de cette fonctionnalité, sous la forme d’une " +"miniature pour la page d’accueil, d’un en-tête personnalisé..." + +#: wp-admin/edit-form-advanced.php:334 +msgid "Publish Settings" +msgstr "Réglages de publication" + +#: wp-admin/edit-form-advanced.php:338 +msgid "" +"Send Trackbacks - Trackbacks are a way to notify legacy " +"blog systems that you’ve linked to them. Enter the URL(s) you want to " +"send trackbacks. If you link to other WordPress sites they’ll be " +"notified automatically using pingbacks, and this field is unnecessary." +msgstr "" +"Envoyer des rétroliens - Un rétrolien est une manière " +"explicite de notifier les anciens systèmes de blog que vous avez fait un " +"lien vers eux. Saisissez les adresses web que vous voulez notifier. Si dans " +"votre article vous faites des liens vers des sites WordPress, ils seront " +"notifiés automatiquement à l’aide de pings, sans devoir passer par un " +"rétrolien explicite." + +#: wp-admin/edit-form-advanced.php:339 +msgid "" +"Discussion - You can turn comments and pings on or off, and " +"if there are comments on the post, you can see them here and moderate them." +msgstr "" +"Discussion - Vous pouvez activer ou désactiver les " +"commentaires et pings, et si votre article reçoit des commentaires, vous " +"pourrez les voir ici et les modérer." + +#: wp-admin/edit-form-advanced.php:343 wp-admin/options-discussion.php:14 +msgid "Discussion Settings" +msgstr "Options de discussion" + +#: wp-admin/edit-form-advanced.php:347 +msgid "" +"Parent - You can arrange your pages in hierarchies. For " +"example, you could have an “About” page that has “Life " +"Story” and “My Dog” pages under it. There are no limits to " +"how many levels you can nest pages." +msgstr "" +"Parent - Vous pouvez arranger vos pages en hiérarchies. Par " +"exemple, vous pourriez avoir une page « Ã€ propos », " +"avec comme sous-pages « Ma vie » et « Mon " +"œuvre ». Il n’y a pas de limite à la profondeur des " +"sous-pages." + +#: wp-admin/edit-form-advanced.php:348 +msgid "" +"Template - Some themes have custom templates you can use " +"for certain pages that might have additional features or custom layouts. If " +"so, you’ll see them in this dropdown menu." +msgstr "" +"Modèle - Certains thèmes utilisent des modèles spéciaux que " +"vous pouvez appliquer à certaines pages, avec des fonctionnalités " +"supplémentaires ou une mise en page qui leur est propre. Si c’est le " +"cas, vous les verrez dans ce menu déroulant." + +#: wp-admin/edit-form-advanced.php:349 +msgid "" +"Order - Pages are usually ordered alphabetically, but you " +"can choose your own order by entering a number (1 for first, etc.) in this " +"field." +msgstr "" +"Ordre - Les pages sont généralement classées par ordre " +"alphabétique, mais vous pouvez indiquer un nombre pour modifier l’" +"ordre d’apparition." + +#: wp-admin/edit-form-advanced.php:375 +msgid "" +"Connection lost. Saving has been disabled until you’" +"re reconnected." +msgstr "" +"Connexion perdue. L’enregistrement a été désactivé " +"jusqu’à ce que vous soyez reconnecté." + +#: wp-admin/edit-form-advanced.php:376 +msgid "We’re backing up this post in your browser, just in case." +msgstr "Nous sauvegardons cet article dans votre navigateur, par sécurité." + +#: wp-admin/edit-form-advanced.php:449 +msgid "Get Shortlink" +msgstr "Obtenir le lien court" + +#: wp-admin/edit-form-advanced.php:496 wp-admin/includes/ajax-actions.php:1816 +msgid "Last edited by %1$s on %2$s at %3$s" +msgstr "Dernière modification par %1$s, le %2$s à %3$s" + +#: wp-admin/edit-form-advanced.php:498 wp-admin/includes/ajax-actions.php:1818 +msgid "Last edited on %1$s at %2$s" +msgstr "Dernière modification le %1$s à %2$s" + +#: wp-admin/edit-form-comment.php:33 +msgid "Name:" +msgstr "Nom :" + +#: wp-admin/edit-form-comment.php:40 +msgid "E-mail (%s):" +msgstr "E-mail (%s) : " + +#: wp-admin/edit-form-comment.php:40 +msgid "send e-mail" +msgstr "envoyer l’e-mail" + +#: wp-admin/edit-form-comment.php:42 +msgid "E-mail:" +msgstr "E-mail :" + +#: wp-admin/edit-form-comment.php:51 +msgid "visit site" +msgstr "aller sur le site" + +#: wp-admin/edit-form-comment.php:52 +msgid "URL (%s):" +msgstr "Adresse web (%s) :" + +#: wp-admin/edit-form-comment.php:54 +msgid "URL:" +msgstr "Adresse web :" + +#: wp-admin/edit-form-comment.php:74 wp-admin/includes/ajax-actions.php:1487 +#: wp-admin/includes/class-wp-posts-list-table.php:998 +msgid "Status" +msgstr "État" + +#: wp-admin/edit-form-comment.php:81 +msgid "View Comment" +msgstr "Afficher le commentaire" + +#. translators: comment type radio button +#: wp-admin/edit-form-comment.php:90 +msgctxt "adjective" +msgid "Pending" +msgstr "En attente" + +#: wp-admin/edit-form-comment.php:96 +msgid "IP address:" +msgstr "Adresse IP :" + +#: wp-admin/edit-form-comment.php:104 +msgid "Submitted on: %1$s" +msgstr "Envoyé le : %1$s" + +#: wp-admin/edit-form-comment.php:116 +#: wp-admin/includes/class-wp-comments-list-table.php:207 +#: wp-admin/includes/class-wp-posts-list-table.php:193 +#: wp-admin/includes/media.php:1239 wp-admin/includes/meta-boxes.php:214 +msgid "Move to Trash" +msgstr "Déplacer dans la Corbeille" + +#: wp-admin/edit-link-form.php:14 +msgid "Links / Edit Link" +msgstr "Liens / Modifier le lien" + +#: wp-admin/edit-link-form.php:15 wp-admin/includes/meta-boxes.php:723 +msgid "Update Link" +msgstr "Mettre à jour le lien" + +#: wp-admin/edit-link-form.php:19 +msgid "Links / Add New Link" +msgstr "Liens / Ajouter un nouveau lien" + +#: wp-admin/edit-link-form.php:30 wp-admin/includes/nav-menu.php:174 +#: wp-admin/includes/nav-menu.php:1184 +msgid "Link Relationship (XFN)" +msgstr "Relation avec le propriétaire du site lié (XFN)" + +#: wp-admin/edit-link-form.php:49 +msgid "" +"You can add or edit links on this screen by entering information in each of " +"the boxes. Only the link’s web address and name (the text you want to " +"display on your site as the link) are required fields." +msgstr "" +"Vous pouvez ajouter ou modifier des liens sur cet écran, en saisissant dans " +"chacun des blocs. Seuls sont obligatoires les champs « Adresse " +"web » et « Nom » (le texte que vous voulez " +"voir affiché sur votre site pour cette adresse)." + +#: wp-admin/edit-link-form.php:50 +msgid "" +"The boxes for link name, web address, and description have fixed positions, " +"while the others may be repositioned using drag and drop. You can also hide " +"boxes you don’t use in the Screen Options tab, or minimize boxes by " +"clicking on the title bar of the box." +msgstr "" +"Les blocs pour le nom, l’adresse web et la description sont fixes, " +"tandis que les autres peuvent être repositionnés par glisser/déposer. Vous " +"pouvez également cacher les blocs que vous n’utilisez pas via l’" +"onglet « Options de l’écran », et fermer les " +"blocs en cliquant sur leur barre de titre." + +#: wp-admin/edit-link-form.php:51 +msgid "" +"XFN stands for XHTML " +"Friends Network, which is optional. WordPress allows the generation of " +"XFN attributes to show how you are related to the authors/owners of the site " +"to which you are linking." +msgstr "" +"XFN signifie XHTML " +"Friends Network, c’est-à-dire Réseau XHTML d’Amis. Son usage " +"est facultatif. WordPress permet de générer les attributs XFN de vos liens, " +"afin d’indiquer la manière dont vous êtes lié à l’auteur ou le " +"propriétaire de la page liée." + +#: wp-admin/edit-link-form.php:56 +msgid "" +"Documentation on Creating Links" +msgstr "" +"Documentation sur la création de liens (en)" + +# contexte +#. translators: add new links +#: wp-admin/edit-link-form.php:65 wp-admin/link-manager.php:73 +#: wp-admin/menu.php:78 +msgctxt "link" +msgid "Add New" +msgstr "Ajouter" + +#: wp-admin/edit-link-form.php:68 +msgid "Link added." +msgstr "Lien ajouté." + +#: wp-admin/edit-link-form.php:86 +#: wp-admin/includes/class-wp-links-list-table.php:81 +msgctxt "link name" +msgid "Name" +msgstr "Nom" + +#: wp-admin/edit-link-form.php:89 +msgid "Example: Nifty blogging software" +msgstr "" +"Exemple : Logiciel de création de sites rapide, puissant et efficace" + +#: wp-admin/edit-link-form.php:94 +msgid "Web Address" +msgstr "Adresse web" + +#: wp-admin/edit-link-form.php:97 +msgid "" +"Example: http://wordpress.org/ — don’t forget the " +"http://" +msgstr "" +"Exemple : http://www.wordpress-fr.net/ — Et n’" +"oubliez pas le http:// !" + +#: wp-admin/edit-link-form.php:105 +msgid "" +"This will be shown when someone hovers over the link in the blogroll, or " +"optionally below the link." +msgstr "" +"Cette description sera affichée lors du survol du lien dans la liste de " +"liens ; elle pourra également apparaître sous le lien si votre thème le " +"prévoit." + +#: wp-admin/edit-tag-form.php:14 +msgid "You did not select an item for editing." +msgstr "Un contenu n’a pas été sélectionné pour l’édition. " + +#: wp-admin/edit-tag-form.php:40 wp-admin/edit-tags.php:392 +msgctxt "Taxonomy Name" +msgid "Name" +msgstr "Nom" + +#: wp-admin/edit-tag-form.php:42 wp-admin/edit-tags.php:394 +msgid "The name is how it appears on your site." +msgstr "Ce nom est utilisé un peu partout sur votre site." + +#: wp-admin/edit-tag-form.php:46 wp-admin/edit-tags.php:398 +msgctxt "Taxonomy Slug" +msgid "Slug" +msgstr "Identifiant" + +#: wp-admin/edit-tag-form.php:48 wp-admin/edit-tags.php:400 +msgid "" +"The “slug” is the URL-friendly version of the name. It is " +"usually all lowercase and contains only letters, numbers, and hyphens." +msgstr "" +"L’identifiant est la version normalisée du nom. Il ne contient " +"généralement que des lettres minuscules non accentuées, des chiffres et des " +"traits d’union." + +#: wp-admin/edit-tag-form.php:53 wp-admin/edit-tags.php:405 +msgctxt "Taxonomy Parent" +msgid "Parent" +msgstr "Parent" + +#: wp-admin/edit-tag-form.php:57 wp-admin/edit-tags.php:421 +msgid "" +"Categories, unlike tags, can have a hierarchy. You might have a Jazz " +"category, and under that have children categories for Bebop and Big Band. " +"Totally optional." +msgstr "" +"Les catégories, contrairement aux mots-clés, peuvent avoir une hiérarchie. " +"Vous pouvez avoir une catégorie nommée Jazz, et à l’intérieur, " +"plusieurs catégories comme Bebop et Big Band. Ceci est totalement facultatif." + +#: wp-admin/edit-tag-form.php:63 wp-admin/edit-tags.php:426 +msgctxt "Taxonomy Description" +msgid "Description" +msgstr "Description" + +#: wp-admin/edit-tag-form.php:65 wp-admin/edit-tags.php:428 +msgid "" +"The description is not prominent by default; however, some themes may show " +"it." +msgstr "" +"La description n’est pas très utilisée par défaut, cependant de plus " +"en plus de thèmes l’affichent." + +#: wp-admin/edit-tags.php:128 wp-admin/edit-tags.php:143 wp-admin/post.php:137 +msgid "" +"You attempted to edit an item that doesn’t exist. Perhaps it was " +"deleted?" +msgstr "" +"Vous tentez de modifier un contenu qui n’existe pas. Peut-être a-t-il " +"été supprimé ?" + +#: wp-admin/edit-tags.php:191 +msgid "" +"You can use categories to define sections of your site and group related " +"posts. The default category is “Uncategorized” until you change " +"it in your writing settings." +msgstr "" +"Vous pouvez utiliser les catégories pour donner des sections à votre site, " +"et grouper les articles connexes. La catégorie par défaut est « " +"Non classé » ; vous pouvez la modifier dans vos options d’écriture." + +#: wp-admin/edit-tags.php:193 +msgid "" +"You can create groups of links by using Link Categories. Link Category names " +"must be unique and Link Categories are separate from the categories you use " +"for posts." +msgstr "" +"Vous pouvez créer des groupes de liens en utilisant les catégories de liens. " +"Le nom d’une catégorie de liens doit être unique, et les catégories de " +"liens ne sont pas les mêmes que les catégories de vos articles." + +#: wp-admin/edit-tags.php:195 +msgid "" +"You can assign keywords to your posts using tags. Unlike " +"categories, tags have no hierarchy, meaning there’s no relationship " +"from one tag to another." +msgstr "" +"Vous pouvez assigner des mots-clés à vos articles via le " +"bloc dédié. Au contraire des catégories, les mots-clés n’ont pas de " +"hiérarchie, ce qui signifie qu’ils ne peuvent pas être liés entre eux." + +#: wp-admin/edit-tags.php:198 +msgid "" +"You can delete Link Categories in the Bulk Action pull-down, but that action " +"does not delete the links within the category. Instead, it moves them to the " +"default Link Category." +msgstr "" +"Vous pouvez supprimer des catégories de liens avec la liste déroulante " +"« Actions groupées », mais cette action ne supprime " +"pas les liens contenus dans la catégorie. Au lieu de cela, ils sont déplacés " +"dans la catégorie de liens par défaut." + +#: wp-admin/edit-tags.php:200 +msgid "" +"What’s the difference between categories and tags? Normally, tags are " +"ad-hoc keywords that identify important information in your post (names, " +"subjects, etc) that may or may not recur in other posts, while categories " +"are pre-determined sections. If you think of your site like a book, the " +"categories are like the Table of Contents and the tags are like the terms in " +"the index." +msgstr "" +"Quelle est la différence entre les catégories et les mots-clés ? " +"Normalement, les mots-clés identifient les informations importantes dans " +"votre article (noms, sujets, etc.) qui seraient susceptibles de revenir dans " +"d’autres articles, ou pas. De leur côté, les catégories ont des " +"sections prédéterminées. Si vous voyez votre site comme un livre, alors les " +"catégories sont la table des matières, et les mots-clés forment l’" +"index." + +#: wp-admin/edit-tags.php:210 +msgid "" +"When adding a new category on this screen, you’ll fill in the " +"following fields:" +msgstr "" +"Quand vous ajoutez une nouvelle catégorie via cet écran, vous devez remplir " +"les champs suivants :" + +#: wp-admin/edit-tags.php:212 +msgid "" +"When adding a new tag on this screen, you’ll fill in the following " +"fields:" +msgstr "" +"Quand vous ajoutez un nouveau mot-clé via cet écran, vous devez remplir les " +"champs suivants :" + +#: wp-admin/edit-tags.php:215 +msgid "Name - The name is how it appears on your site." +msgstr "" +"Nom - Ce nom est utilisé un peu partout sur votre " +"site ;" + +#: wp-admin/edit-tags.php:218 +msgid "" +"Slug - The “slug” is the URL-friendly version " +"of the name. It is usually all lowercase and contains only letters, numbers, " +"and hyphens." +msgstr "" +"Identifiant - L’identifiant est la version normalisée " +"du nom. Il ne contient généralement que des lettres minuscules non " +"accentuées, des chiffres et des traits d’union ;" + +#: wp-admin/edit-tags.php:221 +msgid "" +"Parent - Categories, unlike tags, can have a hierarchy. You " +"might have a Jazz category, and under that have child categories for Bebop " +"and Big Band. Totally optional. To create a subcategory, just choose another " +"category from the Parent dropdown." +msgstr "" +"Parent - Les catégories, contrairement aux mots-clés, " +"peuvent avoir une hiérarchie. Vous pouvez avoir une catégorie nommée «" +" Jazz », et à l’intérieur, plusieurs catégories comme " +"« Bebop » et « Big Band ». Le " +"fait d’avoir une hiérarchie est totalement facultatif. Pour créer une " +"sous-catégorie, choisissez juste une autre catégorie depuis la liste " +"déroulante « Parent » ." + +#: wp-admin/edit-tags.php:223 +msgid "" +"Description - The description is not prominent by default; " +"however, some themes may display it." +msgstr "" +"Description - La description n’est pas très utilisée " +"par défaut, cependant de plus en plus de thèmes l’affichent." + +#: wp-admin/edit-tags.php:225 +msgid "" +"You can change the display of this screen using the Screen Options tab to " +"set how many items are displayed per screen and to display/hide columns in " +"the table." +msgstr "" +"Vous pouvez modifier l’affichage de cet écran via l’onglet " +"« Options de l’écran », afin de définir le " +"nombre d’éléments à afficher par écran, et afficher/cacher les " +"colonnes du tableau." + +#: wp-admin/edit-tags.php:229 +msgid "Adding Categories" +msgstr "Ajout de catégories" + +#: wp-admin/edit-tags.php:229 +msgid "Adding Tags" +msgstr "Ajout de mots-clés" + +#: wp-admin/edit-tags.php:237 +msgid "" +"Documentation on Categories" +msgstr "" +"Documentation sur les catégories (en)" + +#: wp-admin/edit-tags.php:239 +msgid "" +"Documentation on Link Categories" +msgstr "" +"Documentation sur les catégories de liens (en)" + +#: wp-admin/edit-tags.php:241 +msgid "" +"Documentation on Tags" +msgstr "" +"Documentation sur les mots-clés (en)" + +#: wp-admin/edit-tags.php:258 +msgid "Item added." +msgstr "Contenu ajouté." + +#: wp-admin/edit-tags.php:259 +msgid "Item deleted." +msgstr "Contenu supprimé." + +#: wp-admin/edit-tags.php:260 +msgid "Item updated." +msgstr "Contenu mis à jour." + +#: wp-admin/edit-tags.php:261 +msgid "Item not added." +msgstr "Contenu non ajouté." + +#: wp-admin/edit-tags.php:262 wp-admin/includes/ajax-actions.php:1446 +#: wp-admin/includes/ajax-actions.php:1451 +msgid "Item not updated." +msgstr "L’entrée n’a pas été mise à jour" + +#: wp-admin/edit-tags.php:263 +msgid "Items deleted." +msgstr "Contenus supprimés." + +#: wp-admin/edit-tags.php:267 +msgid "Category added." +msgstr "Catégorie ajoutée." + +#: wp-admin/edit-tags.php:268 +msgid "Category deleted." +msgstr "Catégorie effacée." + +#: wp-admin/edit-tags.php:269 +msgid "Category updated." +msgstr "Catégorie mise à jour." + +#: wp-admin/edit-tags.php:270 +msgid "Category not added." +msgstr "Catégorie non ajoutée." + +#: wp-admin/edit-tags.php:271 +msgid "Category not updated." +msgstr "Catégorie non mise à jour." + +#: wp-admin/edit-tags.php:272 +msgid "Categories deleted." +msgstr "Catégories supprimées." + +#: wp-admin/edit-tags.php:276 +msgid "Tag added." +msgstr "Mot-clé ajouté." + +#: wp-admin/edit-tags.php:277 +msgid "Tag deleted." +msgstr "Mot-clé supprimé." + +#: wp-admin/edit-tags.php:278 +msgid "Tag updated." +msgstr "Mot-clé mis à jour." + +#: wp-admin/edit-tags.php:279 +msgid "Tag not added." +msgstr "Mot-clé non ajouté." + +#: wp-admin/edit-tags.php:280 +msgid "Tag not updated." +msgstr "Mot-clé non mis à jour." + +#: wp-admin/edit-tags.php:281 +msgid "Tags deleted." +msgstr "Mot-clé supprimé." + +#: wp-admin/edit-tags.php:333 +msgid "" +"Note:
    Deleting a category does not delete the posts in " +"that category. Instead, posts that were only assigned to the deleted " +"category are set to the category %s." +msgstr "" +"À savoir : supprimer une catégorie ne supprime pas les " +"articles qu’elle contient. Les articles affectés uniquement à la " +"catégorie supprimée seront affectés à celle par défaut  : " +"%s." + +#: wp-admin/edit-tags.php:335 +msgid "" +"Categories can be selectively converted to tags using the category to tag converter." +msgstr "" +"Les catégories peuvent être converties de manière sélective en mots-clés via " +"le convertisseur catégories vers mots-clés." + +#: wp-admin/edit-tags.php:340 +msgid "" +"Tags can be selectively converted to categories using the tag " +"to category converter." +msgstr "" +"Les mots-clés peuvent être convertis de manière sélective en catégories via " +"le convertisseur mots-clés vers catégories" + +#: wp-admin/edit.php:82 wp-admin/post.php:239 +msgid "You are not allowed to move this item to the Trash." +msgstr "" +"Vous n’avez pas l’autorisation de déplacer ce contenu dans la " +"Corbeille." + +#: wp-admin/edit.php:90 wp-admin/post.php:247 +msgid "Error in moving to Trash." +msgstr "Erreur lors du déplacement dans la Corbeille." + +#: wp-admin/edit.php:101 +msgid "You are not allowed to restore this item from the Trash." +msgstr "" +"Vous n’avez pas l’autorisation de récupérer ce contenu depuis la " +"Corbeille." + +#: wp-admin/edit.php:104 wp-admin/post.php:266 +msgid "Error in restoring from Trash." +msgstr "Erreur pendant la récupération depuis la Corbeille." + +#: wp-admin/edit.php:116 wp-admin/post.php:282 +msgid "You are not allowed to delete this item." +msgstr "Vous n’avez pas l’autorisation de supprimer ce contenu." + +#: wp-admin/edit.php:120 wp-admin/edit.php:123 wp-admin/post.php:288 +#: wp-admin/post.php:291 wp-admin/upload.php:126 +msgid "Error in deleting." +msgstr "Erreur pendant la suppression." + +#: wp-admin/edit.php:163 +msgid "" +"This screen provides access to all of your posts. You can customize the " +"display of this screen to suit your workflow." +msgstr "" +"Cet écran vous donne accès à tous vos articles. Vous pouvez personnaliser " +"son affichage afin qu’il corresponde au mieux à vos besoins." + +#: wp-admin/edit.php:167 +msgid "Screen Content" +msgstr "Contenu de l’écran" + +#: wp-admin/edit.php:169 +msgid "" +"You can customize the display of this screen’s contents in a number of " +"ways:" +msgstr "" +"Vous pouvez personnaliser l’affichage de cet écran de plusieurs " +"manières :" + +#: wp-admin/edit.php:171 +msgid "" +"You can hide/display columns based on your needs and decide how many posts " +"to list per screen using the Screen Options tab." +msgstr "" +"Vous pouvez cacher/afficher les colonnes en fonction de vos besoins, et " +"décider du nombre d’articles à afficher par écran à l’aide de " +"l’onglet « Options de l’écran » ." + +#: wp-admin/edit.php:172 +msgid "" +"You can filter the list of posts by post status using the text links in the " +"upper left to show All, Published, Draft, or Trashed posts. The default view " +"is to show all posts." +msgstr "" +"Vous pouvez filtrer la liste des articles par état, à l’aide des liens " +"textuels en haut à gauche, afin d’afficher tous les articles, ou " +"seulement les articles publiés, les brouillons, etc. Par défaut, tous les " +"articles sont affichés ;" + +#: wp-admin/edit.php:173 +msgid "" +"You can view posts in a simple title list or with an excerpt. Choose the " +"view you prefer by clicking on the icons at the top of the list on the right." +msgstr "" +"Vous pouvez afficher une simple liste de titres, ou une liste avec des " +"extraits. Choisissez l’affichage que vous préférez en cliquant sur les " +"icônes en haut à droite de la liste ;" + +#: wp-admin/edit.php:174 +msgid "" +"You can refine the list to show only posts in a specific category or from a " +"specific month by using the dropdown menus above the posts list. Click the " +"Filter button after making your selection. You also can refine the list by " +"clicking on the post author, category or tag in the posts list." +msgstr "" +"Vous pouvez affiner la liste pour qu’elle n’affiche que les " +"articles d’une catégorie spécifique ou d’un mois donné, à " +"l’aide du menu déroulant situé au-dessus de la liste. Cliquez sur le " +"bouton « Filtrer » après avoir fait votre choix. Vous " +"pouvez également affiner la liste en cliquant sur l’auteur d’un " +"article, sa catégorie ou un mot-clé." + +#: wp-admin/edit.php:179 wp-admin/upload.php:159 +msgid "Available Actions" +msgstr "Actions disponibles" + +#: wp-admin/edit.php:181 +msgid "" +"Hovering over a row in the posts list will display action links that allow " +"you to manage your post. You can perform the following actions:" +msgstr "" +"Passer la souris au-dessus d’une ligne de la liste d’articles, " +"fera s’afficher des liens vous permettant de gérer l’article. " +"Vous pouvez lancer les actions suivantes :" + +#: wp-admin/edit.php:183 +msgid "" +"Edit takes you to the editing screen for that post. You can " +"also reach that screen by clicking on the post title." +msgstr "" +"Modifier vous envoie sur l’écran de modification de " +"cet article. Vous pouvez également vous rendre sur cet écran en cliquant sur " +"le titre de l’article." + +#: wp-admin/edit.php:184 +msgid "" +"Quick Edit provides inline access to the metadata of your " +"post, allowing you to update post details without leaving this screen." +msgstr "" +"Modification Rapide vous donne un accès rapide aux " +"métadonnées de votre article, vous permettant de mettre à jour certains " +"détails sans devoir quitter la liste." + +#: wp-admin/edit.php:185 +msgid "" +"Trash removes your post from this list and places it in the " +"trash, from which you can permanently delete it." +msgstr "" +"Mettre à la Corbeille retire l’article de la liste et " +"le déplacer dans la Corbeille, d’où vous pourrez le supprimer " +"définitivement." + +#: wp-admin/edit.php:186 +msgid "" +"Preview will show you what your draft post will look like " +"if you publish it. View will take you to your live site to view the post. " +"Which link is available depends on your post’s status." +msgstr "" +"Aperçu vous donnera une idée de ce à quoi votre brouillon " +"ressemble si vous le publiez tel quel. Afficher vous " +"enverra sur votre site, à l’adresse de l’article. L’action " +"disponible dépend de l’état de votre article." + +#: wp-admin/edit.php:191 wp-admin/includes/class-wp-list-table.php:294 +msgid "Bulk Actions" +msgstr "Actions groupées" + +#: wp-admin/edit.php:193 +msgid "" +"You can also edit or move multiple posts to the trash at once. Select the " +"posts you want to act on using the checkboxes, then select the action you " +"want to take from the Bulk Actions menu and click Apply." +msgstr "" +"Vous pouvez également modifier plusieurs articles à la fois, ou les déplacer " +"dans la Corbeille d’un coup. Sélectionnez les articles sur lesquels " +"vous voulez lancer une action, puis sélectionnez l’action que vous " +"voulez lancer dans le menu « Actions groupées » et " +"cliquez sur « Appliquer »." + +#: wp-admin/edit.php:194 +msgid "" +"When using Bulk Edit, you can change the metadata (categories, author, etc.) " +"for all selected posts at once. To remove a post from the grouping, just " +"click the x next to its name in the Bulk Edit area that appears." +msgstr "" +"Vous pouvez également modifier plusieurs articles en même temps. Cochez les " +"cases des articles que vous voulez modifier, sélectionnez l’option " +"« Modifier » du menu « Actions " +"groupées », et cliquez sur « Appliquer ». " +"Vous pourrez alors d’un coup modifier les métadonnées (catégories, " +"auteur, etc.) pour tous les articles sélectionnés. Pour retirer un article " +"de la sélection, cliquez simplement sur la croix à gauche de son titre dans " +"la zone « Modifications groupées » qui apparaît." + +#: wp-admin/edit.php:199 +msgid "" +"Documentation on Managing Posts" +msgstr "" +"Documentation sur la gestion des articles (en)" + +#: wp-admin/edit.php:208 +msgid "" +"Pages are similar to posts in that they have a title, body text, and " +"associated metadata, but they are different in that they are not part of the " +"chronological blog stream, kind of like permanent posts. Pages are not " +"categorized or tagged, but can have a hierarchy. You can nest pages under " +"other pages by making one the “Parent” of the other, creating a " +"group of pages." +msgstr "" +"Les pages sont comme des articles, en cela qu’elles ont un titre, un " +"contenu et des métadonnées associées ; mais elles diffèrent en cela " +"qu’elles ne font pas partie du flux chronologique du blog - un peu " +"comme des articles permanents. Les pages ne sont pas catégorisées et ne " +"reçoivent pas de mots-clés, mais peuvent disposer d’une hiérarchie. En " +"effet, vous pouvez imbriquer des pages sous d’autres pages, faisant de " +"ces dernières les « parentes » des premières, créant " +"ainsi un groupement de pages." + +#: wp-admin/edit.php:212 +msgid "Managing Pages" +msgstr "Gestion de pages" + +#: wp-admin/edit.php:214 +msgid "" +"Managing pages is very similar to managing posts, and the screens can be " +"customized in the same way." +msgstr "" +"La gestion des pages est très proche de celle des articles, et les écrans " +"peuvent être personnalisés de la même manière." + +#: wp-admin/edit.php:215 +msgid "" +"You can also perform the same types of actions, including narrowing the list " +"by using the filters, acting on a page using the action links that appear " +"when you hover over a row, or using the Bulk Actions menu to edit the " +"metadata for multiple pages at once." +msgstr "" +"Vous pouvez également réaliser les mêmes sortes d’actions, comme " +"réduire la liste par le biais des filtres, en passant par les liens qui " +"apparaissent quand la souris passe au-dessus d’une ligne, ou en " +"utilisant le menu « Actions groupées » pour modifier " +"les métadonnées de plusieurs pages d’un seul coup." + +#: wp-admin/edit.php:220 +msgid "" +"Documentation on Managing Pages" +msgstr "" +"Documentation sur la gestion des pages (en)" + +#: wp-admin/edit.php:237 +msgid "%s post updated." +msgid_plural "%s posts updated." +msgstr[0] "%s article mis à jour." +msgstr[1] "%s articles mis à jour." + +#: wp-admin/edit.php:238 +msgid "%s post not updated, somebody is editing it." +msgid_plural "%s posts not updated, somebody is editing them." +msgstr[0] "" +"%s entrée n’a pas été mise à jour : quelqu’un est déjà en " +"train de la modifier." +msgstr[1] "" +"%s entrées n’ont pas été mises à jour : quelqu’un est déjà " +"en train de les modifier." + +#: wp-admin/edit.php:239 +msgid "%s post permanently deleted." +msgid_plural "%s posts permanently deleted." +msgstr[0] "%s commentaire supprimé définitivement." +msgstr[1] "%s commentaires supprimés définitivement." + +#: wp-admin/edit.php:240 +msgid "%s post moved to the Trash." +msgid_plural "%s posts moved to the Trash." +msgstr[0] "%s commentaire déplacé dans la Corbeille." +msgstr[1] "%s commentaires déplacés dans la Corbeille." + +#: wp-admin/edit.php:241 +msgid "%s post restored from the Trash." +msgid_plural "%s posts restored from the Trash." +msgstr[0] "%s commentaire récupéré depuis la Corbeille." +msgstr[1] "%s commentaires récupérés depuis la Corbeille." + +#: wp-admin/edit.php:244 +msgid "%s page updated." +msgid_plural "%s pages updated." +msgstr[0] "%s page mise à jour." +msgstr[1] "%s pages mises à jour." + +#: wp-admin/edit.php:245 +msgid "%s page not updated, somebody is editing it." +msgid_plural "%s pages not updated, somebody is editing them." +msgstr[0] "" +"%s entrée n’a pas été mise à jour : quelqu’un est déjà en " +"train de la modifier." +msgstr[1] "" +"%s entrées n’ont pas été mises à jour : quelqu’un est déjà " +"en train de les modifier." + +#: wp-admin/edit.php:246 +msgid "%s page permanently deleted." +msgid_plural "%s pages permanently deleted." +msgstr[0] "%s page définitivement supprimée." +msgstr[1] "%s pages définitivement supprimées." + +#: wp-admin/edit.php:247 +msgid "%s page moved to the Trash." +msgid_plural "%s pages moved to the Trash." +msgstr[0] "%s page déplacée dans la Corbeille." +msgstr[1] "%s pages déplacées dans la Corbeille." + +#: wp-admin/edit.php:248 +msgid "%s page restored from the Trash." +msgid_plural "%s pages restored from the Trash." +msgstr[0] "%s page récupérée depuis la Corbeille." +msgstr[1] "%s pages récupérées depuis la Corbeille." + +#: wp-admin/export.php:13 +msgid "" +"You do not have sufficient permissions to export the content of this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour exporter le contenu de ce " +"site." + +#: wp-admin/export.php:17 wp-admin/menu.php:202 +msgid "Export" +msgstr "Exporter" + +#: wp-admin/export.php:49 +msgid "" +"You can export a file of your site’s content in order to import it " +"into another installation or platform. The export file will be an XML file " +"format called WXR. Posts, pages, comments, custom fields, categories, and " +"tags can be included. You can choose for the WXR file to include only " +"certain posts or pages by setting the dropdown filters to limit the export " +"by category, author, date range by month, or publishing status." +msgstr "" +"Vous pouvez exporter le contenu de votre site dans un fichier, afin de " +"l’importer dans une autre installation autonome ou une plate-forme. Le " +"fichier d’export utilise un format de type XML, baptisé WXR. Il peut " +"contenir vos articles, pages, commentaires, champs personnalisés, catégories " +"et mots-clés. Vous pouvez utiliser des filtres pour que le fichier WXR ne " +"contienne les articles que d’une certaine plage de dates (par mois), " +"un auteur donné, une catégorie précise, ou des états de publication." + +#: wp-admin/export.php:50 +msgid "" +"Once generated, your WXR file can be imported by another WordPress site or " +"by another blogging platform able to access this format." +msgstr "" +"Une fois généré, le fichier WXR peut être importé dans une autre " +"installation WordPress, ou une autre plate-forme de blog capable de lire ce " +"format." + +#: wp-admin/export.php:55 +msgid "" +"Documentation on Export" +msgstr "" +"Documentation sur l’exportation (en)" + +#: wp-admin/export.php:150 +msgid "" +"When you click the button below WordPress will create an XML file for you to " +"save to your computer." +msgstr "" +"Cliquez sur ce bouton pour que WordPress crée un fichier XML que vous " +"pourrez enregistrer sur votre ordinateur." + +#: wp-admin/export.php:151 +msgid "" +"This format, which we call WordPress eXtended RSS or WXR, will contain your " +"posts, pages, comments, custom fields, categories, and tags." +msgstr "" +"Ce format, que nous appelons WordPress eXtended RSS (ou WXR), contient tous " +"vos articles, pages, commentaires, champs personnalisés, catégories et mots-" +"clés." + +#: wp-admin/export.php:152 +msgid "" +"Once you’ve saved the download file, you can use the Import function " +"in another WordPress installation to import the content from this site." +msgstr "" +"Une fois que le fichier téléchargé a été enregistré, vous pouvez utiliser la " +"fonction Importer d’un autre site WordPress pour importer ce fichier " +"dans cet autre site." + +#: wp-admin/export.php:154 +msgid "Choose what to export" +msgstr "Choisissez ce que vous souhaitez exporter" + +#: wp-admin/export.php:157 +msgid "All content" +msgstr "Tout le contenu" + +#: wp-admin/export.php:158 +msgid "" +"This will contain all of your posts, pages, comments, custom fields, terms, " +"navigation menus and custom posts." +msgstr "" +"Il contiendra tous vos articles, pages, commentaires, champs personnalisés, " +"termes, menus de navigation et types de contenus personnalisés." + +#: wp-admin/export.php:160 wp-admin/includes/class-wp-terms-list-table.php:108 +#: wp-admin/includes/class-wp-users-list-table.php:169 wp-admin/menu.php:49 +msgid "Posts" +msgstr "Articles" + +#: wp-admin/export.php:163 +msgid "Categories:" +msgstr "Catégories :" + +#: wp-admin/export.php:167 wp-admin/export.php:199 +msgid "Authors:" +msgstr "Auteur :" + +#: wp-admin/export.php:174 wp-admin/export.php:206 +msgid "Date range:" +msgstr "Date de création :" + +#: wp-admin/export.php:176 wp-admin/export.php:208 +msgid "Start Date" +msgstr "Date de début" + +#: wp-admin/export.php:180 wp-admin/export.php:212 +msgid "End Date" +msgstr "Date de fin" + +#: wp-admin/export.php:185 wp-admin/export.php:217 +#: wp-admin/includes/meta-boxes.php:58 +msgid "Status:" +msgstr "État :" + +#: wp-admin/export.php:240 +msgid "Download Export File" +msgstr "Télécharger le fichier d’export" + +#: wp-admin/freedoms.php:36 +msgid "" +"WordPress is Free and open source software, built by a distributed community " +"of mostly volunteer developers from around the world. WordPress comes with " +"some awesome, worldview-changing rights courtesy of its license, the GPL." +msgstr "" +"WordPress est un logiciel libre et au code ouvert (open-source), conçu par " +"une communauté de développeurs majoritairement volontaires, partout dans le " +"monde. WordPress est livré avec des libertés formidables et qui changent la " +"vision du monde, grâce à sa licence, la GPL." + +#: wp-admin/freedoms.php:39 +msgid "You have the freedom to run the program, for any purpose." +msgstr "" +"Vous êtes libre de modifier ce programme, dans n’importe quel but." + +#: wp-admin/freedoms.php:40 +msgid "" +"You have access to the source code, the freedom to study how the program " +"works, and the freedom to change it to make it do what you wish." +msgstr "" +"Vous avez accès au code source, êtes libres d’étudier la manière dont " +"le programme fonctionne, et libres de le modifier pour en faire ce que vous " +"souhaitez." + +#: wp-admin/freedoms.php:41 +msgid "" +"You have the freedom to redistribute copies of the original program so you " +"can help your neighbor." +msgstr "" +"Vous êtes libres de redistribuer des copies du programme original, afin " +"d’aider votre prochain." + +#: wp-admin/freedoms.php:42 +msgid "" +"You have the freedom to distribute copies of your modified versions to " +"others. By doing this you can give the whole community a chance to benefit " +"from your changes." +msgstr "" +"Vous êtes libres de distribuer à autrui des copies de votre propre version " +"modifiée de ce programme. Ce faisant, vous offrez à la communauté la " +"possibilité de profiter de vos modifications." + +#: wp-admin/freedoms.php:45 +msgid "" +"WordPress grows when people like you tell their friends about it, and the " +"thousands of businesses and services that are built on and around WordPress " +"share that fact with their users. We’re flattered every time someone " +"spreads the good word, just make sure to check out our " +"trademark guidelines first." +msgstr "" +"WordPress croît à chaque fois que vous en parlez à vos amis, et cela est " +"également vrai pour les milliers de sociétés et services dans le monde " +"construits à l’aide de ou autour de WordPress. Nous sommes flattés " +"chaque fois que quelqu’un vante les mérites de cet outil ; " +"veillez cependant à respecter les conseils d’" +"utilisation de notre marque déposée." + +#: wp-admin/freedoms.php:52 +msgid "" +"Every plugin and theme in WordPress.org’s directory is 100%% GPL or a " +"similarly free and compatible license, so you can feel safe finding plugins and themes there. If you get a " +"plugin or theme from another source, make sure to ask them " +"if it’s GPL first. If they don’t respect the WordPress " +"license, we don’t recommend them." +msgstr "" +"Tous les thèmes et extensions disponibles sur le répertoire de WordPress.org " +"respectent à 100%% la licence GPL, ou une licence libre et compatible. " +"Ainsi, vous pouvez en toute sûreté y chercher des extensions et des thèmes. Si vous téléchargez " +"une extension ou un thème en provenance d’une autre source, vérifiez " +"bien qu’il respecte la licence GPL. Si ce n’" +"est pas le cas, l’équipe de WordPress ne vous le recommande alors pas." + +#: wp-admin/freedoms.php:54 +msgid "" +"Don’t you wish all software came with these freedoms? So do we! For " +"more information, check out the Free " +"Software Foundation." +msgstr "" +"Ne préféreriez-vous pas que tous vos logiciels vous donnent autant de " +"liberté ? Nous aussi ! Pour obtenir plus d’informations, " +"rendez-vous sur le site de la Free Software " +"Foundation, ou en français, ceux de l’April et de l’Aful." + +#: wp-admin/import.php:15 +msgid "You do not have sufficient permissions to import content in this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour importer du contenu dans ce " +"site." + +#: wp-admin/import.php:22 +msgid "" +"This screen lists links to plugins to import data from blogging/content " +"management platforms. Choose the platform you want to import from, and click " +"Install Now when you are prompted in the popup window. If your platform is " +"not listed, click the link to search the plugin directory for other importer " +"plugins to see if there is one for your platform." +msgstr "" +"Cet écran liste les liens vers les extensions servant à importer des données " +"en provenance d’autres plates-formes de blogs ou gestionnaires de " +"contenus. Choisissez la plate-forme d’origine, et cliquez sur «" +" Installer maintenant » dans la fenêtre qui s’affiche. " +"Si vous ne trouvez pas votre plate-forme, cliquez sur le lien « " +"Recherche » dans le Dépôt d’Extensions et lancez une " +"recherche - peut-être qu’une autre extension répondra à vos attentes." + +#: wp-admin/import.php:23 +msgid "" +"In previous versions of WordPress, all importers were built-in. They have " +"been turned into plugins since most people only use them once or " +"infrequently." +msgstr "" +"Dans les versions précédentes de WordPress, tous les importateurs étaient " +"directement inclus . Nous les avons convertis en extensions, car la " +"plupart des gens ne s’en servent que très rarement, voire une seule " +"fois." + +#: wp-admin/import.php:28 +msgid "" +"Documentation on Import" +msgstr "" +"Documentation sur l’importation (en)" + +#: wp-admin/import.php:58 wp-admin/users.php:225 +msgid "ERROR:" +msgstr "ERREUR :" + +#: wp-admin/import.php:58 +msgid "The %s importer is invalid or is not installed." +msgstr "" +"L’importateur %s est invalide ou n’est pas " +"installé." + +#: wp-admin/import.php:60 +msgid "" +"If you have posts or comments in another system, WordPress can import those " +"into this site. To get started, choose a system to import from below:" +msgstr "" +"Si vous avez des articles ou des commentaires dans un autre système de site, " +"WordPress peut les importer dans votre site actuel. Pour commencer, " +"choisissez un système d’origine ci-dessous :" + +#: wp-admin/import.php:76 +msgid "No importers are available." +msgstr "Aucun outil d’importation n’est disponible." + +#: wp-admin/import.php:95 +msgid "Activate importer" +msgstr "Activer l’importateur" + +#: wp-admin/import.php:102 +msgid "Install importer" +msgstr "Installer l’importateur" + +#: wp-admin/import.php:105 +msgid "" +"This importer is not installed. Please install importers from the main site." +msgstr "" +"Cet importateur n’est pas installé. Veuillez installer les " +"importateurs depuis le site principal." + +#: wp-admin/import.php:126 +msgid "" +"If the importer you need is not listed, search the plugin " +"directory to see if an importer is available." +msgstr "" +"Si l’importateur dont vous avec besoin n’est pas présent, lancez une recherche dans le dépôt d’extensions pour " +"voir s’il s’y trouve." + +#. translators: 1: user_login, 2: user_email +#: wp-admin/includes/ajax-actions.php:225 +msgid "%1$s (%2$s)" +msgstr "%1$s (%2$s)" + +#: wp-admin/includes/ajax-actions.php:311 +#: wp-admin/includes/class-wp-list-table.php:500 +#: wp-admin/includes/class-wp-list-table.php:904 +msgid "1 item" +msgid_plural "%s items" +msgstr[0] "1 élément" +msgstr[1] "%s éléments" + +#: wp-admin/includes/ajax-actions.php:569 +msgid "Comment %d does not exist" +msgstr "Le commentaire %d n’existe pas." + +#: wp-admin/includes/ajax-actions.php:646 +#: wp-admin/includes/ajax-actions.php:1594 +msgid "An error has occurred. Please reload the page and try again." +msgstr "" +"Une erreur est survenue. Veuillez recharger la page et faire une nouvelle " +"tentative." + +#: wp-admin/includes/ajax-actions.php:781 +msgid "ERROR: you are replying to a comment on a draft post." +msgstr "" +"ERREUR : vous être en train de laisser un commentaire sur un brouillon." + +#: wp-admin/includes/ajax-actions.php:800 +msgid "Sorry, you must be logged in to reply to a comment." +msgstr "Désolé, vous devez être connecté(e) pour répondre à un commentaire." + +#: wp-admin/includes/ajax-actions.php:804 +#: wp-admin/includes/ajax-actions.php:867 +msgid "ERROR: please type a comment." +msgstr "ERREUR : veuillez saisir un commentaire." + +#: wp-admin/includes/ajax-actions.php:997 +msgid "Draft created on %1$s at %2$s" +msgstr "Brouillon créé le %1$s à %2$s" + +#: wp-admin/includes/ajax-actions.php:1009 +#: wp-admin/includes/ajax-actions.php:1014 +#: wp-admin/includes/ajax-actions.php:1034 +msgid "Please provide a custom field value." +msgstr "Veuillez saisir une valeur pour le champ personnalisé." + +#: wp-admin/includes/ajax-actions.php:1032 +msgid "Please provide a custom field name." +msgstr "Veuillez saisir un nom pour le champ personnalisé." + +#: wp-admin/includes/ajax-actions.php:1089 +msgid "User %s added" +msgstr "Utilisateur %s ajouté" + +#: wp-admin/includes/ajax-actions.php:1114 +#: wp-admin/includes/ajax-actions.php:1356 wp-admin/includes/post.php:178 +#: wp-admin/includes/post.php:1419 wp-admin/press-this.php:35 +#: wp-admin/upload.php:62 +msgid "You are not allowed to edit this post." +msgstr "Vous n’avez pas l’autorisation de modifier cet article." + +#: wp-admin/includes/ajax-actions.php:1117 +#: wp-admin/includes/ajax-actions.php:1353 wp-admin/includes/post.php:176 +#: wp-admin/includes/post.php:1416 +msgid "You are not allowed to edit this page." +msgstr "Vous n’avez pas l’autorisation de modifier cette page." + +#. translators: draft saved date format, see http:php.net/date +#: wp-admin/includes/ajax-actions.php:1137 +msgid "g:i:s a" +msgstr "G \\h i \\m\\i\\n s \\s" + +#. translators: %s: date and time +#: wp-admin/includes/ajax-actions.php:1139 +msgid "Draft saved at %s." +msgstr "Brouillon enregistré à %s." + +#: wp-admin/includes/ajax-actions.php:1361 +msgid "Someone" +msgstr "Quelqu’un" + +#: wp-admin/includes/ajax-actions.php:1362 +msgid "Saving is disabled: %s is currently editing this page." +msgstr "" +"Enregistrement automatique désactivé : %s modifie actuellement cette " +"page." + +#: wp-admin/includes/ajax-actions.php:1362 +msgid "Saving is disabled: %s is currently editing this post." +msgstr "" +"Enregistrement automatique désactivé : %s modifie actuellement cet " +"article." + +#: wp-admin/includes/ajax-actions.php:1487 +#: wp-admin/includes/class-wp-posts-list-table.php:286 +#: wp-admin/includes/class-wp-posts-list-table.php:801 +msgid "Date" +msgstr "Date" + +#: wp-admin/includes/ajax-actions.php:1497 +#: wp-admin/includes/class-wp-posts-list-table.php:644 +#: wp-admin/includes/class-wp-posts-list-table.php:1005 +#: wp-admin/includes/meta-boxes.php:69 wp-admin/includes/meta-boxes.php:92 +msgid "Scheduled" +msgstr "Planifié" + +#: wp-admin/includes/ajax-actions.php:1798 +msgid "Save failed" +msgstr "L’enregistrement a échoué." + +#: wp-admin/includes/bookmark.php:205 +msgid "Could not update link in the database" +msgstr "Impossible de mettre à jour le lien dans la base de données" + +#: wp-admin/includes/bookmark.php:212 +msgid "Could not insert link into the database" +msgstr "Impossible d’insérer le lien dans la base de données" + +#: wp-admin/includes/bookmark.php:311 +msgid "" +"If you are looking to use the link manager, please install the Link Manager plugin." +msgstr "" +"Si vous souhaitez utiliser le gestionnaire de liens, veuillez installer " +"l’extension Link Manager." + +#: wp-admin/includes/bookmark.php:314 wp-admin/link-manager.php:12 +#: wp-admin/link-manager.php:67 +msgid "You do not have sufficient permissions to edit the links for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour modifier les liens de ce " +"site." + +#: wp-admin/includes/class-wp-comments-list-table.php:138 +msgid "No comments awaiting moderation." +msgstr "Aucun commentaire en attente de modération." + +#: wp-admin/includes/class-wp-comments-list-table.php:140 +msgid "No comments found." +msgstr "Aucun commentaire trouvé." + +#: wp-admin/includes/class-wp-comments-list-table.php:151 +msgctxt "comments" +msgid "All" +msgid_plural "All" +msgstr[0] "Tout" +msgstr[1] "Tout" + +#: wp-admin/includes/class-wp-comments-list-table.php:152 +msgid "" +"Pending (%s)" +msgid_plural "" +"Pending (%s)" +msgstr[0] "" +"En attente (%s)" +msgstr[1] "" +"En attente (%s)" + +#: wp-admin/includes/class-wp-comments-list-table.php:153 +msgid "Approved" +msgid_plural "Approved" +msgstr[0] "Approuvé" +msgstr[1] "Approuvés" + +#: wp-admin/includes/class-wp-comments-list-table.php:154 +msgid "" +"Spam (%s)" +msgid_plural "" +"Spam (%s)" +msgstr[0] "" +"Indésirable (%s)" +msgstr[1] "" +"Indésirables (%s)" + +#: wp-admin/includes/class-wp-comments-list-table.php:155 +msgid "" +"Trash (%s)" +msgid_plural "" +"Trash (%s)" +msgstr[0] "" +"Corbeille (%s)" +msgstr[1] "" +"Corbeille (%s)" + +#: wp-admin/includes/class-wp-comments-list-table.php:193 +#: wp-admin/includes/class-wp-comments-list-table.php:398 +#: wp-admin/includes/class-wp-comments-list-table.php:403 +#: wp-admin/includes/dashboard.php:686 +msgid "Unapprove" +msgstr "Désapprouver" + +#: wp-admin/includes/class-wp-comments-list-table.php:195 +#: wp-admin/includes/class-wp-comments-list-table.php:400 +#: wp-admin/includes/class-wp-comments-list-table.php:402 +#: wp-admin/includes/dashboard.php:685 +msgid "Approve" +msgstr "Approuver" + +#: wp-admin/includes/class-wp-comments-list-table.php:197 +msgctxt "comment" +msgid "Mark as Spam" +msgstr "Marquer comme indésirable" + +#: wp-admin/includes/class-wp-comments-list-table.php:200 +#: wp-admin/includes/class-wp-comments-list-table.php:411 +#: wp-admin/includes/class-wp-media-list-table.php:419 +#: wp-admin/includes/class-wp-posts-list-table.php:186 +#: wp-admin/includes/class-wp-posts-list-table.php:593 +msgid "Restore" +msgstr "Rétablir" + +#: wp-admin/includes/class-wp-comments-list-table.php:202 +#: wp-admin/includes/class-wp-comments-list-table.php:409 +msgctxt "comment" +msgid "Not Spam" +msgstr "N’est pas un indésirable" + +#: wp-admin/includes/class-wp-comments-list-table.php:220 +msgid "Show all comment types" +msgstr "Afficher tous les types de commentaire" + +#: wp-admin/includes/class-wp-comments-list-table.php:224 +#: wp-admin/includes/class-wp-posts-list-table.php:967 +msgid "Pings" +msgstr "Pings" + +#: wp-admin/includes/class-wp-comments-list-table.php:233 +#: wp-admin/includes/class-wp-links-list-table.php:72 +#: wp-admin/includes/class-wp-media-list-table.php:94 +#: wp-admin/includes/class-wp-posts-list-table.php:219 +msgid "Filter" +msgstr "Filtrer" + +#: wp-admin/includes/class-wp-comments-list-table.php:238 +msgid "Empty Spam" +msgstr "Supprimer tous les indésirables" + +#: wp-admin/includes/class-wp-comments-list-table.php:238 +#: wp-admin/includes/class-wp-media-list-table.php:100 +#: wp-admin/includes/class-wp-posts-list-table.php:223 +msgid "Empty Trash" +msgstr "Vider la Corbeille" + +#: wp-admin/includes/class-wp-comments-list-table.php:261 +#: wp-admin/includes/class-wp-comments-list-table.php:533 +msgctxt "column name" +msgid "Comment" +msgstr "Commentaire" + +#: wp-admin/includes/class-wp-comments-list-table.php:264 +msgctxt "column name" +msgid "In Response To" +msgstr "En réponse à" + +#: wp-admin/includes/class-wp-comments-list-table.php:327 +msgid "Select comment" +msgstr "Sélectionnez un commentaire" + +#. translators: 2: comment date, 3: comment time +#: wp-admin/includes/class-wp-comments-list-table.php:359 +msgid "Submitted on %2$s at %3$s" +msgstr "Envoyé le %2$s à %3$s" + +#: wp-admin/includes/class-wp-comments-list-table.php:369 +msgid "In reply to %2$s." +msgstr "En réponse à %2$s." + +#: wp-admin/includes/class-wp-comments-list-table.php:398 +#: wp-admin/includes/class-wp-comments-list-table.php:403 +#: wp-admin/includes/dashboard.php:686 +msgid "Unapprove this comment" +msgstr "Désapprouver ce commentaire" + +#: wp-admin/includes/class-wp-comments-list-table.php:400 +#: wp-admin/includes/class-wp-comments-list-table.php:402 +#: wp-admin/includes/dashboard.php:685 +msgid "Approve this comment" +msgstr "Approuver ce commentaire" + +#: wp-admin/includes/class-wp-comments-list-table.php:407 +#: wp-admin/includes/dashboard.php:689 +msgid "Mark this comment as spam" +msgstr "Marquer ce commentaire comme indésirable" + +#. translators: mark as spam link +#: wp-admin/includes/class-wp-comments-list-table.php:407 +#: wp-admin/includes/dashboard.php:689 +msgctxt "verb" +msgid "Spam" +msgstr "Indésirable" + +#: wp-admin/includes/class-wp-comments-list-table.php:417 +#: wp-admin/includes/dashboard.php:693 +msgid "Move this comment to the trash" +msgstr "Déplacer ce commentaire dans la Corbeille" + +#: wp-admin/includes/class-wp-comments-list-table.php:417 +#: wp-admin/includes/dashboard.php:693 +msgctxt "verb" +msgid "Trash" +msgstr "Corbeille" + +#: wp-admin/includes/class-wp-comments-list-table.php:422 +#: wp-admin/includes/class-wp-posts-list-table.php:776 +#: wp-admin/includes/class-wp-terms-list-table.php:336 +msgid "Quick Edit" +msgstr "Modification rapide" + +#: wp-admin/includes/class-wp-comments-list-table.php:422 +#: wp-admin/includes/class-wp-posts-list-table.php:589 +#: wp-admin/includes/class-wp-terms-list-table.php:258 +msgid "Quick Edit" +msgstr "Modification rapide" + +#: wp-admin/includes/class-wp-comments-list-table.php:423 +#: wp-admin/includes/dashboard.php:688 +msgid "Reply to this comment" +msgstr "Répondre à ce commentaire" + +# Utilisé dans l'affichage des commentaires sous l'article +#: wp-admin/includes/class-wp-comments-list-table.php:481 +msgid "Y/m/d \\a\\t g:ia" +msgstr "d/m/Y \\à\\ G \\h i \\m\\i\\n" + +#: wp-admin/includes/class-wp-filesystem-base.php:251 +msgid "Looking for %1$s in %2$s" +msgstr "Recherche %1$s dans %2$s" + +#: wp-admin/includes/class-wp-filesystem-base.php:272 +msgid "Changing to %s" +msgstr "Modifier à %s" + +#: wp-admin/includes/class-wp-filesystem-base.php:283 +msgid "Found %s" +msgstr "Trouvé %s" + +#: wp-admin/includes/class-wp-filesystem-ftpext.php:28 +msgid "The ftp PHP extension is not available" +msgstr "L’extension ftp de PHP n’est pas disponible" + +#: wp-admin/includes/class-wp-filesystem-ftpext.php:43 +#: wp-admin/includes/class-wp-filesystem-ftpsockets.php:37 +msgid "FTP hostname is required" +msgstr "L’hôte du FTP est obligatoire" + +#: wp-admin/includes/class-wp-filesystem-ftpext.php:52 +#: wp-admin/includes/class-wp-filesystem-ftpsockets.php:46 +msgid "FTP username is required" +msgstr "L’identifiant FTP est obligatoire" + +#: wp-admin/includes/class-wp-filesystem-ftpext.php:57 +#: wp-admin/includes/class-wp-filesystem-ftpsockets.php:51 +msgid "FTP password is required" +msgstr "Le mot de passe FTP est obligatoire" + +#: wp-admin/includes/class-wp-filesystem-ftpext.php:73 +#: wp-admin/includes/class-wp-filesystem-ftpsockets.php:63 +#: wp-admin/includes/class-wp-filesystem-ftpsockets.php:68 +msgid "Failed to connect to FTP Server %1$s:%2$s" +msgstr "Impossible de me connecter au serveur FTP %1$s : %2$s" + +#: wp-admin/includes/class-wp-filesystem-ftpext.php:78 +#: wp-admin/includes/class-wp-filesystem-ftpsockets.php:73 +#: wp-admin/includes/class-wp-filesystem-ssh2.php:110 +msgid "Username/Password incorrect for %s" +msgstr "Le couple identifiant / mot de passe est incorrect pour %s" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:50 +msgid "The ssh2 PHP extension is not available" +msgstr "L’extension ssh2 de PHP n’est pas disponible" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:54 +msgid "" +"The ssh2 PHP extension is available, however, we require the PHP5 function " +"stream_get_contents()" +msgstr "" +"L’extension ssh2 de PHP est disponible, mais nécessite la fonction " +"PHP5 stream_get_contents()" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:65 +msgid "SSH2 hostname is required" +msgstr "Le nom de l’hôte SSH2 est obligatoire" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:81 +msgid "SSH2 username is required" +msgstr "L’identifiant SSH2 est obligatoire" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:89 +msgid "SSH2 password is required" +msgstr "Le mot de passe SSH2 est obligatoire" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:104 +msgid "Failed to connect to SSH2 Server %1$s:%2$s" +msgstr "Impossible de me connecter au serveur SSH2 %1$s : %2$s" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:115 +msgid "Public and Private keys incorrect for %s" +msgstr "Les clés publiques et privées de %s ne sont pas correctes" + +#: wp-admin/includes/class-wp-filesystem-ssh2.php:131 +msgid "Unable to perform command: %s" +msgstr "Impossible de lancer la commande : %s" + +#: wp-admin/includes/class-wp-links-list-table.php:43 +msgid "No links found." +msgstr "Aucun lien trouvé." + +#: wp-admin/includes/class-wp-links-list-table.php:48 +#: wp-admin/includes/class-wp-links-list-table.php:145 +#: wp-admin/includes/class-wp-ms-sites-list-table.php:128 +#: wp-admin/includes/class-wp-ms-sites-list-table.php:271 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:240 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:285 +#: wp-admin/includes/class-wp-ms-users-list-table.php:75 +#: wp-admin/includes/class-wp-ms-users-list-table.php:189 +#: wp-admin/includes/class-wp-plugins-list-table.php:249 +#: wp-admin/includes/class-wp-plugins-list-table.php:347 +#: wp-admin/includes/class-wp-plugins-list-table.php:356 +#: wp-admin/includes/class-wp-terms-list-table.php:84 +#: wp-admin/includes/class-wp-terms-list-table.php:261 +#: wp-admin/includes/class-wp-themes-list-table.php:159 +#: wp-admin/includes/class-wp-users-list-table.php:130 +#: wp-admin/includes/class-wp-users-list-table.php:257 +#: wp-admin/includes/media.php:1233 wp-admin/includes/meta-boxes.php:717 +#: wp-admin/includes/template.php:538 wp-admin/includes/widgets.php:210 +#: wp-admin/widgets.php:284 +msgid "Delete" +msgstr "Supprimer " + +#: wp-admin/includes/class-wp-links-list-table.php:65 +#: wp-admin/includes/class-wp-posts-list-table.php:209 +msgid "View all categories" +msgstr "Voir toutes les catégories" + +#: wp-admin/includes/class-wp-links-list-table.php:84 +msgid "Relationship" +msgstr "Relation" + +#: wp-admin/includes/class-wp-links-list-table.php:85 +msgid "Visible" +msgstr "Visible" + +#: wp-admin/includes/class-wp-links-list-table.php:86 +#: wp-admin/includes/class-wp-plugin-install-list-table.php:187 +#: wp-admin/includes/meta-boxes.php:976 +msgid "Rating" +msgstr "Note" + +#: wp-admin/includes/class-wp-links-list-table.php:134 +#: wp-admin/includes/class-wp-media-list-table.php:213 +#: wp-admin/includes/class-wp-ms-sites-list-table.php:218 +#: wp-admin/includes/class-wp-ms-users-list-table.php:168 +#: wp-admin/includes/class-wp-plugins-list-table.php:373 +#: wp-admin/includes/class-wp-posts-list-table.php:518 +#: wp-admin/includes/class-wp-terms-list-table.php:236 +#: wp-admin/includes/class-wp-users-list-table.php:264 +msgid "Select %s" +msgstr "Sélectionner %s" + +#: wp-admin/includes/class-wp-links-list-table.php:141 +#: wp-admin/includes/class-wp-media-list-table.php:229 +#: wp-admin/includes/class-wp-media-list-table.php:247 +#: wp-admin/includes/class-wp-posts-list-table.php:561 +#: wp-admin/includes/class-wp-terms-list-table.php:253 +#: wp-admin/includes/dashboard.php:593 +msgid "Edit “%s”" +msgstr "Modifier avec « %s »" + +#: wp-admin/includes/class-wp-links-list-table.php:145 +msgid "" +"You are about to delete this link '%s'\n" +" 'Cancel' to stop, 'OK' to delete." +msgstr "" +"Vous êtes sur le point de supprimer le lien « %s ».\n" +" « Annuler » pour abandonner, « OK » pour le supprimer." + +#: wp-admin/includes/class-wp-links-list-table.php:151 +msgid "Visit %s" +msgstr "Aller sur %s" + +#: wp-admin/includes/class-wp-list-table.php:388 +#: wp-admin/includes/media.php:2085 +msgid "Show all dates" +msgstr "Afficher toutes les dates" + +#: wp-admin/includes/class-wp-list-table.php:417 +msgid "List View" +msgstr "Liste simple" + +#: wp-admin/includes/class-wp-list-table.php:418 +msgid "Excerpt View" +msgstr "Liste avec extraits" + +#: wp-admin/includes/class-wp-list-table.php:444 +msgid "%s pending" +msgstr "%s en attente" + +#: wp-admin/includes/class-wp-list-table.php:518 +msgid "Go to the first page" +msgstr "Aller à la première page" + +#: wp-admin/includes/class-wp-list-table.php:525 +msgid "Go to the previous page" +msgstr "Aller à la page précédente" + +#: wp-admin/includes/class-wp-list-table.php:534 +msgid "Current page" +msgstr "Page actuelle" + +#: wp-admin/includes/class-wp-list-table.php:540 +msgctxt "paging" +msgid "%1$s of %2$s" +msgstr "%1$s sur %2$s" + +#: wp-admin/includes/class-wp-list-table.php:544 +msgid "Go to the next page" +msgstr "Aller à la page suivante" + +#: wp-admin/includes/class-wp-list-table.php:551 +msgid "Go to the last page" +msgstr "Aller à la dernière page" + +#: wp-admin/includes/class-wp-media-list-table.php:57 +msgctxt "uploaded files" +msgid "All (%s)" +msgid_plural "All (%s)" +msgstr[0] "Tout (%s)" +msgstr[1] "Tout (%s)" + +#: wp-admin/includes/class-wp-media-list-table.php:69 +msgctxt "detached files" +msgid "Unattached (%s)" +msgid_plural "Unattached (%s)" +msgstr[0] "Non attaché (%s)" +msgstr[1] "Non attachés (%s)" + +#: wp-admin/includes/class-wp-media-list-table.php:72 +msgctxt "uploaded files" +msgid "Trash (%s)" +msgid_plural "Trash (%s)" +msgstr[0] "Corbeille (%s)" +msgstr[1] "Corbeille (%s)" + +#: wp-admin/includes/class-wp-media-list-table.php:81 +msgid "Attach to a post" +msgstr "Joindre à un article" + +#: wp-admin/includes/class-wp-media-list-table.php:98 +msgid "Scan for lost attachments" +msgstr "Rechercher les fichiers attachés perdus" + +#: wp-admin/includes/class-wp-media-list-table.php:124 +msgid "No media attachments found." +msgstr "Pas de fichier média attaché." + +#. translators: column name +#: wp-admin/includes/class-wp-media-list-table.php:132 +msgctxt "column name" +msgid "File" +msgstr "Fichier" + +#. translators: column name +#: wp-admin/includes/class-wp-media-list-table.php:156 +msgctxt "column name" +msgid "Uploaded to" +msgstr "Mis en ligne sur " + +#. translators: column name +#: wp-admin/includes/class-wp-media-list-table.php:161 +msgctxt "column name" +msgid "Date" +msgstr "Date" + +#: wp-admin/includes/class-wp-media-list-table.php:285 +#: wp-admin/includes/class-wp-posts-list-table.php:617 +msgid "Unpublished" +msgstr "Non publié" + +#: wp-admin/includes/class-wp-media-list-table.php:291 +msgid "%s from now" +msgstr "%s à partir de maintenant" + +#: wp-admin/includes/class-wp-media-list-table.php:325 +msgid "(Unattached)" +msgstr "(Non attaché)" + +#: wp-admin/includes/class-wp-media-list-table.php:330 +#: wp-admin/includes/class-wp-media-list-table.php:412 +msgid "Attach" +msgstr "Joindre" + +#: wp-admin/includes/class-wp-media-list-table.php:405 +#: wp-admin/includes/class-wp-media-list-table.php:421 +#: wp-admin/includes/class-wp-posts-list-table.php:595 +#: wp-admin/includes/meta-boxes.php:295 +msgid "Trash" +msgstr "Mettre à la Corbeille" + +#: wp-admin/includes/class-wp-media-list-table.php:410 +#: wp-admin/includes/class-wp-media-list-table.php:429 +#: wp-admin/includes/class-wp-posts-list-table.php:604 +msgid "View “%s”" +msgstr "Afficher « %s »" + +#: wp-admin/includes/class-wp-media-list-table.php:410 +#: wp-admin/includes/class-wp-media-list-table.php:429 +#: wp-admin/includes/class-wp-ms-users-list-table.php:241 +#: wp-admin/includes/class-wp-posts-list-table.php:604 +#: wp-admin/includes/class-wp-terms-list-table.php:263 +msgid "View" +msgstr "Afficher" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:122 +msgid "No sites found." +msgstr "Aucun site trouvé." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:129 +msgctxt "site" +msgid "Mark as Spam" +msgstr "Marquer comme indésirable" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:130 +#: wp-admin/includes/class-wp-ms-sites-list-table.php:266 +msgctxt "site" +msgid "Not Spam" +msgstr "N’est pas un indésirable" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:145 +msgid "Domain" +msgstr "Domaine" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:149 +msgid "Last Updated" +msgstr "Dernière mise à jour" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:150 +msgctxt "site" +msgid "Registered" +msgstr "Inscription" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:155 +#: wp-admin/includes/media.php:1879 wp-admin/users.php:54 +msgid "Actions" +msgstr "Actions" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:174 +msgid "Archived" +msgstr "Archivé" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:175 +#: wp-admin/includes/class-wp-ms-sites-list-table.php:268 +msgctxt "site" +msgid "Spam" +msgstr "Indésirable" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:176 +msgid "Deleted" +msgstr "Supprimé" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:177 +msgid "Mature" +msgstr "Adulte" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:238 +msgctxt "%1$s: site name. %2$s: site tagline." +msgid "%1$s – %2$s" +msgstr "%1$s – %2$s" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:256 +msgid "You are about to activate the site %s" +msgstr "Vous êtes sur le point d’activer le site %s" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:258 +msgid "You are about to deactivate the site %s" +msgstr "Vous êtes sur le point de désactiver le site %s" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:258 +#: wp-admin/includes/class-wp-plugins-list-table.php:243 +#: wp-admin/includes/class-wp-plugins-list-table.php:351 +msgid "Deactivate" +msgstr "Désactiver" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:261 +msgid "You are about to unarchive the site %s." +msgstr "Vous êtes sur le point de désarchiver le site %s." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:261 +msgid "Unarchive" +msgstr "Désarchiver" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:263 +msgid "You are about to archive the site %s." +msgstr "Vous êtes sur le point d’archiver le site %s." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:263 +msgctxt "verb; site" +msgid "Archive" +msgstr "Archiver" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:266 +msgid "You are about to unspam the site %s." +msgstr "Vous êtes sur le point de marquer le site %s comme sain." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:268 +msgid "You are about to mark the site %s as spam." +msgstr "Vous êtes sur le point de marquer le site %s comme indésirable." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:271 +msgid "You are about to delete the site %s." +msgstr "Vous êtes sur le point de supprimer le site %s." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:274 +#: wp-admin/my-sites.php:105 +msgid "Visit" +msgstr "Visiter" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:289 +msgid "Never" +msgstr "Jamais" + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:310 +msgid "Only showing first 5 users." +msgstr "Affiche seulement les 5 premiers utilisateurs." + +#: wp-admin/includes/class-wp-ms-sites-list-table.php:310 +msgid "More" +msgstr "Plus" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:164 +msgid "No themes found." +msgstr "Aucun thème trouvé." + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:166 +msgid "You do not appear to have any themes available at this time." +msgstr "Vous ne semblez pas avoir de thème disponible en ce moment." + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:174 +msgid "Theme" +msgstr "Thème" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:195 +msgctxt "themes" +msgid "All (%s)" +msgid_plural "All (%s)" +msgstr[0] "Tous (%s)" +msgstr[1] "Tous (%s)" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:198 +msgid "Enabled (%s)" +msgid_plural "Enabled (%s)" +msgstr[0] "Activé (%s)" +msgstr[1] "Activés (%s)" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:201 +msgid "Disabled (%s)" +msgid_plural "Disabled (%s)" +msgstr[0] "Désactivé (%s)" +msgstr[1] "Désactivés (%s)" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:204 +#: wp-admin/includes/class-wp-plugins-list-table.php:218 +msgid "Update Available (%s)" +msgid_plural "Update Available (%s)" +msgstr[0] "Prête à mettre à jour (%s)" +msgstr[1] "Prêtes à mettre à jour (%s)" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:207 +msgid "Broken (%s)" +msgid_plural "Broken (%s)" +msgstr[0] "Cassé (%s)" +msgstr[1] "Cassé (%s)" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:233 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:276 +msgid "Enable" +msgstr "Activer" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:233 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:276 +#: wp-admin/includes/class-wp-upgrader-skins.php:454 +msgid "Network Enable" +msgstr "Activer sur le réseau" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:235 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:278 +msgid "Disable" +msgstr "Désactiver" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:235 +#: wp-admin/includes/class-wp-ms-themes-list-table.php:278 +msgid "Network Disable" +msgstr "Désactiver du réseau" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:276 +msgid "Enable this theme" +msgstr "Activer ce thème" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:278 +msgid "Disable this theme" +msgstr "Désactiver ce thème" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:282 +msgid "Open this theme in the Theme Editor" +msgstr "Ouvrir ce thème dans l’éditeur de thème" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:285 +msgid "Delete this theme" +msgstr "Supprimer ce thème" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:320 +msgid "Broken Theme:" +msgstr "Thème cassé :" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:331 +#: wp-admin/includes/class-wp-plugin-install-list-table.php:229 +#: wp-admin/includes/class-wp-plugins-list-table.php:415 +#: wp-admin/includes/class-wp-theme-install-list-table.php:235 +#: wp-admin/includes/class-wp-theme-install-list-table.php:338 +#: wp-admin/includes/class-wp-themes-list-table.php:180 +#: wp-admin/themes.php:155 +msgid "By %s" +msgstr "Par %s" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:334 +msgid "Visit theme homepage" +msgstr "Aller sur la page du thème" + +#: wp-admin/includes/class-wp-ms-themes-list-table.php:334 +msgid "Visit Theme Site" +msgstr "Aller sur le site du thème" + +#: wp-admin/includes/class-wp-ms-users-list-table.php:76 +msgctxt "user" +msgid "Mark as Spam" +msgstr "Marquer comme indésirable" + +#: wp-admin/includes/class-wp-ms-users-list-table.php:77 +msgctxt "user" +msgid "Not Spam" +msgstr "N’est pas un indésirable" + +#: wp-admin/includes/class-wp-ms-users-list-table.php:83 +msgid "No users found." +msgstr "Aucun utilisateur trouvé." + +#: wp-admin/includes/class-wp-ms-users-list-table.php:96 +#: wp-admin/includes/class-wp-users-list-table.php:101 +msgctxt "users" +msgid "All (%s)" +msgid_plural "All (%s)" +msgstr[0] "Tous (%s)" +msgstr[1] "Tous (%s)" + +#: wp-admin/includes/class-wp-ms-users-list-table.php:98 +msgid "Super Admin (%s)" +msgid_plural "Super Admins (%s)" +msgstr[0] "Super-admin (%s)" +msgstr[1] "Super-admins (%s)" + +#: wp-admin/includes/class-wp-ms-users-list-table.php:118 +msgctxt "user" +msgid "Registered" +msgstr "Inscription" + +#: wp-admin/includes/class-wp-ms-users-list-table.php:181 +#: wp-admin/user-edit.php:269 +msgid "Super Admin" +msgstr "Super-admin" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:31 +#: wp-admin/includes/class-wp-theme-install-list-table.php:42 +#: wp-admin/includes/file.php:28 +msgid "Search Results" +msgstr "Résultats de recherche" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:33 +msgctxt "Plugin Installer" +msgid "Featured" +msgstr "Mises en avant" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:34 +msgctxt "Plugin Installer" +msgid "Popular" +msgstr "Populaires" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:35 +msgctxt "Plugin Installer" +msgid "Newest" +msgstr "Ajoutées récemment" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:36 +msgctxt "Plugin Installer" +msgid "Favorites" +msgstr "Favorites" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:126 +#: wp-admin/includes/class-wp-theme-install-list-table.php:104 +#: wp-admin/setup-config.php:175 +msgid "Try again" +msgstr "Recommencer" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:137 +msgid "No plugins match your request." +msgstr "Aucune extension ne correspond à votre requête." + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:185 +msgctxt "plugin name" +msgid "Name" +msgstr "Nom" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:236 +msgid "More information about %s" +msgstr "Plus d’informations à propos de %s" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:236 +#: wp-admin/includes/class-wp-theme-install-list-table.php:242 +#: wp-admin/includes/class-wp-themes-list-table.php:186 +msgid "Details" +msgstr "Détails" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:244 +#: wp-admin/includes/class-wp-theme-install-list-table.php:214 +msgid "Install %s" +msgstr "Installer %s" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:244 +#: wp-admin/includes/class-wp-theme-install-list-table.php:214 +#: wp-admin/includes/plugin-install.php:190 +#: wp-admin/includes/plugin-install.php:371 +#: wp-admin/includes/theme-install.php:144 +msgid "Install Now" +msgstr "Installer maintenant" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:248 +#: wp-admin/includes/class-wp-theme-install-list-table.php:217 +#: wp-admin/includes/class-wp-theme-install-list-table.php:330 +msgid "Update to version %s" +msgstr "Mettre à jour vers la version %s" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:248 +#: wp-admin/update-core.php:39 +msgid "Update Now" +msgstr "Mettre à jour" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:252 +msgid "This plugin is already installed and is up to date" +msgstr "Cette extension est déjà installée et à jour" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:252 +msgctxt "plugin" +msgid "Installed" +msgstr "Installée" + +#: wp-admin/includes/class-wp-plugin-install-list-table.php:273 +#: wp-admin/includes/class-wp-theme-install-list-table.php:308 +#: wp-admin/includes/plugin-install.php:410 +#: wp-admin/includes/plugin-install.php:413 +msgid "(based on %s rating)" +msgid_plural "(based on %s ratings)" +msgstr[0] "(basée sur %s vote)" +msgstr[1] "(basée sur %s votes)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:171 +msgid "No plugins found." +msgstr "Aucune extension trouvée." + +#: wp-admin/includes/class-wp-plugins-list-table.php:173 +msgid "You do not appear to have any plugins available at this time." +msgstr "Vous ne semblez pas avoir d’extension disponible en ce moment." + +#: wp-admin/includes/class-wp-plugins-list-table.php:200 +msgctxt "plugins" +msgid "All (%s)" +msgid_plural "All (%s)" +msgstr[0] "Toutes (%s)" +msgstr[1] "Toutes (%s)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:203 +msgid "Active (%s)" +msgid_plural "Active (%s)" +msgstr[0] "Activée (%s)" +msgstr[1] "Activées (%s)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:206 +msgid "Recently Active (%s)" +msgid_plural "Recently Active (%s)" +msgstr[0] "Récemment désactivée (%s)" +msgstr[1] "Récemment désactivées (%s)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:209 +msgid "Inactive (%s)" +msgid_plural "Inactive (%s)" +msgstr[0] "Désactivée (%s)" +msgstr[1] "Désactivées (%s)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:212 +msgid "Must-Use (%s)" +msgid_plural "Must-Use (%s)" +msgstr[0] "Automatique (Must-Use) (%s)" +msgstr[1] "Automatiques (Must-Use) (%s)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:215 +msgid "Drop-ins (%s)" +msgid_plural "Drop-ins (%s)" +msgstr[0] "Drop-ins (%s)" +msgstr[1] "Drop-ins (%s)" + +#: wp-admin/includes/class-wp-plugins-list-table.php:240 +#: wp-admin/includes/class-wp-plugins-list-table.php:345 +#: wp-admin/includes/class-wp-upgrader-skins.php:374 +msgid "Network Activate" +msgstr "Activer sur le réseau" + +#: wp-admin/includes/class-wp-plugins-list-table.php:243 +#: wp-admin/includes/class-wp-plugins-list-table.php:342 +msgid "Network Deactivate" +msgstr "Désactiver du réseau" + +#: wp-admin/includes/class-wp-plugins-list-table.php:273 +msgid "Clear List" +msgstr "Vider la liste" + +#: wp-admin/includes/class-wp-plugins-list-table.php:275 +msgid "Files in the %s directory are executed automatically." +msgstr "" +"Les fichiers contenus dans le dossier %s sont exécutés " +"automatiquement." + +# Besoin d'une bonne trad pour "drop-ins", gn +#: wp-admin/includes/class-wp-plugins-list-table.php:277 +msgid "" +"Drop-ins are advanced plugins in the %s directory that replace " +"WordPress functionality when present." +msgstr "" +"Les « drop-ins » sont des extensions avancées " +"contenues dans le dossier %s ; elles permettent le " +"remplacement de certaines fonctionnalités de WordPress." + +#: wp-admin/includes/class-wp-plugins-list-table.php:329 +msgid "Inactive:" +msgstr "Inactif :" + +#: wp-admin/includes/class-wp-plugins-list-table.php:329 +msgid "Requires %s in wp-config.php." +msgstr "Nécessite %s dans le fichier wp-config.php." + +#: wp-admin/includes/class-wp-plugins-list-table.php:342 +#: wp-admin/includes/class-wp-plugins-list-table.php:351 +msgid "Deactivate this plugin" +msgstr "Désactiver cette extension" + +#: wp-admin/includes/class-wp-plugins-list-table.php:345 +#: wp-admin/includes/class-wp-upgrader-skins.php:374 +msgid "Activate this plugin for all sites in this network" +msgstr "Activer cette extension sur tous les sites de ce réseau" + +#: wp-admin/includes/class-wp-plugins-list-table.php:347 +#: wp-admin/includes/class-wp-plugins-list-table.php:356 +msgid "Delete this plugin" +msgstr "Supprimer cette extension" + +#: wp-admin/includes/class-wp-plugins-list-table.php:353 +#: wp-admin/includes/class-wp-upgrader-skins.php:129 +#: wp-admin/includes/class-wp-upgrader-skins.php:369 +#: wp-admin/includes/class-wp-upgrader-skins.php:371 +msgid "Activate this plugin" +msgstr "Activer cette extension" + +#: wp-admin/includes/class-wp-plugins-list-table.php:361 +msgid "Open this file in the Plugin Editor" +msgstr "Ouvrir ce fichier dans l’éditeur d’extension" + +#: wp-admin/includes/class-wp-plugins-list-table.php:418 +msgid "Visit plugin site" +msgstr "Aller sur le site de l’extension" + +#: wp-admin/includes/class-wp-posts-list-table.php:139 +msgctxt "posts" +msgid "Mine (%s)" +msgid_plural "Mine (%s)" +msgstr[0] "Le mien (%s)" +msgstr[1] "Les miens (%s)" + +#: wp-admin/includes/class-wp-posts-list-table.php:150 +msgctxt "posts" +msgid "All (%s)" +msgid_plural "All (%s)" +msgstr[0] "Tous (%s)" +msgstr[1] "Tous (%s)" + +#: wp-admin/includes/class-wp-posts-list-table.php:172 +msgctxt "posts" +msgid "Sticky (%s)" +msgid_plural "Sticky (%s)" +msgstr[0] "Mis en avant (%s)" +msgstr[1] "Mis en avant (%s)" + +#. translators: manage posts column name +#: wp-admin/includes/class-wp-posts-list-table.php:258 +msgctxt "column name" +msgid "Title" +msgstr "Titre" + +#: wp-admin/includes/class-wp-posts-list-table.php:575 +#: wp-admin/includes/misc.php:611 +msgid "%s is currently editing" +msgstr "%s modifie actuellement ce contenu" + +#: wp-admin/includes/class-wp-posts-list-table.php:588 +msgid "Edit this item" +msgstr "Modifier cette entrée" + +#: wp-admin/includes/class-wp-posts-list-table.php:589 +msgid "Edit this item inline" +msgstr "Modifier cette entrée sur place" + +#: wp-admin/includes/class-wp-posts-list-table.php:593 +msgid "Restore this item from the Trash" +msgstr "Récupérer ce élément depuis la Corbeille" + +#: wp-admin/includes/class-wp-posts-list-table.php:595 +msgid "Move this item to the Trash" +msgstr "Déplacer cette entrée dans la Corbeille" + +#: wp-admin/includes/class-wp-posts-list-table.php:597 +msgid "Delete this item permanently" +msgstr "Supprimer cette entrée définitivement" + +#: wp-admin/includes/class-wp-posts-list-table.php:602 +#: wp-admin/includes/class-wp-theme-install-list-table.php:191 +#: wp-admin/includes/class-wp-themes-list-table.php:150 +#: wp-admin/includes/class-wp-upgrader-skins.php:449 +#: wp-admin/includes/class-wp-upgrader-skins.php:450 +#: wp-admin/includes/class-wp-upgrader-skins.php:514 +#: wp-admin/includes/class-wp-upgrader-skins.php:515 +msgid "Preview “%s”" +msgstr "Prévisualiser « %s »" + +# Utilisé dans les listes d'articles, pages, fichiers, en rollover de la date. +#: wp-admin/includes/class-wp-posts-list-table.php:620 +#: wp-admin/includes/dashboard.php:593 +msgid "Y/m/d g:i:s A" +msgstr "d/m/Y \\à G \\h i \\m\\i\\n s \\s" + +#: wp-admin/includes/class-wp-posts-list-table.php:642 +msgid "Missed schedule" +msgstr "Planification manquée" + +#: wp-admin/includes/class-wp-posts-list-table.php:646 +msgid "Last Modified" +msgstr "Dernière modification" + +#: wp-admin/includes/class-wp-posts-list-table.php:776 +msgid "Bulk Edit" +msgstr "Modifications groupées" + +#: wp-admin/includes/class-wp-posts-list-table.php:821 +#: wp-admin/includes/class-wp-posts-list-table.php:901 +#: wp-admin/includes/class-wp-posts-list-table.php:926 +#: wp-admin/includes/class-wp-posts-list-table.php:960 +#: wp-admin/includes/class-wp-posts-list-table.php:969 +#: wp-admin/includes/class-wp-posts-list-table.php:1001 +#: wp-admin/includes/class-wp-posts-list-table.php:1022 +#: wp-admin/includes/class-wp-posts-list-table.php:1050 +msgid "— No Change —" +msgstr "— Aucun changement —" + +#. translators: Between password field and private checkbox on post quick edit +#. interface +#: wp-admin/includes/class-wp-posts-list-table.php:847 +msgid "–OR–" +msgstr "— OU —" + +#: wp-admin/includes/class-wp-posts-list-table.php:889 +#: wp-admin/includes/meta-boxes.php:653 wp-admin/includes/meta-boxes.php:654 +msgid "Parent" +msgstr "Parent" + +#: wp-admin/includes/class-wp-posts-list-table.php:895 +msgid "Main Page (no parent)" +msgstr "Page principale (pas de page parente)" + +#: wp-admin/includes/class-wp-posts-list-table.php:913 +#: wp-admin/includes/media.php:1000 wp-admin/includes/media.php:1878 +#: wp-admin/includes/meta-boxes.php:669 wp-admin/includes/meta-boxes.php:670 +msgid "Order" +msgstr "Ordre" + +#: wp-admin/includes/class-wp-posts-list-table.php:928 +#: wp-admin/includes/meta-boxes.php:664 +msgid "Default Template" +msgstr "Modèle par défaut" + +#: wp-admin/includes/class-wp-posts-list-table.php:961 +#: wp-admin/includes/class-wp-posts-list-table.php:970 +msgid "Allow" +msgstr "Autoriser" + +#: wp-admin/includes/class-wp-posts-list-table.php:962 +#: wp-admin/includes/class-wp-posts-list-table.php:971 +msgid "Do not allow" +msgstr "Refuser" + +#: wp-admin/includes/class-wp-posts-list-table.php:983 +msgid "Allow Comments" +msgstr "Autoriser les commentaires" + +#: wp-admin/includes/class-wp-posts-list-table.php:988 +msgid "Allow Pings" +msgstr "Autoriser les notifications par ping" + +# Y'a p'tet mieux comme trad, non ? "tête de blog" ? boaf... +#: wp-admin/includes/class-wp-posts-list-table.php:1020 +#: wp-admin/includes/class-wp-posts-list-table.php:1023 +#: wp-admin/includes/template.php:1493 +msgid "Sticky" +msgstr "Mettre en avant" + +# Y'a p'tet mieux comme trad, non ? "tête de blog" ? boaf... +#: wp-admin/includes/class-wp-posts-list-table.php:1024 +msgid "Not Sticky" +msgstr "Ne pas mettre en avant" + +#: wp-admin/includes/class-wp-posts-list-table.php:1032 +msgid "Make this post sticky" +msgstr "Mettre ce contenu en avant" + +#: wp-admin/includes/class-wp-terms-list-table.php:99 +#: wp-admin/includes/class-wp-terms-list-table.php:339 +msgctxt "term name" +msgid "Name" +msgstr "Nom" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:44 +msgctxt "Theme Installer" +msgid "Featured" +msgstr "Mis en avant" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:46 +msgctxt "Theme Installer" +msgid "Newest" +msgstr "Les + récents" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:47 +msgctxt "Theme Installer" +msgid "Recently Updated" +msgstr "Mis à jour récemment" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:116 +msgid "No themes match your request." +msgstr "Aucun thème ne correspond à votre requête." + +#: wp-admin/includes/class-wp-theme-install-list-table.php:221 +#: wp-admin/includes/class-wp-theme-install-list-table.php:334 +msgid "This theme is already installed and is up to date" +msgstr "Ce thème est déjà installé et à jour" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:221 +#: wp-admin/includes/class-wp-theme-install-list-table.php:334 +msgctxt "theme" +msgid "Installed" +msgstr "Installés" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:225 +msgid "Preview %s" +msgstr "Aperçu de %s" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:258 +msgid "← Close" +msgstr "← Fermer" + +#: wp-admin/includes/class-wp-theme-install-list-table.php:327 +#: wp-admin/includes/dashboard.php:1000 +msgid "Install" +msgstr "Installer" + +#: wp-admin/includes/class-wp-themes-list-table.php:68 +msgid "" +"You only have one theme enabled for this site right now. Visit the Network " +"Admin to enable or install more " +"themes." +msgstr "" +"Vous n’avez qu’un thème activé sur ce site actuellement. " +"Veuillez vous rendre sur la page d’administration du réseau pour activer ou installer plus de thèmes." + +#: wp-admin/includes/class-wp-themes-list-table.php:72 +msgid "" +"You only have one theme enabled for this site right now. Visit the Network " +"Admin to enable more themes." +msgstr "" +"Vous n’avez qu’un thème activé sur ce site actuellement. " +"Veuillez vous rendre sur la page d’administration du réseau pour activer plus de thèmes." + +#: wp-admin/includes/class-wp-themes-list-table.php:79 +msgid "" +"You only have one theme installed right now. Live a little! You can choose " +"from over 1,000 free themes in the WordPress.org Theme Directory at any " +"time: just click on the Install Themes tab above." +msgstr "" +"Vous n’avez qu’un seul thème d’installé pour le moment. " +"Faites vivre votre site ! Vous pouvez quand vous le voulez choisir " +"parmi plus de 1 000 thèmes sur le dépôt de thèmes de WordPress." +"org : cliquez simplement sur l’onglet « Installer des thèmes » ci-dessus." + +#: wp-admin/includes/class-wp-themes-list-table.php:85 +msgid "" +"Only the current theme is available to you. Contact the %s administrator for " +"information about accessing additional themes." +msgstr "" +"Vous n’avez accès qu’au thème déjà en place. Contactez l’" +"administrateur de %s pour obtenir des informations sur l’accès à " +"d’autres thèmes." + +#: wp-admin/includes/class-wp-themes-list-table.php:147 +#: wp-admin/includes/class-wp-upgrader-skins.php:451 +#: wp-admin/includes/class-wp-upgrader-skins.php:516 +msgid "Activate “%s”" +msgstr "Activer « %s »" + +#: wp-admin/includes/class-wp-themes-list-table.php:154 +#: wp-admin/includes/class-wp-upgrader-skins.php:450 +#: wp-admin/includes/class-wp-upgrader-skins.php:515 +msgid "Live Preview" +msgstr "Prévisualiser" + +#: wp-admin/includes/class-wp-themes-list-table.php:158 +msgid "" +"You are about to delete this theme '%s'\n" +" 'Cancel' to stop, 'OK' to delete." +msgstr "" +"Vous êtes sur le point de supprimer le thème « %s ».\n" +" « Annuler » pour abandonner, « OK » pour le supprimer." + +#: wp-admin/includes/class-wp-themes-list-table.php:194 +msgid "Version: " +msgstr "Version :" + +#: wp-admin/includes/class-wp-themes-list-table.php:197 +#: wp-admin/themes.php:160 +msgid "This child theme requires its parent theme, %2$s." +msgstr "Ce thème enfant nécessite son thème parent, %2$s." + +#: wp-admin/includes/class-wp-themes-list-table.php:198 +#: wp-admin/theme-editor.php:33 wp-admin/themes.php:161 +#: wp-admin/update-core.php:297 +msgid "http://codex.wordpress.org/Child_Themes" +msgstr "http://codex.wordpress.org/fr:Thèmes_Enfant" + +#: wp-admin/includes/class-wp-upgrader-skins.php:111 wp-admin/update.php:54 +msgid "Update Plugin" +msgstr "Mettre à jour l’extension" + +#: wp-admin/includes/class-wp-upgrader-skins.php:129 +#: wp-admin/includes/class-wp-upgrader-skins.php:371 +msgid "Activate Plugin" +msgstr "Activer l’extension" + +#: wp-admin/includes/class-wp-upgrader-skins.php:130 +#: wp-admin/includes/class-wp-upgrader-skins.php:287 +msgid "Go to plugins page" +msgstr "Aller sur la page des extensions" + +#: wp-admin/includes/class-wp-upgrader-skins.php:130 +#: wp-admin/includes/class-wp-upgrader-skins.php:287 +#: wp-admin/includes/class-wp-upgrader-skins.php:383 +msgid "Return to Plugins page" +msgstr "Retourner sur la page des extensions" + +#: wp-admin/includes/class-wp-upgrader-skins.php:167 +msgid "" +"The update process is starting. This process may take a while on some hosts, " +"so please be patient." +msgstr "" +"Le processus de mise à jour se lance. Il peut prendre un certain temps chez " +"certains hébergeurs, merci pour votre patience." + +#: wp-admin/includes/class-wp-upgrader-skins.php:168 +msgid "An error occurred while updating %1$s: %2$s" +msgstr "" +"Une erreur est survenue pendant la mise à jour de %1$s : %2$s" + +#: wp-admin/includes/class-wp-upgrader-skins.php:169 +msgid "The update of %1$s failed." +msgstr "La mise à jour de %1$s a échoué." + +#: wp-admin/includes/class-wp-upgrader-skins.php:170 +msgid "%1$s updated successfully." +msgstr "%1$s a bien été mis à jour." + +#: wp-admin/includes/class-wp-upgrader-skins.php:170 +msgid "Show Details" +msgstr "Afficher les détails" + +#: wp-admin/includes/class-wp-upgrader-skins.php:170 +msgid "Hide Details" +msgstr "Cacher les détails" + +#: wp-admin/includes/class-wp-upgrader-skins.php:171 +msgid "All updates have been completed." +msgstr "Toutes les mises à jour sont terminées." + +#: wp-admin/includes/class-wp-upgrader-skins.php:274 +msgid "Updating Plugin %1$s (%2$d/%3$d)" +msgstr "Mise à jour de l’extension %1$s (%2$d/%3$d)" + +#: wp-admin/includes/class-wp-upgrader-skins.php:288 +#: wp-admin/includes/class-wp-upgrader-skins.php:323 +#: wp-admin/includes/class-wp-upgrader-skins.php:573 +msgid "Go to WordPress Updates page" +msgstr "Aller à la page des mises à jour de WordPress" + +#: wp-admin/includes/class-wp-upgrader-skins.php:288 +#: wp-admin/includes/class-wp-upgrader-skins.php:323 +#: wp-admin/includes/class-wp-upgrader-skins.php:573 +msgid "Return to WordPress Updates" +msgstr "Retourner aux mises à jour de WordPress" + +#: wp-admin/includes/class-wp-upgrader-skins.php:308 +msgid "Updating Theme %1$s (%2$d/%3$d)" +msgstr "Mise à jour du thème %1$s (%2$d/%3$d)" + +#: wp-admin/includes/class-wp-upgrader-skins.php:322 +msgid "Go to themes page" +msgstr "Aller à la page des thèmes" + +#: wp-admin/includes/class-wp-upgrader-skins.php:322 +#: wp-admin/includes/class-wp-upgrader-skins.php:459 +#: wp-admin/includes/class-wp-upgrader-skins.php:523 +msgid "Return to Themes page" +msgstr "Retourner sur la page des thèmes" + +#: wp-admin/includes/class-wp-upgrader-skins.php:357 +msgid "Successfully installed the plugin %s %s." +msgstr "L’extension %s %s a bien été installée." + +#: wp-admin/includes/class-wp-upgrader-skins.php:369 +msgid "Activate Plugin & Run Importer" +msgstr "Activer l’extension & lancer l’importateur" + +#: wp-admin/includes/class-wp-upgrader-skins.php:379 +msgid "Return to Importers" +msgstr "Retour aux importateurs" + +#: wp-admin/includes/class-wp-upgrader-skins.php:381 +msgid "Return to Plugin Installer" +msgstr "Retourner à l’installeur d’extensions" + +#: wp-admin/includes/class-wp-upgrader-skins.php:454 +msgid "Enable this theme for all sites in this network" +msgstr "Activer ce thème sur tous les sites de ce réseau" + +#: wp-admin/includes/class-wp-upgrader-skins.php:457 +msgid "Return to Theme Installer" +msgstr "Retourner à l’installeur de thèmes" + +#: wp-admin/includes/class-wp-upgrader-skins.php:459 +msgid "Themes page" +msgstr "Page des thèmes" + +#: wp-admin/includes/class-wp-upgrader-skins.php:481 wp-admin/update.php:157 +msgid "Update Theme" +msgstr "Mettre à jour le thème" + +#: wp-admin/includes/class-wp-upgrader-skins.php:512 wp-admin/themes.php:126 +msgid "Customize “%s”" +msgstr "Personnaliser « %s »" + +#: wp-admin/includes/class-wp-upgrader-skins.php:544 +#: wp-admin/update-core.php:348 wp-admin/update-core.php:621 +msgid "Update Translations" +msgstr "Mise à jour des traductions" + +#: wp-admin/includes/class-wp-upgrader-skins.php:558 +#: wp-admin/includes/class-wp-upgrader.php:1889 +msgid "Updating translations for %1$s (%2$s)…" +msgstr "Mise à jour de la traduction de %1$s (%2$s)…" + +#: wp-admin/includes/class-wp-upgrader.php:41 +msgid "Invalid Data provided." +msgstr "Les données fournies ne sont pas valides." + +#: wp-admin/includes/class-wp-upgrader.php:42 wp-admin/includes/file.php:542 +#: wp-admin/includes/plugin.php:776 wp-admin/includes/theme.php:53 +msgid "Could not access filesystem." +msgstr "Impossible d’accéder au système de fichier." + +#: wp-admin/includes/class-wp-upgrader.php:43 wp-admin/includes/plugin.php:779 +#: wp-admin/includes/theme.php:56 +msgid "Filesystem error." +msgstr "Erreur du système de fichier." + +#: wp-admin/includes/class-wp-upgrader.php:44 +msgid "Unable to locate WordPress Root directory." +msgstr "Impossible de localiser le dossier racine de WordPress." + +#: wp-admin/includes/class-wp-upgrader.php:45 +msgid "Unable to locate WordPress Content directory (wp-content)." +msgstr "" +"Impossible de localiser le dossier de contenu de WordPress (wp-content)." + +#: wp-admin/includes/class-wp-upgrader.php:46 wp-admin/includes/plugin.php:784 +msgid "Unable to locate WordPress Plugin directory." +msgstr "Impossible de localiser le dossier d’extension de WordPress." + +#: wp-admin/includes/class-wp-upgrader.php:47 +msgid "Unable to locate WordPress Theme directory." +msgstr "Impossible de localiser le dossier des thèmes de WordPress." + +#. translators: %s: directory name +#: wp-admin/includes/class-wp-upgrader.php:49 +msgid "Unable to locate needed folder (%s)." +msgstr "Impossible de localiser le dossier nécessaire (%s)." + +#: wp-admin/includes/class-wp-upgrader.php:51 +msgid "Download failed." +msgstr "Le téléchargement a échoué." + +#: wp-admin/includes/class-wp-upgrader.php:52 +msgid "Installing the latest version…" +msgstr "Installation de la dernière version…" + +#: wp-admin/includes/class-wp-upgrader.php:53 +msgid "The package contains no files." +msgstr "Ce paquet ne contient aucun fichier." + +#: wp-admin/includes/class-wp-upgrader.php:54 +msgid "Destination folder already exists." +msgstr "Le dossier de destination existe déjà." + +#: wp-admin/includes/class-wp-upgrader.php:55 wp-admin/includes/file.php:650 +#: wp-admin/includes/file.php:753 wp-admin/includes/file.php:804 +#: wp-admin/includes/update-core.php:941 +msgid "Could not create directory." +msgstr "Impossible de créer le dossier." + +#: wp-admin/includes/class-wp-upgrader.php:56 +msgid "The package could not be installed." +msgstr "L’archive n’a pas pu être installée." + +#: wp-admin/includes/class-wp-upgrader.php:58 +#: wp-admin/includes/update-core.php:736 +msgid "Enabling Maintenance mode…" +msgstr "Activation du mode maintenance…" + +#: wp-admin/includes/class-wp-upgrader.php:59 +#: wp-admin/includes/update-core.php:809 +msgid "Disabling Maintenance mode…" +msgstr "Désactivation du mode maintenance…" + +#: wp-admin/includes/class-wp-upgrader.php:414 +msgid "The plugin is at the latest version." +msgstr "Vous avez la dernière version de cette extension." + +#: wp-admin/includes/class-wp-upgrader.php:415 +#: wp-admin/includes/class-wp-upgrader.php:723 +#: wp-admin/includes/class-wp-upgrader.php:1134 +#: wp-admin/includes/class-wp-upgrader.php:1307 +msgid "Update package not available." +msgstr "Pas d’archive de mise à jour disponible." + +#: wp-admin/includes/class-wp-upgrader.php:416 +#: wp-admin/includes/class-wp-upgrader.php:724 +#: wp-admin/includes/class-wp-upgrader.php:1308 +msgid "Downloading update from %s…" +msgstr "" +"Téléchargement de la mise à jour depuis %s…" + +#: wp-admin/includes/class-wp-upgrader.php:417 +#: wp-admin/includes/class-wp-upgrader.php:725 +#: wp-admin/includes/class-wp-upgrader.php:1136 +#: wp-admin/includes/class-wp-upgrader.php:1309 +msgid "Unpacking the update…" +msgstr "Décompression de la mise à jour…" + +#: wp-admin/includes/class-wp-upgrader.php:418 +msgid "Removing the old version of the plugin…" +msgstr "Retrait de l’ancienne version de l’extension…" + +#: wp-admin/includes/class-wp-upgrader.php:419 +msgid "Could not remove the old plugin." +msgstr "Impossible de supprimer l’ancienne extension." + +#: wp-admin/includes/class-wp-upgrader.php:420 +msgid "Plugin update failed." +msgstr "La mise à jour de l’extension a échoué." + +#: wp-admin/includes/class-wp-upgrader.php:421 +msgid "Plugin updated successfully." +msgstr "L’extension a bien été mise à jour." + +#: wp-admin/includes/class-wp-upgrader.php:425 +#: wp-admin/includes/class-wp-upgrader.php:733 +msgid "Install package not available." +msgstr "L’archive d’installation n’est pas disponible." + +#: wp-admin/includes/class-wp-upgrader.php:426 +#: wp-admin/includes/class-wp-upgrader.php:734 +msgid "Downloading install package from %s…" +msgstr "" +"Téléchargement de l’archive d’installation depuis %s…" + +#: wp-admin/includes/class-wp-upgrader.php:427 +#: wp-admin/includes/class-wp-upgrader.php:735 +msgid "Unpacking the package…" +msgstr "Décompression de l’archive de l’extension…" + +#: wp-admin/includes/class-wp-upgrader.php:428 +msgid "Installing the plugin…" +msgstr "Installation de l’extension…" + +#: wp-admin/includes/class-wp-upgrader.php:429 +msgid "The plugin contains no files." +msgstr "Cette extension ne contient aucun fichier." + +#: wp-admin/includes/class-wp-upgrader.php:430 +msgid "Plugin install failed." +msgstr "L’installation de l’extension a échoué." + +#: wp-admin/includes/class-wp-upgrader.php:431 +msgid "Plugin installed successfully." +msgstr "L’extension a bien été installée." + +#: wp-admin/includes/class-wp-upgrader.php:638 +msgid "No valid plugins were found." +msgstr "Aucune extension valide trouvée." + +#: wp-admin/includes/class-wp-upgrader.php:722 +msgid "The theme is at the latest version." +msgstr "Vous avez la dernière version de ce thème." + +#: wp-admin/includes/class-wp-upgrader.php:726 +msgid "Removing the old version of the theme…" +msgstr "Retrait de l’ancienne version du thème…" + +#: wp-admin/includes/class-wp-upgrader.php:727 +msgid "Could not remove the old theme." +msgstr "Impossible de supprimer l’ancien thème." + +#: wp-admin/includes/class-wp-upgrader.php:728 +msgid "Theme update failed." +msgstr "La mise à jour du thème a échoué." + +#: wp-admin/includes/class-wp-upgrader.php:729 +msgid "Theme updated successfully." +msgstr "Le thème a bien été mis à jour." + +#: wp-admin/includes/class-wp-upgrader.php:736 +msgid "Installing the theme…" +msgstr "Installation du thème…" + +#: wp-admin/includes/class-wp-upgrader.php:737 +msgid "The theme contains no files." +msgstr "Ce thème ne contient aucun fichier." + +#: wp-admin/includes/class-wp-upgrader.php:738 +msgid "Theme install failed." +msgstr "L’installation du thème a échoué." + +#: wp-admin/includes/class-wp-upgrader.php:739 +msgid "Theme installed successfully." +msgstr "Le thème a bien été installé." + +#. translators: 1: theme name, 2: version +#: wp-admin/includes/class-wp-upgrader.php:741 +msgid "Successfully installed the theme %1$s %2$s." +msgstr "Le thème %1$s %2$s a bien été installé." + +#: wp-admin/includes/class-wp-upgrader.php:742 +msgid "This theme requires a parent theme. Checking if it is installed…" +msgstr "" +"Ce thème nécessite un thème parent. Nous vérifions s’il est " +"installé…" + +#. translators: 1: theme name, 2: version +#: wp-admin/includes/class-wp-upgrader.php:744 +msgid "Preparing to install %1$s %2$s…" +msgstr "" +"Préparation à l’installation de %1$s %2$s…" + +#. translators: 1: theme name, 2: version +#: wp-admin/includes/class-wp-upgrader.php:746 +msgid "The parent theme, %1$s %2$s, is currently installed." +msgstr "Le thème parent, %1$s %2$s, est bien installé." + +#. translators: 1: theme name, 2: version +#: wp-admin/includes/class-wp-upgrader.php:748 +msgid "Successfully installed the parent theme, %1$s %2$s." +msgstr "Le thème parent, %1$s %2$s, a bien été installé." + +#: wp-admin/includes/class-wp-upgrader.php:749 +msgid "" +"The parent theme could not be found. You will need to " +"install the parent theme, %s, before you can use this child " +"theme." +msgstr "" +"Le thème parent n’a pas pu être trouvé. Vous allez " +"devoir installer le thème parent, %s, avant de pouvoir " +"utiliser ce thème enfant." + +#: wp-admin/includes/class-wp-upgrader.php:1015 +msgid "The theme is missing the style.css stylesheet." +msgstr "Il manque le fichier style.css à ce thème." + +#: wp-admin/includes/class-wp-upgrader.php:1020 +msgid "" +"The style.css stylesheet doesn't contain a valid theme header." +msgstr "" +"Le fichier style.css ne contient pas un en-tête valide de thème." + +#: wp-admin/includes/class-wp-upgrader.php:1024 +msgid "The theme is missing the index.php file." +msgstr "Il manque le fichier index.php au thème." + +#: wp-admin/includes/class-wp-upgrader.php:1132 +msgid "" +"Some of your translations need updating. Sit tight for a few more seconds " +"while we update them as well." +msgstr "" +"Certaines de vos traductions ont besoin d’être mises à jour. Patientez " +"encore quelques secondes, le temps que nous les mettions également à jour." + +#: wp-admin/includes/class-wp-upgrader.php:1133 +msgid "The translation is up to date." +msgstr "La traduction est à jour." + +#: wp-admin/includes/class-wp-upgrader.php:1135 +msgid "Downloading translation from %s…" +msgstr "" +"Téléchargement de la traduction depuis %s…" + +#: wp-admin/includes/class-wp-upgrader.php:1137 +msgid "Translation update failed." +msgstr "La mise à jour de la traduction a échoué." + +#: wp-admin/includes/class-wp-upgrader.php:1138 +msgid "Translation updated successfully." +msgstr "La traduction a bien été mise à jour." + +#: wp-admin/includes/class-wp-upgrader.php:1269 +msgid "" +"The language pack is missing either the .po or .mo " +"files." +msgstr "" +"Il manque les fichiers .po et/ou .mo du pack de " +"langue." + +#: wp-admin/includes/class-wp-upgrader.php:1306 +msgid "WordPress is at the latest version." +msgstr "Vous avez la dernière version de WordPress." + +#: wp-admin/includes/class-wp-upgrader.php:1310 +msgid "Could not copy files." +msgstr "Impossible de copier les fichiers." + +#: wp-admin/includes/class-wp-upgrader.php:1311 wp-admin/includes/file.php:628 +#: wp-admin/includes/file.php:730 +msgid "Could not copy files. You may have run out of disk space." +msgstr "" +"Impossible de copier les fichiers. Il se pourrait que vous manquiez de place." + +#: wp-admin/includes/class-wp-upgrader.php:1312 +msgid "Attempting to roll back to previous version." +msgstr "Tentative de retour à la version précédente." + +#: wp-admin/includes/class-wp-upgrader.php:1313 +msgid "" +"Due to an error during updating, WordPress has rolled back to your previous " +"version." +msgstr "" +"Suite à une erreur pendant la mise à jour, WordPress vous a ramené à votre " +"version précédente." + +#: wp-admin/includes/class-wp-upgrader.php:1374 +#: wp-admin/includes/update-core.php:664 wp-admin/includes/update-core.php:732 +msgid "" +"The update cannot be installed because we will be unable to copy some files. " +"This is usually due to inconsistent file permissions." +msgstr "" +"La mise à jour ne peut pas être installée parce que nous n'allons pas " +"pouvoir copier certains fichiers. Ce problème est généralement dû à des " +"incohérences dans les permissions de fichiers." + +#: wp-admin/includes/class-wp-upgrader.php:1558 +#: wp-admin/includes/class-wp-upgrader.php:1592 +msgid "Please select a file" +msgstr "Veuillez choisir un fichier" + +#: wp-admin/includes/class-wp-upgrader.php:1873 +msgid "Updating to WordPress %s" +msgstr "Mise à jour vers WordPress %s" + +#: wp-admin/includes/class-wp-upgrader.php:1874 +msgid "WordPress %s" +msgstr "WordPress %s" + +#: wp-admin/includes/class-wp-upgrader.php:1879 +msgid "Updating theme: %s" +msgstr "Mise à jour du thème : %s" + +#: wp-admin/includes/class-wp-upgrader.php:1884 +msgid "Updating plugin: %s" +msgstr "Mise à jour de l’extension : %s" + +#: wp-admin/includes/class-wp-upgrader.php:1888 +msgid "Translations for %s" +msgstr "Traductions pour %s" + +#: wp-admin/includes/class-wp-upgrader.php:1903 wp-admin/update-core.php:413 +msgid "Installation Failed" +msgstr "Échec de l’installation" + +#: wp-admin/includes/class-wp-upgrader.php:1905 +#: wp-admin/includes/update-core.php:984 wp-admin/update-core.php:418 +msgid "WordPress updated successfully" +msgstr "WordPress a bien été mis à jour" + +# Pas d'entité HTML : envoyé par mail. +#. translators: 1: Site name, 2: WordPress version number. +#: wp-admin/includes/class-wp-upgrader.php:2158 +msgid "[%1$s] Your site has updated to WordPress %2$s" +msgstr "[%1$s] Votre site a été mis à jour vers WordPress %2$s" + +# Pas d'entité HTML : envoyé par mail. +#. translators: 1: Site name, 2: WordPress version number. +#: wp-admin/includes/class-wp-upgrader.php:2164 +msgid "[%1$s] WordPress %2$s is available. Please update!" +msgstr "[%1$s] WordPress %2$s est disponible. Veuillez faire une mise à jour !" + +# Pas d'entité HTML : envoyé par mail. +#. translators: 1: Site name. +#: wp-admin/includes/class-wp-upgrader.php:2169 +msgid "[%1$s] URGENT: Your site may be down due to a failed update" +msgstr "" +"[%1$s] URGENT : suite à une mise à jour échouée, votre site est peut-être " +"inaccessible." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2184 +msgid "" +"Howdy! Your site at %1$s has been updated automatically to WordPress %2$s." +msgstr "" +"Salutations ! Votre site à l'adresse %1$s a été automatiquement mis à jour " +"vers WordPress %2$s." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2187 +msgid "No further action is needed on your part." +msgstr "Vous n'avez rien de plus à faire." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2191 +msgid "For more on version %s, see the About WordPress screen:" +msgstr "" +"Pour en savoir plus sur la version %s, lisez l'écran À Propos de WordPress : " + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2195 +msgid "WordPress %s is also now available." +msgstr "WordPress %s est disponible." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2196 +#: wp-admin/includes/class-wp-upgrader.php:2213 +msgid "Updating is easy and only takes a few moments:" +msgstr "La mise à jour est facile et ne requiert que quelques secondes :" + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2204 +msgid "Please update your site at %1$s to WordPress %2$s." +msgstr "" +"Veuillez mettre à jour votre site à l'adresse %s1$s pour le passer à " +"WordPress %2$s." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2211 +msgid "We tried but were unable to update your site automatically." +msgstr "" +"Malgré nos tentatives, nous n'avons pas pu mettre votre site à jour " +"automatiquement." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2219 +msgid "" +"Your site at %1$s experienced a critical failure while trying to update " +"WordPress to version %2$s." +msgstr "" +"Votre site à l'adresse %1$s a fait face à un échec critique en essayant de " +"faire une mise à jour de WordPress vers la version %2$s." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2221 +msgid "" +"Your site at %1$s experienced a critical failure while trying to update to " +"the latest version of WordPress, %2$s." +msgstr "" +"Votre site à l'adresse %1$s a fait face à un échec critique en essayant de " +"faire une mise à jour vers la dernière version de WordPress, la %2$s." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2223 +msgid "" +"This means your site may be offline or broken. Don't panic; this can be " +"fixed." +msgstr "" +"Cela signifie que votre site est peut-être hors ligne ou cassé. Ne paniquez " +"pas, cela peut être réparé." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2225 +msgid "" +"Please check out your site now. It's possible that everything is working. If " +"it says you need to update, you should do so:" +msgstr "" +"Veuillez vérifier votre site immédiatelement. Il se peut que tout " +"fonctionne. S'il affiche que vous devez faire une mise à jour, vous devriez " +"suivre son conseil :" + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2232 +msgid "" +"Keeping your site updated is important for security. It also makes the " +"internet a safer place for you and your readers." +msgstr "" +"Pour des questions de sécurité, il est important de garder votre site à " +"jour. Par ailleurs, cela rend le Web plus sûr pour vous et vos lecteurs." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2235 +msgid "" +"If you experience any issues or need support, the volunteers in the " +"WordPress.org support forums may be able to help." +msgstr "" +"Si vous rencontrez des problèmes ou avez besoin d'assistance, les " +"volontaires du forum d'entraide de WordPress-fr.net devraient pouvoir vous " +"aider." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2240 +msgid "" +"You also have some plugins or themes with updates available. Update them now:" +msgstr "" +"Certains de vos thèmes et extensions ont également des mises à jour " +"disponibles. Veuillez les mettre à jour dès maintenant :" + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2244 +msgid "The WordPress Team" +msgstr "L'équipe WordPress" + +#: wp-admin/includes/class-wp-upgrader.php:2248 +msgid "Your site was running version %s." +msgstr "Votre site utilise la version %s." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2249 +msgid "We have some data that describes the error your site encountered." +msgstr "" +"Nous avons quelques données qui décrivent l'erreur que votre site a " +"rencontré." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2250 +msgid "" +"Your hosting company, support forum volunteers, or a friendly developer may " +"be able to use this information to help you:" +msgstr "" +"Votre hébergeur, les volontaires du forum d'entraide ou un ami développeur " +"devraient pouvoir vous aider à comprendre cette information pour vous aider :" + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/includes/class-wp-upgrader.php:2263 +msgid "Error code: %s" +msgstr "Code d'erreur : %s" + +#: wp-admin/includes/class-wp-users-list-table.php:79 +msgid "No matching users were found." +msgstr "Aucun utilisateur ne correspond." + +#. translators: User role name with count +#: wp-admin/includes/class-wp-users-list-table.php:115 +msgid "%1$s (%2$s)" +msgstr "%1$s (%2$s)" + +#: wp-admin/includes/class-wp-users-list-table.php:142 +#: wp-admin/includes/class-wp-users-list-table.php:144 +msgid "Change role to…" +msgstr "Changer de rôle pour…" + +#: wp-admin/includes/class-wp-users-list-table.php:148 +msgid "Change" +msgstr "Changer" + +#: wp-admin/includes/class-wp-users-list-table.php:168 +#: wp-admin/user-edit.php:249 wp-admin/user-new.php:300 +#: wp-admin/user-new.php:411 +msgid "Role" +msgstr "Rôle" + +#: wp-admin/includes/class-wp-users-list-table.php:306 +msgid "View posts by this author" +msgstr "Afficher les articles de cet auteur" + +#: wp-admin/includes/dashboard.php:33 +msgid "You are using an insecure browser!" +msgstr "Vous utilisez un navigateur peu sûr !" + +#: wp-admin/includes/dashboard.php:35 +msgid "Your browser is out of date!" +msgstr "Votre navigateur est obsolète !" + +#: wp-admin/includes/dashboard.php:40 wp-admin/includes/dashboard.php:43 +msgid "Right Now" +msgstr "Aujourd’hui" + +#: wp-admin/includes/dashboard.php:70 +msgid "Incoming Links" +msgstr "Liens entrants" + +#: wp-admin/includes/dashboard.php:79 +msgid "QuickPress" +msgstr "Press-Minute" + +#: wp-admin/includes/dashboard.php:83 +msgid "Recent Drafts" +msgstr "Brouillons récents" + +#: wp-admin/includes/dashboard.php:89 +msgid "http://wordpress.org/news/" +msgstr "http://www.wordpress-fr.net/" + +#: wp-admin/includes/dashboard.php:90 +msgid "http://wordpress.org/news/feed/" +msgstr "http://feeds.feedburner.com/WordpressFrancophone" + +#: wp-admin/includes/dashboard.php:91 +msgid "WordPress Blog" +msgstr "Blog WordPress" + +#: wp-admin/includes/dashboard.php:104 +msgid "http://planet.wordpress.org/" +msgstr "http://www.wordpress-fr.net/planet/" + +#: wp-admin/includes/dashboard.php:105 +msgid "http://planet.wordpress.org/feed/" +msgstr "http://feeds2.feedburner.com/WordpressFrancophonePlanet" + +#: wp-admin/includes/dashboard.php:106 +msgid "Other WordPress News" +msgstr "Autres actualités de WordPress (en français)" + +#: wp-admin/includes/dashboard.php:129 wp-admin/includes/dashboard.php:602 +msgid "View all" +msgstr "Afficher tout" + +#: wp-admin/includes/dashboard.php:163 +msgid "Configure" +msgstr "Configurer" + +#: wp-admin/includes/dashboard.php:245 +msgid "Post" +msgid_plural "Posts" +msgstr[0] "Article" +msgstr[1] "Articles" + +#: wp-admin/includes/dashboard.php:273 +msgid "Page" +msgid_plural "Pages" +msgstr[0] "Page" +msgstr[1] "Pages" + +#: wp-admin/includes/dashboard.php:285 +msgid "Category" +msgid_plural "Categories" +msgstr[0] "Catégorie" +msgstr[1] "Catégories" + +#: wp-admin/includes/dashboard.php:297 +msgid "Tag" +msgid_plural "Tags" +msgstr[0] "Mot-clé" +msgstr[1] "Mots-clés" + +#: wp-admin/includes/dashboard.php:315 +msgid "Comment" +msgid_plural "Comments" +msgstr[0] "Commentaire" +msgstr[1] "Commentaires" + +#: wp-admin/includes/dashboard.php:327 +msgctxt "Right Now" +msgid "Approved" +msgid_plural "Approved" +msgstr[0] "Approuvé" +msgstr[1] "Approuvés" + +#: wp-admin/includes/dashboard.php:339 +msgid "Pending" +msgid_plural "Pending" +msgstr[0] "En attente" +msgstr[1] "En attente" + +#: wp-admin/includes/dashboard.php:351 +msgctxt "comment" +msgid "Spam" +msgid_plural "Spam" +msgstr[0] "Indésirable" +msgstr[1] "Indésirables" + +#: wp-admin/includes/dashboard.php:371 wp-admin/themes.php:146 +msgid "ERROR: %s" +msgstr "ERREUR : %s" + +#: wp-admin/includes/dashboard.php:387 +msgid "" +"Theme %1$s with %2$s Widget" +msgid_plural "" +"Theme %1$s with %2$s Widgets" +msgstr[0] "" +"Thème %1$s avec %2$s widget" +msgstr[1] "" +"Thème %1$s avec %2$s widgets" + +#: wp-admin/includes/dashboard.php:389 +msgid "" +"Theme %1$s with %2$s Widget" +msgid_plural "" +"Theme %1$s with %2$s Widgets" +msgstr[0] "" +"Thème %1$s avec %2$s widget" +msgstr[1] "" +"Thème %1$s avec %2$s widgets" + +#: wp-admin/includes/dashboard.php:393 +msgid "Theme %1$s" +msgstr "Thème %1$s" + +#: wp-admin/includes/dashboard.php:395 +msgid "Theme %1$s" +msgstr "Thème %1$s" + +#: wp-admin/includes/dashboard.php:401 +msgid "Your site is asking search engines not to index its content" +msgstr "" +"Votre site indique aux moteurs de recherche de ne pas indexer son contenu" + +#: wp-admin/includes/dashboard.php:402 +msgid "Search Engines Discouraged" +msgstr "Moteurs de recherche refusés" + +#: wp-admin/includes/dashboard.php:417 wp-admin/includes/ms.php:682 +msgid "Create a New Site" +msgstr "Créer un nouveau site" + +#: wp-admin/includes/dashboard.php:419 +msgid "Create a New User" +msgstr "Créer un nouvel utilisateur" + +#: wp-admin/includes/dashboard.php:424 +msgid "%s user" +msgid_plural "%s users" +msgstr[0] "%s utilisateur" +msgstr[1] "%s utilisateurs" + +#: wp-admin/includes/dashboard.php:425 +msgid "%s site" +msgid_plural "%s sites" +msgstr[0] "%s site" +msgstr[1] "%s sites" + +#: wp-admin/includes/dashboard.php:427 +msgid "You have %1$s and %2$s." +msgstr "Vous avez %1$s et %2$s." + +#: wp-admin/includes/dashboard.php:446 wp-admin/users.php:446 +msgid "Search Users" +msgstr "Chercher un utilisateur" + +#: wp-admin/includes/dashboard.php:453 +msgid "Search Sites" +msgstr "Chercher un site" + +#: wp-admin/includes/dashboard.php:470 +msgid "" +"Post published. View post | Edit post" +msgstr "" +"Article publié. Afficher l’article | Modifier l’article" + +#: wp-admin/includes/dashboard.php:472 +msgid "" +"Post submitted. Preview post | Edit post" +msgstr "" +"Article envoyé. Prévisualiser l’article | Modifier l’article" + +#: wp-admin/includes/dashboard.php:474 +msgid "" +"Draft saved. Preview post | Edit post" +msgstr "" +"Brouillon enregistré. Afficher l’article | Modifier l’article" + +#: wp-admin/includes/dashboard.php:487 +msgid "You can also try %s, easy blogging from anywhere on the Web." +msgstr "" +"Vous pouvez aussi essayer %s, qui simplifie la création d’articles " +"depuis n’importe où sur le Web." + +#: wp-admin/includes/dashboard.php:487 wp-admin/options-writing.php:27 +#: wp-admin/options-writing.php:123 wp-admin/options-writing.php:127 +#: wp-admin/press-this.php:302 wp-admin/press-this.php:462 +#: wp-admin/tools.php:16 wp-admin/tools.php:41 wp-admin/tools.php:46 +msgid "Press This" +msgstr "Publier un article" + +#: wp-admin/includes/dashboard.php:550 +msgid "Tags (separate with commas)" +msgstr "Mots-clés (séparés par des virgules)" + +#: wp-admin/includes/dashboard.php:556 wp-admin/includes/meta-boxes.php:233 +#: wp-admin/includes/meta-boxes.php:234 wp-admin/press-this.php:471 +msgid "Submit for Review" +msgstr "Soumettre à relecture" + +#: wp-admin/includes/dashboard.php:564 +msgid "Reset" +msgstr "Réinitialiser" + +#: wp-admin/includes/dashboard.php:605 +msgid "There are no drafts at the moment" +msgstr "Il n’y a pas de brouillon actuellement" + +#. translators: 1: comment author, 2: post link, 3: notification if the comment +#. is pending +#: wp-admin/includes/dashboard.php:719 +msgid "From %1$s on %2$s%3$s" +msgstr "Par %1$s, sur %2$s%3$s" + +#: wp-admin/includes/dashboard.php:720 +msgid "[Pending]" +msgstr "[En attente]" + +#. translators: %1$s is type of comment, %2$s is link to the post +#: wp-admin/includes/dashboard.php:739 +msgctxt "dashboard" +msgid "%1$s on %2$s" +msgstr "%1$s dans %2$s" + +#: wp-admin/includes/dashboard.php:798 +msgid "" +"This dashboard widget queries Google Blog Search so that when another blog links to your site it " +"will show up here. It has found no incoming links… yet. It’s " +"okay — there is no rush." +msgstr "" +"Ce widget envoie une requête vers le moteur de recherche des blogs de Google, de sorte que quand un " +"autre site fera un lien vers le vôtre, son nom s’affichera ici. Ce " +"moteur n’a pas encore trouvé de lien entrant… Ce n’est " +"pas grave, on n’est pas pressé." + +#: wp-admin/includes/dashboard.php:822 wp-admin/includes/dashboard.php:824 +msgid "Somebody" +msgstr "Quelqu’un" + +#. translators: incoming links feed, %1$s is other person, %3$s is content +#: wp-admin/includes/dashboard.php:836 +msgid "%1$s linked here saying, \"%3$s\"" +msgstr "" +"%1$s a fait un lien vers ce site en écrivant «" +" %3$s »" + +#. translators: incoming links feed, %1$s is other person, %3$s is content +#: wp-admin/includes/dashboard.php:839 +msgid "%1$s linked here saying, \"%3$s\"" +msgstr "%1$s a fait un lien vers ce site en écrivant « %3$s »" + +#. translators: incoming links feed, %1$s is other person, %3$s is content, +#. %4$s is the date +#: wp-admin/includes/dashboard.php:844 +msgid "%1$s linked here saying, \"%3$s\" on %4$s" +msgstr "" +"%1$s a fait un lien vers ce site en écrivant «" +" %3$s », le %4$s" + +#. translators: incoming links feed, %1$s is other person, %3$s is content, +#. %4$s is the date +#: wp-admin/includes/dashboard.php:847 +msgid "%1$s linked here saying, \"%3$s\" on %4$s" +msgstr "" +"%1$s a fait un lien vers ce site en écrivant « %3$s », le %4$s" + +#: wp-admin/includes/dashboard.php:947 +msgid "Most Popular" +msgstr "Plus populaire" + +#: wp-admin/includes/dashboard.php:947 +msgid "Newest Plugins" +msgstr "Nouvelles extensions" + +#: wp-admin/includes/dashboard.php:1024 +msgid "Loading…" +msgstr "Chargement…" + +#: wp-admin/includes/dashboard.php:1024 +msgid "This widget requires JavaScript." +msgstr "Ce widget requiert JavaScript." + +#: wp-admin/includes/dashboard.php:1145 +msgid "Storage Space" +msgstr "Espace disque" + +#: wp-admin/includes/dashboard.php:1149 +msgid "" +"%2$sMB" +msgstr "" +"%2$s Mo" + +#: wp-admin/includes/dashboard.php:1150 +msgid "Space Allowed" +msgstr "Espace disque alloué" + +#: wp-admin/includes/dashboard.php:1157 +msgid "" +"%2$sMB (%3$s%%)" +"" +msgstr "" +"%2$s Mo (%3$s" +"%%)" + +#: wp-admin/includes/dashboard.php:1158 +msgid "Space Used" +msgstr "Espace disque utilisé" + +#: wp-admin/includes/dashboard.php:1174 +msgid "" +"It looks like you're using an insecure version of %s. Using " +"an outdated browser makes your computer unsafe. For the best WordPress " +"experience, please update your browser." +msgstr "" +"Il semble que vous utilisez une version peu sûre de %s. Un " +"navigateur dépassé met votre ordinateur en danger. Pour utiliser WordPress " +"dans des conditions optimales, veuillez mettre à jour votre navigateur." + +#: wp-admin/includes/dashboard.php:1176 +msgid "" +"It looks like you're using an old version of %s. For the " +"best WordPress experience, please update your browser." +msgstr "" +"Il semble que vous utilisez une vieille version de %s. Pour " +"utiliser WordPress dans des conditions optimales, veuillez mettre à jour " +"votre navigateur." + +#: wp-admin/includes/dashboard.php:1193 +msgid "" +"Update %2$s or learn how " +"to browse happy" +msgstr "" +"Mettez %2$s à jour, ou " +"apprenez à naviguer " +"sereinement" + +#: wp-admin/includes/dashboard.php:1271 +msgid "Welcome to WordPress!" +msgstr "Bienvenue dans WordPress !" + +#: wp-admin/includes/dashboard.php:1272 +msgid "We’ve assembled some links to get you started:" +msgstr "Voici quelques liens pour vous aider à démarrer :" + +#: wp-admin/includes/dashboard.php:1275 +msgid "Get Started" +msgstr "Lancez-vous !" + +#: wp-admin/includes/dashboard.php:1276 wp-admin/includes/dashboard.php:1277 +msgid "Customize Your Site" +msgstr "Personnalisez votre site" + +#: wp-admin/includes/dashboard.php:1279 +msgid "or, change your theme completely" +msgstr "ou alors, changez complètement de thème" + +#: wp-admin/includes/dashboard.php:1283 +msgid "Next Steps" +msgstr "Étapes suivantes" + +#: wp-admin/includes/dashboard.php:1286 wp-admin/includes/dashboard.php:1289 +msgid "Edit your front page" +msgstr "Modifiez votre page d’accueil" + +#: wp-admin/includes/dashboard.php:1287 wp-admin/includes/dashboard.php:1290 +msgid "Add additional pages" +msgstr "Ajoutez de nouvelles pages" + +#: wp-admin/includes/dashboard.php:1291 +msgid "Add a blog post" +msgstr "Écrivez un article" + +#: wp-admin/includes/dashboard.php:1293 +msgid "Write your first blog post" +msgstr "Écrivez votre premier article" + +#: wp-admin/includes/dashboard.php:1294 +msgid "Add an About page" +msgstr "Ajoutez une page « Ã€ propos »" + +#: wp-admin/includes/dashboard.php:1296 +msgid "View your site" +msgstr "Affichez votre site" + +#: wp-admin/includes/dashboard.php:1300 +msgid "More Actions" +msgstr "Plus d’actions" + +#: wp-admin/includes/dashboard.php:1302 +msgid "Manage widgets or menus" +msgstr "" +"Gérez vos widgets ou vos menus" + +#: wp-admin/includes/dashboard.php:1303 +msgid "Turn comments on or off" +msgstr "Activez ou désactivez les commentaires" + +#: wp-admin/includes/dashboard.php:1304 +msgid "Learn more about getting started" +msgstr "Plus d’informations pour bien démarrer" + +#: wp-admin/includes/dashboard.php:1304 +msgid "http://codex.wordpress.org/First_Steps_With_WordPress" +msgstr "http://codex.wordpress.org/fr:Premiers_pas_avec_WordPress" + +#: wp-admin/includes/deprecated.php:557 +msgid "No matching users were found!" +msgstr "Aucun utilisateur ne correspond !" + +#: wp-admin/includes/deprecated.php:594 +msgid "Displaying %s–%s of %s" +msgstr "Affichage de %s à %s sur %s" + +#: wp-admin/includes/file.php:13 +msgid "Main Index Template" +msgstr "Modèle pour la page d’accueil" + +#: wp-admin/includes/file.php:15 +msgid "Visual Editor Stylesheet" +msgstr "Feuille de style de l’éditeur visuel" + +#: wp-admin/includes/file.php:16 +msgid "Visual Editor RTL Stylesheet" +msgstr "" +"Feuille de style de l’éditeur visuel (lecture de droite à gauche)" + +#: wp-admin/includes/file.php:17 +msgid "RTL Stylesheet" +msgstr "Feuille de style RTL" + +#: wp-admin/includes/file.php:19 +msgid "Popup Comments" +msgstr "Commentaires en popup" + +#: wp-admin/includes/file.php:20 +msgid "Footer" +msgstr "Pied de page" + +#: wp-admin/includes/file.php:24 +msgid "Author Template" +msgstr "Modèle pour un auteur" + +#: wp-admin/includes/file.php:25 +msgid "Tag Template" +msgstr "Modèle pour mot-clé" + +#: wp-admin/includes/file.php:26 +msgid "Category Template" +msgstr "Modèle pour les catégories" + +#: wp-admin/includes/file.php:27 wp-admin/includes/meta-boxes.php:663 +msgid "Page Template" +msgstr "Modèle de page" + +#: wp-admin/includes/file.php:29 +msgid "Search Form" +msgstr "Formulaire de recherche" + +#: wp-admin/includes/file.php:30 +msgid "Single Post" +msgstr "Article seul" + +#: wp-admin/includes/file.php:31 +msgid "404 Template" +msgstr "Modèle pour l’erreur 404" + +#: wp-admin/includes/file.php:32 +msgid "Links Template" +msgstr "Modèle pour les liens" + +#: wp-admin/includes/file.php:33 +msgid "Theme Functions" +msgstr "Fonctions du thème" + +#: wp-admin/includes/file.php:34 +msgid "Attachment Template" +msgstr "Modèle pour les fichiers attachés" + +#: wp-admin/includes/file.php:35 +msgid "Image Attachment Template" +msgstr "Modèle pour les images attachées" + +#: wp-admin/includes/file.php:36 +msgid "Video Attachment Template" +msgstr "Modèle pour les vidéos attachées" + +#: wp-admin/includes/file.php:37 +msgid "Audio Attachment Template" +msgstr "Modèle pour les fichiers audio attachés" + +#: wp-admin/includes/file.php:38 +msgid "Application Attachment Template" +msgstr "Modèle pour les programmes attachés" + +#: wp-admin/includes/file.php:39 +msgid "my-hacks.php (legacy hacks support)" +msgstr "my-hacks.php (reconnaissance des hacks existants)" + +#: wp-admin/includes/file.php:40 +msgid ".htaccess (for rewrite rules )" +msgstr ".htaccess (pour les règles de réécriture)" + +#: wp-admin/includes/file.php:43 +msgid "Comments Template" +msgstr "Modèle pour les commentaires" + +#: wp-admin/includes/file.php:44 +msgid "Popup Comments Template" +msgstr "Modèle pour la fenêtre de commentaires" + +#: wp-admin/includes/file.php:67 +msgid "%s Page Template" +msgstr "Modèle de page %s" + +#: wp-admin/includes/file.php:180 +msgid "" +"Sorry, can’t edit files with “..” in the name. If you are " +"trying to edit a file in your WordPress home directory, you can just type " +"the name of the file in." +msgstr "" +"Désolé, on ne peut pas modifier les fichiers avec « .. » dans le " +"nom. Si vous tentez de modifier un fichier dans votre répertoire WordPress, " +"vous pouvez simplement saisir le nom du fichier." + +#: wp-admin/includes/file.php:234 +msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini." +msgstr "" +"La taille du fichier envoyé excède celle indiquée dans la directive " +"upload_max_filesize, dans php.ini." + +#: wp-admin/includes/file.php:235 +msgid "" +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in " +"the HTML form." +msgstr "" +"La taille du fichier envoyé excède celle indiquée dans la directive " +"MAX_FILE_SIZE du formulaire HTML." + +#: wp-admin/includes/file.php:236 wp-admin/includes/file.php:369 +msgid "The uploaded file was only partially uploaded." +msgstr "Le fichier n’a été que partiellement envoyé." + +#: wp-admin/includes/file.php:237 wp-admin/includes/file.php:370 +msgid "No file was uploaded." +msgstr "Aucun fichier n’a été envoyé." + +#: wp-admin/includes/file.php:239 wp-admin/includes/file.php:372 +msgid "Missing a temporary folder." +msgstr "Un dossier temporaire est manquant." + +#: wp-admin/includes/file.php:240 wp-admin/includes/file.php:373 +msgid "Failed to write file to disk." +msgstr "Échec de l’écriture du fichier sur le disque." + +#: wp-admin/includes/file.php:241 wp-admin/includes/file.php:374 +msgid "File upload stopped by extension." +msgstr "L’envoi de fichier est arrêté par l’extension." + +#: wp-admin/includes/file.php:258 wp-admin/includes/file.php:390 +msgid "Invalid form submission." +msgstr "Envoi non valide du formulaire." + +#: wp-admin/includes/file.php:267 +msgid "File is empty. Please upload something more substantial." +msgstr "" +"Le fichier est vide. Merci d’envoyer quelque chose de plus consistant." + +#: wp-admin/includes/file.php:269 wp-admin/includes/import.php:63 +msgid "" +"File is empty. Please upload something more substantial. This error could " +"also be caused by uploads being disabled in your php.ini or by post_max_size " +"being defined as smaller than upload_max_filesize in php.ini." +msgstr "" +"Ce fichier est vide. Veuillez envoyer quelque chose de plus substantiel. " +"Cette erreur peut également être due à la désactivation de l’envoi de " +"fichier dans le fichier php.ini de votre serveur, ou par une valeur de " +"post_max_size inférieure à celle de upload_max_filesize dans ce même php.ini." + +#: wp-admin/includes/file.php:275 +msgid "Specified file failed upload test." +msgstr "Le test d’envoi du fichier spécifié a échoué." + +#: wp-admin/includes/file.php:288 wp-admin/includes/file.php:415 +msgid "Sorry, this file type is not permitted for security reasons." +msgstr "" +"Désolé, ce type de fichier n’est pas autorisé pour des raisons de " +"sécurité." + +#: wp-admin/includes/file.php:313 wp-admin/includes/file.php:441 +msgid "The uploaded file could not be moved to %s." +msgstr "Le fichier n’ a pas pu être déplacé vers %s." + +#: wp-admin/includes/file.php:367 +msgid "" +"The uploaded file exceeds the upload_max_filesize directive in " +"php.ini." +msgstr "" +"La taille du fichier envoyé excède celle indiquée dans la directive de " +"taille maximale autorisée, upload_max_filesize, dans php." +"ini." + +#: wp-admin/includes/file.php:368 +msgid "" +"The uploaded file exceeds the MAX_FILE_SIZE directive that was " +"specified in the HTML form." +msgstr "" +"La taille du fichier envoyé excède celle indiquée dans la directive " +"MAX_FILE_SIZE du formulaire HTML." + +#: wp-admin/includes/file.php:398 +msgid "" +"File is empty. Please upload something more substantial. This error could " +"also be caused by uploads being disabled in your php.ini." +msgstr "" +"Ce fichier est vide. Veuillez envoyer quelque chose de plus substantiel. " +"Cette erreur peut également être due à la désactivation de l’envoi de " +"fichier dans le fichier php.ini de votre serveur." + +#: wp-admin/includes/file.php:402 +msgid "Specified file does not exist." +msgstr "Le fichier spécifié n’existe pas." + +#: wp-admin/includes/file.php:470 +msgid "Invalid URL Provided." +msgstr "L’URL fournie est invalide" + +#: wp-admin/includes/file.php:474 +msgid "Could not create Temporary file." +msgstr "Impossible de créer le fichier temporaire." + +#: wp-admin/includes/file.php:522 +msgid "" +"The checksum of the file (%1$s) does not match the expected checksum value " +"(%2$s)." +msgstr "" +"L’empreinte de contrôle (ou checksum) de votre fichier (%1$s) " +"ne correspond pas à la valeur de l’empreinte attendue (%2$s)." + +#: wp-admin/includes/file.php:601 wp-admin/includes/file.php:705 +msgid "Incompatible Archive." +msgstr "Archive incompatible." + +#: wp-admin/includes/file.php:607 wp-admin/includes/file.php:656 +msgid "Could not retrieve file from archive." +msgstr "Impossible de récupérer le fichier depuis l’archive." + +#: wp-admin/includes/file.php:666 +msgid "Could not extract file from archive." +msgstr "Impossible d’extraire les fichiers depuis l’archive." + +#: wp-admin/includes/file.php:669 wp-admin/includes/file.php:766 +#: wp-admin/includes/file.php:799 wp-admin/includes/update-core.php:846 +#: wp-admin/includes/update-core.php:936 +msgid "Could not copy file." +msgstr "Impossible de copier le fichier." + +#: wp-admin/includes/file.php:708 +msgid "Empty archive." +msgstr "Archive vide." + +#: wp-admin/includes/file.php:1002 +msgid "" +"ERROR: There was an error connecting to the server, Please " +"verify the settings are correct." +msgstr "" +"Erreur : Une erreur s’est produite lors de la " +"connexion au serveur, vérifiez que vos paramètres sont corrects." + +#: wp-admin/includes/file.php:1010 +msgid "FTP" +msgstr "FTP" + +#: wp-admin/includes/file.php:1012 +msgid "FTPS (SSL)" +msgstr "FTPS (SSL)" + +#: wp-admin/includes/file.php:1014 +msgid "SSH2" +msgstr "SSH2" + +#: wp-admin/includes/file.php:1034 +msgid "Connection Information" +msgstr "Informations sur connexion" + +#: wp-admin/includes/file.php:1038 +msgid "" +"To perform the requested action, WordPress needs to access your web server." +msgstr "" +"Pour lancer la requête demandée, WordPress a besoin d’accéder à votre " +"serveur web." + +#: wp-admin/includes/file.php:1042 +msgid "Please enter your FTP or SSH credentials to proceed." +msgstr "Veuillez saisir votre identifiant FTP ou SSH pour continuer." + +#: wp-admin/includes/file.php:1043 +msgid "FTP/SSH Username" +msgstr "Identifiant FTP/SSH" + +#: wp-admin/includes/file.php:1044 +msgid "FTP/SSH Password" +msgstr "Mot de passe FTP/SSH" + +#: wp-admin/includes/file.php:1046 +msgid "Please enter your FTP credentials to proceed." +msgstr "Veuillez saisir votre identifiant FTP pour continuer." + +#: wp-admin/includes/file.php:1047 +msgid "FTP Username" +msgstr "Identifiant FTP" + +#: wp-admin/includes/file.php:1048 +msgid "FTP Password" +msgstr "Mot de passe FTP" + +#: wp-admin/includes/file.php:1052 +msgid "" +"If you do not remember your credentials, you should contact your web host." +msgstr "" +"Si vous ne vous souvenez pas de votre identifiant, vous devriez contacter " +"votre hébergeur." + +#: wp-admin/includes/file.php:1056 +msgid "Hostname" +msgstr "Nom de l’Hôte :" + +#: wp-admin/includes/file.php:1068 +msgid "This password will not be stored on the server." +msgstr "Le mot de passe ne sera pas stocké sur le serveur." + +#: wp-admin/includes/file.php:1073 +msgid "Authentication Keys" +msgstr "Clés d’authentification" + +#: wp-admin/includes/file.php:1075 +msgid "Public Key:" +msgstr "Clé publique :" + +#: wp-admin/includes/file.php:1076 +msgid "Private Key:" +msgstr "Clé privée :" + +#: wp-admin/includes/file.php:1079 +msgid "" +"Enter the location on the server where the keys are located. If a passphrase " +"is needed, enter that in the password field above." +msgstr "" +"Saisissez l’adresse du serveur où se trouvent les clés. Si un mot de " +"passe est nécessaire, saisissez-le dans le champ ci-dessus." + +#: wp-admin/includes/file.php:1084 wp-admin/includes/file.php:1086 +msgid "Connection Type" +msgstr "Type de connexion" + +#: wp-admin/includes/file.php:1105 +msgid "Proceed" +msgstr "Continuer" + +#: wp-admin/includes/image-edit.php:19 wp-admin/includes/image-edit.php:607 +msgid "Image data does not exist. Please re-upload the image." +msgstr "" +"Il n’y a pas de données d’image. Veuillez envoyer l’image " +"à nouveau." + +#: wp-admin/includes/image-edit.php:41 +msgid "Crop" +msgstr "Recadrer" + +# Pas d'entité HTML : attribut title="". +#: wp-admin/includes/image-edit.php:45 +msgid "Rotate counter-clockwise" +msgstr "Tourner dans le sens inverse des aiguilles d’une montre" + +# Pas d'entité HTML : attribut title="". +#: wp-admin/includes/image-edit.php:46 +msgid "Rotate clockwise" +msgstr "Tourner dans le sens des aiguilles d’une montre" + +#: wp-admin/includes/image-edit.php:48 +msgid "Image rotation is not supported by your web host." +msgstr "" +"La rotation d’image n’est pas disponible avec cet hébergeur." + +#: wp-admin/includes/image-edit.php:54 +msgid "Flip vertically" +msgstr "Inversion verticale" + +#: wp-admin/includes/image-edit.php:55 +msgid "Flip horizontally" +msgstr "Inversion horizontale" + +#: wp-admin/includes/image-edit.php:83 +msgid "Scale Image" +msgstr "Redimensionnement de l’image" + +#: wp-admin/includes/image-edit.php:85 +msgid "" +"You can proportionally scale the original image. For best results the " +"scaling should be done before performing any other operations on it like " +"crop, rotate, etc. Note that images can only be scaled down, not up." +msgstr "" +"Vous pouvez changer la taille de l’image originale de manière " +"proportionnelle. Pour obtenir un meilleur résultat, la modification devra " +"être faite avant toute autre opération sur l’image, comme le " +"recadrage, la rotation, etc. Notez bien que vous ne pouvez que réduire la " +"taille d’une image, pas l’agrandir." + +#: wp-admin/includes/image-edit.php:87 +msgid "Original dimensions %s" +msgstr "Taille originale : %s" + +#: wp-admin/includes/image-edit.php:102 +msgid "Discard any changes and restore the original image." +msgstr "Abandonner tout changement et rétablir l’image originale." + +#: wp-admin/includes/image-edit.php:105 +msgid "Previously edited copies of the image will not be deleted." +msgstr "" +"Les copies de l’image précédemment modifiées ne seront pas effacées." + +#: wp-admin/includes/image-edit.php:109 +msgid "Restore image" +msgstr "Rétablir l’image" + +#: wp-admin/includes/image-edit.php:120 +msgid "Image Crop" +msgstr "Recadrage de l’image" + +#: wp-admin/includes/image-edit.php:121 wp-admin/includes/image-edit.php:159 +msgid "(help)" +msgstr "(aide)" + +#: wp-admin/includes/image-edit.php:123 +msgid "" +"The image can be cropped by clicking on it and dragging to select the " +"desired part. While dragging the dimensions of the selection are displayed " +"below." +msgstr "" +"L’image peut être recadrée en cliquant dessus et en tirant une zone de " +"sélection sur la partie désirée. Les dimensions de la sélection sont " +"affichées ci-dessous." + +#: wp-admin/includes/image-edit.php:125 +msgid "Crop Aspect Ratio" +msgstr "Proportion de taille du recadrage" + +#: wp-admin/includes/image-edit.php:126 +msgid "" +"You can specify the crop selection aspect ratio then hold down the Shift key " +"while dragging to lock it. The values can be 1:1 (square), 4:3, 16:9, etc. " +"If there is a selection, specifying aspect ratio will set it immediately." +msgstr "" +"Vous pouvez préciser la proportion de taille de la sélection de recadrage en " +"maintenant la touche Shift enfoncée tandis que vous tirez la zone de " +"sélection avec la souris. Ses valeurs peuvent être 1:1 (carré), 4:3, 16:9, " +"etc. Si une sélection a déjà été faite, préciser la proportion l’" +"appliquera aussitôt." + +#: wp-admin/includes/image-edit.php:128 +msgid "Crop Selection" +msgstr "Sélection de recadrage" + +#: wp-admin/includes/image-edit.php:129 +msgid "" +"Once started, the selection can be adjusted by entering new values (in " +"pixels). Note that these values are scaled to approximately match the " +"original image dimensions. The minimum selection size equals the thumbnail " +"size as set in the Media settings." +msgstr "" +"Une fois commencée, la sélection peut être ajustée en entrant de nouvelles " +"valeurs (en pixels). Notez bien que ces valeurs sont ajustées pour " +"correspondre approximativement aux dimensions de l’image originale. La " +"taille minimale de la sélection est égale à la taille de la miniature, telle " +"que fixée dans les réglages des médias." + +#: wp-admin/includes/image-edit.php:134 +msgid "Aspect ratio:" +msgstr "Proportion de taille :" + +#: wp-admin/includes/image-edit.php:143 +msgid "Selection:" +msgstr "Sélection :" + +#: wp-admin/includes/image-edit.php:158 +msgid "Thumbnail Settings" +msgstr "Réglages de la miniature" + +#: wp-admin/includes/image-edit.php:160 +msgid "" +"The thumbnail image can be cropped differently. For example it can be square " +"or contain only a portion of the original image to showcase it better. Here " +"you can select whether to apply changes to all image sizes or make the " +"thumbnail different." +msgstr "" +"L’image miniature peut être recadrée de manière différente. Par " +"exemple, elle peut être au format carré, ou ne contenir qu’une partie " +"de l’image originale afin de mieux la présenter. Vous pouvez ici " +"sélectionner si vous souhaitez voir vos modifications appliquées à toutes " +"les tailles d’images, ou choisir d’avoir une miniature " +"différente." + +#: wp-admin/includes/image-edit.php:164 +msgid "Current thumbnail" +msgstr "Miniature actuelle" + +#: wp-admin/includes/image-edit.php:168 +msgid "Apply changes to:" +msgstr "Appliquer les modifications à :" + +#: wp-admin/includes/image-edit.php:172 +msgid "All image sizes" +msgstr "Toutes les tailles" + +#: wp-admin/includes/image-edit.php:180 +msgid "All sizes except thumbnail" +msgstr "Toutes les tailles sauf la miniature" + +# Pas d'entité HTML : alert() JavaScript +#: wp-admin/includes/image-edit.php:190 +msgid "" +"There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to " +"return to the Image Editor." +msgstr "" +"Les modifications qui n'ont pas été enregistrées seront perdues. « OK » pour " +"continuer, « Annuler » pour revenir à l'éditeur d'images." + +#: wp-admin/includes/image-edit.php:213 wp-admin/includes/image-edit.php:252 +#: wp-admin/includes/image-edit.php:352 +msgid "$image needs to be an WP_Image_Editor object" +msgstr "$image doit être un objet WP_Image_Editor" + +#: wp-admin/includes/image-edit.php:280 +msgid "Use WP_Image_Editor::rotate" +msgstr "Utilisez WP_Image_Editor::rotate" + +#: wp-admin/includes/image-edit.php:302 +msgid "Use WP_Image_Editor::flip" +msgstr "Utilisez WP_Image_Editor::flip" + +#: wp-admin/includes/image-edit.php:487 +msgid "Cannot load image metadata." +msgstr "Impossible de charger les métadonnées de l’image." + +#: wp-admin/includes/image-edit.php:542 +msgid "Cannot save image metadata." +msgstr "Impossible d’enregistrer les métadonnées de l’image." + +#: wp-admin/includes/image-edit.php:547 +msgid "Image metadata is inconsistent." +msgstr "Les métadonnées de l’image ne sont pas cohérentes." + +#: wp-admin/includes/image-edit.php:549 +msgid "Image restored successfully." +msgstr "L’image a bien été rétablie." + +#: wp-admin/includes/image-edit.php:568 +msgid "Unable to create new image." +msgstr "Échec lors de la création d’une nouvelle image." + +#: wp-admin/includes/image-edit.php:591 +msgid "" +"Error while saving the scaled image. Please reload the page and try again." +msgstr "" +"Une erreur est survenue pendant la modification de l’échelle de " +"l’image. Veuillez recharger la page pour faire une nouvelle tentative." + +#: wp-admin/includes/image-edit.php:599 +msgid "Nothing to save, the image has not changed." +msgstr "Rien à enregistrer, l’image n’a pas été modifiée." + +#: wp-admin/includes/image-edit.php:642 +msgid "Unable to save the image." +msgstr "Échec lors de l’enregistrement de l’image." + +#: wp-admin/includes/image-edit.php:732 +msgid "Image saved" +msgstr "Image enregistrée" + +#: wp-admin/includes/import.php:138 +msgid "Blogger" +msgstr "Blogger" + +#: wp-admin/includes/import.php:139 +msgid "" +"Install the Blogger importer to import posts, comments, and users from a " +"Blogger blog." +msgstr "" +"Installer l’importateur Blogger, pour importer les articles, " +"commentaires et utilisateurs d’un blog Blogger." + +#: wp-admin/includes/import.php:144 wp-admin/tools.php:21 +#: wp-admin/tools.php:60 +msgid "Categories and Tags Converter" +msgstr "Convertisseur de catégories et mots-clés" + +#: wp-admin/includes/import.php:145 +msgid "" +"Install the category/tag converter to convert existing categories to tags or " +"tags to categories, selectively." +msgstr "" +"Installer le convertisseur catégorie/mot-clé, pour convertir les catégories " +"en mots-clés, ou vice-versa." + +#: wp-admin/includes/import.php:150 +msgid "LiveJournal" +msgstr "LiveJournal" + +#: wp-admin/includes/import.php:151 +msgid "" +"Install the LiveJournal importer to import posts from LiveJournal using " +"their API." +msgstr "" +"Installer l’importateur LiveJournal, pour importer les articles depuis " +"un blog LiveJournal en utilisant leur API." + +#: wp-admin/includes/import.php:156 +msgid "Movable Type and TypePad" +msgstr "Movable Type et TypePad" + +#: wp-admin/includes/import.php:157 +msgid "" +"Install the Movable Type importer to import posts and comments from a " +"Movable Type or TypePad blog." +msgstr "" +"Installer l’importateur Movable Type, pour importer les articles et " +"commentaires en provenance d’un blog Movable Type ou TypePad." + +#: wp-admin/includes/import.php:162 +msgid "Blogroll" +msgstr "Liens" + +#: wp-admin/includes/import.php:163 +msgid "Install the blogroll importer to import links in OPML format." +msgstr "" +"Installer l’importateur de blogoliste, pour importer une liste de " +"liens au format OPML." + +#: wp-admin/includes/import.php:169 +msgid "Install the RSS importer to import posts from an RSS feed." +msgstr "" +"Installer l’importateur RSS, pour importer des articles à partir " +"d’un flux RSS." + +#: wp-admin/includes/import.php:174 +msgid "Tumblr" +msgstr "Tumblr" + +#: wp-admin/includes/import.php:175 +msgid "" +"Install the Tumblr importer to import posts & media from Tumblr using " +"their API." +msgstr "" +"Installer l’importateur Tumblr pour importer les articles et fichiers " +"média depuis un Tumblr en utilisant leur API." + +#: wp-admin/includes/import.php:181 +msgid "" +"Install the WordPress importer to import posts, pages, comments, custom " +"fields, categories, and tags from a WordPress export file." +msgstr "" +"Installer l’importateur WordPress, pour importer les articles, pages, " +"commentaires, champs personnalisés, catégories et mots-clés à partir d’" +"un fichier d’export WordPress." + +#: wp-admin/includes/media.php:18 +msgid "From Computer" +msgstr "Depuis votre ordinateur" + +#: wp-admin/includes/media.php:19 +msgid "From URL" +msgstr "Depuis le Web" + +#: wp-admin/includes/media.php:20 +msgid "Gallery" +msgstr "Galerie" + +#: wp-admin/includes/media.php:53 +msgid "Gallery (%s)" +msgstr "Galerie (%s)" + +#. translators: 1: audio track title, 2: album title, 3: artist name +#: wp-admin/includes/media.php:239 +msgid "\"%1$s\" from %2$s by %3$s." +msgstr "%1$s tiré de %2$s par %3$s." + +#. translators: 1: audio track title, 2: album title +#: wp-admin/includes/media.php:242 +msgid "\"%1$s\" from %2$s." +msgstr "%1$s tiré de %2$s" + +#. translators: 1: audio track title, 2: artist name +#: wp-admin/includes/media.php:245 +msgid "\"%1$s\" by %2$s." +msgstr "%1$s par %2$s." + +#: wp-admin/includes/media.php:247 +msgid "\"%s\"." +msgstr "%s." + +#. translators: 1: audio album title, 2: artist name +#: wp-admin/includes/media.php:254 +msgid "%1$s by %2$s." +msgstr "%1$s par %2$s." + +#: wp-admin/includes/media.php:266 +msgid "Released: %d." +msgstr "Date de sortie : %d." + +#: wp-admin/includes/media.php:271 +msgid "Track %1$s of %2$s." +msgstr "Piste %1$s sur %2$s." + +#: wp-admin/includes/media.php:273 +msgid "Track %1$s." +msgstr "Piste %1$s." + +#: wp-admin/includes/media.php:277 +msgid "Genre: %s." +msgstr "Genre : %s" + +#: wp-admin/includes/media.php:382 +msgid "Uploads" +msgstr "Fichiers envoyés" + +#: wp-admin/includes/media.php:382 wp-admin/includes/template.php:1411 +#: wp-admin/install.php:66 wp-admin/maint/repair.php:24 +#: wp-admin/setup-config.php:109 wp-admin/upgrade.php:61 +msgid "WordPress" +msgstr "WordPress" + +#: wp-admin/includes/media.php:851 wp-admin/includes/media.php:1004 +msgid "File URL" +msgstr "Adresse web du fichier" + +#: wp-admin/includes/media.php:852 +msgid "Attachment Post URL" +msgstr "Adresse de l’article du fichier joint" + +#: wp-admin/includes/media.php:922 +msgid "Empty Title filled from filename." +msgstr "Titre absent, il sera rempli à partir du nom du fichier." + +#: wp-admin/includes/media.php:1008 +msgid "Location of the uploaded file." +msgstr "Emplacement du fichier envoyé." + +#: wp-admin/includes/media.php:1049 wp-admin/includes/media.php:2201 +msgid "Alt text for the image, e.g. “The Mona Lisa”" +msgstr "" +"Texte alternatif de l’image, exemple : « La Joconde »" + +#: wp-admin/includes/media.php:1132 wp-admin/includes/media.php:1864 +msgid "Show" +msgstr "Afficher" + +#: wp-admin/includes/media.php:1133 wp-admin/includes/media.php:1865 +msgid "Hide" +msgstr "Cacher" + +#: wp-admin/includes/media.php:1206 wp-admin/includes/media.php:2442 +msgid "File name:" +msgstr "Nom du fichier :" + +#: wp-admin/includes/media.php:1207 wp-admin/includes/media.php:2445 +msgid "File type:" +msgstr "Type du fichier :" + +#: wp-admin/includes/media.php:1208 +msgid "Upload date:" +msgstr "Date de mise en ligne :" + +#: wp-admin/includes/media.php:1210 wp-admin/includes/media.php:2550 +msgid "Dimensions:" +msgstr "Taille :" + +#: wp-admin/includes/media.php:1228 wp-admin/includes/media.php:2231 +#: wp-admin/includes/media.php:2237 +msgid "Insert into Post" +msgstr "Insérer dans l’article" + +#: wp-admin/includes/media.php:1234 +msgid "You are about to delete %s." +msgstr "Vous êtes sur le point de supprimer %s." + +#: wp-admin/includes/media.php:1235 wp-admin/upgrade.php:67 +#: wp-admin/upgrade.php:99 +msgid "Continue" +msgstr "Continuer" + +#: wp-admin/includes/media.php:1604 +msgid "Drop files here" +msgstr "Déposez vos fichiers ici" + +#: wp-admin/includes/media.php:1605 +msgctxt "Uploader: Drop files here - or - Select Files" +msgid "or" +msgstr "ou" + +#: wp-admin/includes/media.php:1627 +msgid "" +"Your browser has some limitations uploading large files with the multi-file " +"uploader. Please use the browser uploader for files over 100MB." +msgstr "" +"Votre navigateur a certaines limites quand il s’agit de mettre en " +"ligne plusieurs larges fichiers en même temps. Veuillez utiliser l’" +"outil du navigateur pour les fichiers dépassant 100 Mo." + +#: wp-admin/includes/media.php:1661 +msgid "Add media files from your computer" +msgstr "Ajouter un fichier média depuis votre ordinateur" + +#: wp-admin/includes/media.php:1690 wp-admin/includes/media.php:1888 +#: wp-admin/includes/media.php:2135 +msgid "Save all changes" +msgstr "Enregistrer toutes les modifications" + +#: wp-admin/includes/media.php:1725 +msgid "Insert media from another website" +msgstr "Insérer un média depuis un autre site" + +#: wp-admin/includes/media.php:1863 +msgid "All Tabs:" +msgstr "Tous les onglets :" + +#: wp-admin/includes/media.php:1867 +msgid "Sort Order:" +msgstr "Ordre de tri :" + +#: wp-admin/includes/media.php:1868 wp-admin/includes/media.php:1936 +msgid "Ascending" +msgstr "Croissant" + +#: wp-admin/includes/media.php:1869 wp-admin/includes/media.php:1939 +msgid "Descending" +msgstr "Décroissant" + +#: wp-admin/includes/media.php:1870 +msgctxt "verb" +msgid "Clear" +msgstr "Effacer" + +#: wp-admin/includes/media.php:1877 wp-admin/menu.php:63 wp-admin/menu.php:213 +msgid "Media" +msgstr "Médias" + +#: wp-admin/includes/media.php:1900 +msgid "Link thumbnails to:" +msgstr "Lier les miniatures à :" + +#: wp-admin/includes/media.php:1905 +msgid "Image File" +msgstr "Fichier image" + +#: wp-admin/includes/media.php:1915 +msgid "Order images by:" +msgstr "Ranger les images par :" + +#: wp-admin/includes/media.php:1920 +msgid "Menu order" +msgstr "Ordre du menu" + +#: wp-admin/includes/media.php:1922 +msgid "Date/Time" +msgstr "Horodatage" + +#: wp-admin/includes/media.php:1923 +msgid "Random" +msgstr "Aléatoire" + +#: wp-admin/includes/media.php:1931 +msgid "Order:" +msgstr "Ordre :" + +#: wp-admin/includes/media.php:1946 +msgid "Gallery columns:" +msgstr "Colonnes de galerie :" + +#: wp-admin/includes/media.php:1967 +msgid "Update gallery settings" +msgstr "Mettre à jour les réglages de galerie" + +#: wp-admin/includes/media.php:2015 wp-admin/includes/media.php:2017 +#: wp-admin/upload.php:238 +msgid "Search Media" +msgstr "Chercher parmi les médias" + +#: wp-admin/includes/media.php:2040 +msgid "All Types" +msgstr "Tous les types" + +#: wp-admin/includes/media.php:2063 wp-admin/includes/nav-menu.php:648 +#: wp-admin/includes/nav-menu.php:873 +msgid "«" +msgstr "«" + +#: wp-admin/includes/media.php:2064 wp-admin/includes/nav-menu.php:649 +#: wp-admin/includes/nav-menu.php:874 +msgid "»" +msgstr "»" + +#: wp-admin/includes/media.php:2105 +msgid "Filter »" +msgstr "Filtrer »" + +#: wp-admin/includes/media.php:2155 +msgid "Image Caption" +msgstr "Légende de l’image" + +#: wp-admin/includes/media.php:2176 +msgid "Audio, Video, or Other File" +msgstr "Audio, vidéo ou un autre format" + +#: wp-admin/includes/media.php:2194 +msgid "Link text, e.g. “Ransom Demands (PDF)”" +msgstr "Texte du lien, par exemple « Théorie sur le chaos (PDF) »" + +#: wp-admin/includes/media.php:2220 +msgid "Link Image To:" +msgstr "Lier l’image à :" + +#: wp-admin/includes/media.php:2225 +msgid "Link to image" +msgstr "Lier à l’image" + +#: wp-admin/includes/media.php:2260 +msgid "" +"You are using the multi-file uploader. Problems? Try the browser uploader instead." +msgstr "" +"Vous utilisez l’outil de mise en ligne multi-fichiers. Si vous " +"rencontrez des problèmes, essayez la méthode du navigateur " +"à la place." + +#: wp-admin/includes/media.php:2274 +msgid "" +"You are using the browser’s built-in file uploader. The WordPress " +"uploader includes multiple file selection and drag and drop capability. Switch to the multi-file uploader." +msgstr "" +"Vous utilisez l’outil de mise en ligne du navigateur. Le nouvel outil " +"de mise en ligne de WordPress inclus la possibilité de télécharger plusieurs " +"fichiers à la fois par glisser/déposer. Passer au nouvel outil " +"de mise en ligne." + +#. translators: %1$s is link start tag, %2$s is link end tag, %3$d is width, +#. %4$d is height +#: wp-admin/includes/media.php:2305 +msgid "" +"Scale images to match the large size selected in %1$simage options%2$s (%3$d " +"× %4$d)." +msgstr "" +"Redimensionner les images pour correspondre à la taille large définie dans " +"les %1$sréglages des médias%2$s (%3$d × %4$d)." + +#: wp-admin/includes/media.php:2317 +msgid "Sorry, you have used all of your storage quota of %s MB." +msgstr "" +"Désolé, vous avez utilisé l’intégralité de votre quota de stockage (%s " +"Mo)." + +#: wp-admin/includes/media.php:2438 +msgid "File URL:" +msgstr "Adresse web du fichier :" + +#: wp-admin/includes/media.php:2464 +msgid "File size:" +msgstr "Taille du fichier :" + +#: wp-admin/includes/media.php:2489 +msgid "Mime-type:" +msgstr "Type MIME :" + +#: wp-admin/includes/media.php:2490 +msgid "Year:" +msgstr "Année :" + +#: wp-admin/includes/media.php:2491 +msgid "Genre:" +msgstr "Genre :" + +#: wp-admin/includes/media.php:2506 +msgid "Bitrate:" +msgstr "Débit binaire :" + +#: wp-admin/includes/media.php:2533 +msgid "Audio Format:" +msgstr "Format audio :" + +#: wp-admin/includes/media.php:2534 +msgid "Audio Codec:" +msgstr "Codex audio :" + +#: wp-admin/includes/menu.php:226 +msgid "You do not have sufficient permissions to access this page." +msgstr "Vous n’avez pas les droits suffisants pour accéder à cette page." + +#: wp-admin/includes/meta-boxes.php:42 +msgid "Preview Changes" +msgstr "Prévisualiser les modifications" + +#: wp-admin/includes/meta-boxes.php:109 +msgid "Visibility:" +msgstr "Visibilité :" + +#: wp-admin/includes/meta-boxes.php:117 wp-admin/includes/meta-boxes.php:140 +#: wp-admin/includes/template.php:1484 +msgid "Password protected" +msgstr "Protégé par mot de passe" + +#: wp-admin/includes/meta-boxes.php:138 +msgid "Stick this post to the front page" +msgstr "Mettre cet article en avant sur la page d’accueil" + +#: wp-admin/includes/meta-boxes.php:158 +msgid "Scheduled for: %1$s" +msgstr "Planifié pour : %1$s" + +#: wp-admin/includes/meta-boxes.php:160 +msgid "Published on: %1$s" +msgstr "Publié le : %1$s" + +#: wp-admin/includes/meta-boxes.php:162 wp-admin/includes/meta-boxes.php:170 +msgid "Publish immediately" +msgstr "Publier tout de suite" + +# Ne pas mettre d'entité HTML ( ...) : chaîne utilisée par JavaScript. +#: wp-admin/includes/meta-boxes.php:164 +msgid "Schedule for: %1$s" +msgstr "Planifier pour : %1$s" + +#: wp-admin/includes/meta-boxes.php:166 +msgid "Publish on: %1$s" +msgstr "Publier le : %1$s" + +#: wp-admin/includes/meta-boxes.php:180 +msgid "Your site is configured to keep only the last %s revisions." +msgstr "" +"Votre site est configuré pour conserver seulement les %s dernières révisions." + +#: wp-admin/includes/meta-boxes.php:182 wp-admin/includes/meta-boxes.php:185 +msgid "Revisions: %s" +msgstr "Révisions : %s" + +#: wp-admin/includes/meta-boxes.php:188 +msgctxt "revisions" +msgid "Browse" +msgstr "Parcourir" + +#: wp-admin/includes/meta-boxes.php:278 +msgid "Uploaded on: %1$s" +msgstr "Mise en ligne le : %1$s" + +#: wp-admin/includes/meta-boxes.php:373 wp-admin/includes/meta-boxes.php:773 +#: wp-admin/press-this.php:554 +msgid "Add" +msgstr "Ajouter" + +#: wp-admin/includes/meta-boxes.php:406 wp-admin/includes/meta-boxes.php:748 +#: wp-admin/includes/nav-menu.php:909 wp-admin/press-this.php:502 +msgid "Most Used" +msgstr "Les plus utilisées" + +#. translators: %s: add new taxonomy label +#: wp-admin/includes/meta-boxes.php:430 wp-admin/press-this.php:524 +msgid "+ %s" +msgstr "+ %s" + +#: wp-admin/includes/meta-boxes.php:461 +msgid "" +"Excerpts are optional hand-crafted summaries of your content that can be " +"used in your theme. Learn more about manual excerpts." +msgstr "" +"Les extraits sont des résumés facultatifs de vos articles, écrits à la main. " +"Il se peut que votre thème s’en serve. En savoir plus (en)." + +#: wp-admin/includes/meta-boxes.php:475 +msgid "Already pinged:" +msgstr "Déjà notifié(s) par ping :" + +#: wp-admin/includes/meta-boxes.php:484 +msgid "Send trackbacks to:" +msgstr "Envoyer un rétrolien vers :" + +#: wp-admin/includes/meta-boxes.php:484 +msgid "Separate multiple URLs with spaces" +msgstr "Séparez les adresses web par des espaces" + +#: wp-admin/includes/meta-boxes.php:485 +msgid "" +"Trackbacks are a way to notify legacy blog systems that you’ve linked " +"to them. If you link other WordPress sites they’ll be notified " +"automatically using pingbacks, no other action necessary." +msgstr "" +"Un rétrolien est une manière explicite de notifier les anciens systèmes de " +"blog que vous avez fait un lien vers eux. Si vous faites un lien vers des " +"sites WordPress, ils seront notifiés automatiquement à l’aide des pings (en), sans que vous n’ayez rien à faire." + +#: wp-admin/includes/meta-boxes.php:511 +msgid "" +"Custom fields can be used to add extra metadata to a post that you can use in your theme." +msgstr "" +"Les champs personnalisés peuvent être utilisés afin d’ajouter des " +"données supplémentaires à vos articles. Vous pouvez les utiliser dans " +"votre thème (en)." + +#: wp-admin/includes/meta-boxes.php:526 +msgid "Allow comments." +msgstr "Autoriser les commentaires." + +#: wp-admin/includes/meta-boxes.php:527 +msgid "" +"Allow trackbacks and pingbacks on this " +"page." +msgstr "" +"Autoriser les rétroliens et pings sur " +"cette page." + +#: wp-admin/includes/meta-boxes.php:527 +msgid "http://codex.wordpress.org/Introduction_to_Blogging#Managing_Comments" +msgstr "http://codex.wordpress.org/Introduction_to_Blogging#Managing_Comments" + +#: wp-admin/includes/meta-boxes.php:558 +msgid "Add comment" +msgstr "Ajouter un commentaire" + +#: wp-admin/includes/meta-boxes.php:576 +msgid "Show comments" +msgstr "Affiche les commentaires" + +#: wp-admin/includes/meta-boxes.php:644 +msgid "(no parent)" +msgstr "(pas de parent)" + +#: wp-admin/includes/meta-boxes.php:671 +msgid "Need help? Use the Help tab in the upper right of your screen." +msgstr "" +"Besoin d’aide ? Utiliser l’onglet Aide présent dans le coin " +"supérieur droit de votre écran." + +#: wp-admin/includes/meta-boxes.php:698 +msgid "Visit Link" +msgstr "Visiter le lien" + +#: wp-admin/includes/meta-boxes.php:706 +msgid "Keep this link private" +msgstr "Ce lien est privé" + +#: wp-admin/includes/meta-boxes.php:717 +msgid "" +"You are about to delete this link '%s'\n" +" 'Cancel' to stop, 'OK' to delete." +msgstr "" +"Vous êtes sur le point de supprimer le lien « %s ».\n" +" « Annuler » pour abandonner, « OK » pour le supprimer." + +#: wp-admin/includes/meta-boxes.php:769 wp-admin/includes/meta-boxes.php:771 +msgid "+ Add New Category" +msgstr "+ Ajouter une nouvelle catégorie" + +#: wp-admin/includes/meta-boxes.php:772 +msgid "New category name" +msgstr "Nom de la nouvelle catégorie" + +#: wp-admin/includes/meta-boxes.php:793 +msgid "_blank — new window or tab." +msgstr "_blank — nouvelle fenêtre ou onglet." + +#: wp-admin/includes/meta-boxes.php:796 +msgid "_top — current window or tab, with no frames." +msgstr "_top — fenêtre ou onglet en cours, sans frame." + +#: wp-admin/includes/meta-boxes.php:799 +msgid "_none — same window or tab." +msgstr "_none — même fenêtre ou onglet." + +#: wp-admin/includes/meta-boxes.php:801 +msgid "Choose the target frame for your link." +msgstr "Choisir la frame que cible le lien." + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:846 +msgid "rel:" +msgstr "rel :" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:850 wp-admin/includes/meta-boxes.php:851 +msgid "identity" +msgstr "identité" + +#: wp-admin/includes/meta-boxes.php:854 +msgid "another web address of mine" +msgstr "Une autre de mes adresses Web" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:858 wp-admin/includes/meta-boxes.php:859 +msgid "friendship" +msgstr "amitié" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:861 +msgid "contact" +msgstr "contact" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:864 +msgid "acquaintance" +msgstr "connaissance" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:867 +msgid "friend" +msgstr "ami(e)" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:870 wp-admin/includes/meta-boxes.php:903 +#: wp-admin/includes/meta-boxes.php:926 +msgid "none" +msgstr "aucune" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:875 wp-admin/includes/meta-boxes.php:876 +msgid "physical" +msgstr "physique" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:878 +msgid "met" +msgstr "rencontré(e)" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:883 wp-admin/includes/meta-boxes.php:884 +msgid "professional" +msgstr "professionnel" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:886 +msgid "co-worker" +msgstr "collègue de travail" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:889 +msgid "colleague" +msgstr "confrère" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:894 wp-admin/includes/meta-boxes.php:895 +msgid "geographical" +msgstr "géographique" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:897 +msgid "co-resident" +msgstr "colocataire" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:900 +msgid "neighbor" +msgstr "voisin" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:908 wp-admin/includes/meta-boxes.php:909 +msgid "family" +msgstr "famille" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:911 +msgid "child" +msgstr "enfant" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:914 +msgid "kin" +msgstr "apparenté" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:917 +msgid "parent" +msgstr "parent" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:920 +msgid "sibling" +msgstr "frère/sœur" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:923 +msgid "spouse" +msgstr "conjoint" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:931 wp-admin/includes/meta-boxes.php:932 +msgid "romantic" +msgstr "romantique" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:934 +msgid "muse" +msgstr "muse" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:937 +msgid "crush" +msgstr "coup de foudre" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:940 +msgid "date" +msgstr "petit(e)-ami(e)" + +#. translators: xfn: http:gmpg.org/xfn/ +#: wp-admin/includes/meta-boxes.php:943 +msgid "sweetheart" +msgstr "être aimé" + +#: wp-admin/includes/meta-boxes.php:949 +msgid "" +"If the link is to a person, you can specify your relationship with them " +"using the above form. If you would like to learn more about the idea check " +"out XFN." +msgstr "" +"Si le lien pointe sur une personne, vous pouvez préciser la relation que " +"vous entretenez avec elle via le formulaire ci-dessus. Si vous souhaitez en " +"apprendre plus sur ce système, consultez le site de XFN." + +#: wp-admin/includes/meta-boxes.php:964 +msgid "Image Address" +msgstr "Adresse de l’image" + +#: wp-admin/includes/meta-boxes.php:968 +msgid "RSS Address" +msgstr "Adresse du flux RSS" + +#: wp-admin/includes/meta-boxes.php:972 +msgid "Notes" +msgstr "Commentaires" + +#: wp-admin/includes/meta-boxes.php:985 +msgid "(Leave at 0 for no rating.)" +msgstr "(laissez à 0 pour ne pas donner de note.)" + +#: wp-admin/includes/misc.php:566 wp-admin/user-edit.php:213 +msgid "Admin Color Scheme" +msgstr "Couleurs de l’interface d’administration" + +#: wp-admin/includes/misc.php:646 +msgid "%s has taken over and is currently editing." +msgstr "%s a pris la main et modifie actuellement ce contenu." + +#: wp-admin/includes/ms-deprecated.php:30 +msgid "Sorry, you must delete files before you can upload any more." +msgstr "" +"Désolé, vous devez effacer quelques fichiers avant de pouvoir en envoyer " +"d’autres." + +#: wp-admin/includes/ms.php:32 +msgid "Not enough space to upload. %1$s KB needed." +msgstr "Pas assez d’espace pour l’envoi. %1$s Ko sont nécessaires." + +#: wp-admin/includes/ms.php:34 +msgid "This file is too big. Files must be less than %1$s KB in size." +msgstr "" +"Ce fichier est trop gros. La taille des fichiers doit être inférieure %1$s " +"Ko." + +#: wp-admin/includes/ms.php:36 +msgid "You have used your space quota. Please delete files before uploading." +msgstr "" +"Vous avez utilisé l’intégralité de votre quota. Veuillez supprimer " +"quelques fichiers avant l’envoi." + +#: wp-admin/includes/ms.php:39 +msgid "Back" +msgstr "Retour" + +# Pas d'entité HTML : texte envoyé par mail +#: wp-admin/includes/ms.php:229 +msgid "" +"Dear user,\n" +"\n" +"You recently requested to have the administration email address on\n" +"your site changed.\n" +"If this is correct, please click on the following link to change it:\n" +"###ADMIN_URL###\n" +"\n" +"You can safely ignore and delete this email if you do not want to\n" +"take this action.\n" +"\n" +"This email has been sent to ###EMAIL###\n" +"\n" +"Regards,\n" +"All at ###SITENAME###\n" +"###SITEURL###" +msgstr "" +"Cher utilisateur,\n" +"\n" +"Vous avez récemment demandé à modifier l'adresse de messagerie " +"d'administration de votre site.\n" +"Si c'est bien le cas, veuillez cliquer sur le lien suivant pour valider la " +"modification :\n" +"###ADMIN_URL###\n" +"\n" +"Vous pouvez ignorer et supprimer ce message si vous ne souhaitez pas lancer " +"cette action.\n" +"\n" +"Ce message a été envoyé à ###EMAIL###\n" +"\n" +"Cordialement,\n" +"\n" +"L'équipe de ###SITENAME###\n" +"###SITEURL###" + +# Pas d'entité HTML : titre de mail +#: wp-admin/includes/ms.php:266 +msgid "[%s] New Admin Email Address" +msgstr "[%s] Nouvelle adresse e-mail d'administration" + +#: wp-admin/includes/ms.php:287 +msgid "ERROR: The email address is already used." +msgstr "" +"ERREUR : l’adresse de messagerie est déjà " +"utilisée." + +# Pas d'entité HTML : texte envoyé par mail +#: wp-admin/includes/ms.php:299 +msgid "" +"Dear user,\n" +"\n" +"You recently requested to have the email address on your account changed.\n" +"If this is correct, please click on the following link to change it:\n" +"###ADMIN_URL###\n" +"\n" +"You can safely ignore and delete this email if you do not want to\n" +"take this action.\n" +"\n" +"This email has been sent to ###EMAIL###\n" +"\n" +"Regards,\n" +"All at ###SITENAME###\n" +"###SITEURL###" +msgstr "" +"Cher utilisateur,\n" +"\n" +"Vous avez récemment demandé à modifier l'adresse e-mail d'administration de " +"votre compte.\n" +"Si c'est bien le cas, veuillez cliquer sur le lien suivant pour valider la " +"modification:\n" +"###ADMIN_URL###\n" +"\n" +"Vous pouvez ignorer et supprimer ce mail si vous n'avez pas demandé cette " +"action.\n" +"\n" +"Cet email a été envoyé à ###EMAIL###\n" +"\n" +"Cordialement,\n" +"Depuis ###SITENAME###\n" +"###SITEURL###" + +#: wp-admin/includes/ms.php:335 +msgid "[%s] New Email Address" +msgstr "[%s] Nouvelle adresse e-mail" + +#: wp-admin/includes/ms.php:343 +msgid "" +"Your email address has not been updated yet. Please check your inbox at %s " +"for a confirmation email." +msgstr "" +"Votre adresse e-mail n’a pas encore été mise à jour. Veuillez vérifier " +"votre boite de réception %s pour consulter l’e-mail de confirmation." + +#: wp-admin/includes/ms.php:367 +msgid "" +"Sorry, you have used your space allocation. Please delete some files to " +"upload more files." +msgstr "" +"Désolé, vous avez utilisé l’intégralité de votre quota aloué. Veuillez " +"supprimer quelques fichiers avant d’en envoyer d’autres." + +#. translators: Gigabytes +#: wp-admin/includes/ms.php:388 +msgid "GB" +msgstr "Go" + +#. translators: Megabytes +#: wp-admin/includes/ms.php:392 +msgid "MB" +msgstr "Mo" + +#: wp-admin/includes/ms.php:395 +msgid "Used: %1$s%% of %2$s" +msgstr "Taux d’utilisation : %1$s%% sur %2$s" + +#: wp-admin/includes/ms.php:429 +msgid "Site Upload Space Quota " +msgstr "Quota de l’espace disque du site" + +#: wp-admin/includes/ms.php:430 +msgid "MB (Leave blank for network default)" +msgstr "Mo (Laisser vide pour utiliser la valeur par défaut du réseau)" + +#: wp-admin/includes/ms.php:534 wp-admin/includes/ms.php:536 +msgid "" +"You attempted to access the \"%1$s\" dashboard, but you do not currently " +"have privileges on this site. If you believe you should be able to access " +"the \"%1$s\" dashboard, please contact your network administrator." +msgstr "" +"Vous avez tenté d’accéder au tableau de bord de « %1$s " +"». Cependant, vous ne disposez pas pour le moment des droits " +"nécessaires sur ce site. Si vous pensez que vous devriez pouvoir accéder au " +"tableau de bord de « %1$s », contactez l’" +"administrateur du réseau." + +#: wp-admin/includes/ms.php:537 +msgid "" +"If you reached this screen by accident and meant to visit one of your own " +"sites, here are some shortcuts to help you find your way." +msgstr "" +"Si vous êtes arrivé sur cet écran par accident, et que vous vouliez en fait " +"vous rendre sur l’un de vos propres sites, voici quelques raccourcis " +"pour vous aider à trouver votre chemin." + +#: wp-admin/includes/ms.php:539 +msgid "Your Sites" +msgstr "Vos sites" + +#: wp-admin/includes/ms.php:548 +msgid "Visit Dashboard" +msgstr "Se rendre sur le Tableau de bord" + +#: wp-admin/includes/ms.php:548 +msgid "View Site" +msgstr "Afficher le site" + +#: wp-admin/includes/ms.php:575 +msgid "American English" +msgstr "Anglais (US)" + +#: wp-admin/includes/ms.php:579 +msgid "British English" +msgstr "Anglais (UK)" + +#: wp-admin/includes/ms.php:589 +msgid "English" +msgstr "Anglais" + +#: wp-admin/includes/ms.php:611 +msgid "" +"Thank you for Updating! Please visit the Upgrade Network " +"page to update all your sites." +msgstr "" +"Merci d’avoir fait cette mise à jour ! Rendez-vous sur la page " +"de mise à jour du réseau afin de mettre à jour tous vos " +"sites." + +#. translators: My sites label +#: wp-admin/includes/ms.php:644 +msgid "Primary Site" +msgstr "Site principal" + +#. translators: %s: title of menu item which is invalid +#: wp-admin/includes/nav-menu.php:85 +msgid "%s (Invalid)" +msgstr "%s (non valide)" + +#. translators: %s: title of menu item in draft status +#: wp-admin/includes/nav-menu.php:89 +msgid "%s (Pending)" +msgstr "%s (en attente)" + +#: wp-admin/includes/nav-menu.php:102 +msgid "sub item" +msgstr "sous-élément" + +#: wp-admin/includes/nav-menu.php:117 +msgid "Move up" +msgstr "Monter" + +#: wp-admin/includes/nav-menu.php:130 +msgid "Move down" +msgstr "Descendre" + +#: wp-admin/includes/nav-menu.php:132 wp-admin/includes/nav-menu.php:134 +msgid "Edit Menu Item" +msgstr "Modifier une entrée du menu" + +#: wp-admin/includes/nav-menu.php:150 +msgid "Navigation Label" +msgstr "Titre de la navigation" + +#: wp-admin/includes/nav-menu.php:156 +msgid "Title Attribute" +msgstr "Attribut de titre" + +#: wp-admin/includes/nav-menu.php:168 +msgid "CSS Classes (optional)" +msgstr "Classes CSS (facultatives)" + +#: wp-admin/includes/nav-menu.php:182 +msgid "" +"The description will be displayed in the menu if the current theme supports " +"it." +msgstr "" +"La description sera affichée dans le menu si le thème actuel l’accepte." + +#: wp-admin/includes/nav-menu.php:188 +msgid "Move" +msgstr "Déplacer" + +#: wp-admin/includes/nav-menu.php:189 +msgid "Up one" +msgstr "Un cran vers le haut" + +#: wp-admin/includes/nav-menu.php:190 +msgid "Down one" +msgstr "Descendre d’un cran" + +#: wp-admin/includes/nav-menu.php:193 +msgid "To the top" +msgstr "Tout en haut" + +#: wp-admin/includes/nav-menu.php:200 +msgid "Original: %s" +msgstr "Original : %s" + +#: wp-admin/includes/nav-menu.php:313 wp-admin/includes/nav-menu.php:775 +msgctxt "nav menu home label" +msgid "Home" +msgstr "Accueil" + +#: wp-admin/includes/nav-menu.php:314 +msgctxt "nav menu front page title" +msgid "Home: %s" +msgstr "Accueil : %s" + +#: wp-admin/includes/nav-menu.php:578 +msgid "Link Text" +msgstr "Cible du lien" + +#: wp-admin/includes/nav-menu.php:579 +msgid "Menu Item" +msgstr "Élément du menu" + +#: wp-admin/includes/nav-menu.php:585 +msgid "Add to Menu" +msgstr "Ajouter au menu" + +#: wp-admin/includes/nav-menu.php:630 wp-admin/includes/nav-menu.php:857 +msgid "No items." +msgstr "Aucune entrée." + +#: wp-admin/includes/nav-menu.php:687 +msgid "Most Recent" +msgstr "Les plus récentes" + +#: wp-admin/includes/nav-menu.php:692 wp-admin/includes/nav-menu.php:914 +msgid "View All" +msgstr "Afficher tout" + +#: wp-admin/includes/nav-menu.php:1134 +msgid "Add menu items from the column on the left." +msgstr "Ajouter des éléments de menu depuis la colonne de gauche." + +#: wp-admin/includes/nav-menu.php:1145 +msgid "The Walker class named %s does not exist." +msgstr "La classe Walker nommée %s n’existe pas." + +#: wp-admin/includes/nav-menu.php:1156 +msgid "Click Save Menu to make pending menu items public." +msgstr "" +"Cliquez sur « Enregistrer le menu » pour rendre " +"publics les éléments en attente." + +#: wp-admin/includes/nav-menu.php:1159 +msgid "There are some invalid menu items. Please check or delete them." +msgstr "" +"Certains éléments du menu ne sont pas valides. Veuillez les vérifier ou les " +"effacer." + +#: wp-admin/includes/nav-menu.php:1180 +msgid "Show advanced menu properties" +msgstr "Afficher les propriétés avancées du menu" + +#: wp-admin/includes/nav-menu.php:1182 +msgid "Link Target" +msgstr "Cible du lien" + +#: wp-admin/includes/nav-menu.php:1183 +msgid "CSS Classes" +msgstr "Classes CSS" + +#: wp-admin/includes/nav-menu.php:1286 +msgid "%1$s has been updated." +msgstr "%s a bien été mis à jour." + +#: wp-admin/includes/plugin-install.php:76 +#: wp-admin/includes/plugin-install.php:80 wp-admin/includes/theme.php:297 +#: wp-admin/includes/theme.php:301 +msgid "" +"An unexpected error occurred. Something may be wrong with WordPress.org or " +"this server’s configuration. If you continue to have problems, please " +"try the support forums." +msgstr "" +"Une erreur inattendue est survenue. Il pourrait y avoir un problème avec " +"WordPress.org ou la configuration de ce serveur. Si ce problème persiste, " +"exposez-le au forum d’entraide " +"communautaire." + +#: wp-admin/includes/plugin-install.php:123 +msgid "" +"Plugins extend and expand the functionality of WordPress. You may " +"automatically install plugins from the WordPress Plugin " +"Directory or upload a plugin in .zip format via this " +"page." +msgstr "" +"Les extensions étendent les fonctionnalités de WordPress, et en ajoutent de " +"nouvelles. Vous pouvez installer des extensions automatiquement en " +"provenance du répertoire des extensions WordPress, ou " +"mettre en ligne une extension au format .zip, via cette " +"page." + +#: wp-admin/includes/plugin-install.php:128 +msgid "Popular tags" +msgstr "Mots-clés populaires" + +#: wp-admin/includes/plugin-install.php:129 +msgid "" +"You may also browse based on the most popular tags in the Plugin Directory:" +msgstr "" +"Vous pouvez également naviguer en fonction des mots-clés les plus populaires " +"sur WordPress.org :" + +#: wp-admin/includes/plugin-install.php:146 +msgid "%s plugin" +msgstr "%s extension" + +#: wp-admin/includes/plugin-install.php:146 +msgid "%s plugins" +msgstr "%s extensions" + +#: wp-admin/includes/plugin-install.php:165 +#: wp-admin/includes/theme-install.php:65 +msgid "Keyword" +msgstr "Mot-clé" + +#: wp-admin/includes/plugin-install.php:167 +msgctxt "Plugin Installer" +msgid "Tag" +msgstr "Mot-clé" + +#: wp-admin/includes/plugin-install.php:171 +#: wp-admin/includes/plugin-install.php:172 +msgid "Search Plugins" +msgstr "Chercher parmi les extensions" + +#: wp-admin/includes/plugin-install.php:184 +msgid "Install a plugin in .zip format" +msgstr "Installer une extension au format .zip" + +#: wp-admin/includes/plugin-install.php:185 +msgid "" +"If you have a plugin in a .zip format, you may install it by uploading it " +"here." +msgstr "" +"Si vous avez une extension au format .zip, vous pouvez l’installer en " +"la mettant en ligne ici." + +#: wp-admin/includes/plugin-install.php:188 +msgid "Plugin zip file" +msgstr "Archive Zip de l’extension" + +#: wp-admin/includes/plugin-install.php:204 +msgid "" +"If you have marked plugins as favorites on WordPress.org, you can browse " +"them here." +msgstr "" +"Si vous avez mis des extensions en favoris sur WordPress.org, vous pouvez " +"les voir ici." + +#: wp-admin/includes/plugin-install.php:208 +msgid "Your WordPress.org username:" +msgstr "Votre identifiant WordPress.org :" + +#: wp-admin/includes/plugin-install.php:210 +msgid "Get Favorites" +msgstr "Récupérer les extensions favorites." + +#: wp-admin/includes/plugin-install.php:322 +msgctxt "Plugin installer section title" +msgid "Description" +msgstr "Description" + +#: wp-admin/includes/plugin-install.php:323 +msgctxt "Plugin installer section title" +msgid "Installation" +msgstr "Installation" + +#: wp-admin/includes/plugin-install.php:324 +msgctxt "Plugin installer section title" +msgid "FAQ" +msgstr "FAQ" + +#: wp-admin/includes/plugin-install.php:325 +msgctxt "Plugin installer section title" +msgid "Screenshots" +msgstr "Captures d’écrans" + +#: wp-admin/includes/plugin-install.php:326 +msgctxt "Plugin installer section title" +msgid "Changelog" +msgstr "Liste des modifications" + +#: wp-admin/includes/plugin-install.php:327 +msgctxt "Plugin installer section title" +msgid "Other Notes" +msgstr "Autres notes" + +#: wp-admin/includes/plugin-install.php:344 wp-admin/update.php:103 +msgid "Plugin Install" +msgstr "Installation d’extensions" + +#: wp-admin/includes/plugin-install.php:375 +msgid "Install Update Now" +msgstr "Installer la mise à jour maintenant" + +#: wp-admin/includes/plugin-install.php:378 +msgid "Newer Version (%s) Installed" +msgstr "Une version plus récente (%s) est installée" + +#: wp-admin/includes/plugin-install.php:381 +msgid "Latest Version Installed" +msgstr "Dernière version installée" + +#. translators: For Your Information +#: wp-admin/includes/plugin-install.php:387 +msgid "FYI" +msgstr "Pour information" + +#: wp-admin/includes/plugin-install.php:392 +msgid "Author:" +msgstr "Auteur :" + +#: wp-admin/includes/plugin-install.php:394 +msgid "Last Updated:" +msgstr "Dernière mise à jour :" + +#: wp-admin/includes/plugin-install.php:397 +msgid "Requires WordPress Version:" +msgstr "Nécessite WordPress en version :" + +#: wp-admin/includes/plugin-install.php:397 +msgid "%s or higher" +msgstr "%s ou plus" + +#: wp-admin/includes/plugin-install.php:399 +msgid "Compatible up to:" +msgstr "Compatible jusqu’à la version : " + +#: wp-admin/includes/plugin-install.php:401 +msgid "Downloaded:" +msgstr "Téléchargé :" + +#: wp-admin/includes/plugin-install.php:401 +msgid "%s time" +msgid_plural "%s times" +msgstr[0] "%s fois" +msgstr[1] "%s fois" + +#: wp-admin/includes/plugin-install.php:403 +msgid "WordPress.org Plugin Page »" +msgstr "Page WordPress.org de l’extension »" + +#: wp-admin/includes/plugin-install.php:405 +msgid "Plugin Homepage »" +msgstr "Site Web de l’extension »" + +#: wp-admin/includes/plugin-install.php:409 +msgid "Average Rating" +msgstr "Moyenne des notes" + +#: wp-admin/includes/plugin-install.php:419 +msgid "" +"Warning: This plugin has not been tested " +"with your current version of WordPress." +msgstr "" +"Attention : cette extension n’a pas été " +"testée avec votre version de WordPress." + +#: wp-admin/includes/plugin-install.php:422 +msgid "" +"Warning: This plugin has not been marked as " +"compatible with your version of WordPress." +msgstr "" +"Attention : cette extension n’a pas été " +"marquée comme étant compatible avec votre version de WordPress" + +#: wp-admin/includes/plugin.php:92 +msgid "" +"The %1$s plugin header is deprecated. Use %2$s " +"instead." +msgstr "" +"L’en-tête de l’extension %1$s%2$s." + +#: wp-admin/includes/plugin.php:163 +msgid "Visit plugin homepage" +msgstr "Aller sur le site de l’extension" + +#: wp-admin/includes/plugin.php:171 +msgid "By %s." +msgstr "par %s" + +#: wp-admin/includes/plugin.php:411 +msgid "Advanced caching plugin." +msgstr "Extension de cache avancée." + +#: wp-admin/includes/plugin.php:412 +msgid "Custom database class." +msgstr "Classe personnalisée de connexion à la base de données." + +#: wp-admin/includes/plugin.php:413 +msgid "Custom database error message." +msgstr "Message personnalisé pour l’erreur de base de données." + +#: wp-admin/includes/plugin.php:414 +msgid "Custom install script." +msgstr "Script d’installation personnalisée." + +#: wp-admin/includes/plugin.php:415 +msgid "Custom maintenance message." +msgstr "Message personnalisé pour la maintenance." + +#: wp-admin/includes/plugin.php:416 +msgid "External object cache." +msgstr "Cache d’objet externe." + +#: wp-admin/includes/plugin.php:420 +msgid "Executed before Multisite is loaded." +msgstr "Exécuté avant que la fonctionnalité multisites ne soit chargée." + +#: wp-admin/includes/plugin.php:421 +msgid "Custom site deleted message." +msgstr "Message personnalisé de site supprimé." + +#: wp-admin/includes/plugin.php:422 +msgid "Custom site inactive message." +msgstr "Message personnalisé de site inactif." + +#: wp-admin/includes/plugin.php:423 +msgid "Custom site suspended message." +msgstr "Message personnalisé de site suspendu." + +#: wp-admin/includes/plugin.php:592 +msgid "The plugin generated unexpected output." +msgstr "Cette extension a produit un résultat inattendu." + +#: wp-admin/includes/plugin.php:721 +msgid "One of the plugins is invalid." +msgstr "L’une des extensions n’est pas valide." + +#: wp-admin/includes/plugin.php:807 +msgid "Could not fully remove the plugin(s) %s." +msgstr "Impossible de supprimer complètement la ou les extensions %s." + +#: wp-admin/includes/plugin.php:868 +msgid "Invalid plugin path." +msgstr "Chemin d’extension non valide" + +#: wp-admin/includes/plugin.php:870 +msgid "Plugin file does not exist." +msgstr "Le fichier de l’extension n’existe pas." + +#: wp-admin/includes/plugin.php:874 +msgid "The plugin does not have a valid header." +msgstr "Cette extension ne dispose pas d’un en-tête valide." + +#: wp-admin/includes/plugin.php:1706 wp-admin/includes/plugin.php:1711 +#: wp-admin/includes/plugin.php:1734 wp-admin/includes/plugin.php:1739 +#: wp-admin/includes/template.php:1065 wp-admin/includes/template.php:1070 +msgid "The \"%s\" options group has been removed. Use another settings group." +msgstr "" +"Le groupement d’options « %s » a été supprimé. " +"Utilisez un autre groupement de réglages." + +#: wp-admin/includes/post.php:33 wp-admin/includes/post.php:71 +msgid "You are not allowed to edit pages as this user." +msgstr "" +"Vous n’avez pas l’autorisation de modifier des pages sous cet " +"identifiant." + +#: wp-admin/includes/post.php:35 wp-admin/includes/post.php:73 +msgid "You are not allowed to edit posts as this user." +msgstr "" +"Vous n’avez pas l’autorisation de modifier des articles sous cet " +"identifiant." + +#: wp-admin/includes/post.php:322 +msgid "You are not allowed to edit pages." +msgstr "Vous n’avez pas l’autorisation de modifier les pages." + +#: wp-admin/includes/post.php:324 +msgid "You are not allowed to edit posts." +msgstr "Vous n’avez pas l’autorisation de modifier les articles." + +#: wp-admin/includes/post.php:469 +msgid "Auto Draft" +msgstr "Brouillon auto" + +#: wp-admin/includes/post.php:558 +msgid "You are not allowed to create pages on this site." +msgstr "" +"Vous n’avez pas l’autorisation de créer des pages sur ce site." + +#: wp-admin/includes/post.php:560 +msgid "You are not allowed to create posts or drafts on this site." +msgstr "" +"Vous n’avez pas l’autorisation de créer des articles ou des " +"brouillons sur ce site." + +#: wp-admin/includes/post.php:1086 +msgid "Click to edit this part of the permalink" +msgstr "Cliquez pour modifier cette section du permalien" + +#: wp-admin/includes/post.php:1088 +msgid "Temporary permalink. Click to edit this part." +msgstr "Permalien temporaire. Cliquez pour modifier cette section." + +#: wp-admin/includes/post.php:1092 wp-admin/includes/post.php:1120 +msgid "Permalink:" +msgstr "Permalien :" + +#: wp-admin/includes/post.php:1094 +msgid "Change Permalinks" +msgstr "Modifier les permaliens" + +#: wp-admin/includes/post.php:1161 +msgid "Remove featured image" +msgstr "Supprimer l’image à la Une" + +#: wp-admin/includes/post.php:1283 +msgid "This content is currently locked." +msgstr "Ce contenu est actuellement vérouillé." + +#: wp-admin/includes/post.php:1285 +msgid "If you take over, %s will be blocked from continuing to edit." +msgstr "" +"Si vous souhaitez vous en occuper, %s sera bloqué et ne pourra pas terminer " +"sa modification." + +#: wp-admin/includes/post.php:1299 +msgid "Take over" +msgstr "Prendre la main" + +#: wp-admin/includes/post.php:1313 +msgid "Saving revision..." +msgstr "Enregistrement des révisions" + +#: wp-admin/includes/post.php:1314 +msgid "Your latest changes were saved as a revision." +msgstr "Vos dernières modifications ont été enregistrées dans une révision." + +#: wp-admin/includes/post.php:1400 +msgid "Preview not available. Please save as a draft first." +msgstr "" +"Aperçu non disponible. Veuillez d’abord enregistrer le brouillon." + +#: wp-admin/includes/revision.php:171 +msgctxt "revision date short format" +msgid "j M @ G:i" +msgstr "j M \\à G \\h i \\m\\i\\n" + +#. translators: default GMT offset or timezone string. Must be either a valid +#. offset (-12 to 14) +#. or a valid timezone string (America/New_York). See +#. http:us3.php.net/manual/en/timezones.php +#. for all timezone strings supported by PHP. +#: wp-admin/includes/schema.php:355 +msgctxt "default GMT offset or timezone string" +msgid "0" +msgstr "1" + +#: wp-admin/includes/schema.php:363 +msgid "My Site" +msgstr "Mon site" + +#. translators: blog tagline +#: wp-admin/includes/schema.php:365 +msgid "Just another WordPress site" +msgstr "Un site utilisant WordPress" + +#. translators: default start of the week. 0 = Sunday, 1 = Monday +#: wp-admin/includes/schema.php:369 +msgctxt "start of week" +msgid "1" +msgstr "1" + +#. translators: blog tagline +#: wp-admin/includes/schema.php:494 +msgid "Just another %s site" +msgstr "Un site utilisant %s" + +#. translators: user role +#: wp-admin/includes/schema.php:595 +msgctxt "User role" +msgid "Administrator" +msgstr "Administrateur" + +#. translators: user role +#: wp-admin/includes/schema.php:597 +msgctxt "User role" +msgid "Editor" +msgstr "Éditeur" + +#. translators: user role +#: wp-admin/includes/schema.php:599 +msgctxt "User role" +msgid "Author" +msgstr "Auteur" + +#. translators: user role +#: wp-admin/includes/schema.php:601 +msgctxt "User role" +msgid "Contributor" +msgstr "Contributeur" + +#. translators: user role +#: wp-admin/includes/schema.php:603 +msgctxt "User role" +msgid "Subscriber" +msgstr "Abonné" + +#: wp-admin/includes/schema.php:857 +msgid "You must provide a domain name." +msgstr "vous devez fournir un nom de domaine." + +#: wp-admin/includes/schema.php:859 +msgid "You must provide a name for your network of sites." +msgstr "vous devez fournir un nom pour votre réseau de sites." + +#: wp-admin/includes/schema.php:863 +msgid "The network already exists." +msgstr "Le réseau existe déjà." + +#: wp-admin/includes/schema.php:867 +msgid "You must provide a valid e-mail address." +msgstr "Vous devez saisir une adresse de messagerie valide." + +#: wp-admin/includes/schema.php:928 wp-admin/includes/upgrade.php:135 +msgid "" +"Welcome to SITE_NAME. This is your first post. Edit " +"or delete it, then start blogging!" +msgstr "" +"Bienvenue dans SITE_NAME. Ceci est votre premier " +"article. Modifiez-le ou supprimez-le, puis lancez-vous !" + +#: wp-admin/includes/schema.php:996 +msgid "Warning! Wildcard DNS may not be configured correctly!" +msgstr "" +"Attention ! L’enregistrement DNS générique (joker) peut ne pas " +"être configuré correctement !" + +#: wp-admin/includes/schema.php:997 +msgid "" +"The installer attempted to contact a random hostname (%1$s) on " +"your domain." +msgstr "" +"L’installateur a tenté de contacter un nom d’hôte aléatoire " +"(%1$s) sur votre domaine." + +#: wp-admin/includes/schema.php:999 +msgid "This resulted in an error message: %s" +msgstr "Cela a abouti à ce message d’erreur : %s" + +#: wp-admin/includes/schema.php:1001 +msgid "" +"To use a subdomain configuration, you must have a wildcard entry in your " +"DNS. This usually means adding a * hostname record pointing at " +"your web server in your DNS configuration tool." +msgstr "" +"Pour utiliser la configuration en sous-domaine, il vous faut ajouter un " +"enregistrement générique (joker) à vos enregistrements DNS. Cela signifique " +"ajouter un hôte * pointant vers votre serveur dans votre outil " +"de configuration DNS." + +#: wp-admin/includes/schema.php:1002 +msgid "" +"You can still use your site but any subdomain you create may not be " +"accessible. If you know your DNS is correct, ignore this message." +msgstr "" +"Vous pouvez toujours utiliser votre site, mais tout sous-domaine créé " +"pourrait ne pas être accessible. Si vous êtes sûr de votre configuration " +"DNS, ignorez ce message." + +#: wp-admin/includes/screen.php:797 +msgid "Contextual Help Tab" +msgstr "Onglet d’aide contextuelle" + +#: wp-admin/includes/screen.php:885 +msgid "Screen Options" +msgstr "Options de l’écran" + +#: wp-admin/includes/screen.php:904 +msgid "Enable accessibility mode" +msgstr "Activer le mode « Accessibilité »" + +#: wp-admin/includes/screen.php:904 +msgid "Disable accessibility mode" +msgstr "Désactiver le mode Accessibilité" + +#: wp-admin/includes/screen.php:933 +msgid "Screen Options Tab" +msgstr "Onglet des options de l’écran" + +#: wp-admin/includes/screen.php:936 +msgid "Show on screen" +msgstr "Afficher à l’écran" + +#: wp-admin/includes/screen.php:956 +msgctxt "Welcome panel" +msgid "Welcome" +msgstr "Bienvenue" + +#: wp-admin/includes/screen.php:1013 +msgid "Screen Layout" +msgstr "Présentation de l’écran" + +#: wp-admin/includes/screen.php:1015 +msgid "Number of Columns:" +msgstr "Nombre de colonnes :" + +#: wp-admin/includes/taxonomy.php:101 +msgid "You did not enter a category name." +msgstr "Vous n’avez pas entré de nom de catégorie." + +#: wp-admin/includes/template.php:373 +msgid "Reply to Comment" +msgstr "Répondre au commentaire" + +#: wp-admin/includes/template.php:374 +msgid "Add new Comment" +msgstr "Ajouter un nouveau commentaire" + +#: wp-admin/includes/template.php:402 +msgid "Add Comment" +msgstr "Ajouter un commentaire" + +#: wp-admin/includes/template.php:403 +msgid "Update Comment" +msgstr "Mettre à jour le commentaire" + +#: wp-admin/includes/template.php:404 +msgid "Submit Reply" +msgstr "Envoyer la réponse" + +#: wp-admin/includes/template.php:441 +msgid "Comment by %s moved to the trash." +msgstr "Commentaire de %s déplacé dans la Corbeille." + +#: wp-admin/includes/template.php:444 +msgid "Comment by %s marked as spam." +msgstr "Commentaire de %s marqué comme indésirable." + +#: wp-admin/includes/template.php:463 wp-admin/includes/template.php:478 +#: wp-admin/includes/template.php:574 +msgctxt "meta name" +msgid "Name" +msgstr "Nom" + +#: wp-admin/includes/template.php:464 wp-admin/includes/template.php:479 +#: wp-admin/includes/template.php:545 wp-admin/includes/template.php:575 +msgid "Value" +msgstr "Valeur" + +#: wp-admin/includes/template.php:535 +msgid "Key" +msgstr "Clé" + +#: wp-admin/includes/template.php:570 +msgid "Add New Custom Field:" +msgstr "Ajouter un nouveau champ personnalisé :" + +#: wp-admin/includes/template.php:596 +msgid "Enter new" +msgstr "Saisissez-en un nouveau" + +#: wp-admin/includes/template.php:607 +msgid "Add Custom Field" +msgstr "Ajouter un champ personnalisé" + +#. translators: 1: month number (01, 02, etc.), 2: month abbreviation +#: wp-admin/includes/template.php:662 +msgid "%1$s-%2$s" +msgstr "%1$s-%2$s" + +#: wp-admin/includes/template.php:783 +msgid "" +"Before you can upload your import file, you will need to fix the following " +"error:" +msgstr "" +"Avant de mettre en ligne votre fichier d’import, il vous faut corriger " +"l’erreur suivante :" + +#: wp-admin/includes/template.php:789 +msgid "Choose a file from your computer:" +msgstr "Choisissez un fichier sur votre ordinateur :" + +#: wp-admin/includes/template.php:789 +msgid "Maximum size: %s" +msgstr "Taille maximale : %s" + +#: wp-admin/includes/template.php:794 +msgid "Upload file and import" +msgstr "Envoyer le fichier et l’importer" + +#: wp-admin/includes/template.php:921 wp-admin/press-this.php:461 +#: wp-admin/press-this.php:495 wp-admin/press-this.php:545 +msgid "Click to toggle" +msgstr "Cliquer pour inverser." + +#: wp-admin/includes/template.php:1103 +msgid "" +"The miscellaneous options group has been removed. Use another settings group." +msgstr "" +"Le groupement d’options « Divers » a été " +"supprimé. Utilisez un autre groupement de réglages." + +#: wp-admin/includes/template.php:1108 +msgid "The privacy options group has been removed. Use another settings group." +msgstr "" +"Le groupement d’options « Vie privée » a été " +"supprimé. Utilisez un autre groupement de réglages." + +#: wp-admin/includes/template.php:1323 +msgid "Find Posts or Pages" +msgstr "Chercher parmi les articles et pages" + +#. translators: post state +#: wp-admin/includes/template.php:1491 +msgctxt "post state" +msgid "Pending" +msgstr "En attente" + +#: wp-admin/includes/template.php:1815 +msgid "New Feature: Toolbar" +msgstr "Nouvelle fonctionnalité : barre d’outils" + +#: wp-admin/includes/template.php:1816 +msgid "" +"We’ve combined the admin bar and the old Dashboard header into one " +"persistent toolbar. Hover over the toolbar items to see what’s new." +msgstr "" +"Nous avons combiné la barre d’administration et l’ancien en-tête " +"du tableau de bord, pour donner une seule barre qui reste toujours visible. " +"En survolant ses éléments pour découvrir les nouveautés." + +#: wp-admin/includes/template.php:1819 +msgid "Network Admin is now located in the My Sites menu." +msgstr "" +"L’administration du réseau est désormais située dans le menu «" +" Mes sites »." + +#: wp-admin/includes/template.php:1840 +msgid "New Feature: Saving Widgets" +msgstr "Nouvelle fonctionnalité : sauvegarde des widgets" + +#: wp-admin/includes/template.php:1841 +msgid "" +"If you change your mind and revert to your previous theme, we’ll put " +"the widgets back the way you had them." +msgstr "" +"Si vous changez d’avis et voulez revenir à votre thème précédent, nous " +"remettrons vos widgets là où vous les aviez." + +#: wp-admin/includes/template.php:1855 +msgid "New Feature: Customizer" +msgstr "Nouvelle fonctionnalité : personnalisateur" + +#: wp-admin/includes/template.php:1856 +msgid "" +"Click Customize to change the header, background, title and menus of the " +"current theme, all in one place." +msgstr "" +"Cliquez sur « Personnaliser » pour modifier l’en-" +"tête, l’image de fond, le titre et les menus du thème actuel, en une " +"seule page." + +#: wp-admin/includes/template.php:1857 +msgid "" +"Click the Live Preview links in the Available Themes list below to customize " +"and preview another theme before activating it." +msgstr "" +"Cliquez sur les liens « Prévisualiser » de la liste " +"« Thèmes disponibles » ci-dessous, afin de " +"personnaliser le thème sélectionné, et ensuite l’activer si vous le " +"souhaitez." + +#: wp-admin/includes/template.php:1871 +msgid "New Feature: Choose Image from Library" +msgstr "" +"Nouvelle fonctionnalité : choisir une image depuis la bibliothèque" + +#: wp-admin/includes/template.php:1872 +msgid "" +"Want to use an image you uploaded earlier? Select it from your media library " +"instead of uploading it again." +msgstr "" +"Besoin d’utiliser une image que vous avez déjà mise en ligne ? " +"Sélectionnez-la dans votre bibliothèque de médias au lieu de la remettre en " +"ligne." + +#: wp-admin/includes/template.php:1881 +msgid "New Media Manager" +msgstr "Nouveau gestionnaire de médias" + +#: wp-admin/includes/template.php:1882 +msgid "" +"Uploading files and creating image galleries has a whole new look. Check it " +"out!" +msgstr "" +"La mise en ligne de fichiers et la création de galeries d’images " +"dispose d’un tout nouveau style. Jetez-y un oeil !" + +#: wp-admin/includes/template.php:1891 +msgid "Compare Revisions" +msgstr "Comparer des révisions" + +#: wp-admin/includes/template.php:1892 +msgid "" +"View, compare, and restore other versions of this content on the improved " +"revisions screen." +msgstr "" +"Affichez, comparez et rétablissez les autres versions de ce contenu à " +"l’aide de l’écran de révisions amélioré." + +#: wp-admin/includes/template.php:1901 +msgid "Edit Lock" +msgstr "Modifier le verrouillage" + +#: wp-admin/includes/template.php:1902 +msgid "" +"Someone else is editing this. No need to refresh; the lock will disappear " +"when they’re done." +msgstr "" +"Quelqu’un est déjà en train de modifier ce contenu. Inutile de " +"recharger le page : le verrouillage disparaîtra une fois la " +"modification validée." + +#: wp-admin/includes/template.php:1936 +msgid "" +"Likely direct inclusion of wp-admin/includes/template.php in order to use " +"add_meta_box(). This is very wrong. Hook the add_meta_box() call into the " +"add_meta_boxes action instead." +msgstr "" +"Il semble y avoir une inclusion directe de wp-admin/includes/template." +"php afin d’utiliser add_meta_box(). Ce n’est " +"pas comme cela qu’il faut faire. Attachez plutôt le crochet " +"add_meta_box() à l’action add_meta_box." + +#: wp-admin/includes/template.php:1953 +msgid "" +"The backup of this post in your browser is different from the version below." +msgstr "" +"La sauvegarde de cet article dans votre navigateur est différente de la " +"version ci-dessous." + +#: wp-admin/includes/template.php:1954 +msgid "Restore the backup." +msgstr "Rétablir la sauvegarde." + +#: wp-admin/includes/template.php:1957 +msgid "Post restored successfully." +msgstr "L’article a bien été rétabli." + +#: wp-admin/includes/template.php:1958 +msgid "Undo." +msgstr "Annuler." + +#: wp-admin/includes/theme-install.php:58 +msgid "Search for themes by keyword." +msgstr "Chercher un thème par mot-clé." + +#: wp-admin/includes/theme-install.php:63 +msgid "Type of search" +msgstr "Type de recherche" + +#: wp-admin/includes/theme-install.php:67 +msgctxt "Theme Installer" +msgid "Tag" +msgstr "Mot-clé" + +#: wp-admin/includes/theme-install.php:72 +#: wp-admin/includes/theme-install.php:83 +msgid "Search by keyword" +msgstr "Recherche par mot-clé (terme)." + +#: wp-admin/includes/theme-install.php:75 +msgid "Search by author" +msgstr "Recherche par auteur" + +#: wp-admin/includes/theme-install.php:78 +msgid "Search by tag" +msgstr "Recherche par mot-clé (tag)" + +#: wp-admin/includes/theme-install.php:99 wp-admin/themes.php:244 +msgid "Feature Filter" +msgstr "Filtre de fonctionnalités" + +#: wp-admin/includes/theme-install.php:100 +msgid "Find a theme based on specific features." +msgstr "Trouver un thème selon des critères précis." + +#: wp-admin/includes/theme-install.php:131 +msgid "Find Themes" +msgstr "Trouver des thèmes" + +#: wp-admin/includes/theme-install.php:139 +msgid "Install a theme in .zip format" +msgstr "Installer un thème au format .zip" + +#: wp-admin/includes/theme-install.php:140 +msgid "" +"If you have a theme in a .zip format, you may install it by uploading it " +"here." +msgstr "" +"Si vous avez un thème au format .zip, vous pouvez l’installer en le " +"mettant en ligne ici." + +#: wp-admin/includes/theme-install.php:189 +msgid "Theme Install" +msgstr "Installation du thème" + +#: wp-admin/includes/theme.php:61 +msgid "Unable to locate WordPress theme directory." +msgstr "Impossible de localiser le dossier des thèmes de WordPress." + +#: wp-admin/includes/theme.php:68 +msgid "Could not fully remove the theme %s." +msgstr "Impossible de supprimer complètement le thème %s." + +#: wp-admin/includes/theme.php:130 +msgid "" +"Updating this theme will lose any customizations you have made. 'Cancel' to " +"stop, 'OK' to update." +msgstr "" +"Mettre à jour ce thème vous fera perdre toutes les modifications " +"personnelles que vous y avez apportées. « Annuler » pour arrêter, « OK » " +"pour mettre à jour." + +#: wp-admin/includes/theme.php:134 +msgid "" +"There is a new version of %1$s available. View version %3$s details." +msgstr "" +"Une nouvelle version de %1$s est disponible. Afficher les détails de la version %3$s." + +#: wp-admin/includes/theme.php:136 +msgid "" +"There is a new version of %1$s available. View version %3$s details. Automatic update is " +"unavailable for this theme." +msgstr "" +"Une nouvelle version de %1$s est disponible. Afficher les détails de la version %3$s. " +"Pas de possibilité de mise à jour automatique pour ce thème." + +#: wp-admin/includes/theme.php:138 +msgid "" +"There is a new version of %1$s available. View version %3$s details or update now." +msgstr "" +"Une nouvelle version de %1$s est disponible. Afficher les détails de la version %3$s ou " +"mettez à jour automatiquement." + +#: wp-admin/includes/theme.php:165 +msgid "Tan" +msgstr "Ocre" + +#: wp-admin/includes/theme.php:168 +msgid "Dark" +msgstr "Sombre" + +#: wp-admin/includes/theme.php:169 +msgid "Light" +msgstr "Clair" + +#: wp-admin/includes/theme.php:173 +msgid "One Column" +msgstr "Une colonne" + +#: wp-admin/includes/theme.php:174 +msgid "Two Columns" +msgstr "Deux colonnes" + +#: wp-admin/includes/theme.php:175 +msgid "Three Columns" +msgstr "Trois colonnes" + +#: wp-admin/includes/theme.php:176 +msgid "Four Columns" +msgstr "Quatre colonnes" + +#: wp-admin/includes/theme.php:177 +msgid "Left Sidebar" +msgstr "Colonne latérale gauche" + +#: wp-admin/includes/theme.php:178 +msgid "Right Sidebar" +msgstr "Colonne latérale droite" + +#: wp-admin/includes/theme.php:182 +msgid "Fixed Width" +msgstr "Largeur fixe" + +#: wp-admin/includes/theme.php:183 +msgid "Flexible Width" +msgstr "Largeur flexible" + +#: wp-admin/includes/theme.php:186 wp-admin/includes/theme.php:233 +msgid "Features" +msgstr "Fonctionnalités" + +#: wp-admin/includes/theme.php:187 +msgid "Blavatar" +msgstr "Blavatar" + +#: wp-admin/includes/theme.php:188 +msgid "BuddyPress" +msgstr "BuddyPress" + +#: wp-admin/includes/theme.php:190 +msgid "Custom Colors" +msgstr "Couleurs personnalisées" + +#: wp-admin/includes/theme.php:193 +msgid "Editor Style" +msgstr "Éditeur de style" + +#: wp-admin/includes/theme.php:194 +msgid "Featured Image Header" +msgstr "Image d’en-tête à la Une" + +#: wp-admin/includes/theme.php:195 +msgid "Featured Images" +msgstr "Images à la Une" + +#: wp-admin/includes/theme.php:196 +msgid "Flexible Header" +msgstr "En-tête flexible" + +#: wp-admin/includes/theme.php:197 +msgid "Front Page Posting" +msgstr "Page d’accueil personnalisée" + +#: wp-admin/includes/theme.php:198 +msgid "Full Width Template" +msgstr "Modèle pleine largeur" + +#: wp-admin/includes/theme.php:199 +msgid "Microformats" +msgstr "Microformats" + +#: wp-admin/includes/theme.php:200 +msgid "Post Formats" +msgstr "Format d’article" + +#: wp-admin/includes/theme.php:201 +msgid "RTL Language Support" +msgstr "Support des langues RTL" + +# Y'a p'tet mieux comme trad, non ? "tête de blog" ? boaf... +#: wp-admin/includes/theme.php:202 +msgid "Sticky Post" +msgstr "Mise en avant" + +#: wp-admin/includes/theme.php:203 +msgid "Theme Options" +msgstr "Options du thème" + +#: wp-admin/includes/theme.php:204 +msgid "Threaded Comments" +msgstr "Commentaires imbriqués" + +#: wp-admin/includes/theme.php:205 +msgid "Translation Ready" +msgstr "Prêt à être traduit" + +#: wp-admin/includes/theme.php:208 wp-admin/includes/theme.php:233 +msgid "Subject" +msgstr "Thème" + +#: wp-admin/includes/theme.php:209 +msgid "Holiday" +msgstr "Vacances" + +#: wp-admin/includes/theme.php:210 +msgid "Photoblogging" +msgstr "Photoblogging" + +#: wp-admin/includes/theme.php:211 +msgid "Seasonal" +msgstr "Saisonnier" + +#: wp-admin/includes/update-core.php:645 +msgid "Verifying the unpacked files…" +msgstr "Vérification des fichiers décompressés…" + +#: wp-admin/includes/update-core.php:656 +msgid "The update could not be unpacked" +msgstr "La mise à jour ne peut pas être décompressée" + +#: wp-admin/includes/update-core.php:685 +msgid "" +"The update cannot be installed because WordPress %1$s requires PHP version " +"%2$s or higher and MySQL version %3$s or higher. You are running PHP version " +"%4$s and MySQL version %5$s." +msgstr "" +"Cette mise à jour ne peut être installée car WordPress %1$s requiert une " +"version de PHP égale ou supérieure à la %2$s, et une version de MySQL égale " +"ou supérieure à la %3$s. Votre hébergement utilise PHP version %4$s et MySQL " +"version %5$s." + +#: wp-admin/includes/update-core.php:687 +msgid "" +"The update cannot be installed because WordPress %1$s requires PHP version " +"%2$s or higher. You are running version %3$s." +msgstr "" +"Cette mise à jour ne peut être installée car WordPress %1$s requiert une " +"version de PHP égale ou supérieure à la %2$s. Votre hébergement utilise PHP " +"version %3$s." + +#: wp-admin/includes/update-core.php:689 +msgid "" +"The update cannot be installed because WordPress %1$s requires MySQL version " +"%2$s or higher. You are running version %3$s." +msgstr "" +"Cette mise à jour ne peut être installée car WordPress %1$s requiert une " +"version de MySQL égale ou supérieure à la %2$s. Votre hébergement utilise " +"MySQL version %3$s." + +#: wp-admin/includes/update-core.php:691 +msgid "Preparing to install the latest version…" +msgstr "Préparation de l’installation de la dernière version…" + +#: wp-admin/includes/update-core.php:743 +msgid "Copying the required files…" +msgstr "Copie des fichiers requis…" + +#: wp-admin/includes/update-core.php:778 +msgid "There is not enough free disk space to complete the update." +msgstr "" +"Il n’y a pas assez d’espace sur le disque pour terminer la mise " +"à jour." + +#: wp-admin/includes/update-core.php:880 +msgid "Upgrading database…" +msgstr "Mise à jour de la base de données…" + +#: wp-admin/includes/update-core.php:987 wp-admin/update-core.php:419 +msgid "" +"Welcome to WordPress %1$s. You will be redirected to the About WordPress " +"screen. If not, click here." +msgstr "" +"Bienvenue dans WordPress %1$s. Vous allez être redirigé vers l’écran " +"« Ã€ propos » de WordPress. Si ce n’est pas le " +"cas, cliquez ici." + +#: wp-admin/includes/update-core.php:988 wp-admin/update-core.php:420 +msgid "Welcome to WordPress %1$s. Learn more." +msgstr "Bienvenu dans WordPress %1$s. En savoir plus." + +#: wp-admin/includes/update.php:179 +msgid "" +"You are using a development version (%1$s). Cool! Please stay updated." +msgstr "" +"Vous utilisez une version de développement (%1$s). C’est super ! " +"Veillez à rester à jour." + +#: wp-admin/includes/update.php:183 +msgid "Get Version %2$s" +msgstr "Téléchargez la version %2$s" + +#: wp-admin/includes/update.php:209 +msgid "" +"WordPress %1$s is " +"available! Please update now." +msgstr "" +"WordPress %1$s est " +"disponible ! Pensez à faire la mise à jour." + +#: wp-admin/includes/update.php:211 +msgid "" +"WordPress %1$s is " +"available! Please notify the site administrator." +msgstr "" +"WordPress %1$s est " +"disponible ! Veuillez en notifier l’administrateur du site." + +#: wp-admin/includes/update.php:220 +msgid "You are using WordPress %s." +msgstr "Vous utilisez WordPress %s." + +#: wp-admin/includes/update.php:226 +msgid "Update to %s" +msgstr "Mettre à jour vers la version %s" + +#: wp-admin/includes/update.php:226 +msgid "Latest" +msgstr "Dernière version" + +#: wp-admin/includes/update.php:278 wp-admin/includes/update.php:335 +msgid "" +"There is a new version of %1$s available. View version %4$s details." +msgstr "" +"Il y a une nouvelle version de %1$s disponible. Afficher les détails de la version %4$s." + +#: wp-admin/includes/update.php:280 +msgid "" +"There is a new version of %1$s available. View version %4$s details. Automatic update is " +"unavailable for this plugin." +msgstr "" +"Il y a une nouvelle version de %1$s disponible. Afficher les détails de la version %4$s. " +"La mise à jour automatique n’est pas possible pour cette " +"extension." + +#: wp-admin/includes/update.php:282 wp-admin/includes/update.php:339 +msgid "" +"There is a new version of %1$s available. View version %4$s details or update " +"now." +msgstr "" +"Une nouvelle version de %1$s est disponible. Afficher les détails de la version %4$s ou " +"mettez à jour automatiquement." + +#: wp-admin/includes/update.php:337 +msgid "" +"There is a new version of %1$s available. View version %4$s details. Automatic update is " +"unavailable for this theme." +msgstr "" +"Une nouvelle version de %1$s est disponible. Afficher les détails de la version %4$s. " +"Pas de possibilité de mise à jour automatique pour ce thème." + +#: wp-admin/includes/update.php:371 +msgid "" +"An automated WordPress update has failed to complete - please " +"attempt the update again now." +msgstr "" +"Une mise à jour automatique de WordPress a échoué en cours de route ; " +"vous pouvez tenter de la relancer." + +#: wp-admin/includes/update.php:373 +msgid "" +"An automated WordPress update has failed to complete! Please notify the site " +"administrator." +msgstr "" +"Une mise à jour automatique de WordPress a échoué en cours de route ! " +"Veuillez en notifier l’administrateur du site." + +#: wp-admin/includes/upgrade.php:66 +msgid "" +"Note that password carefully! It is a random password that was generated just for you." +msgstr "" +"Notez bien ce mot de passe sans vous " +"tromper ! Il a été créé aléatoirement et vous est unique." + +#: wp-admin/includes/upgrade.php:72 +msgid "Your chosen password." +msgstr "Le mot de passe que vous avez choisi." + +#: wp-admin/includes/upgrade.php:75 +msgid "User already exists. Password inherited." +msgstr "L’utilisateur existe déjà, et a hérité du mot de passe." + +# Pas d'entité : envoyé par mail. +#: wp-admin/includes/upgrade.php:85 +msgid "The password you chose during the install." +msgstr "Le mot de passe que vous avez choisi pendant l’installation." + +#. translators: Default category slug +#: wp-admin/includes/upgrade.php:109 +msgctxt "Default category slug" +msgid "Uncategorized" +msgstr "non-classe" + +#: wp-admin/includes/upgrade.php:140 +msgid "" +"Welcome to WordPress. This is your first post. Edit or delete it, then start " +"blogging!" +msgstr "" +"Bienvenue dans WordPress. Ceci est votre premier article. Modifiez-le ou " +"supprimez-le, puis lancez-vous !" + +#: wp-admin/includes/upgrade.php:149 +msgid "Hello world!" +msgstr "Bonjour tout le monde !" + +#. translators: Default post slug +#: wp-admin/includes/upgrade.php:151 +msgctxt "Default post slug" +msgid "hello-world" +msgstr "bonjour-tout-le-monde" + +#: wp-admin/includes/upgrade.php:163 +msgid "Mr WordPress" +msgstr "Monsieur WordPress" + +#: wp-admin/includes/upgrade.php:165 +msgid "" +"Hi, this is a comment.\n" +"To delete a comment, just log in and view the post's comments. There " +"you will have the option to edit or delete them." +msgstr "" +"Bonjour, ceci est un commentaire.\n" +"Pour supprimer un commentaire, connectez-vous et affichez les commentaires " +"de cet article. Vous pourrez alors les modifier ou les supprimer." + +# Eviter les entités HTML : contenu mis directement dans une page d'exemple. +#: wp-admin/includes/upgrade.php:183 +msgid "" +"This is an example page. It's different from a blog post because it will " +"stay in one place and will show up in your site navigation (in most themes). " +"Most people start with an About page that introduces them to potential site " +"visitors. It might say something like this:\n" +"\n" +"
    Hi there! I'm a bike messenger by day, aspiring actor by night, " +"and this is my blog. I live in Los Angeles, have a great dog named Jack, and " +"I like piña coladas. (And gettin' caught in the rain.)
    \n" +"\n" +"...or something like this:\n" +"\n" +"
    The XYZ Doohickey Company was founded in 1971, and has been " +"providing quality doohickeys to the public ever since. Located in Gotham " +"City, XYZ employs over 2,000 people and does all kinds of awesome things for " +"the Gotham community.
    \n" +"\n" +"As a new WordPress user, you should go to your dashboard " +"to delete this page and create new pages for your content. Have fun!" +msgstr "" +"Voici un exemple de page. Elle est différente d'un article de blog, en cela " +"qu'elle restera à la même place, et s'affichera dans le menu de navigation " +"de votre site (en fonction de votre thème). La plupart des gens commencent " +"par écrire une page « À Propos » qui les présente aux visiteurs potentiels " +"du site. Vous pourriez y écrire quelque chose de ce tenant :\n" +"\n" +"
    Bonjour ! Je suis un mécanicien qui aspire à devenir un acteur, " +"et voici mon blog. J'habite à Bordeaux, j'ai un super chien baptisé Russell, " +"et j'aime la vodka-ananas (ainsi que regarder la pluie tomber).\n" +"\n" +"...ou bien quelque chose comme ça :\n" +"\n" +"
    La société 123 Machin Truc a été créée en 1971, et n'a cessé de " +"proposer au public des machins-trucs de qualité depuis lors. Située à Saint-" +"Remy-en-Bouzemont-Saint-Genest-et-Isson, 123 Machin Truc emploie 2 000 " +"personnes, et fabrique toutes sortes de bidules super pour la communauté " +"bouzemontoise.
    \n" +"\n" +"Étant donné que vous êtes un nouvel utilisateur de WordPress, vous devriez " +"vous rendre sur votre tableau de bord pour effacer la " +"présente page, et créer de nouvelles pages avec votre propre contenu. Amusez-" +"vous bien !" + +#: wp-admin/includes/upgrade.php:201 +msgid "Sample Page" +msgstr "Page d’exemple" + +#. translators: Default page slug +#: wp-admin/includes/upgrade.php:203 +msgid "sample-page" +msgstr "page-d-exemple" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-admin/includes/upgrade.php:264 +msgid "" +"Your new WordPress site has been successfully set up at:\n" +"\n" +"%1$s\n" +"\n" +"You can log in to the administrator account with the following information:\n" +"\n" +"Username: %2$s\n" +"Password: %3$s\n" +"\n" +"We hope you enjoy your new site. Thanks!\n" +"\n" +"--The WordPress Team\n" +"http://wordpress.org/\n" +msgstr "" +"Votre nouveau site WordPress a bien été créé à l'adresse suivante :\n" +"\n" +"%1$s\n" +"\n" +"Vous pouvez vous connecter au compte administrateur avec les informations " +"suivantes :\n" +"\n" +"Identifiant : %2$s\n" +"Mot de passe : %3$s\n" +"\n" +"Nous espérons que vous apprécierez votre nouveau site. Merci !\n" +"\n" +"--L'équipe WordPress\n" +"http://wordpress.org/\n" +"http://www.wordpress-fr.net/ (traduction française et assistance)\n" + +#: wp-admin/includes/upgrade.php:279 +msgid "New WordPress Site" +msgstr "Nouveau site WordPress" + +#: wp-admin/includes/user.php:62 wp-admin/users.php:113 +msgid "You can’t give users that role." +msgstr "Vous ne pouvez pas donner ce rôle aux utilisateurs." + +#: wp-admin/includes/user.php:116 wp-admin/includes/user.php:118 +msgid "ERROR: You entered your new password only once." +msgstr "" +"ERREUR : vous n’avez tapé votre nouveau mot de " +"passe qu’une seule fois." + +#: wp-admin/includes/user.php:121 +msgid "ERROR: Please enter your password." +msgstr "ERREUR : veuillez renseigner votre mot de passe." + +#: wp-admin/includes/user.php:123 +msgid "ERROR: Please enter your password twice." +msgstr "" +"ERREUR : veuillez renseigner deux fois le mot de passe." + +#: wp-admin/includes/user.php:128 +msgid "ERROR: Passwords may not contain the character \"\\\"." +msgstr "" +"ERREUR : le mot de passe ne doit pas contenir le " +"caractère « \\ »." + +#: wp-admin/includes/user.php:132 +msgid "" +"ERROR: Please enter the same password in the two password " +"fields." +msgstr "" +"ERREUR : les deux mots de passe ne sont pas identiques." + +#: wp-admin/includes/user.php:145 +msgid "ERROR: Please enter an e-mail address." +msgstr "" +"ERREUR : veuillez saisir une adresse de messagerie." + +#: wp-admin/includes/user.php:367 +msgid "Notice:" +msgstr "Avertissement :" + +#: wp-admin/includes/user.php:368 +msgid "" +"You’re using the auto-generated password for your account. Would you " +"like to change it to something easier to remember?" +msgstr "" +"Votre compte utilise toujours le mot de passe généré automatiquement. " +"Souhaitez-vous le changer pour un mot de passe plus facile à mémoriser ?" + +#: wp-admin/includes/user.php:370 +msgid "Yes, take me to my profile page" +msgstr "Oui, je veux aller sur mon profil maintenant" + +#: wp-admin/includes/user.php:371 +msgid "No thanks, do not remind me again" +msgstr "Non, ne pas me relancer à ce sujet" + +#: wp-admin/includes/widgets.php:183 +msgctxt "widget" +msgid "Edit" +msgstr "Modifier" + +#: wp-admin/includes/widgets.php:184 +msgctxt "widget" +msgid "Add" +msgstr "Ajouter" + +#: wp-admin/index.php:37 +msgid "" +"Welcome to your WordPress Dashboard! This is the screen you will see when " +"you log in to your site, and gives you access to all the site management " +"features of WordPress. You can get help for any screen by clicking the Help " +"tab in the upper corner." +msgstr "" +"Bienvenu dans votre tableau de bord WordPress ! Ceci est l’écran " +"que vous verrez lorsque vous vous connectez à votre site, et qui vous donne " +"accès à l’ensemble des fonctionnalités de gestion de WordPress. Vous " +"pouvez obtenir de l’aide dans n’importe quel écran en cliquant " +"sur l’onglet « Aide » présent en haut à droite de votre navigateur." + +#: wp-admin/index.php:50 +msgid "" +"The left-hand navigation menu provides links to all of the WordPress " +"administration screens, with submenu items displayed on hover. You can " +"minimize this menu to a narrow icon strip by clicking on the Collapse Menu " +"arrow at the bottom." +msgstr "" +"La navigation située à gauche de l’écran fournit tous les liens pour " +"accéder à la console d’administration de WordPress, avec les sous-" +"menus qui s’affichant au survol. Vous pouvez réduire ce menu à ses " +"seules icônes en cliquant sur la flèche de repliement située en bas du menu." + +#: wp-admin/index.php:51 +msgid "" +"Links in the Toolbar at the top of the screen connect your dashboard and the " +"front end of your site, and provide access to your profile and helpful " +"WordPress information." +msgstr "" +"Les liens contenus dans la barre d’outils placée en haut de l’" +"écran relient votre tableau de bord à la partie publique de votre site, et " +"fournissent un accès rapide à votre profil et de précieuses informations sur " +"WordPress." + +#: wp-admin/index.php:59 +msgid "" +"You can use the following controls to arrange your Dashboard screen to suit " +"your workflow. This is true on most other administration screens as well." +msgstr "" +"Vous pouvez utiliser les contrôles suivants pour organiser l’écran du " +"tableau de bord pour afin de se plier à votre manière de l’utiliser. " +"La plupart des écrans de la console d’administration peuvent également " +"être organisés de cette manière." + +#: wp-admin/index.php:60 +msgid "" +"Screen Options - Use the Screen Options tab to choose which " +"Dashboard boxes to show, and how many columns to display." +msgstr "" +"Réglages d’écran - Utiliser l’onglet des " +"réglages d’écran pour choisir les blocs du tableau de bord à afficher, " +"et le nombre de colonnes afficher." + +#: wp-admin/index.php:61 +msgid "" +"Drag and Drop - To rearrange the boxes, drag and drop by " +"clicking on the title bar of the selected box and releasing when you see a " +"gray dotted-line rectangle appear in the location you want to place the box." +msgstr "" +"Glisser/déposer - Pour réarranger les blocs, glissez/" +"déposez-les en cliquant sur la barre de titre du bloc sélectionné, et " +"relâchez-la lorsque vous apercevez un rectangle avec une bordure grise à " +"l’emplacement où vous souhaitez placer le bloc." + +#: wp-admin/index.php:62 +msgid "" +"Box Controls - Click the title bar of the box to expand or " +"collapse it. In addition, some boxes have configurable content, and will " +"show a “Configure” link in the title bar if you hover over it." +msgstr "" +"Contrôle des blocs - Cliquez sur la barre de titre d’" +"un bloc pour l’étendre ou le réduire. Par ailleurs, certains blocks " +"ont un contenu configurable, et afficheront un lien « " +"Configurer » dans la barre de titre lorsque la souris le " +"survolera." + +#: wp-admin/index.php:66 +msgid "Layout" +msgstr "Arrangement" + +#: wp-admin/index.php:70 +msgid "The boxes on your Dashboard screen are:" +msgstr "Les blocs de l’écran du tableau de bord sont :" + +#: wp-admin/index.php:72 +msgid "" +"Right Now - Displays a summary of the content on your site " +"and identifies which theme and version of WordPress you are using." +msgstr "" +"Aujourd’hui - Affiche un résumé du contenu de votre " +"site, et indique le thème et la version de WordPress que vous utilisez." + +#: wp-admin/index.php:74 +msgid "" +"Recent Comments - Shows the most recent comments on your " +"posts (configurable, up to 30) and allows you to moderate them." +msgstr "" +"Commentaires récents - Affiche les commentaires les plus " +"récents sur vos articles (configurable, jusqu’à 30), et vous permet de " +"les modérer directement." + +#: wp-admin/index.php:76 +msgid "" +"Incoming Links - Shows links to your site found by Google " +"Blog Search." +msgstr "" +"Liens entrants - Affiche les liens vers votre site, tels " +"qu’indiqués par Google Blog Search." + +#: wp-admin/index.php:78 +msgid "" +"QuickPress - Allows you to create a new post and either " +"publish it or save it as a draft." +msgstr "" +"Press-Minute - Crée un nouvel article rapidement, et de le " +"publier directement ou de le garder comme brouillon." + +#: wp-admin/index.php:79 +msgid "" +"Recent Drafts - Displays links to the 5 most recent draft " +"posts you’ve started." +msgstr "" +"Brouillons récents - Affiche un lien vers les 5 derniers " +"brouillons d’articles que vous avez commencés." + +#: wp-admin/index.php:81 +msgid "" +"WordPress Blog - Latest news from the official WordPress " +"project." +msgstr "" +"Blog de WordPress - Affiche les dernières nouvelles " +"officielles du projet WordPress." + +#: wp-admin/index.php:82 +msgid "" +"Other WordPress News - Shows the WordPress Planet feed. You can " +"configure it to show a different feed of your choosing." +msgstr "" +"Autres actualités de WordPress (en français) - Affiche le " +"flux du Planet de WordPress-FR. Vous pouvez configurer ce bloc pour utiliser " +"un flux de votre choix." + +#: wp-admin/index.php:84 +msgid "" +"Plugins - Features the most popular, newest, and recently " +"updated plugins from the WordPress.org Plugin Directory." +msgstr "" +"Extensions - Affiche l’extension la plus populaire, " +"la plus récente et la plus récemment mise à jour, en provenance du dépôt " +"d’extensions de WordPress.org." + +#: wp-admin/index.php:86 +msgid "" +"Welcome - Shows links for some of the most common tasks " +"when setting up a new site." +msgstr "" +"Bienvenue - Affiche des liens pour certaines des tâches les " +"plus courantes lors de l’installation d’un nouveau site." + +#: wp-admin/index.php:98 +msgid "" +"Documentation on Dashboard" +msgstr "" +"Documentation sur le tableau de bord (en)" + +#: wp-admin/install.php:60 +msgid "WordPress › Installation" +msgstr "WordPress » Installation" + +#: wp-admin/install.php:107 +msgid "User(s) already exists." +msgstr "L’utilisateur existe déjà." + +#: wp-admin/install.php:110 +msgid "" +"Usernames can have only alphanumeric characters, spaces, underscores, " +"hyphens, periods and the @ symbol." +msgstr "" +"Les identifiants doivent contenir uniquement des caractères alphanumériques, " +"espaces, tiret bas, tiret, points et le symbole @." + +#: wp-admin/install.php:118 +msgid "Password, twice" +msgstr "Mot de passe, deux fois" + +#: wp-admin/install.php:119 +msgid "" +"A password will be automatically generated for you if you leave this blank." +msgstr "" +"Un mot de passe vous sera automatiquement généré si vous laissez ce champ " +"vide." + +#: wp-admin/install.php:130 +msgid "Your E-mail" +msgstr "Votre adresse de messagerie" + +#: wp-admin/install.php:132 +msgid "Double-check your email address before continuing." +msgstr "Vérifiez bien cette adresse de messagerie avant de continuer." + +#: wp-admin/install.php:135 +msgid "Privacy" +msgstr "Vie privée" + +#: wp-admin/install.php:139 +msgid "Install WordPress" +msgstr "Installer WordPress" + +#: wp-admin/install.php:156 +msgid "" +"You cannot install because WordPress %1$s requires PHP version %2$s or higher and MySQL version " +"%3$s or higher. You are running PHP version %4$s and MySQL version %5$s." +msgstr "" +"Vous ne pouvez pas installer WordPress %1$s, car cette version requiert une version de PHP " +"égale ou supérieure à la %2$s, et une version de MySQL égale ou supérieure à " +"la %3$s. Votre hébergement utilise PHP version %4$s et MySQL version %5$s." + +#: wp-admin/install.php:158 +msgid "" +"You cannot install because WordPress %1$s requires PHP version %2$s or higher. You are running " +"version %3$s." +msgstr "" +"Vous ne pouvez pas installer WordPress %1$s, car cette version requiert une version de PHP " +"égale ou supérieure à la %2$s. Votre hébergement utilise PHP version %3$s." + +#: wp-admin/install.php:160 +msgid "" +"You cannot install because WordPress %1$s requires MySQL version %2$s or higher. You are running " +"version %3$s." +msgstr "" +"Vous ne pouvez pas installer WordPress %1$s, car cette version requiert une version de MySQL " +"égale ou supérieure à la %2$s. Votre hébergement utilise MySQL version %3$s." + +#: wp-admin/install.php:164 +msgid "Insufficient Requirements" +msgstr "Les conditions requises ne sont pas remplies" + +#: wp-admin/install.php:169 +msgid "Configuration Error" +msgstr "Erreur de configuration" + +#: wp-admin/install.php:169 +msgid "" +"Your wp-config.php file has an empty database table prefix, " +"which is not supported." +msgstr "" +"Votre fichier wp-config.php ne défini pas préfixe de table de " +"base de données. Il en faut obligatoirement un." + +#: wp-admin/install.php:177 +msgctxt "Howdy" +msgid "Welcome" +msgstr "Bienvenue" + +#: wp-admin/install.php:178 +msgid "" +"Welcome to the famous five minute WordPress installation process! You may " +"want to browse the ReadMe documentation at your leisure. " +"Otherwise, just fill in the information below and you’ll be on your " +"way to using the most extendable and powerful personal publishing platform " +"in the world." +msgstr "" +"Bienvenue dans le célèbre processus d’installation en 5 minutes de " +"WordPress ! Vous pouvez parcourir le fichier ReadMe " +"à loisir. Autrement, remplissez simplement les champs ci-dessous, et vous " +"serez prêt à installer la plate-forme de publication personnelle la plus " +"puissante et la plus extensible au monde." + +#: wp-admin/install.php:180 +msgid "Information needed" +msgstr "Informations nécessaires" + +#: wp-admin/install.php:181 +msgid "" +"Please provide the following information. Don’t worry, you can always " +"change these settings later." +msgstr "" +"Veuillez renseigner les informations suivantes. Ne vous inquiétez pas, vous " +"pourrez les modifier plus tard." + +#: wp-admin/install.php:202 +msgid "Please provide a valid username." +msgstr "Veuillez saisir un identifiant valide." + +#: wp-admin/install.php:205 +msgid "The username you provided has invalid characters." +msgstr "" +"L’identifiant que vous avez fourni contient des caractères invalides." + +#: wp-admin/install.php:209 +msgid "Your passwords do not match. Please try again." +msgstr "Vos mots de passe ne correspondent pas. Veuillez réessayer." + +#: wp-admin/install.php:213 +msgid "You must provide an email address." +msgstr "Vous devez saisir une adresse de messagerie." + +#: wp-admin/install.php:217 +msgid "" +"Sorry, that isn’t a valid email address. Email addresses look like " +"username@example.com." +msgstr "" +"Désolé, ce n’est pas une adresse de messagerie valide. Les adresses de " +"messagerie ressemblent à cela : utilisateur@exemple.com." + +#: wp-admin/install.php:227 +msgid "Success!" +msgstr "Quel succès !" + +#: wp-admin/install.php:229 +msgid "" +"WordPress has been installed. Were you expecting more steps? Sorry to " +"disappoint." +msgstr "" +"WordPress est installé. Vous attendiez-vous à d’autres étapes ? " +"Désolé de vous décevoir ;-)" + +#: wp-admin/link-add.php:13 +msgid "You do not have sufficient permissions to add links to this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour ajouter les liens à ce site." + +#: wp-admin/link-add.php:15 +msgid "Add New Link" +msgstr "Ajouter un lien" + +#: wp-admin/link-manager.php:47 +msgid "" +"You can add links here to be displayed on your site, usually using Widgets. By default, links to several sites in the WordPress " +"community are included as examples." +msgstr "" +"Vous pouvez ici ajouter les liens que vous voulez voir affichés sur votre " +"site, généralement par le biais de widgets. Des liens " +"vers de nombreux sites de la communauté WordPress sont inclus par défaut." + +#: wp-admin/link-manager.php:48 +msgid "" +"Links may be separated into Link Categories; these are different than the " +"categories used on your posts." +msgstr "" +"Les liens peuvent être rangés dans des catégories de liens ; ce ne sont " +"pas les mêmes catégories que pour vos articles." + +#: wp-admin/link-manager.php:49 +msgid "" +"You can customize the display of this screen using the Screen Options tab " +"and/or the dropdown filters above the links table." +msgstr "" +"Vous pouvez personnaliser l’affichage de cet écran en utilisant les " +"réglages d’affichage et/ou le filtre déroulant présent au-dessous du " +"tableau de liens." + +#: wp-admin/link-manager.php:53 +msgid "Deleting Links" +msgstr "Suppression de liens" + +#: wp-admin/link-manager.php:55 +msgid "" +"If you delete a link, it will be removed permanently, as Links do not have a " +"Trash function yet." +msgstr "" +"Si vous supprimez un lien, il sera supprimé définitivement, car les liens " +"n’ont pas accès à la Corbeille pour le moment." + +#: wp-admin/link-manager.php:60 +msgid "" +"Documentation on Managing Links" +msgstr "" +"Documentation sur la gestion des liens (en)" + +#: wp-admin/link-manager.php:82 +msgid "%s link deleted." +msgid_plural "%s links deleted" +msgstr[0] "%s lien supprimé" +msgstr[1] "%s liens supprimés" + +#: wp-admin/link-manager.php:90 +msgid "Search Links" +msgstr "Chercher un lien" + +#: wp-admin/link-parse-opml.php:90 +msgid "XML error: %1$s at line %2$s" +msgstr "Erreur XML : %1$s à la ligne %2$s" + +#: wp-admin/link.php:107 +msgid "Edit Link" +msgstr "Modifier le lien" + +#: wp-admin/link.php:112 +msgid "Link not found." +msgstr "Lien non trouvé." + +#: wp-admin/maint/repair.php:18 +msgid "WordPress › Database Repair" +msgstr "WordPress » Réparation de la base de données" + +#: wp-admin/maint/repair.php:29 +msgid "" +"To allow use of this page to automatically repair database problems, please " +"add the following line to your wp-config.php file. Once this " +"line is added to your config, reload this page." +msgstr "" +"Pour autoriser cette page à réparer automatiquement les problèmes de base de " +"données, veuillez ajouter la ligne suivante dans votre fichier wp-" +"config.php. Une fois cette ligne ajoutée à votre configuration, " +"rechargez cette page." + +#. translators: %s: table name +#: wp-admin/maint/repair.php:57 +msgid "The %s table is okay." +msgstr "La table %s est correcte." + +#. translators: 1: table name, 2: error message, +#: wp-admin/maint/repair.php:60 +msgid "" +"The %1$s table is not okay. It is reporting the following error: %2$s. " +"WordPress will attempt to repair this table…" +msgstr "" +"La table %1$s est dans un mauvais état. Elle renvoie l’erreur " +"suivante : %2$s. WordPress va tenter de la réparer…" + +#. translators: %s: table name +#: wp-admin/maint/repair.php:67 +msgid "Successfully repaired the %s table." +msgstr "La table %s a bien été réparée." + +#. translators: 1: table name, 2: error message, +#: wp-admin/maint/repair.php:70 +msgid "Failed to repair the %1$s table. Error: %2$s" +msgstr "Impossible de réparer la table %1$s. Erreur : %2$s" + +#. translators: %s: table name +#: wp-admin/maint/repair.php:82 +msgid "The %s table is already optimized." +msgstr "La table %s a déjà été optimisée." + +#. translators: %s: table name +#: wp-admin/maint/repair.php:89 +msgid "Successfully optimized the %s table." +msgstr "La table %s a bien été optimisée." + +#. translators: 1: table name, 2: error message, +#: wp-admin/maint/repair.php:92 +msgid "Failed to optimize the %1$s table. Error: %2$s" +msgstr "Impossible d’optimiser la table %1$s. Erreur : %2$s" + +#: wp-admin/maint/repair.php:100 +msgid "" +"Some database problems could not be repaired. Please copy-and-paste the " +"following list of errors to the WordPress support forums " +"to get additional assistance." +msgstr "" +"Certains problèmes de la base de données n’ont pas pu être réparés. " +"Veuillez copier/coller la liste d’erreurs suivantes sur le forum de support de WordPress pour recevoir plus d’informations." + +#: wp-admin/maint/repair.php:100 +msgid "http://wordpress.org/support/forum/how-to-and-troubleshooting" +msgstr "http://www.wordpress-fr.net/support/" + +#: wp-admin/maint/repair.php:106 +msgid "" +"Repairs complete. Please remove the following line from wp-config.php to " +"prevent this page from being used by unauthorized users." +msgstr "" +"Réparations effectuées. Veuillez retirer la ligne suivante de votre fichier " +"wp-config.php, pour empêcher que cette page soit utilisée par des " +"utilisateurs non autorisés." + +#: wp-admin/maint/repair.php:110 +msgid "" +"One or more database tables are unavailable. To allow WordPress to attempt " +"to repair these tables, press the “Repair Database” button. " +"Repairing can take a while, so please be patient." +msgstr "" +"Une ou plusieurs tables de votre base de données sont indisponibles. Pour " +"autoriser WordPress à tenter de réparer ces tables, cliquez sur le bouton " +"« Réparer la base de données ». La réparation peut " +"prendre un certain temps, merci donc d’être patient." + +#: wp-admin/maint/repair.php:112 +msgid "" +"WordPress can automatically look for some common database problems and " +"repair them. Repairing can take a while, so please be patient." +msgstr "" +"WordPress peut automatiquement chercher les problèmes courants des base de " +"données et les réparer. La réparation peut prendre un certain temps, merci " +"donc de votre patience." + +#: wp-admin/maint/repair.php:114 +msgid "Repair Database" +msgstr "Réparer la base de données" + +#: wp-admin/maint/repair.php:115 +msgid "" +"WordPress can also attempt to optimize the database. This improves " +"performance in some situations. Repairing and optimizing the database can " +"take a long time and the database will be locked while optimizing." +msgstr "" +"WordPress peut également tenter d’optimiser la base de données. Cela " +"peut améliorer ses performances dans certains cas. La réparation et l’" +"optimisation peuvent prendre longtemps, et la base de données sera " +"verrouillée durant l’optimisation." + +#: wp-admin/maint/repair.php:116 +msgid "Repair and Optimize Database" +msgstr "Réparer et optimiser la base de données" + +#: wp-admin/media-new.php:40 +msgid "Upload New Media" +msgstr "Envoi d’un nouveau média" + +#: wp-admin/media-new.php:47 +msgid "" +"You can upload media files here without creating a post first. This allows " +"you to upload files to use with posts and pages later and/or to get a web " +"link for a particular file that you can share. There are three options for " +"uploading files:" +msgstr "" +"Vous pouvez ici mettre des fichiers en ligne sans devoir créer un nouvel " +"article avant. Ceci vous permet d’envoyer des fichiers qui seront " +"utilisables par les articles et les pages ultérieurement et/ou seront " +"utilisés via un lien internet pour partager un fichier particulier. Il y a 3 " +"méthodes pour envoyer des fichiers :" + +#: wp-admin/media-new.php:49 +msgid "" +"Drag and drop your files into the area below. Multiple " +"files are allowed." +msgstr "" +"Glissez/déposez vos fichiers dans la zone ci-dessous. Vous " +"pouvez en déposer plusieurs à la fois." + +#: wp-admin/media-new.php:50 +msgid "" +"Clicking Select Files opens a navigation window showing you " +"files in your operating system. Selecting Open after " +"clicking on the file you want activates a progress bar on the uploader " +"screen." +msgstr "" +"Un clic sur Sélectionner les fichiers ouvre la fenêtre de " +"navigation, vous donnant accès aux fichiers de votre machine. Après avoir " +"cliqué sur un fichier, cliquez sur Ouvrir pour l’" +"affichage de la barre de téléchargement." + +#: wp-admin/media-new.php:51 +msgid "" +"Revert to the Browser Uploader by clicking the link below " +"the drag and drop box." +msgstr "" +"Revenez à l’outil de mise en ligne du navigateur en " +"cliquant sur le lien sous la zone de glisser-déposer." + +#: wp-admin/media-new.php:56 +msgid "" +"Documentation on Uploading Media Files" +msgstr "" +"Documentation sur la mise en ligne de fichiers média (en)" + +#: wp-admin/media.php:23 wp-admin/media.php:57 +msgid "You are not allowed to edit this attachment." +msgstr "" +"Vous n’avez pas l’autorisation de modifier ce fichier attaché." + +#: wp-admin/media.php:61 +msgid "" +"You attempted to edit an attachment that doesn’t exist. Perhaps it was " +"deleted?" +msgstr "" +"Vous tentez de modifier un fichier attaché qui n’existe pas. Peut-être " +"a-t-il été supprimé ?" + +#: wp-admin/media.php:62 +msgid "" +"You attempted to edit an item that isn’t an attachment. Please go back " +"and try again." +msgstr "" +"Vous avez tenté de modifier un élément qui n’est pas un fichier joint. " +"Veuillez réessayer." + +#: wp-admin/media.php:63 +msgid "" +"You can’t edit this attachment because it is in the Trash. Please move " +"it out of the Trash and try again." +msgstr "" +"Vous ne pouvez pas modifier ce fichier attaché, car il est dans la " +"Corbeille. Sortez-l’en, puis réessayez." + +#: wp-admin/media.php:75 +msgid "" +"This screen allows you to edit five fields for metadata in a file within the " +"media library." +msgstr "" +"Cet écran vous permet de modifier les 4 champs des métadonnées des fichiers " +"dans la bibliothèque des médias." + +#. translators: add new file +#: wp-admin/media.php:111 wp-admin/menu.php:66 wp-admin/upload.php:185 +msgctxt "file" +msgid "Add New" +msgstr "Ajouter" + +#: wp-admin/media.php:117 wp-admin/media.php:126 +msgid "Update Media" +msgstr "Mettre à jour le fichier" + +#: wp-admin/menu-header.php:171 +msgid "Collapse menu" +msgstr "Réduire le menu" + +#: wp-admin/menu.php:43 +msgid "Updates %s" +msgstr "Mises à jour %s" + +#: wp-admin/menu.php:64 +msgid "Library" +msgstr "Bibliothèque" + +#: wp-admin/menu.php:76 +msgctxt "admin menu" +msgid "All Links" +msgstr "Tous les liens" + +#: wp-admin/menu.php:96 +msgid "Comments %s" +msgstr "Commentaires %s" + +#: wp-admin/menu.php:99 +msgid "All Comments" +msgstr "Tous les commentaires" + +#: wp-admin/menu.php:141 +msgid "Appearance" +msgstr "Apparence" + +#: wp-admin/menu.php:154 +msgctxt "theme editor" +msgid "Editor" +msgstr "Éditeur" + +#: wp-admin/menu.php:164 +msgid "Plugins %s" +msgstr "Extensions %s" + +#: wp-admin/menu.php:166 +msgid "Installed Plugins" +msgstr "Extensions installées" + +#. translators: add new plugin +#: wp-admin/menu.php:170 wp-admin/plugins.php:412 +msgctxt "plugin" +msgid "Add New" +msgstr "Ajouter" + +#: wp-admin/menu.php:171 +msgctxt "plugin editor" +msgid "Editor" +msgstr "Éditeur" + +#: wp-admin/menu.php:179 wp-admin/user/menu.php:14 wp-admin/user-edit.php:28 +msgid "Profile" +msgstr "Profil" + +#: wp-admin/menu.php:183 +msgid "All Users" +msgstr "Tous les utilisateurs" + +# contexte +#: wp-admin/menu.php:185 wp-admin/menu.php:187 wp-admin/user-edit.php:185 +#: wp-admin/users.php:433 +msgctxt "user" +msgid "Add New" +msgstr "Ajouter" + +#: wp-admin/menu.php:189 wp-admin/menu.php:192 +msgid "Your Profile" +msgstr "Votre profil" + +#: wp-admin/menu.php:194 wp-admin/menu.php:196 wp-admin/user-new.php:144 +#: wp-admin/user-new.php:334 +msgid "Add New User" +msgstr "Ajouter un utilisateur" + +#: wp-admin/menu.php:199 wp-admin/tools.php:12 +msgid "Tools" +msgstr "Outils" + +#: wp-admin/menu.php:200 +msgid "Available Tools" +msgstr "Outils disponibles" + +#: wp-admin/menu.php:204 wp-admin/ms-delete-site.php:30 +msgid "Delete Site" +msgstr "Supprimer mon site" + +#: wp-admin/menu.php:206 +msgid "Network Setup" +msgstr "Création du réseau" + +#: wp-admin/menu.php:209 +msgctxt "settings screen" +msgid "General" +msgstr "Général" + +#: wp-admin/menu.php:210 +msgid "Writing" +msgstr "Écriture" + +#: wp-admin/menu.php:211 +msgid "Reading" +msgstr "Lecture" + +#: wp-admin/menu.php:214 +msgid "Permalinks" +msgstr "Permaliens" + +#: wp-admin/ms-delete-site.php:13 wp-admin/my-sites.php:13 +msgid "Multisite support is not enabled." +msgstr "Le support multisites n’est pas activé." + +#: wp-admin/ms-delete-site.php:17 +msgid "You do not have sufficient permissions to delete this site." +msgstr "Vous n’avez pas les droits suffisants pour effacer ce site." + +#: wp-admin/ms-delete-site.php:22 +msgid "" +"Thank you for using %s, your site has been deleted. Happy trails to you " +"until we meet again." +msgstr "" +"Merci d’avoir utilisé notre service %s, votre site a été effacé. Ce " +"n’est qu’un au revoir..." + +#: wp-admin/ms-delete-site.php:24 +msgid "I'm sorry, the link you clicked is stale. Please select another option." +msgstr "" +"Je suis désolé, mais le lien que vous avez cliqué ne répond pas. Veuillez " +"sélectionner une autre option." + +# Pas d'entité HTML : envoyé par mail. +#: wp-admin/ms-delete-site.php:46 +msgid "" +"Dear User,\n" +"You recently clicked the 'Delete Site' link on your site and filled in a\n" +"form on that page.\n" +"If you really want to delete your site, click the link below. You will not\n" +"be asked to confirm again so only click this link if you are absolutely " +"certain:\n" +"###URL_DELETE###\n" +"\n" +"If you delete your site, please consider opening a new site here\n" +"some time in the future! (But remember your current site and username\n" +"are gone forever.)\n" +"\n" +"Thanks for using the site,\n" +"Webmaster\n" +"###SITE_NAME###" +msgstr "" +"Cher utilisateur,\n" +"Vous avez récemment cliqué sur le lien \"Effacer mon site\" dans la console " +"d'administration de votre site \n" +"et complété le formulaire présent sur cette même page.\n" +"Si vous êtes sûr de vouloir supprimer votre site, cliquez sur le lien ci-" +"dessous. Aucune confirmation ne vous sera demandée à l'avenir, soyez donc " +"totalement certain de ce que vous faites :\n" +"###URL_DELETE###\n" +"\n" +"Si vous effacez votre site, n'hésitez pas à revenir créer un site à " +"l'avenir ! (mais souvenez-vous que votre site actuel et votre identifiant ne " +"seront plus jamais disponibles)\n" +"\n" +"Merci d'avoir utilisé notre site,\n" +"\n" +"Le webmaster\n" +"###SITE_NAME###" + +#: wp-admin/ms-delete-site.php:72 +msgid "Delete My Site" +msgstr "Supprimer le site" + +#: wp-admin/ms-delete-site.php:75 +msgid "" +"Thank you. Please check your email for a link to confirm your action. Your " +"site will not be deleted until this link is clicked. " +msgstr "" +"Merci. Veuillez consulter le message que nous vous avons envoyé pour " +"confirmer cette action. Votre site ne sera pas effacé tant que vous n’" +"aurez pas cliqué le lien qu’il contient." + +#: wp-admin/ms-delete-site.php:79 +msgid "" +"If you do not want to use your %s site any more, you can delete it using the " +"form below. When you click Delete My Site Permanently you " +"will be sent an email with a link in it. Click on this link to delete your " +"site." +msgstr "" +"Si vous ne souhaitez plus utiliser votre site %s, vous pouvez l’" +"effacer à l’aide du formulaire ci-dessous. Après avoir cliqué sur " +"Effacer mon site, vous recevrez un message avec un lien. " +"Cliquez sur ce lien pour effacer votre site." + +#: wp-admin/ms-delete-site.php:80 +msgid "Remember, once deleted your site cannot be restored." +msgstr "" +"Rappelez-vous qu’une fois supprimé, votre site ne peut être rétabli." + +#: wp-admin/ms-delete-site.php:85 +msgid "" +"I'm sure I want to permanently disable my site, and I am aware I can never " +"get it back or use %s again." +msgstr "" +"Je suis certain de vouloir effacer mon site définitivement, et je me rends " +"compte que je ne pourrais jamais le récupérer ni utiliser %s pour un nouveau " +"site." + +#: wp-admin/ms-delete-site.php:86 +msgid "Delete My Site Permanently" +msgstr "Effacer mon site définitivement" + +#: wp-admin/my-sites.php:16 +msgid "You do not have sufficient permissions to view this page." +msgstr "Vous n’avez pas les droits suffisants pour accéder à cette page." + +#: wp-admin/my-sites.php:31 +msgid "The primary site you chose does not exist." +msgstr "Le site principal que vous avez choisi n’existe pas." + +#: wp-admin/my-sites.php:42 +msgid "" +"This screen shows an individual user all of their sites in this network, and " +"also allows that user to set a primary site. He or she can use the links " +"under each site to visit either the frontend or the dashboard for that site." +msgstr "" +"Cet écran affiche tous les sites d’un utilisateur du réseau, et permet " +"également à l’utilisateur d’indiquer son site principal. Il peut " +"utiliser les liens placés sous chaque site pour se rendre sur leur page " +"d’administration ou leur page d’accueil." + +#: wp-admin/my-sites.php:43 +msgid "" +"Up until WordPress version 3.0, what is now called a Multisite Network had " +"to be installed separately as WordPress MU (multi-user)." +msgstr "" +"Avant la version 3.0 de WordPress, l’équivalent du réseau multisite " +"devait être installé avec une édition spéciale de WordPress, appelée " +"WordPress MU (pour Multi-Utilisateurs)." + +#: wp-admin/my-sites.php:48 +msgid "" +"Documentation on My Sites" +msgstr "" +"Documentation sur Mes Sites (en)" + +#: wp-admin/my-sites.php:64 +msgid "You must be a member of at least one site to use this page." +msgstr "" +"Vous devez être membre d’au moins un site pour utiliser cette page." + +#: wp-admin/my-sites.php:78 +msgid "Global Settings" +msgstr "Réglages globaux" + +#: wp-admin/nav-menus.php:19 +msgid "Your theme does not support navigation menus or widgets." +msgstr "" +"Le thème actuel n’accepte pas les menus de navigation ni les widgets." + +#: wp-admin/nav-menus.php:227 +msgid "The menu item has been successfully deleted." +msgstr "L’élément du menu a bien été supprimé." + +#: wp-admin/nav-menus.php:246 +msgid "The menu has been successfully deleted." +msgstr "Le menu a bien été supprimé." + +#: wp-admin/nav-menus.php:263 +msgid "Selected menus have been successfully deleted." +msgstr "Les menus sélectionnés ont bien été supprimés." + +#: wp-admin/nav-menus.php:322 wp-admin/nav-menus.php:332 +msgid "Please enter a valid menu name." +msgstr "Veuillez saisir un nom de menu valide." + +#: wp-admin/nav-menus.php:369 +msgid "Menu locations updated." +msgstr "Les emplacements de menu ont été mis à jour." + +#: wp-admin/nav-menus.php:389 +msgid "Move up one" +msgstr "Monter d’un cran" + +#: wp-admin/nav-menus.php:390 +msgid "Move down one" +msgstr "Descendre d’un cran" + +#: wp-admin/nav-menus.php:391 +msgid "Move to the top" +msgstr "Déplacer tout en haut" + +#. translators: %s: previous item name +#: wp-admin/nav-menus.php:393 +msgid "Move under %s" +msgstr "Placer sous %s" + +#. translators: %s: previous item name +#: wp-admin/nav-menus.php:395 +msgid "Move out from under %s" +msgstr "Sortir de sous %s" + +#. translators: %s: previous item name +#: wp-admin/nav-menus.php:397 +msgid "Under %s" +msgstr "Sous %s" + +#. translators: %s: previous item name +#: wp-admin/nav-menus.php:399 +msgid "Out from under %s" +msgstr "Sortir de sous %s" + +#. translators: 1: item name, 2: item position, 3: total number of items +#: wp-admin/nav-menus.php:401 +msgid "%1$s. Menu item %2$d of %3$d." +msgstr "%1$s. Élément de menu %2$d sur %3$d." + +#. translators: 1: item name, 2: item position, 3: parent item name +#: wp-admin/nav-menus.php:403 +msgid "%1$s. Sub item number %2$d under %3$s." +msgstr "%1$s. Sous-élément numéro %2$d sous %3$s." + +#: wp-admin/nav-menus.php:475 +msgid "" +"Your theme does not natively support menus, but you can use them in sidebars " +"by adding a “Custom Menu” widget on the Widgets screen." +msgstr "" +"Votre thème ne peut pas utiliser les menus nativement, mais vous pouvez les " +"utiliser dans la barre latérale en ajoutant le widget “Menu " +"personnalisé” depuis l’écran Widgets." + +#: wp-admin/nav-menus.php:478 +msgid "This screen is used for managing your custom navigation menus." +msgstr "" +"Cet écran est utilisé pour gérer vos menus de navigations personnalisés." + +#: wp-admin/nav-menus.php:479 +msgid "" +"Menus can be displayed in locations defined by your theme, even used in " +"sidebars by adding a “Custom Menu” widget on the Widgets screen. If your theme does not support the custom menus " +"feature (the default themes, %2$s and %3$s, do), you can learn about adding " +"this support by following the Documentation link to the side." +msgstr "" +"Les menus peuvent être affichés à des emplacements définis par votre thème, " +"et même dans les barres latérales grâce au widget « Menus " +"personnalisés » de l’écran Widgets. Si " +"votre thème ne reconnaît pas encore cette fonctionnalité (les thèmes par " +"défaut, %2$s and %3$s, les intègrent très bien), vous pouvez apprendre à " +"ajouter cette reconnaissance vous-même en suivant le lien de documentation " +"situé sur le côté." + +#: wp-admin/nav-menus.php:480 +msgid "From this screen you can:" +msgstr "Depuis cet écran, vous pouvez :" + +#: wp-admin/nav-menus.php:481 +msgid "Create, edit, and delete menus" +msgstr "Créer, modifier et supprimer des menus" + +#: wp-admin/nav-menus.php:482 +msgid "Add, organize, and modify individual menu items" +msgstr "Ajouter, organiser et modifier des éléments de menu individuels" + +#: wp-admin/nav-menus.php:490 +msgid "" +"The menu management box at the top of the screen is used to control which " +"menu is opened in the editor below." +msgstr "" +"Le bloc de gestion des menus, en haut de l’écran, est utilisé pour " +"contrôler le menu qui est ouvert dans l’éditeur ci-dessous." + +#: wp-admin/nav-menus.php:491 +msgid "" +"To edit an existing menu, choose a menu from the drop down and click " +"Select" +msgstr "" +"Pour modifier un menu existant, choisissez un menu depuis la liste " +"déroulant et cliquez sur Sélectionner" + +#: wp-admin/nav-menus.php:492 +msgid "" +"If you haven’t yet created any menus, click the ’create " +"a new menu’ link to get started" +msgstr "" +"Si vous n’avez pas encore créé de menu, cliquez sur le lien " +"« Créer un nouveau menu » pour vous lancer" + +#: wp-admin/nav-menus.php:493 +msgid "" +"You can assign theme locations to individual menus by selecting the " +"desired settings at the bottom of the menu editor. To assign menus " +"to all theme locations at once, visit the Manage Locations tab at the top of the screen." +msgstr "" +"Vous pouvez assigner un emplacement du thème à chaque menu en " +"sélectionnant les réglages souhaités en bas de l’" +"éditeur de menu. Pour assigner un menu à tous les emplacements d’un " +"coup, rendez-vous dans l’onglet Gérer les emplacements en haut de l’écran." + +#: wp-admin/nav-menus.php:497 +msgid "Menu Management" +msgstr "Gestion des menus" + +#: wp-admin/nav-menus.php:501 +msgid "" +"Each custom menu may contain a mix of links to pages, categories, custom " +"URLs or other content types. Menu links are added by selecting items from " +"the expanding boxes in the left-hand column below." +msgstr "" +"Chaque menu personnalisé peut contenir un mélange de liens vers des pages, " +"des catégories, des adresses web personnalisées ou d’autres types de " +"contenu. Pour ajouter un lien dans un menu, sélectionnez un élément dans " +"l’un des blocs situés dans le colonne de gauche ci-dessous." + +#: wp-admin/nav-menus.php:502 +msgid "" +"Clicking the arrow to the right of any menu item in the " +"editor will reveal a standard group of settings. Additional settings such as " +"link target, CSS classes, link relationships, and link descriptions can be " +"enabled and disabled via the Screen Options tab." +msgstr "" +"En cliquant sur le titre de n’importe élément du menu " +"dans l’éditeur, un ensemble de réglages standards s’ouvrira. " +"D’autres réglages, tels que la cible du lien, les classes CSS, les " +"relations du lien et la description du lien, peuvent être activés et " +"désactivés dans l’onglet « Options de l’écran " +"»." + +#: wp-admin/nav-menus.php:503 +msgid "" +"Add one or several items at once by selecting the checkbox next to " +"each item and clicking Add to Menu" +msgstr "" +"Ajoutez un ou plusieurs éléments à la fois en cochant la case à côté " +"de chaque élément puis en cliquant sur «&nsbp;Ajouter au menu " +"»" + +#: wp-admin/nav-menus.php:504 +msgid "" +"To add a custom link, expand the Links section, enter a URL and link " +"text, and click Add to Menu" +msgstr "" +"Pour ajouter un lien personnalisé, ouvrez la section Liens, " +"saisissez une adresse web et un texte pour le lien, et cliquez sur Ajouter " +"au menu" + +#: wp-admin/nav-menus.php:505 +msgid "" +"To reorganize menu items, drag and drop items with your mouse or use " +"your keyboard. Drag or move a menu item a little to the right to " +"make it a submenu" +msgstr "" +"Pour réorganiser les éléments du menu, glissez/déposez les éléments " +"avec la souris ou utilisez votre clavier. Glissez ou déplacez " +"légèrement un élement du menu pour en faire un sous-menu" + +#: wp-admin/nav-menus.php:506 +msgid "" +"Delete a menu item by expanding it and clicking the Remove link" +msgstr "" +"Supprimez un élément du menu en l’ouvrant et en cliquant sur " +"le bouton Supprimer" + +#: wp-admin/nav-menus.php:510 +msgid "Editing Menus" +msgstr "Modification des menus" + +#: wp-admin/nav-menus.php:514 +msgid "" +"This screen is used for globally assigning menus to locations defined by " +"your theme." +msgstr "" +"Cet écran est utilisé pour assigner de manière globale vos menus à des " +"emplacements définis par votre thème." + +#: wp-admin/nav-menus.php:515 +msgid "" +"To assign menus to one or more theme locations, select a menu from " +"each location’s drop down. When you’re finished, " +"click Save Changes" +msgstr "" +"Pour assigner des menus à un ou plusieurs emplacements, sélectionnez " +"le menu depuis la liste déroulante de chaque emplacement. Lorsque " +"vous avez terminé, cliquez sur Enregistrer les modifications" + +#: wp-admin/nav-menus.php:516 +msgid "" +"To edit a menu currently assigned to a theme location, click the " +"adjacent ’Edit’ link" +msgstr "" +"Pour modifier un menu actuellement assigné à un emplacement du thème, " +"cliquez sur le lien « Modifier » adjacent" + +#: wp-admin/nav-menus.php:517 +msgid "" +"To add a new menu instead of assigning an existing one, click the " +"’Use new menu’ link. Your new menu will be " +"automatically assigned to that theme location" +msgstr "" +"Pour ajouter un nouveau menu au lieu d’en assigner un qui existe déjà, " +"cliquez sur le lien « Utiliser un nouveau menu »" +". Votre nouveau menu sera automatiquement ajouté à cet emplacement " +"du thème" + +#: wp-admin/nav-menus.php:528 +msgid "" +"Documentation on Menus" +msgstr "" +"Documentation sur les menus personnalisés (en)" + +#: wp-admin/nav-menus.php:538 +msgid "Edit Menus" +msgstr "Modifier les menus" + +#: wp-admin/nav-menus.php:540 +msgid "Manage Locations" +msgstr "Gérer les emplacements" + +#: wp-admin/nav-menus.php:557 wp-admin/nav-menus.php:563 +msgid "Theme Location" +msgstr "Emplacement du thème" + +#: wp-admin/nav-menus.php:558 wp-admin/nav-menus.php:564 +msgid "Assigned Menu" +msgstr "Menu assigné" + +#: wp-admin/nav-menus.php:573 +msgid "Select a Menu" +msgstr "Choisir un menu" + +#: wp-admin/nav-menus.php:585 +msgctxt "menu" +msgid "Edit" +msgstr "Modifier" + +#: wp-admin/nav-menus.php:591 +msgctxt "menu" +msgid "Use new menu" +msgstr "Utiliser le nouveau menu" + +#: wp-admin/nav-menus.php:610 +msgid "Edit your menu below, or create a new menu." +msgstr "" +"Modifiez votre menu ci-dessous, ou créez un nouveau menu." + +#: wp-admin/nav-menus.php:615 +msgid "Select a menu to edit:" +msgstr "Sélectionnez le menu à modifier :" + +#: wp-admin/nav-menus.php:618 +msgid "-- Select --" +msgstr "-- Sélectionner --" + +#: wp-admin/nav-menus.php:644 +msgid "or create a new menu." +msgstr "ou créez un nouveau menu." + +#: wp-admin/nav-menus.php:679 +msgid "Menu Name" +msgstr "Nom du menu" + +#: wp-admin/nav-menus.php:680 +msgid "Enter menu name here" +msgstr "Saisissez ici le nom du menu" + +#: wp-admin/nav-menus.php:680 +msgid "Menu 1" +msgstr "Menu 1" + +#: wp-admin/nav-menus.php:683 wp-admin/nav-menus.php:754 +msgid "Create Menu" +msgstr "Créer le menu" + +#: wp-admin/nav-menus.php:683 wp-admin/nav-menus.php:754 +msgid "Save Menu" +msgstr "Enregistrer le menu" + +#: wp-admin/nav-menus.php:690 +msgid "Menu Structure" +msgstr "Structure du menu" + +#: wp-admin/nav-menus.php:691 +msgid "" +"Edit your default menu by adding or removing items. Drag each item into the " +"order you prefer. Click Create Menu to save your changes." +msgstr "" +"Modifiez votre menu par défaut en ajoutant ou en enlevant des éléments. " +"Faites glissez chaque élément pour les mettre dans l’ordre que vous " +"souhaitez. Cliquez sur « Créer le menu » pour " +"enregistrer vos modifications." + +#: wp-admin/nav-menus.php:691 +msgid "" +"Drag each item into the order you prefer. Click the arrow on the right of " +"the item to reveal additional configuration options." +msgstr "" +"Glissez chaque élément pour les placer dans l’ordre que vous préférez. " +"Cliquez sur la flèche à droite de l’élément pour afficher d’" +"autres options de configuration." + +#: wp-admin/nav-menus.php:704 +msgid "Give your menu a name above, then click Create Menu." +msgstr "" +"Donnez à votre un menu un nom ci-dessus, puis cliquez sur « Créer " +"le menu »." + +#: wp-admin/nav-menus.php:710 +msgid "Menu Settings" +msgstr "Réglages du menu" + +#: wp-admin/nav-menus.php:723 +msgid "Auto add pages" +msgstr "Ajoutez automatiquement des pages" + +#: wp-admin/nav-menus.php:724 +msgid "Automatically add new top-level pages to this menu" +msgstr "" +"Ajouter automatiquement les nouvelles pages principales de haut niveau à ce " +"menu" + +#: wp-admin/nav-menus.php:730 +msgid "Theme locations" +msgstr "Emplacements du thème" + +#: wp-admin/nav-menus.php:735 +msgid "(Currently set to: %s)" +msgstr "(Actuellement réglé sur : %s)" + +#: wp-admin/nav-menus.php:750 +msgid "Delete Menu" +msgstr "Supprimer le menu" + +#: wp-admin/options-discussion.php:12 wp-admin/options-general.php:13 +#: wp-admin/options-media.php:13 wp-admin/options-permalink.php:13 +#: wp-admin/options-reading.php:13 wp-admin/options-writing.php:13 +msgid "You do not have sufficient permissions to manage options for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour gérer les options de ce " +"site." + +#: wp-admin/options-discussion.php:20 +msgid "" +"This screen provides many options for controlling the management and display " +"of comments and links to your posts/pages. So many, in fact, they won’" +"t all fit here! :) Use the documentation links to get information on what " +"each discussion setting does." +msgstr "" +"Cet écran offre plusieurs options pour contrôler la gestion et l’" +"affichage des commentaires et liens sur vos articles/pages. En fait, il y en " +"a tellement qu’elles ne tiennent pas toutes ici ! :) " +"Utiliser le lien vers la documentation pour obtenir des informations sur ce " +"que fait chaque réglage de discussion." + +#: wp-admin/options-discussion.php:21 wp-admin/options-general.php:69 +#: wp-admin/options-media.php:24 wp-admin/options-permalink.php:23 +#: wp-admin/options-permalink.php:32 wp-admin/options-permalink.php:39 +#: wp-admin/options-reading.php:59 wp-admin/options-writing.php:22 +msgid "" +"You must click the Save Changes button at the bottom of the screen for new " +"settings to take effect." +msgstr "" +"Vous devez cliquer sur « Enregistrer les modifications " +"» en bas de l’écran pour que les nouveaux réglages prennent " +"effet." + +#: wp-admin/options-discussion.php:26 +msgid "" +"Documentation on Discussion Settings" +msgstr "" +"Documentation sur les réglages des discussions (en)" + +#: wp-admin/options-discussion.php:42 wp-admin/options-discussion.php:43 +msgid "Default article settings" +msgstr "Réglages par défaut des articles" + +#: wp-admin/options-discussion.php:46 +msgid "Attempt to notify any blogs linked to from the article" +msgstr "Tenter de notifier les sites liés depuis le contenu des articles" + +#: wp-admin/options-discussion.php:56 +msgid "These settings may be overridden for individual articles." +msgstr "Ces réglages peuvent être modifiés pour chaque article." + +#: wp-admin/options-discussion.php:60 wp-admin/options-discussion.php:61 +msgid "Other comment settings" +msgstr "Autres réglages des commentaires" + +#: wp-admin/options-discussion.php:62 +msgid "Comment author must fill out name and e-mail" +msgstr "" +"L’auteur d’un commentaire doit renseigner son nom et son adresse " +"de messagerie" + +#: wp-admin/options-discussion.php:66 +msgid "Users must be registered and logged in to comment" +msgstr "" +"Un utilisateur doit être enregistré et connecté pour publier des commentaires" + +#: wp-admin/options-discussion.php:67 +msgid "(Signup has been disabled. Only members of this site can comment.)" +msgstr "" +" (L’inscription a été désactivée. Seuls les membres de ce site peuvent " +"laisser un commentaire.)" + +#: wp-admin/options-discussion.php:73 +msgid "Automatically close comments on articles older than %s days" +msgstr "" +"Fermer automatiquement les commentaires pour les articles vieux de plus de " +"%s jours" + +#: wp-admin/options-discussion.php:96 +msgid "Enable threaded (nested) comments %s levels deep" +msgstr "Activer les commentaires imbriqués jusqu’à %s niveaux" + +# va avec "page" +#: wp-admin/options-discussion.php:106 +msgid "last" +msgstr "dernière" + +# va avec "page" +#: wp-admin/options-discussion.php:108 +msgid "first" +msgstr "première" + +#: wp-admin/options-discussion.php:110 +msgid "" +"Break comments into pages with %1$s top level comments per page and the %2$s " +"page displayed by default" +msgstr "" +"Diviser les commentaires en pages, avec %1$s commentaires de premier niveau " +"par page et la %2$s page affichée par défaut" + +# va avec "commentaire le plus ..." +#: wp-admin/options-discussion.php:118 +msgid "older" +msgstr "ancien" + +# va avec "commentaire le plus ..." +#: wp-admin/options-discussion.php:120 +msgid "newer" +msgstr "récent" + +#: wp-admin/options-discussion.php:122 +msgid "" +"Comments should be displayed with the %s comments at the top of each page" +msgstr "Les commentaires doivent être affichés avec le plus %s en premier" + +#: wp-admin/options-discussion.php:128 wp-admin/options-discussion.php:129 +msgid "E-mail me whenever" +msgstr "M’envoyer un message lorsque" + +#: wp-admin/options-discussion.php:132 +msgid "Anyone posts a comment" +msgstr "Un nouveau commentaire est publié" + +#: wp-admin/options-discussion.php:136 +msgid "A comment is held for moderation" +msgstr "Un commentaire est en attente de modération" + +#: wp-admin/options-discussion.php:140 wp-admin/options-discussion.php:141 +msgid "Before a comment appears" +msgstr "Avant la publication d’un commentaire" + +#: wp-admin/options-discussion.php:144 +msgid "Comment must be manually approved" +msgstr "Le commentaire doit être approuvé manuellement" + +#: wp-admin/options-discussion.php:146 +msgid "Comment author must have a previously approved comment" +msgstr "" +"L’auteur d’un commentaire doit avoir déjà au moins un " +"commentaire approuvé" + +#: wp-admin/options-discussion.php:150 wp-admin/options-discussion.php:151 +msgid "Comment Moderation" +msgstr "Modération de commentaires" + +#: wp-admin/options-discussion.php:152 +msgid "" +"Hold a comment in the queue if it contains %s or more links. (A common " +"characteristic of comment spam is a large number of hyperlinks.)" +msgstr "" +"Garder un commentaire dans la file d’attente s’il contient plus " +"de %s lien(s) (une des caractéristiques typiques d’un commentaire " +"indésirable (spam) est son nombre important de liens)" + +#: wp-admin/options-discussion.php:154 +msgid "" +"When a comment contains any of these words in its content, name, URL, e-" +"mail, or IP, it will be held in the moderation queue. One word or IP per line. It " +"will match inside words, so “press” will match “" +"WordPress”." +msgstr "" +"Lorsqu’un commentaire contient l’un de ces mots dans son " +"contenu, son nom, son adresse web, son adresse de messagerie, ou son IP, " +"celui-ci est retenu dans la file de modération. Un seul mot ou une seule " +"IP par ligne. Cette fonction reconnaît l’intérieur des mots, donc " +"« press » suffira pour reconnaître « " +"WordPress »." + +#: wp-admin/options-discussion.php:161 wp-admin/options-discussion.php:162 +msgid "Comment Blacklist" +msgstr "Liste noire pour les commentaires" + +#: wp-admin/options-discussion.php:163 +msgid "" +"When a comment contains any of these words in its content, name, URL, e-" +"mail, or IP, it will be marked as spam. One word or IP per line. It will " +"match inside words, so “press” will match “" +"WordPress”." +msgstr "" +"Lorsqu’un commentaire contient l’un de ces mots dans son " +"contenu, nom, adresse web, adresse de messagerie, ou IP, le marquer comme " +"indésirable. Un seul mot ou IP par ligne. Il reconnaît l’intérieur des " +"mots, donc « press » suffira pour reconnaître « WordPress " +"»." + +#: wp-admin/options-discussion.php:172 +msgid "Avatars" +msgstr "Avatars" + +#: wp-admin/options-discussion.php:174 +msgid "" +"An avatar is an image that follows you from weblog to weblog appearing " +"beside your name when you comment on avatar enabled sites. Here you can " +"enable the display of avatars for people who comment on your site." +msgstr "" +"Un avatar est une image qui vous suit de site en site, apparaissant à côté " +"de votre nom quand vous laissez un commentaire sur un site capable de le " +"reconnaître. Vous pouvez ici activer l’affichage des avatars des gens " +"qui laissent un commentaire sur votre site." + +#: wp-admin/options-discussion.php:180 wp-admin/options-discussion.php:181 +msgid "Avatar Display" +msgstr "Affichage des avatars" + +#: wp-admin/options-discussion.php:184 +msgid "Show Avatars" +msgstr "Afficher les avatars" + +#: wp-admin/options-discussion.php:189 wp-admin/options-discussion.php:190 +msgid "Maximum Rating" +msgstr "Classement maximal" + +#. translators: Content suitability rating: http:bit.ly/89QxZA +#: wp-admin/options-discussion.php:195 +msgid "G — Suitable for all audiences" +msgstr "G — Visibles par tous" + +#. translators: Content suitability rating: http:bit.ly/89QxZA +#: wp-admin/options-discussion.php:197 +msgid "PG — Possibly offensive, usually for audiences 13 and above" +msgstr "" +"PG — Possiblement offensants, réservés normalement aux personnes de 13 " +"ans et plus" + +#. translators: Content suitability rating: http:bit.ly/89QxZA +#: wp-admin/options-discussion.php:199 +msgid "R — Intended for adult audiences above 17" +msgstr "R — Réservés aux personnes de plus de 17 ans" + +#. translators: Content suitability rating: http:bit.ly/89QxZA +#: wp-admin/options-discussion.php:201 +msgid "X — Even more mature than above" +msgstr "X — Réservés aux adultes" + +#: wp-admin/options-discussion.php:212 wp-admin/options-discussion.php:213 +msgid "Default Avatar" +msgstr "Avatar par défaut" + +#: wp-admin/options-discussion.php:215 +msgid "" +"For users without a custom avatar of their own, you can either display a " +"generic logo or a generated one based on their e-mail address." +msgstr "" +"Les utilisateurs n’ayant pas d’avatar peuvent se voir attribuer " +"un logo générique, ou un avatar généré à partir de leur adresse de " +"messagerie." + +#: wp-admin/options-discussion.php:219 +msgid "Mystery Man" +msgstr "Homme mystère" + +#: wp-admin/options-discussion.php:220 +msgid "Blank" +msgstr "Vide" + +#: wp-admin/options-discussion.php:221 +msgid "Gravatar Logo" +msgstr "Logo Gravatar" + +#: wp-admin/options-discussion.php:222 +msgid "Identicon (Generated)" +msgstr "Identicon (généré)" + +#: wp-admin/options-discussion.php:223 +msgid "Wavatar (Generated)" +msgstr "Wavatar (généré)" + +#: wp-admin/options-discussion.php:224 +msgid "MonsterID (Generated)" +msgstr "MonsterID (généré)" + +#: wp-admin/options-discussion.php:225 +msgid "Retro (Generated)" +msgstr "Rétro (généré)" + +#: wp-admin/options-general.php:15 +msgid "General Settings" +msgstr "Réglages généraux" + +#. translators: date and time format for exact current time, mainly about +#. timezones, see http:php.net/date +#: wp-admin/options-general.php:18 +msgctxt "timezone date format" +msgid "Y-m-d G:i:s" +msgstr "Y-m-d G:i:s" + +#: wp-admin/options-general.php:60 +msgid "" +"The fields on this screen determine some of the basics of your site setup." +msgstr "" +"Les champs de cet écran déterminent certains des réglages de base de votre " +"site." + +#: wp-admin/options-general.php:61 +msgid "" +"Most themes display the site title at the top of every page, in the title " +"bar of the browser, and as the identifying name for syndicated feeds. The " +"tagline is also displayed by many themes." +msgstr "" +"La plupart des thèmes affichent le titre du site en haut de chaque page, " +"dans la barre de titre du navigateur, et en tant qu’identifiant pour " +"les flux de syndication, sauf si votre thème en décide autrement. Le slogan " +"est également utilisé par de nombreux thèmes." + +#: wp-admin/options-general.php:64 +msgid "" +"The WordPress URL and the Site URL can be the same (example.com) or " +"different; for example, having the WordPress core files (example.com/" +"wordpress) in a subdirectory instead of the root directory." +msgstr "" +"L’adresse web de WordPress et celle du site peuvent être identiques " +"(exemple.fr) ou différentes. Ainsi, vous pourriez avoir les " +"fichiers de WordPress dans un sous-dossier (exemple.fr/wordpress) plutôt qu’à la racine du site." + +#: wp-admin/options-general.php:65 +msgid "" +"If you want site visitors to be able to register themselves, as opposed to " +"by the site administrator, check the membership box. A default user role can " +"be set for all new users, whether self-registered or registered by the site " +"admin." +msgstr "" +"Si vous voulez que les visiteurs du site puissent s’inscrire eux-mêmes " +"plutôt que de devoir être inscrits par l’administrateur du site, " +"cochez la case « Inscription ». Un rôle d’" +"utilisateur par défaut peut être assigné pour tout nouveau inscrit, qu’" +"il se soit enregistré lui-même ou par le biais de l’administrateur." + +#: wp-admin/options-general.php:68 +msgid "UTC means Coordinated Universal Time." +msgstr "UTC signifie « Temps universel coordonné »." + +#: wp-admin/options-general.php:79 +msgid "" +"Documentation on General Settings" +msgstr "" +"Documentation sur les réglages généraux (en)" + +#: wp-admin/options-general.php:101 +msgid "In a few words, explain what this site is about." +msgstr "En quelques mots, décrivez la raison d’être de ce site." + +#: wp-admin/options-general.php:111 +msgid "" +"Enter the address here if you want your site homepage to be different from the " +"directory you installed WordPress." +msgstr "" +"Si vous souhaitez que l’adresse de la page d’accueil de votre " +"site soit différente du répertoire où " +"vous avez installé WordPress, saisissez cette adresse ici." + +#: wp-admin/options-general.php:114 wp-admin/options-general.php:133 +msgid "E-mail Address" +msgstr "Adresse de messagerie" + +#: wp-admin/options-general.php:116 +msgid "This address is used for admin purposes, like new user notification." +msgstr "" +"Cette adresse n’est utilisée que pour l’administration du " +"site ; par exemple, la notification de l’inscription d’un " +"nouvel utilisateur." + +#: wp-admin/options-general.php:119 wp-admin/options-general.php:120 +msgid "Membership" +msgstr "Inscription" + +#: wp-admin/options-general.php:122 +msgid "Anyone can register" +msgstr "Tout le monde peut s’enregistrer" + +#: wp-admin/options-general.php:126 +msgid "New User Default Role" +msgstr "Rôle par défaut de tout nouvel utilisateur" + +#: wp-admin/options-general.php:135 +msgid "" +"This address is used for admin purposes. If you change this we will send you " +"an e-mail at your new address to confirm it. The new address will " +"not become active until confirmed." +msgstr "" +"Cette adresse est utilisée à des fins d’administration. Si vous la " +"modifiez, nous enverrons un message à la nouvelle adresse afin de la " +"confirmer. La nouvelle adresse ne sera pas active tant que vous ne " +"l’aurez pas confirmée." + +#: wp-admin/options-general.php:140 +msgid "" +"There is a pending change of the admin e-mail to %1$s. Cancel" +msgstr "" +"Il y a une modification de l’adresse de contact de l’" +"administrateur en cours, en faveur de %1$s. Annuler" + +#: wp-admin/options-general.php:168 +msgid "Timezone" +msgstr "Fuseau horaire" + +#: wp-admin/options-general.php:175 +msgid "" +"UTC time is %s" +msgstr "" +" L’heure UTC actuelle " +"est %s" + +#: wp-admin/options-general.php:177 +msgid "Local time is %1$s" +msgstr "L’heure locale actuelle est %1$s" + +#: wp-admin/options-general.php:179 +msgid "Choose a city in the same timezone as you." +msgstr "Choisissez une ville dans le même fuseau horaire que le vôtre." + +#: wp-admin/options-general.php:188 +msgid "This timezone is currently in daylight saving time." +msgstr "Ce fuseau horaire est actuellement à l’heure d’été." + +#: wp-admin/options-general.php:190 +msgid "This timezone is currently in standard time." +msgstr "Ce fuseau horaire est actuellement à l’heure d’hiver." + +#: wp-admin/options-general.php:211 +msgid "Daylight saving time begins on: %s." +msgstr "Le passage à l’heure d’été se fait le %s." + +#: wp-admin/options-general.php:212 +msgid "Standard time begins on: %s." +msgstr "" +"Le passage à l’heure d’hiver se fait le : %s." + +#: wp-admin/options-general.php:216 +msgid "This timezone does not observe daylight saving time." +msgstr "Ce fuseau horaire n’a pas d’heure d’été" + +#: wp-admin/options-general.php:254 wp-admin/options-general.php:288 +msgid "Custom:" +msgstr "Personnalisé :" + +#: wp-admin/options-general.php:256 +msgid "" +"Documentation on date and time formatting." +msgstr "" +"Documentation sur le format des dates (en)." + +#: wp-admin/options-general.php:295 +msgid "Week Starts On" +msgstr "La semaine débute le" + +#: wp-admin/options-general.php:311 +msgid "Site Language" +msgstr "Langue du site" + +#: wp-admin/options-media.php:15 +msgid "Media Settings" +msgstr "Réglages des médias" + +#: wp-admin/options-media.php:18 +msgid "" +"You can set maximum sizes for images inserted into your written content; you " +"can also insert an image as Full Size." +msgstr "" +"Vous pouvez indiquer une taille maximale pour les images insérées dans votre " +"contenu textuel. Vous pourrez insérer l’image dans sa taille d’" +"origine." + +#: wp-admin/options-media.php:21 +msgid "" +"Uploading Files allows you to choose the folder and path for storing your " +"uploaded files." +msgstr "" +"« Envoi de fichiers » vous permet de choisir le " +"dossier et le chemin de stockage de vos fichiers mis en ligne." + +#: wp-admin/options-media.php:34 +msgid "" +"Documentation on Media Settings" +msgstr "" +"Documentation sur les réglages des médias (en)" + +#: wp-admin/options-media.php:49 +msgid "Image sizes" +msgstr "Taille des images" + +#: wp-admin/options-media.php:50 +msgid "" +"The sizes listed below determine the maximum dimensions in pixels to use " +"when adding an image to the Media Library." +msgstr "" +"Les tailles précisées ci-dessous déterminent les dimensions maximales (en " +"pixels) à utiliser lors de l’insertion d’une image dans la " +"bibliothèque de médias." + +#: wp-admin/options-media.php:54 +msgid "Thumbnail size" +msgstr "Taille des miniatures" + +#: wp-admin/options-media.php:61 +msgid "" +"Crop thumbnail to exact dimensions (normally thumbnails are proportional)" +msgstr "" +"Recadrer les images pour parvenir aux dimensions exactes (normalement, les " +"miniatures sont proportionnées)" + +#: wp-admin/options-media.php:66 wp-admin/options-media.php:67 +msgid "Medium size" +msgstr "Taille moyenne" + +#: wp-admin/options-media.php:68 wp-admin/options-media.php:78 +msgid "Max Width" +msgstr "Largeur maximale" + +#: wp-admin/options-media.php:70 wp-admin/options-media.php:80 +msgid "Max Height" +msgstr "Hauteur maximale" + +#: wp-admin/options-media.php:76 wp-admin/options-media.php:77 +msgid "Large size" +msgstr "Grande taille" + +#: wp-admin/options-media.php:89 +msgid "Embeds" +msgstr "Affichages distants" + +#: wp-admin/options-media.php:96 +msgid "Uploading Files" +msgstr "Envoi de fichiers" + +#: wp-admin/options-media.php:103 +msgid "Store uploads in this folder" +msgstr "Stocker les fichiers envoyés dans ce dossier" + +#: wp-admin/options-media.php:105 +msgid "Default is wp-content/uploads" +msgstr "Par défaut, wp-content/uploads" + +#: wp-admin/options-media.php:110 +msgid "Full URL path to files" +msgstr "Adresse web complète pour les fichiers" + +#: wp-admin/options-media.php:112 +msgid "Configuring this is optional. By default, it should be blank." +msgstr "Ce réglage est facultatif. Par défaut, ce champ devrait être vide." + +#: wp-admin/options-media.php:120 +msgid "Organize my uploads into month- and year-based folders" +msgstr "Organiser mes fichiers envoyés dans des dossiers mensuels et annuels" + +#: wp-admin/options-permalink.php:15 +msgid "Permalink Settings" +msgstr "Options des permaliens" + +#: wp-admin/options-permalink.php:21 +msgid "" +"Permalinks are the permanent URLs to your individual pages and blog posts, " +"as well as your category and tag archives. A permalink is the web address " +"used to link to your content. The URL to each post should be permanent, and " +"never change — hence the name permalink." +msgstr "" +"Les permaliens sont des adresses Web permanentes vers vos pages " +"individuelles et vos articles, ainsi que vos archives de catégorie et de mot-" +"clé. Ils offrent un lien plus compréhensible vers votre contenu. Les " +"adresses de chaque article devraient être permanentes et ne jamais changer, " +"d’où le nom de permalien." + +#: wp-admin/options-permalink.php:22 +msgid "" +"This screen allows you to choose your default permalink structure. You can " +"choose from common settings or create custom URL structures." +msgstr "" +"Cet écran vous permet de choisir la structure de permalien par défaut. Vous " +"pouvez choisir les réglages les plus courants, ou créer la vôtre." + +#: wp-admin/options-permalink.php:28 wp-admin/options-permalink.php:196 +msgid "Common Settings" +msgstr "Réglages les plus courants" + +#: wp-admin/options-permalink.php:29 +msgid "" +"Many people choose to use “pretty permalinks,” URLs that contain " +"useful information such as the post title rather than generic post ID " +"numbers. You can choose from any of the permalink formats under Common " +"Settings, or can craft your own if you select Custom Structure." +msgstr "" +"De nombreuses personnes préfèrent utiliser les liens simplifiés (\"pretty " +"permalinks\"), qui contiennent des informations utiles, telles que le titre " +"de l’article, plutôt qu’un numéro d’article générique. " +"Vous pouvez choisir n’importe quel type de format de permalien parmi " +"les réglages les plus courants, ou concevoir votre propre structure " +"personnalisée." + +#: wp-admin/options-permalink.php:30 +msgid "" +"If you pick an option other than Default, your general URL path with " +"structure tags, terms surrounded by %, will also appear in the " +"custom structure field and your path can be further modified there." +msgstr "" +"Si vous choisissez une option autre que « Valeur par défaut " +"», la structure de vos permaliens, avec les marqueurs utilisés " +"(encadrés par %), apparaîtra dans le champ de « " +"Structure personnalisée », d’où vous pourrez la modifier au " +"plus proche de vos besoins." + +#: wp-admin/options-permalink.php:31 +msgid "" +"When you assign multiple categories or tags to a post, only one can show up " +"in the permalink: the lowest numbered category. This applies if your custom " +"structure includes %category% or %tag%." +msgstr "" +"Quand vous assignez un article à plusieurs catégories, une seule apparaîtra " +"dans le permalien : la catégorie avec l’identifiant numérique le " +"plus bas. Idem pour les mots-clés. Cela s’applique si votre structure " +"comprend %category% ou %tag%." + +#: wp-admin/options-permalink.php:37 +msgid "Custom Structures" +msgstr "Structure personnalisée" + +#: wp-admin/options-permalink.php:38 +msgid "" +"The Optional fields let you customize the “category” and “" +"tag” base names that will appear in archive URLs. For example, the " +"page listing all posts in the “Uncategorized” category could be " +"/topics/uncategorized instead of /category/uncategorized." +msgstr "" +"Les champs facultatifs, en bas de page, vous permettent de personnaliser les " +"dénominations utilisées pour les chemins /category/ et /" +"tags/ lors de l’affichage des archives. Par exemple, la page " +"listant tous les articles de la catégorie « Non classé " +"» pourrait se lire comme /sujet/non-classe/ plutôt que " +"/category/non-classe/." + +#: wp-admin/options-permalink.php:44 +msgid "" +"Documentation on Permalinks Settings" +msgstr "" +"Documentation sur les réglages des permaliens (en)" + +#: wp-admin/options-permalink.php:45 +msgid "" +"Documentation on Using Permalinks" +msgstr "" +"Documentation sur l’utilisation des permaliens (en)" + +#: wp-admin/options-permalink.php:152 +msgid "You should update your web.config now." +msgstr "Vous devriez mettre à jour votre fichier web.config maintenant." + +#: wp-admin/options-permalink.php:154 +msgid "" +"Permalink structure updated. Remove write access on web.config file now!" +msgstr "" +"La structure des permaliens a été mise à jour. Pensez à retirer les droits " +"d’accès au fichier web.config dès maintenant !" + +#: wp-admin/options-permalink.php:156 wp-admin/options-permalink.php:158 +#: wp-admin/options-permalink.php:163 wp-admin/options-permalink.php:166 +msgid "Permalink structure updated." +msgstr "Structure des permaliens enregistrée." + +#: wp-admin/options-permalink.php:161 +msgid "You should update your .htaccess now." +msgstr "Vous devriez mettre à jour votre fichier .htaccess maintenant." + +#: wp-admin/options-permalink.php:179 +msgid "" +"By default WordPress uses web URLs which have question marks and lots of numbers in them; " +"however, WordPress offers you the ability to create a custom URL structure " +"for your permalinks and archives. This can improve the aesthetics, " +"usability, and forward-compatibility of your links. A number of tags are available, and here " +"are some examples to get you started." +msgstr "" +"Par défaut, WordPress utilise des adresses web (URL) ayant un point d’interrogation et une " +"suite de chiffres. Cependant, WordPress vous offre la possibilité de créer " +"une structure d’adresses personnalisée pour vos permaliens et " +"archives. Ceci peut améliorer l’esthétique, l’utilisation et la " +"pérennité de vos liens. De nombreux marqueurs sont disponibles (en), et nous " +"vous donnons quelques exemples pour commencer." + +#: wp-admin/options-permalink.php:192 wp-admin/options-permalink.php:212 +msgctxt "sample permalink base" +msgid "archives" +msgstr "archives" + +#: wp-admin/options-permalink.php:203 +msgid "Day and name" +msgstr "Date et titre" + +#: wp-admin/options-permalink.php:204 wp-admin/options-permalink.php:208 +#: wp-admin/options-permalink.php:216 +msgctxt "sample permalink structure" +msgid "sample-post" +msgstr "exemple-article" + +#: wp-admin/options-permalink.php:207 +msgid "Month and name" +msgstr "Mois et titre" + +#: wp-admin/options-permalink.php:211 +msgid "Numeric" +msgstr "Numérique" + +#: wp-admin/options-permalink.php:215 +msgid "Post name" +msgstr "Nom de l’article" + +#: wp-admin/options-permalink.php:221 +msgid "Custom Structure" +msgstr "Structure personnalisée" + +#: wp-admin/options-permalink.php:231 +msgid "Optional" +msgstr "Facultatif" + +#. translators: %s is a placeholder that must come at the start of the URL +#. path. +#: wp-admin/options-permalink.php:239 +msgid "" +"If you like, you may enter custom structures for your category and tag URLs here. For example, using " +"topics as your category base would make your category links " +"like http://example.org/%stopics/uncategorized/. If you leave " +"these blank the defaults will be used." +msgstr "" +"Si vous le souhaitez, vous pouvez spécifier une structure personnalisée pour " +"vos mots-clés et de vos catégories. Par exemple, en utilisant sujet comme préfixe pour vos catégories, vous obtiendrez des adresses web " +"comme : http://exemple.fr/%ssujet/non-classe/. Si vous " +"laissez ce champ vide, la valeur par défaut sera appliquée." + +#. translators: prefix for category permalinks +#: wp-admin/options-permalink.php:243 +msgid "Category base" +msgstr "Préfixe des catégories" + +#: wp-admin/options-permalink.php:247 +msgid "Tag base" +msgstr "Base des mots-clés" + +#: wp-admin/options-permalink.php:261 +msgid "" +"If your web.config file were writable, we could do this " +"automatically, but it isn’t so this is the url rewrite rule you should " +"have in your web.config file. Click in the field and press " +"CTRL + a to select all. Then insert this rule inside of the " +"/<configuration>/<system.webServer>/<rewrite>/<" +"rules> element in web.config file." +msgstr "" +"Si vous aviez les droits en écriture sur le " +"fichier web.config, nous pourrions faire cela automatiquement. " +"Ce n’est pas le cas, donc voici les règles de réécriture que vous " +"devrez mettre dans votre fichier web.config. Cliquez sur le " +"champ et appuyez sur Ctrl-a pour tout sélectionner. Insérez " +"ensuite cette règle dans l’élément /<configuration>/<" +"system.webServer>/<rewrite>/<rules> du fichier " +"web.config." + +#: wp-admin/options-permalink.php:266 +msgid "" +"If you temporarily make your web.config file writable for us to " +"generate rewrite rules automatically, do not forget to revert the " +"permissions after rule has been saved." +msgstr "" +"Si vous rendez le fichier web.config accessible en écriture " +"afin de générer automatiquement les règles de réécriture, n’oubliez " +"surtout pas de remettre les droits originaux en place une fois que les " +"règles ont été enregistrées." + +#: wp-admin/options-permalink.php:268 +msgid "" +"If the root directory of your site were writable, we could do this automatically, " +"but it isn’t so this is the url rewrite rule you should have in your " +"web.config file. Create a new file, called web.config in the root directory of your site. Click in the field and press " +"CTRL + a to select all. Then insert this code into the web." +"config file." +msgstr "" +"Si vous aviez les droits en écriture sur le " +"fichier web.config, nous pourrions faire cela automatiquement. " +"Ce n’est pas le cas, donc voici les règles de réécriture que vous " +"devrez mettre dans votre fichier web.config. Créez un nouveau " +"fichier texte, nommé web.config, dans le dossier racine de " +"votre site. Cliquez sur le champ et appuyez sur Ctrl-a pour tout " +"sélectionner. Insérez ensuite le contenu dans le fichier web.config." + +#: wp-admin/options-permalink.php:273 +msgid "" +"If you temporarily make your site’s root directory writable for us to " +"generate the web.config file automatically, do not forget to " +"revert the permissions after the file has been created." +msgstr "" +"Si vous rendez temporairement le dossier racine accessible en écriture afin " +"que nous y générions directement le fichier web.config,n’" +"oubliez surtout pas de remettre les droits originaux en place une fois que " +"les règles ont été enregistrées." + +#: wp-admin/options-permalink.php:278 +msgid "" +"If your .htaccess file were writable, we could do this " +"automatically, but it isn’t so these are the mod_rewrite rules you " +"should have in your .htaccess file. Click in the field and " +"press CTRL + a to select all." +msgstr "" +"Si vous aviez les droits en écriture sur le " +"fichier .htaccess, nous pourrions faire cela automatiquement. " +"Ce n’est pas le cas, donc voici les règles de réécriture que vous " +"devrez mettre dans votre fichier .htaccess. Cliquez sur le " +"champ et appuyez sur Ctrl-a pour tout sélectionner." + +#: wp-admin/options-reading.php:15 +msgid "Reading Settings" +msgstr "Options de lecture" + +#: wp-admin/options-reading.php:50 +msgid "" +"The character " +"encoding of your site (UTF-8 is recommended)" +msgstr "" +"L’encodage de caractères utilisé par votre site (UTF-8 est recommandé)" + +#: wp-admin/options-reading.php:56 +msgid "" +"This screen contains the settings that affect the display of your content." +msgstr "" +"Cet écran présente les réglages qui influent sur l’affichage de votre " +"contenu." + +#: wp-admin/options-reading.php:57 +msgid "" +"You can choose what’s displayed on the front page of your site. It can " +"be posts in reverse chronological order (classic blog), or a fixed/static " +"page. To set a static home page, you first need to create two Pages. One will become the front page, and the other will be where " +"your posts are displayed." +msgstr "" +"Vous pouvez choisir ce qui est affiché en page d’accueil de votre " +"site. Au choix, le mode « blog » classique (les " +"articles dans l’ordre chronologique inverse) ou une page statique. " +"Pour mettre en place une page statique, vous devez d’abord créer deux " +"pages : la première servira de page d’accueil, " +"la seconde affichera vos articles." + +#: wp-admin/options-reading.php:58 +msgid "" +"You can also control the display of your content in RSS feeds, including the " +"maximum numbers of posts to display and whether to show full text or a " +"summary." +msgstr "" +"Vous pouvez également contrôler l’affichage de votre contenu dans les " +"flux RSS, comme le nombre maximum d’entrées à afficher, et s’il " +"faut afficher l’article en entier ou juste un résumé." + +#: wp-admin/options-reading.php:64 wp-admin/options-reading.php:145 +#: wp-admin/options-reading.php:146 +msgid "Site Visibility" +msgstr "Visibilité du site" + +#: wp-admin/options-reading.php:64 wp-admin/options-reading.php:145 +#: wp-admin/options-reading.php:146 +msgid "Search Engine Visibility" +msgstr "Visibilité pour les moteurs de recherche" + +#: wp-admin/options-reading.php:65 +msgid "" +"You can choose whether or not your site will be crawled by robots, ping " +"services, and spiders. If you want those services to ignore your site, click " +"the checkbox next to “Discourage search engines from indexing this " +"site” and click the Save Changes button at the bottom of the screen. " +"Note that your privacy is not complete; your site is still visible on the " +"web." +msgstr "" +"Vous pouvez choisir si votre site est parcouru par les robots et autres " +"logiciels automatisés, ou non. Si vous préférez que ces services ignorent " +"votre site, cliquez sur le bouton radio marqué « Demander aux " +"moteurs de recherche de ne pas indexer ce site » et cliquez sur " +"le bouton « Enregistrer les modifications » en bas de " +"l’écran. Notez bien que votre vie privée n’est pas " +"assurée : votre site reste visible de tous sur le Web." + +#: wp-admin/options-reading.php:66 +msgid "" +"When this setting is in effect, a reminder is shown in the Right Now box of " +"the Dashboard that says, “Search Engines Discouraged,” to remind " +"you that your site is not being crawled." +msgstr "" +"Quand ce réglage prend effet, un rappel apparaît dans la section «" +" Aujourd’hui » du Tableau de Bord, indiquant «" +" Moteurs de recherche refusés », pour vous rappeler que " +"votre site n’est pas parcouru automatiquement." + +#: wp-admin/options-reading.php:71 +msgid "" +"Documentation on Reading Settings" +msgstr "" +"Documentation sur les réglages de la lecture (en)" + +#: wp-admin/options-reading.php:87 +msgid "Encoding for pages and feeds" +msgstr "Encodage pour les pages et les flux RSS" + +#: wp-admin/options-reading.php:113 +msgid "A static page (select below)" +msgstr "Une page statique (choisir ci-dessous)" + +#: wp-admin/options-reading.php:117 +msgid "Front page: %s" +msgstr "Page d’accueil : %s" + +#: wp-admin/options-reading.php:118 +msgid "Posts page: %s" +msgstr "Page des articles : %s" + +#: wp-admin/options-reading.php:121 +msgid "Warning: these pages should not be the same!" +msgstr "" +"Attention : ces pages ne devraient pas être les " +"mêmes !" + +#: wp-admin/options-reading.php:127 +msgid "Blog pages show at most" +msgstr "Les pages du site doivent afficher au plus" + +#: wp-admin/options-reading.php:129 +msgid "posts" +msgstr "articles" + +#: wp-admin/options-reading.php:133 +msgid "Syndication feeds show the most recent" +msgstr "Les flux de syndication affichent les derniers" + +#: wp-admin/options-reading.php:134 +msgid "items" +msgstr "éléments" + +#: wp-admin/options-reading.php:137 wp-admin/options-reading.php:138 +msgid "For each article in a feed, show" +msgstr "Pour chaque article d’un flux, fournir" + +#: wp-admin/options-reading.php:139 +msgid "Full text" +msgstr "Le texte complet" + +#: wp-admin/options-reading.php:140 +msgid "Summary" +msgstr "L’extrait" + +#: wp-admin/options-reading.php:149 +msgid "Allow search engines to index this site" +msgstr "Autoiser les moteurs de recherche à indexer ce site" + +#: wp-admin/options-reading.php:151 wp-admin/options-reading.php:171 +msgid "Discourage search engines from indexing this site" +msgstr "Demander aux moteurs de recherche de ne pas indexer ce site" + +#: wp-admin/options-reading.php:152 +msgid "" +"Note: Neither of these options blocks access to your site — it is up " +"to search engines to honor your request." +msgstr "" +"Note : Aucune de ses options ne bloque l’accès à votre site " +"— c’est au moteur de recherche de respecter votre demande." + +#: wp-admin/options-reading.php:172 +msgid "It is up to search engines to honor this request." +msgstr "" +"Certains moteurs de recherche peuvent décider de l’indexer malgré tout." + +#: wp-admin/options-writing.php:15 +msgid "Writing Settings" +msgstr "Options d’écriture" + +#: wp-admin/options-writing.php:21 +msgid "" +"You can submit content in several different ways; this screen holds the " +"settings for all of them. The top section controls the editor within the " +"dashboard, while the rest control external publishing methods. For more " +"information on any of these methods, use the documentation links." +msgstr "" +"Vous disposez de plusieurs méthodes pour envoyer du contenu. Cet écran vous " +"présente les réglages de chacune. La première section gère l’éditeur " +"de l’administration de WordPress, tandis que les autres gèrent les " +"méthodes externes. Pour obtenir plus d’informations sur toutes ces " +"méthodes, suivez les liens vers la documentation." + +#: wp-admin/options-writing.php:28 wp-admin/tools.php:17 +msgid "" +"Press This is a bookmarklet that makes it easy to blog about something you " +"come across on the web. You can use it to just grab a link, or to post an " +"excerpt. Press This will even allow you to choose from images included on " +"the page and use them in your post. Just drag the Press This link on this " +"screen to your bookmarks bar in your browser, and you’ll be on your " +"way to easier content creation. Clicking on it while on another website " +"opens a popup window with all these options." +msgstr "" +"« Publier un article » est un bookmarklet qui vous " +"facilite la publication sur votre site quand vous voyez une page " +"intéressante sur Internet. Vous pouvez l’utiliser simplement pour " +"publier un lien, ou pour en publier un extrait. « Publier un " +"article » vous permet même de choisir parmi les images incluses " +"dans la page, et de les utiliser dans votre article. Glissez simplement le " +"lien « Publier un article » dans la barre de liens de " +"votre navigateur, et à vous la publication facile ! En cliquant dessus " +"lors de la visite d’un site, une fenêtre s’ouvrira avec toutes " +"les options utiles." + +#: wp-admin/options-writing.php:35 +msgid "Post Via Email" +msgstr "Envoi d’article par e-mail" + +#: wp-admin/options-writing.php:36 +msgid "" +"Post via email settings allow you to send your WordPress install an email " +"with the content of your post. You must set up a secret e-mail account with " +"POP3 access to use this, and any mail received at this address will be " +"posted, so it’s a good idea to keep this address very secret." +msgstr "" +"Les réglages de publication par e-mail vous permettant d’envoyer à " +"votre installation WordPress un e-mail dont le contenu sera publié dans un " +"article. Vous devez définir un compte e-mail secret avec une adresse POP3. " +"Tout message reçu à cette adresse sera publié. Il vaut donc mieux garder " +"cette adresse à l’abri des regards. " + +#: wp-admin/options-writing.php:50 wp-admin/options-writing.php:174 +msgid "Update Services" +msgstr "Services de mise à jour" + +#: wp-admin/options-writing.php:51 +msgid "" +"If desired, WordPress will automatically alert various services of your new " +"posts." +msgstr "" +"Si vous le souhaitez, WordPress peut automatiquement informer différents " +"services en ligne de vos nouvelles publications." + +#: wp-admin/options-writing.php:57 +msgid "" +"Documentation on Writing Settings" +msgstr "" +"Documentation sur les réglages de l’écriture (en)" + +#: wp-admin/options-writing.php:73 wp-admin/options-writing.php:74 +msgid "Formatting" +msgstr "Mise en forme" + +#: wp-admin/options-writing.php:77 +msgid "" +"Convert emoticons like :-) and :-P to graphics on " +"display" +msgstr "" +"Convertir les émoticônes, comme :-) et :-P, en " +"images lors de l’affichage" + +#: wp-admin/options-writing.php:78 +msgid "WordPress should correct invalidly nested XHTML automatically" +msgstr "WordPress doit automatiquement corriger les balises XHTML non valides" + +#: wp-admin/options-writing.php:82 +msgid "Default Post Category" +msgstr "Catégorie par défaut des articles" + +#: wp-admin/options-writing.php:94 +msgid "Default Post Format" +msgstr "Format par défaut des articles" + +#: wp-admin/options-writing.php:108 +msgid "Default Link Category" +msgstr "Catégorie par défaut des liens" + +#: wp-admin/options-writing.php:124 wp-admin/tools.php:42 +msgid "" +"Press This is a bookmarklet: a little app that runs in your browser and lets " +"you grab bits of the web." +msgstr "" +"Ceci est un bookmarklet : une petite application qui se lance dans " +"votre navigateur, et vous permet de récupérer des portions du Web pour les " +"bloguer." + +#: wp-admin/options-writing.php:125 wp-admin/tools.php:44 +msgid "" +"Use Press This to clip text, images and videos from any web page. Then edit " +"and add more straight from Press This before you save or publish it in a " +"post on your site." +msgstr "" +"Utilisez-le pour récupérer du texte, des images et des vidéos depuis n’" +"importe quelle page Web. Puis modifiez l’article et ajoutez vos " +"propres textes directement dans le bookmarklet, avant d’enregistrer le " +"tout ou de le publier dans un article sur votre site." + +#: wp-admin/options-writing.php:126 wp-admin/tools.php:45 +msgid "" +"Drag-and-drop the following link to your bookmarks bar or right click it and " +"add it to your favorites for a posting shortcut." +msgstr "" +"Glissez le lien suivant dans votre barre de favoris, ou faites un clic-droit " +"et ajoutez-le à vos favoris pour obtenir un raccourci de publication." + +#: wp-admin/options-writing.php:129 wp-admin/tools.php:48 +msgid "" +"If your bookmarks toolbar is hidden: copy the code below, open your " +"Bookmarks manager, create new bookmark, type Press This into the name field " +"and paste the code into the URL field." +msgstr "" +"Si votre barre de favoris est cachée : copier le code ci-dessous, " +"ouvrez votre gestionnaire de favoris, créez-en un nouveau, saisissez «" +" Publier un article » comme nom, et collez le code dans le " +"champ d’adresse Web." + +#: wp-admin/options-writing.php:137 +msgid "Post via e-mail" +msgstr "Envoi d’article par e-mail" + +#: wp-admin/options-writing.php:138 +msgid "" +"To post to WordPress by e-mail you must set up a secret e-mail account with " +"POP3 access. Any mail received at this address will be posted, so it’s " +"a good idea to keep this address very secret. Here are three random strings " +"you could use: %s, %s, %s." +msgstr "" +"Pour publier dans WordPress par e-mail, vous devez définir un compte e-mail " +"secret avec une adresse POP3. Tout e-mail reçu à cette adresse sera publié. " +"Il vaut donc mieux garder cette adresse à l’abri des regards. Voici " +"trois chaînes aléatoires que vous pourriez utiliser : %s, " +"%s, %s." + +#: wp-admin/options-writing.php:142 +msgid "Mail Server" +msgstr "Serveur de messagerie" + +#: wp-admin/options-writing.php:144 +msgid "Port" +msgstr "Port" + +#: wp-admin/options-writing.php:149 +msgid "Login Name" +msgstr "Identifiant" + +#: wp-admin/options-writing.php:159 +msgid "Default Mail Category" +msgstr "Catégorie par défaut des articles envoyés par e-mail" + +#: wp-admin/options-writing.php:178 +msgid "" +"When you publish a new post, WordPress automatically notifies the following " +"site update services. For more about this, see Update Services on the Codex. Separate " +"multiple service URLs with " +"line breaks." +msgstr "" +"Quand vous publiez un nouvel article, WordPress peut notifier un service de " +"mise à jour. Une explication se trouve sur la page Update Services du Codex anglophone. " +"Séparez les adresses web par des retours à la ligne." + +#: wp-admin/options-writing.php:184 +msgid "" +"WordPress is not notifying any Update Services because of your site’s visibility settings." +msgstr "" +"WordPress ne notifie aucun des services de notification (en), du fait des réglages de vie privée de votre site." + +#: wp-admin/options.php:143 +msgid "ERROR: options page not found." +msgstr "" +"ERREUR : La page d’options est introuvable." + +#: wp-admin/options.php:147 +msgid "" +"You do not have sufficient permissions to modify unregistered settings for " +"this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour modifier les réglages non " +"enregistrés de ce site." + +#: wp-admin/options.php:170 +msgid "" +"The %1$s setting is unregistered. Unregistered settings are " +"deprecated. See http://codex.wordpress.org/Settings_API" +msgstr "" +"L’option %1$s n’est pas enregistrée. Les options " +"non enregistrées sont obsolètes. Consultez la documentation sur la page " +"http://codex.wordpress.org/Settings_API" + +#: wp-admin/options.php:204 +msgid "All Settings" +msgstr "Toutes les options" + +#: wp-admin/plugin-editor.php:18 +msgid "You do not have sufficient permissions to edit plugins for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour modifier les extensions de " +"ce site." + +#: wp-admin/plugin-editor.php:20 +msgid "Edit Plugins" +msgstr "Modifier les extensions" + +#: wp-admin/plugin-editor.php:28 +msgid "There are no plugins installed on this site." +msgstr "Il n’y a pas d’options pour ce widget sur ce site." + +#: wp-admin/plugin-editor.php:108 +msgid "No such file exists! Double check the name and try again." +msgstr "" +"Ce fichier n’existe pas ! Veuillez vérifier son nom et réessayer." + +#: wp-admin/plugin-editor.php:115 +msgid "Files of this type are not editable." +msgstr "Les fichiers de ce type ne sont pas éditables." + +#: wp-admin/plugin-editor.php:123 +msgid "" +"You can use the editor to make changes to any of your plugins’ " +"individual PHP files. Be aware that if you make changes, plugins updates " +"will overwrite your customizations." +msgstr "" +"Vous pouvez utiliser l’éditeur pour modifier n’importe quel " +"fichier de vos extensions. Soyez cependant conscient que si vous modifiez " +"les fichiers, les mises à jour les annuleront..." + +#: wp-admin/plugin-editor.php:124 +msgid "" +"Choose a plugin to edit from the menu in the upper right and click the " +"Select button. Click once on any file name to load it in the editor, and " +"make your changes. Don’t forget to save your changes (Update File) " +"when you’re finished." +msgstr "" +"Choisissez une extension à modifier dans le menu en haut à droite, et " +"cliquez sur le bouton « Sélectionner »." + +#: wp-admin/plugin-editor.php:125 +msgid "" +"The Documentation menu below the editor lists the PHP functions recognized " +"in the plugin file. Clicking Look Up takes you to a web page about that " +"particular function." +msgstr "" +"Le menu « Documentation », situé sous l’éditeur, " +"liste les fonctions PHP reconnues dans le fichier de l’extension. En " +"cliquant sur « Consulter », vous serez envoyé sur une " +"page web documentant cette fonction." + +#: wp-admin/plugin-editor.php:126 wp-admin/theme-editor.php:30 +msgid "" +"In the editing area the Tab key enters a tab character. To move below this " +"area by pressing Tab, press the Esc key followed by the Tab key." +msgstr "" +"Dans la zone d’édition, la touche Tab ajouter un caractère de " +"tabulation. Pour sortir de cette zone en pressant cette touche, combinez-la " +"avec la touche Esc : Esc-Tab." + +#: wp-admin/plugin-editor.php:127 +msgid "" +"If you want to make changes but don’t want them to be overwritten when " +"the plugin is updated, you may be ready to think about writing your own " +"plugin. For information on how to edit plugins, write your own from scratch, " +"or just better understand their anatomy, check out the links below." +msgstr "" +"Si vous voulez faire des modifications et ne pas les perdre à la prochaine " +"mise à jour, cela signifie que vous êtes prêt à écrire votre propre " +"extension. Pour obtenir des informations sur la manière de modifier une " +"extension ou d’en créer une, ou simplement pour comprendre leur " +"fonctionnement, suivez les liens ci-dessous." + +#: wp-admin/plugin-editor.php:128 wp-admin/theme-editor.php:34 +msgid "" +"Any edits to files from this screen will be reflected on all sites in the " +"network." +msgstr "" +"Toute modification aux fichiers de cet écran affectera l’ensemble des " +"sites du réseau." + +#: wp-admin/plugin-editor.php:133 +msgid "" +"Documentation on Editing Plugins" +msgstr "" +"Documentation sur l’édition des extensions (en)" + +#: wp-admin/plugin-editor.php:134 +msgid "" +"Documentation on Writing Plugins" +msgstr "" +"Documentation sur la création d’extensions (en)" + +#: wp-admin/plugin-editor.php:149 wp-admin/theme-editor.php:115 +msgid "Function Name…" +msgstr "Nom de fonction…" + +#: wp-admin/plugin-editor.php:160 wp-admin/theme-editor.php:127 +msgid "File edited successfully." +msgstr "Le fichier a bien été modifié." + +#: wp-admin/plugin-editor.php:162 +msgid "" +"This plugin has been deactivated because your changes resulted in a " +"fatal error." +msgstr "" +"Cette extension a été désactivée, car vos modifications ont abouti à une " +"erreur fatale" + +#: wp-admin/plugin-editor.php:178 +msgid "Editing %s (active)" +msgstr "Modification de %s (activé)" + +#: wp-admin/plugin-editor.php:180 +msgid "Browsing %s (active)" +msgstr "Contenu de %s (activé)" + +#: wp-admin/plugin-editor.php:183 +msgid "Editing %s (inactive)" +msgstr "Modification de %s (désactivé)" + +#: wp-admin/plugin-editor.php:185 +msgid "Browsing %s (inactive)" +msgstr "Contenu de %s (désactivée)" + +#: wp-admin/plugin-editor.php:191 +msgid "Select plugin to edit:" +msgstr "Sélectionnez l’extension à modifier :" + +#: wp-admin/plugin-editor.php:213 +msgid "Plugin Files" +msgstr "Fichiers de l’extension" + +#: wp-admin/plugin-editor.php:242 wp-admin/theme-editor.php:210 +msgid "Documentation:" +msgstr "Documentation :" + +#: wp-admin/plugin-editor.php:242 wp-admin/theme-editor.php:212 +msgid "Look Up" +msgstr "Consulter" + +#: wp-admin/plugin-editor.php:246 +msgid "" +"Warning: Making changes to active plugins is not " +"recommended. If your changes cause a fatal error, the plugin will be " +"automatically deactivated." +msgstr "" +"Attention : il n’est pas recommandé de modifier " +"des extensions activées. Si vos modifications amènent une erreur fatale, " +"l’extension sera automatiquement désactivée." + +#: wp-admin/plugin-editor.php:252 +msgid "Update File and Attempt to Reactivate" +msgstr "Mettre à jour le fichier et tenter de réactiver l’extension" + +#: wp-admin/plugin-editor.php:254 wp-admin/theme-editor.php:223 +msgid "Update File" +msgstr "Mettre à jour le fichier" + +#: wp-admin/plugin-editor.php:259 wp-admin/theme-editor.php:225 +msgid "" +"You need to make this file writable before you can save your changes. See the Codex " +"for more information." +msgstr "" +"Vous devez rendre ce fichier accessible en écriture avant de pouvoir " +"enregistrer vos modifications. Lire la documentation CHMOD pour plus d’informations." + +#: wp-admin/plugin-install.php:18 wp-admin/update.php:93 +#: wp-admin/update.php:124 +msgid "You do not have sufficient permissions to install plugins on this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour installer des extensions " +"sur ce site." + +#: wp-admin/plugin-install.php:29 +msgid "Install Plugins" +msgstr "Installer des extensions" + +#: wp-admin/plugin-install.php:52 +msgid "" +"Plugins hook into WordPress to extend its functionality with custom " +"features. Plugins are developed independently from the core WordPress " +"application by thousands of developers all over the world. All plugins in " +"the official WordPress.org Plugin " +"Directory are compatible with the license WordPress uses. You can find " +"new plugins to install by searching or browsing the Directory right here in " +"your own Plugins section." +msgstr "" +"Les extensions s’ajoutent à WordPress afin d’ étendre ses " +"fonctionnalités par le biais de fonctions personnalisées. Les extensions " +"sont développées indépendamment du code de WordPress, par des milliers de " +"développeurs à travers le monde. Toutes les extensions présentes dans le dépôt officiel d’extensions de WordPress." +"org utilisent une licence compatible avec celle de WordPress. Vous " +"pouvez trouver de nouvelles extensions à installer en lançant une recherche " +"ou en parcourant le dépôt directement depuis la présente page." + +#: wp-admin/plugin-install.php:56 +msgid "Adding Plugins" +msgstr "Ajout d’extensions" + +#: wp-admin/plugin-install.php:58 +msgid "" +"If you know what you’re looking for, Search is your best bet. The " +"Search screen has options to search the WordPress.org Plugin Directory for a " +"particular Term, Author, or Tag. You can also search the directory by " +"selecting popular tags. Tags in larger type mean more plugins have been " +"labeled with that tag." +msgstr "" +"Si vous savez ce que vous voulez, commencez par le champ « " +"Recherche » : il vous permet de lancer une recherche sur le " +"dépôt d’extensions de WordPress.org, pour un terme, un auteur, ou un " +"mot-clé particulier. Vous pouvez également lancer une recherche en cliquant " +"sur un des mots-clés populaires. Plus un mot-clé est grand, plus il fait " +"référence à un grand nombre d’extensions." + +#: wp-admin/plugin-install.php:59 +msgid "" +"If you just want to get an idea of what’s available, you can browse " +"Featured, Popular, and Newest plugins by using the links in the upper left " +"of the screen. These sections rotate regularly." +msgstr "" +"Si vous voulez juste voir ce qu’offre le dépôt, vous pouvez parcourir " +"les extensions les plus populaires, les plus récentes ou celles mises en " +"avant en cliquant sur les liens proposés. Ces sections changent " +"régulièrement." + +#: wp-admin/plugin-install.php:60 +msgid "" +"You can also browse a user’s favorite plugins, by using the Favorites " +"link in the upper left of the screen and entering their WordPress.org " +"username." +msgstr "" +"Vous pouvez voir les extensions préférées d’un utililsateur en " +"utilisant le lien Préférées situé en haut à gauche de l’écran, et en " +"renseignant leur identifiant WordPress.org" + +#: wp-admin/plugin-install.php:61 +msgid "" +"If you want to install a plugin that you’ve downloaded elsewhere, " +"click the Upload link in the upper left. You will be prompted to upload the ." +"zip package, and once uploaded, you can activate the new plugin." +msgstr "" +"Si vous voulez installer une extension que vous avez téléchargée depuis un " +"site tiers, cliquez sur le lien « Envoyer ». Il vous " +"sera demandé d’indiquer le fichier .zip à mettre en ligne, et ceci " +"fait, vous pourrez activer l’extension." + +#: wp-admin/plugin-install.php:66 +msgid "" +"Documentation on Installing Plugins" +msgstr "" +"Documentation sur l’installation des extensions (en)" + +#: wp-admin/plugins.php:13 +msgid "You do not have sufficient permissions to manage plugins for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour gérer les extensions de ce " +"site." + +#: wp-admin/plugins.php:31 wp-admin/plugins.php:66 wp-admin/plugins.php:132 +msgid "" +"You do not have sufficient permissions to activate plugins for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour activer les extensions de " +"ce site." + +#: wp-admin/plugins.php:113 wp-admin/update-core.php:222 +#: wp-admin/update-core.php:279 wp-admin/update-core.php:570 +#: wp-admin/update-core.php:575 +msgid "Update Plugins" +msgstr "Mettre à jour les extensions" + +#: wp-admin/plugins.php:155 wp-admin/plugins.php:175 +msgid "" +"You do not have sufficient permissions to deactivate plugins for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour désactiver les extensions " +"de ce site." + +#: wp-admin/plugins.php:206 +msgid "You do not have sufficient permissions to delete plugins for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour supprimer les extensions de " +"ce site." + +#: wp-admin/plugins.php:263 +msgid "Delete Plugin" +msgid_plural "Delete Plugins" +msgstr[0] "Supprimer l’extension" +msgstr[1] "Supprimer les extensions" + +#: wp-admin/plugins.php:266 +msgid "This plugin may be active on other sites in the network." +msgid_plural "These plugins may be active on other sites in the network." +msgstr[0] "" +"Cette extension peut uniquement être activée sur l’ensemble des sites " +"du réseau." +msgstr[1] "" +"Ces extensions peuvent uniquement être activées sur l’ensemble des " +"sites du réseau." + +#: wp-admin/plugins.php:268 +msgid "You are about to remove the following plugin:" +msgid_plural "You are about to remove the following plugins:" +msgstr[0] "" +"Vous êtes sur le point de supprimer l’extension suivante :" +msgstr[1] "Vous êtes sur le point de supprimer les extensions suivantes :" + +#. translators: 1: plugin name, 2: plugin author +#: wp-admin/plugins.php:275 +msgid "" +"%1$s by %2$s (will also delete its data)" +msgstr "" +"%1$s par %2$s (attention : supprimera " +"également les données liées)" + +#. translators: 1: plugin name, 2: plugin author +#: wp-admin/plugins.php:279 +msgid "%1$s by %2$s" +msgstr "%1$s par %2$s" + +#: wp-admin/plugins.php:286 +msgid "Are you sure you wish to delete these files and data?" +msgstr "Vouslez-vous vraiment supprimer ces fichiers et données ?" + +#: wp-admin/plugins.php:288 +msgid "Are you sure you wish to delete these files?" +msgstr "Voulez-vous vraiment supprimer ces fichiers ?" + +#: wp-admin/plugins.php:298 +msgid "Yes, Delete these files and data" +msgstr "Oui, supprimer ces fichiers et les données" + +#: wp-admin/plugins.php:298 +msgid "Yes, Delete these files" +msgstr "Oui, supprimer ces fichiers" + +#: wp-admin/plugins.php:301 +msgid "No, Return me to the plugin list" +msgstr "Non, retourner à la liste des extensions" + +#: wp-admin/plugins.php:304 +msgid "Click to view entire list of files which will be deleted" +msgstr "Cliquez pour voir la liste des fichiers qui seront supprimés" + +#: wp-admin/plugins.php:336 +msgctxt "plugins per page (screen options)" +msgid "Plugins" +msgstr "Extensions" + +#: wp-admin/plugins.php:342 +msgid "" +"Plugins extend and expand the functionality of WordPress. Once a plugin is " +"installed, you may activate it or deactivate it here." +msgstr "" +"Les extensions étendent les fonctionnalités de WordPress. Une fois une " +"extension installée, vous pouvez l’activer ou la désactiver ici." + +#: wp-admin/plugins.php:343 +msgid "" +"You can find additional plugins for your site by using the Plugin Browser/Installer functionality or by browsing the WordPress Plugin Directory directly and " +"installing new plugins manually. To manually install a plugin you generally " +"just need to upload the plugin file into your /wp-content/plugins directory. Once a plugin has been installed, you can activate it here." +msgstr "" +"Vous pouvez trouver d’autres extensions pour votre site au moyen de la " +"fonctionnalité de découverte/installation d’" +"extensions, ou en vous rendant sur le répertoire des extensions WordPress et en les installant " +"manuellement. Pour installer une extension manuellement, il vous " +"suffit généralement de mettre ses fichiers en ligne dans le dossier /" +"wp-content/plugins. Ceci fait, vous pourrez activer cette extension " +"depuis la présente page." + +#: wp-admin/plugins.php:347 +msgid "Troubleshooting" +msgstr "Diagnostic" + +#: wp-admin/plugins.php:349 +msgid "" +"Most of the time, plugins play nicely with the core of WordPress and with " +"other plugins. Sometimes, though, a plugin’s code will get in the way " +"of another plugin, causing compatibility issues. If your site starts doing " +"strange things, this may be the problem. Try deactivating all your plugins " +"and re-activating them in various combinations until you isolate which one" +"(s) caused the issue." +msgstr "" +"La plupart du temps, les extensions fonctionnent comme il le faut, tant avec " +"WordPress qu’entre elles. Mais parfois, les ajouts d’une " +"extension peuvent empiéter sur celles d’une autre, ce qui provoque une " +"incompatibilité. Si votre site réagit bizarrement, le problème vient peut-" +"être de là. Essayez de désactiver toutes les extensions, puis de les " +"réactiver une à une pour trouver celle(s) en cause." + +#: wp-admin/plugins.php:350 +msgid "" +"If something goes wrong with a plugin and you can’t use WordPress, " +"delete or rename that file in the %s directory and it will be " +"automatically deactivated." +msgstr "" +"Si une extension ne fonctionne pas correctement et que vous ne pouvez plus " +"utiliser WordPress, supprimez ou renommez son fichier dans le répertoire " +"%s et elle sera automatiquement désactivée." + +#: wp-admin/plugins.php:355 +msgid "" +"Documentation on Managing Plugins" +msgstr "" +"Documentation sur la gestion des extensions (en)" + +#: wp-admin/plugins.php:367 +msgid "" +"The plugin %s has been deactivated due to an " +"error: %s" +msgstr "" +"L’extension %s a été désactivée suit à " +"l’erreur : %s" + +#: wp-admin/plugins.php:373 +msgid "You cannot delete a plugin while it is active on the main site." +msgstr "" +"Vous ne pouvez pas effacer une extension tant qu’elle est activée sur " +"le site principal." + +#: wp-admin/plugins.php:375 +msgid "" +"The plugin generated %d characters of unexpected output " +"during activation. If you notice “headers already sent” " +"messages, problems with syndication feeds or other issues, try deactivating " +"or removing this plugin." +msgstr "" +"L’extension a généré %d caractères d’affichage " +"inattendu lors de l’activation. Si vous voyez un message " +"« headers already sent » (Les en-têtes ont déjà " +"été envoyés), des problèmes avec les flux de syndication ou d’autres " +"erreurs, essayez de désactiver ou enlever cette extension." + +#: wp-admin/plugins.php:377 +msgid "" +"Plugin could not be activated because it triggered a fatal error." +msgstr "" +"L’extension n’a pu être activée, car elle a déclenché une " +"erreur fatale." + +#: wp-admin/plugins.php:392 +msgid "Plugin could not be deleted due to an error: %s" +msgstr "" +"L’extension n’a pu être supprimée suite à une erreur " +"fatale : %s" + +#: wp-admin/plugins.php:394 +msgid "The selected plugins have been deleted." +msgstr "Les extensions sélectionnées ont été supprimées." + +#: wp-admin/plugins.php:397 +msgid "Plugin activated." +msgstr "Extension activée" + +#: wp-admin/plugins.php:399 +msgid "Selected plugins activated." +msgstr "Les extensions sélectionnées ont été activées." + +#: wp-admin/plugins.php:401 +msgid "Plugin deactivated." +msgstr "Extension désactivée" + +#: wp-admin/plugins.php:403 +msgid "Selected plugins deactivated." +msgstr "Les extensions sélectionnées ont été désactivées." + +#: wp-admin/plugins.php:405 +msgid "No out of date plugins were selected." +msgstr "Aucune extension périmée n’a été sélectionnée." + +#: wp-admin/plugins.php:423 +msgid "Search Installed Plugins" +msgstr "Chercher parmi les extensions installées" + +#: wp-admin/post.php:146 +msgid "" +"You can’t edit this item because it is in the Trash. Please restore it " +"and try again." +msgstr "" +"Vous ne pouvez pas modifier ce contenu, car il est dans la Corbeille. Sortez-" +"l’en, puis réessayez." + +#: wp-admin/post.php:233 +msgid "The item you are trying to move to the Trash no longer exists." +msgstr "" +"L’élément que vous essayez de placer dans la Corbeille n’existe " +"plus." + +#: wp-admin/post.php:243 +msgid "You cannot move this item to the Trash. %s is currently editing." +msgstr "" +"Vous ne pouvez pas déplacer ce contenu dans la Corbeille. %s est en train de " +"le modifier." + +#: wp-admin/post.php:257 +msgid "The item you are trying to restore from the Trash no longer exists." +msgstr "" +"L’élément que vous essayez de sortir de la Corbeille n’existe " +"plus." + +#: wp-admin/post.php:263 +msgid "You are not allowed to move this item out of the Trash." +msgstr "" +"Vous n’avez pas l’autorisation de déplacer ce contenu en dehors " +"de la Corbeille." + +#: wp-admin/post.php:276 +msgid "This item has already been deleted." +msgstr "Cet élément a déjà été supprimé." + +#: wp-admin/press-this.php:127 +msgid "Embed Code" +msgstr "Code embarqué" + +#: wp-admin/press-this.php:130 +msgid "Insert Video" +msgstr "Insérer la vidéo" + +#: wp-admin/press-this.php:156 +msgid "Click to insert." +msgstr "Cliquez pour insérer." + +#: wp-admin/press-this.php:230 +msgid "Unable to retrieve images or no images on page." +msgstr "" +"Impossible de récupérer d’image ou il n’y a pas d’image " +"dans cette page." + +#: wp-admin/press-this.php:291 +msgid "Add Photos" +msgstr "Ajouter des images" + +#: wp-admin/press-this.php:291 +msgid "click images to select" +msgstr "cliquez sur les images pour les sélectionner" + +#: wp-admin/press-this.php:291 +msgid "Add from URL" +msgstr "Ajouter depuis une adresse web" + +#: wp-admin/press-this.php:481 +msgid "Post Format:" +msgstr "Format d’article :" + +#: wp-admin/press-this.php:518 +msgid "You cannot modify this Taxonomy." +msgstr "Vous ne pouvez pas modifier cette taxinomie." + +#: wp-admin/press-this.php:579 +msgid "Your post has been saved." +msgstr "Votre article a été enregistré." + +#: wp-admin/press-this.php:580 +msgid "View post" +msgstr "Afficher l’article" + +#: wp-admin/press-this.php:582 +msgid "Close Window" +msgstr "Fermer la fenêtre" + +#: wp-admin/press-this.php:592 +msgid "Loading…" +msgstr "Chargement…" + +#: wp-admin/press-this.php:612 +msgid "via " +msgstr "via" + +#: wp-admin/press-this.php:620 +msgid "Add:" +msgstr "Ajouter :" + +#: wp-admin/press-this.php:624 wp-admin/press-this.php:625 +msgid "Insert an Image" +msgstr "Insérer une image" + +#: wp-admin/press-this.php:629 +msgid "Embed a Video" +msgstr "Ajouter un vidéo" + +#: wp-admin/revision.php:76 +msgid "Compare Revisions of “%1$s”" +msgstr "Comparer les versions de « %1$s »" + +#: wp-admin/revision.php:103 +msgid "This screen is used for managing your content revisions." +msgstr "Cet écran est utilisé pour gérer les révisions de vos contenus." + +#: wp-admin/revision.php:104 +msgid "" +"Revisions are saved copies of your post or page, which are periodically " +"created as you update your content. The red text on the left shows the " +"content that was removed. The green text on the right shows the content that " +"was added." +msgstr "" +"Les révisions sont des copies de votre article ou votre page, périodiquement " +"créées tandis que vous modifiez votre contenu. Sur la gauche, le texte en " +"rouge indique le contenu qui a été enlevé. Sur la droite, le texte en vert " +"indique le contenu qui a été ajouté." + +#: wp-admin/revision.php:105 +msgid "From this screen you can review, compare, and restore revisions:" +msgstr "" +"Depuis cet écran, vous pouvez visualiser, comparer et rétablir les " +"révisions :" + +#: wp-admin/revision.php:106 +msgid "" +"To navigate between revisions, drag the slider handle left or right or use the Previous or Next buttons." +msgstr "" +"Pour naviguer entre les révisions, faites glisser le curseur vers la " +"gauche ou vers la droite ou utilisez les boutons " +"Précédente ou Suivante." + +#: wp-admin/revision.php:107 +msgid "" +"Compare two different revisions by selecting the “Compare any " +"two revisions” box to the side." +msgstr "" +"Comparez deux révisions différentes en cochant la case « " +"Comparer n’importe quelles révisions sur le côté." + +#: wp-admin/revision.php:108 +msgid "To restore a revision, click Restore This Revision." +msgstr "" +"Pour rétablir cette révision, cliquez sur « Rétablir " +"cette révision »." + +#: wp-admin/revision.php:117 +msgid "" +"Revisions Management" +msgstr "" +"Gestion des révisions (en)" + +#: wp-admin/revision.php:138 +msgctxt "Button label for a previous revision" +msgid "Previous" +msgstr "Précédente" + +#: wp-admin/revision.php:142 +msgctxt "Button label for a next revision" +msgid "Next" +msgstr "Suivante" + +#: wp-admin/revision.php:156 +msgid "Compare any two revisions" +msgstr "Comparer n’importe quelles révisions" + +#: wp-admin/revision.php:165 +msgctxt "Followed by post revision info" +msgid "From:" +msgstr "Depuis :" + +#: wp-admin/revision.php:167 +msgctxt "Followed by post revision info" +msgid "To:" +msgstr "Vers :" + +#: wp-admin/revision.php:173 +msgid "Autosave by %s" +msgstr "Sauvegarde automatique par %s" + +#: wp-admin/revision.php:176 +msgid "Current Revision by %s" +msgstr "Révision actuelle par %s" + +#: wp-admin/revision.php:179 +msgid "Revision by %s" +msgstr "Révision par %s" + +#: wp-admin/revision.php:194 +msgid "Restore This Autosave" +msgstr "Rétablir cette sauvegarde automatique" + +#: wp-admin/revision.php:196 +msgid "Restore This Revision" +msgstr "Rétablir cette révision" + +#: wp-admin/revision.php:208 +msgid "" +"Sorry, something went wrong. The requested comparison could not be loaded." +msgstr "" +"Désolé, quelque chose s’est mal déroulé. La comparaison demandée " +"n’a pas pu être chargée." + +#: wp-admin/setup-config.php:74 +msgid "" +"Sorry, I need a wp-config-sample.php file to work from. Please re-upload " +"this file from your WordPress installation." +msgstr "" +"Désolé, j’ai besoin d’un fichier wp-config-sample.php à partir " +"duquel travailler. Veuillez remettre ce fichier en ligne au sein de votre " +"installation WordPress." + +#: wp-admin/setup-config.php:78 +msgid "" +"The file 'wp-config.php' already exists. If you need to reset any of the " +"configuration items in this file, please delete it first. You may try installing now." +msgstr "" +"Le fichier wp-config.php existe déjà. Si vous devez mettre à " +"zéro n’importe quelle valeur de configuration dans ce fichier, " +"veuillez commencer par le supprimer. Vous pouvez essayer " +"l’installation maintenant." + +#: wp-admin/setup-config.php:82 +msgid "" +"The file 'wp-config.php' already exists one level above your WordPress " +"installation. If you need to reset any of the configuration items in this " +"file, please delete it first. You may try installing " +"now." +msgstr "" +"Le fichier wp-config.php existe déjà, un niveau au-dessus de " +"votre installation WordPress. Si vous devez mettre à zéro vos éléments de " +"configuration, veuillez d’abord effacer ce fichier. Vous pouvez " +"essayer de lancer l’installation." + +#: wp-admin/setup-config.php:103 +msgid "WordPress › Setup Configuration File" +msgstr "WordPress › Fichier de configuration" + +#: wp-admin/setup-config.php:118 +msgid "" +"Welcome to WordPress. Before getting started, we need some information on " +"the database. You will need to know the following items before proceeding." +msgstr "" +"Bienvenue dans WordPress. Avant de nous lancer, nous avons besoin de " +"certaines informations sur votre base de données. Il va vous falloir réunir " +"les informations suivantes pour continuer." + +#: wp-admin/setup-config.php:120 +msgid "Database name" +msgstr "Nom de la base de données" + +#: wp-admin/setup-config.php:121 +msgid "Database username" +msgstr "Nom d’utilisateur MySQL" + +#: wp-admin/setup-config.php:122 +msgid "Database password" +msgstr "Mot de passe de l’utilisateur" + +#: wp-admin/setup-config.php:123 +msgid "Database host" +msgstr "Adresse de la base de données" + +#: wp-admin/setup-config.php:124 +msgid "" +"Table prefix (if you want to run more than one WordPress in a single " +"database)" +msgstr "" +"Préfixe de table (si vous souhaitez avoir plusieurs WordPress sur une même " +"base de données)" + +#: wp-admin/setup-config.php:126 +msgid "" +"If for any reason this automatic file creation doesn’t work, don’" +"t worry. All this does is fill in the database information to a " +"configuration file. You may also simply open wp-config-sample.php in a text editor, fill in your information, and save it as wp-" +"config.php." +msgstr "" +"Si, pour quelque raison que ce soit, la création automatique du fichier ne " +"fonctionne pas, pas de panique. Tout ce qu’elle fait, c’est de " +"compléter le fichier de configuration avec les informations de connexion à " +"la base de données. Vous pouvez tout aussi bien ouvrir le fichier wp-" +"config-sample.php dans un éditeur de texte, y saisir les informations " +"en question, et enregistrer le fichier sous le nom wp-config.php." + +#: wp-admin/setup-config.php:127 +msgid "" +"In all likelihood, these items were supplied to you by your Web Host. If you " +"do not have this information, then you will need to contact them before you " +"can continue. If you’re all ready…" +msgstr "" +"Vous devriez normalement avoir reçu ces informations de la part de votre " +"hébergeur. Si vous ne les avez pas, il vous faudra contacter votre hébergeur " +"afin de continuer. Si vous êtes prêt…" + +#: wp-admin/setup-config.php:129 +msgid "Let’s go!" +msgstr "C’est parti !" + +#: wp-admin/setup-config.php:137 +msgid "" +"Below you should enter your database connection details. If you’re not " +"sure about these, contact your host." +msgstr "" +"Vous devez saisir ci-dessous les détails de connexion à votre base de " +"données. Si vous ne les connaissez pas, contactez votre hébergeur." + +#: wp-admin/setup-config.php:140 +msgid "Database Name" +msgstr "Nom de la base de données" + +#: wp-admin/setup-config.php:142 +msgid "The name of the database you want to run WP in." +msgstr "" +"Le nom de la base de données dans laquelle vous souhaitez installer " +"WordPress." + +#: wp-admin/setup-config.php:145 +msgid "User Name" +msgstr "Identifiant" + +#: wp-admin/setup-config.php:146 +msgctxt "example username" +msgid "username" +msgstr "utilisateur" + +#: wp-admin/setup-config.php:147 +msgid "Your MySQL username" +msgstr "Votre identifiant MySQL" + +#: wp-admin/setup-config.php:151 +msgctxt "example password" +msgid "password" +msgstr "mot de passe" + +#: wp-admin/setup-config.php:152 +msgid "…and your MySQL password." +msgstr "…et son mot de passe MySQL." + +#: wp-admin/setup-config.php:155 +msgid "Database Host" +msgstr "Adresse de la base de données" + +#: wp-admin/setup-config.php:157 +msgid "" +"You should be able to get this info from your web host, if localhost does not work." +msgstr "" +"Si localhost ne fonctionne pas, votre hébergeur doit pouvoir " +"vous donner la bonne information." + +#: wp-admin/setup-config.php:160 +msgid "Table Prefix" +msgstr "Préfixe des tables" + +#: wp-admin/setup-config.php:162 +msgid "" +"If you want to run multiple WordPress installations in a single database, " +"change this." +msgstr "" +"Si vous souhaitez faire tourner plusieurs installations de WordPress sur une " +"même base de données, modifiez ce réglage." + +#: wp-admin/setup-config.php:265 +msgid "Sorry, but I can’t write the wp-config.php file." +msgstr "" +"Désolé, mais je ne peux écrire dans le fichier wp-config.php." + +#: wp-admin/setup-config.php:266 +msgid "" +"You can create the wp-config.php manually and paste the " +"following text into it." +msgstr "" +"Vous pouvez créer le fichier wp-config.php à la main, en y " +"copiant/collant le texte suivant." + +#: wp-admin/setup-config.php:272 +msgid "After you’ve done that, click “Run the install.”" +msgstr "" +"Après cela, cliquez sur « Lancer l’installation " +"»." + +#: wp-admin/setup-config.php:273 wp-admin/setup-config.php:300 +msgid "Run the install" +msgstr "Lancer l’installation" + +#: wp-admin/setup-config.php:298 +msgid "" +"All right, sparky! You’ve made it through this part of the " +"installation. WordPress can now communicate with your database. If you are " +"ready, time now to…" +msgstr "" +"C’est parfait ! Vous avez passé la première partie de l’" +"installation. WordPress peut désormais communiquer avec votre base de " +"données. Si vous êtes prêt(e), il est maintenant temps de…" + +#: wp-admin/theme-editor.php:18 +msgid "You do not have sufficient permissions to edit templates for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour modifier les modèles de ce " +"site." + +#: wp-admin/theme-editor.php:20 +msgid "Edit Themes" +msgstr "Modifier les thèmes" + +#: wp-admin/theme-editor.php:27 +msgid "" +"You can use the Theme Editor to edit the individual CSS and PHP files which " +"make up your theme." +msgstr "" +"Vous pouvez utiliser l’éditeur de thème pour modifier les fichiers CSS " +"et PHP qui composent votre thème." + +#: wp-admin/theme-editor.php:28 +msgid "" +"Begin by choosing a theme to edit from the dropdown menu and clicking " +"Select. A list then appears of all the template files. Clicking once on any " +"file name causes the file to appear in the large Editor box." +msgstr "" +"Commencez par choisir un thème à modifier via le menu déroulant, et cliquez " +"sur « Sélectionner ». Une liste apparaîtra ensuite " +"avec tous les fichiers modèles. En cliquant sur n’importe quel de ces " +"fichiers, vous verrez son contenu apparaître dans l’éditeur." + +#: wp-admin/theme-editor.php:29 +msgid "" +"For PHP files, you can use the Documentation dropdown to select from " +"functions recognized in that file. Look Up takes you to a web page with " +"reference material about that particular function." +msgstr "" +"Pour les fichiers PHP, vous pouvez utiliser le menu déroulant « " +"Documentation » pour en apprendre plus sur les fonctions trouvées " +"dans le ce fichier. Le bouton « Consulter » vous " +"enverra sur la page dédiée de cette fonction." + +#: wp-admin/theme-editor.php:31 +msgid "After typing in your edits, click Update File." +msgstr "" +"Après avoir fait vos modifications, cliquez sur « Mettre à jour " +"le fichier »." + +#: wp-admin/theme-editor.php:32 +msgid "" +"Advice: think very carefully about your site crashing if " +"you are live-editing the theme currently in use." +msgstr "" +"Conseil : gardez bien en tête que si vous modifiez le " +"thème actuellement utilisé, vos visiteurs pourraient avoir une vision " +"déroutante de votre site..." + +#: wp-admin/theme-editor.php:33 +msgid "" +"Upgrading to a newer version of the same theme will override changes made " +"here. To avoid this, consider creating a child theme instead." +msgstr "" +"La mise à jour vers une nouvelle version du thème supprimera les " +"modifications que vous aurez faites. Pour éviter cela, nous vous conseillons " +"de passer plutôt par un Thème-Enfant (en)." + +#: wp-admin/theme-editor.php:39 +msgid "" +"Documentation on Theme Development" +msgstr "" +"Documentation sur le développement de thème (en)" + +#: wp-admin/theme-editor.php:40 wp-admin/themes.php:89 +msgid "" +"Documentation on Using Themes" +msgstr "" +"Documentation sur l’utilisation des thèmes (en)" + +#: wp-admin/theme-editor.php:41 +msgid "" +"Documentation on Editing Files" +msgstr "" +"Documentation sur l’édition des fichiers" + +#: wp-admin/theme-editor.php:42 +msgid "" +"Documentation on Template Tags" +msgstr "" +"Documentation sur les marqueurs des modèles (en)" + +#: wp-admin/theme-editor.php:56 wp-admin/theme-editor.php:59 +msgid "The requested theme does not exist." +msgstr "Le thème demandé n’existe pas." + +#: wp-admin/theme-editor.php:145 +msgid "Select theme to edit:" +msgstr "Sélectionnez le thème à modifier :" + +#: wp-admin/theme-editor.php:164 +msgid "This theme is broken." +msgstr "Le thème est cassé." + +#: wp-admin/theme-editor.php:171 +msgid "Templates" +msgstr "Modèles" + +#: wp-admin/theme-editor.php:173 +msgid "This child theme inherits templates from a parent theme, %s." +msgstr "Ce thème enfant hérite de certains modèles de son thème parent, %s." + +#: wp-admin/theme-editor.php:181 +msgctxt "Theme stylesheets in theme editor" +msgid "Styles" +msgstr "Styles" + +#: wp-admin/theme-editor.php:198 +msgid "Oops, no such file exists! Double check the name and try again, merci." +msgstr "" +"Oops, ce fichier n’existe pas ! Vérifiez son nom et réessayez, " +"merci." + +#: wp-admin/theme-editor.php:219 +msgid "This is a file in your current parent theme." +msgstr "Ceci est un fichier de votre thème parent actuel." + +#: wp-admin/theme-install.php:16 wp-admin/update.php:197 +#: wp-admin/update.php:227 +msgid "You do not have sufficient permissions to install themes on this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour installer des thèmes sur ce " +"site." + +#: wp-admin/theme-install.php:27 wp-admin/update.php:209 +msgid "Install Themes" +msgstr "Installer des thèmes" + +#: wp-admin/theme-install.php:40 +msgid "" +"You can find additional themes for your site by using the Theme Browser/" +"Installer on this screen, which will display themes from the WordPress.org Theme Directory. These themes are " +"designed and developed by third parties, are available free of charge, and " +"are compatible with the license WordPress uses." +msgstr "" +"Vous pouvez trouver plus de thèmes pour votre site en utilisant le " +"Navigateur/Installeur de thème sur cet écran, qui affiche les thèmes en " +"provenance du dépôt de thèmes de WordPress." +"org. Ces thèmes sont conçus et développés par des designers tiers, sont " +"gratuits et utilisent une licence compatible avec celle de WordPress." + +#: wp-admin/theme-install.php:41 +msgid "" +"You can Search for themes by keyword, author, or tag, or can get more " +"specific and search by criteria listed in the feature filter. Alternately, " +"you can browse the themes that are Featured, Newest, or Recently Updated. " +"When you find a theme you like, you can preview it or install it." +msgstr "" +"Vous pouvez chercher un thème par mot, par auteur ou par mot-clé. Vous " +"pouvez également donner plus de détails en sélectionnant les critères que " +"vous souhaitez. Autrement, vous pouvez parcourir les thèmes mis en avant, " +"les plus récents, ou récemment mis à jour. Quand vous aurez trouvé le thème " +"qu’il vous faut, vous pourrez le prévisualiser puis l’installer." + +#: wp-admin/theme-install.php:42 +msgid "" +"You can Upload a theme manually if you have already downloaded its ZIP " +"archive onto your computer (make sure it is from a trusted and original " +"source). You can also do it the old-fashioned way and copy a downloaded " +"theme’s folder via FTP into your /wp-content/themes " +"directory." +msgstr "" +"Si vous disposez d’un thème sous forme d’archive Zip sur votre " +"ordinateur, vous pouvez mettre en ligne ce fichier avec le lien Envoyer. " +"Assurez-vous bien que ce fichier provient d’une source de confiance. " +"Vous pouvez également le faire à l’ancienne, c’est-à-dire passer " +"par un client FTP pour déposer les fichiers dans le dossier /wp-content/" +"themes." + +#: wp-admin/theme-install.php:51 +msgid "" +"Once you have generated a list of themes, you can preview and install any of " +"them. Click on the thumbnail of the theme you’re interested in " +"previewing. It will open up in a full-screen Preview page to give you a " +"better idea of how that theme will look." +msgstr "" +"Une fois que vous avez généré une liste de thèmes, vous pouvez les " +"prévisualiser et les installer. Cliquez sur la miniature du thème que vous " +"souhaitez prévisualiser. Cela ouvrira une page de prévisualisation en plein " +"écran, afin de vous donner une meilleure idée de l’aspect de ce thème." + +#: wp-admin/theme-install.php:52 +msgid "" +"To install the theme so you can preview it with your site’s content " +"and customize its theme options, click the \"Install\" button at the top of " +"the left-hand pane. The theme files will be downloaded to your website " +"automatically. When this is complete, the theme is now available for " +"activation, which you can do by clicking the \"Activate\" link, or by " +"navigating to your Manage Themes screen and clicking the \"Live Preview\" " +"link under any installed theme’s thumbnail image." +msgstr "" +"Pour installer un thème dans le but de le prévisualiser avec le contenu de " +"votre site et d’en personnaliser les options, cliquez sur le bouton " +"« Installer » en haut du panneau de gauche. Les " +"fichiers du thème seront automatiquement téléchargés vers votre site. Ceci " +"fait, le thème sera disponible, et vous pourrez l’activer en cliquant " +"sur le lien « Activer », ou en vous rendant sur " +"l’écran « Gérer les thèmes » et en cliquant sur " +"le lien « Prévisualisation » situé sous la miniature " +"de chaque thème." + +#: wp-admin/theme-install.php:56 +msgid "Previewing and Installing" +msgstr "Voir l’aperçu et installer" + +#: wp-admin/theme-install.php:62 +msgid "" +"Documentation on Adding New Themes" +msgstr "" +"Documentation sur l’ajout de thèmes (en)" + +#: wp-admin/theme-install.php:75 +msgctxt "theme" +msgid "Manage Themes" +msgstr "Gérer les thèmes" + +#: wp-admin/themes.php:41 +msgid "Manage Themes" +msgstr "Gérer les thèmes" + +#: wp-admin/themes.php:46 +msgid "" +"Aside from the default theme included with your WordPress installation, " +"themes are designed and developed by third parties." +msgstr "" +"En dehors du thème par défaut inclus avec WordPress, les thèmes sont conçus " +"et développés par des designers tiers." + +#: wp-admin/themes.php:47 +msgid "" +"You can see your active theme at the top of the screen. Below are the other " +"themes you have installed that are not currently in use. You can see what " +"your site would look like with one of these themes by clicking the Live " +"Preview link (see \"Previewing and Customizing\" help tab). To change " +"themes, click the Activate link." +msgstr "" +"Vous pouvez voir votre thème actif en haut de l’écran. En dessous se " +"trouvent les autres thèmes que vous avez installés et qui ne sont pas " +"activés pour le moment. Vous pouvez voir à quoi votre site ressemblerait " +"avec ces thèmes en cliquant sur le lien « Prévisualisation et " +"personnalisation » (voir l’onglet d’aide « " +"Prévisualisation et personnalisation »). Pour changer de thème, " +"cliquez sur le lien « Activer »." + +#: wp-admin/themes.php:57 +msgid "" +"Installing themes on Multisite can only be done from the Network Admin " +"section." +msgstr "" +"En mode Multisite, vous pouvez installer des thèmes depuis la section Admin " +"du Réseau." + +#: wp-admin/themes.php:59 +msgid "" +"If you would like to see more themes to choose from, click on the “" +"Install Themes” tab and you will be able to browse or search for " +"additional themes from the WordPress.org " +"Theme Directory. Themes in the WordPress.org Theme Directory are " +"designed and developed by third parties, and are compatible with the license " +"WordPress uses. Oh, and they’re free!" +msgstr "" +"Si vous souhaitez choisir parmi plus de thèmes, cliquez sur l’onglet " +"« Ajouter des thèmes » et vous pourrez parcourir le dépôt de thèmes de WordPress.org, ou y " +"lancer une recherche. Les thèmes du dépôt sont conçus et développés par des " +"designers tiers, et utilisent une licence compatible avec celle de " +"WordPress. Ah, et ils sont gratuits !" + +#: wp-admin/themes.php:64 +msgid "Adding Themes" +msgstr "Ajout de thèmes" + +#: wp-admin/themes.php:75 +msgid "" +"Click on the \"Live Preview\" link under any theme to preview that theme and " +"change theme options in a separate, full-screen view. Any installed theme " +"can be previewed and customized in this way." +msgstr "" +"Cliquez sur le lien « Prévisualisation » sous n’" +"importe quel thème pour le prévisualiser et modifier les options du thème, " +"le tout en mode plein écran. Tout thème installé peut être prévisualisé et " +"personnalisé ainsi." + +#: wp-admin/themes.php:76 +msgid "" +"The theme being previewed is fully interactive — navigate to different " +"pages to see how the theme handles posts, archives, and other page templates." +msgstr "" +"Le thème actuellement prévisualisé est totalement interactif — " +"naviguez entre les différentes pages pour voir comment il gère les articles, " +"les archives, et les autres contenus." + +#: wp-admin/themes.php:77 +msgid "" +"In the left-hand pane you can edit the theme settings. The settings will " +"differ, depending on what theme features the theme being previewed supports. " +"To accept the new settings and activate the theme all in one step, click the " +"\"Save & Activate\" button at the top of the left-hand pane." +msgstr "" +"À gauche du personnalisateur de thème se trouvent les réglages du thème. " +"Ceux-ci peuvent différer en fonction des possibilités offertes par le thème " +"en cours de prévisualisation. Pour valider les nouveaux réglages et activer " +"le thème en une étape, cliquez sur le bouton « Enregistrer et " +"activer » en bas de la colonne latérale de gauche." + +#: wp-admin/themes.php:78 +msgid "" +"When previewing on smaller monitors, you can use the \"Collapse\" icon at " +"the bottom of the left-hand pane. This will hide the pane, giving you more " +"room to preview your site in the new theme. To bring the pane back, click on " +"the Collapse icon again." +msgstr "" +"Lorsque vous faites une prévisualisation sur un petit écran, vous pouvez " +"utiliser l’icône « Réduire » en bas du panneau " +"de gauche. Cela cachera ce panneau, vous donnant ainsi plus de place pour " +"apprécier votre site avec son nouveau thème. Pour ramener le panneau, " +"cliquez à nouveau sur l’icône « Réduire »." + +#: wp-admin/themes.php:82 +msgid "Previewing and Customizing" +msgstr "Aperçu et personnalisation" + +#: wp-admin/themes.php:103 +msgctxt "theme" +msgid "Install Themes" +msgstr "Installer des thèmes" + +#: wp-admin/themes.php:110 +msgid "The active theme is broken. Reverting to the default theme." +msgstr "Le thème courant est endommagé. Retour au thème par défaut." + +#: wp-admin/themes.php:113 +msgid "Settings saved and theme activated. Visit site" +msgstr "Réglages enregistrés et thème activé. Voir le site" + +#: wp-admin/themes.php:115 +msgid "New theme activated. Visit site" +msgstr "Nouveau thème activé. Voir le site" + +#: wp-admin/themes.php:118 +msgid "Theme deleted." +msgstr "Thème supprimé." + +#: wp-admin/themes.php:133 wp-admin/themes.php:136 +msgid "Current theme preview" +msgstr "Aperçu du thème actuel" + +#: wp-admin/themes.php:139 +msgid "Current Theme" +msgstr "Thème actuel" + +#: wp-admin/themes.php:207 +msgid "Options:" +msgstr "Options:" + +#: wp-admin/themes.php:236 +msgid "Available Themes" +msgstr "Thèmes disponibles" + +#: wp-admin/themes.php:241 wp-admin/themes.php:243 +msgid "Search Installed Themes" +msgstr "Chercher parmi les thèmes installés" + +#: wp-admin/themes.php:250 +msgid "Theme filters" +msgstr "Filtres du thème" + +#: wp-admin/themes.php:276 +msgid "Apply Filters" +msgstr "Appliquer les filtres" + +#: wp-admin/themes.php:278 +msgid "Close filters" +msgstr "Fermer les filtres" + +#: wp-admin/themes.php:299 +msgid "Broken Themes" +msgstr "Thèmes endommagés" + +#: wp-admin/themes.php:300 +msgid "" +"The following themes are installed but incomplete. Themes must have a " +"stylesheet and a template." +msgstr "" +"Les thèmes suivants sont installés, mais incomplets. Les thèmes doivent " +"avoir au moins une feuille de style et un modèle." + +#: wp-admin/themes.php:304 +msgctxt "theme name" +msgid "Name" +msgstr "Nom" + +#: wp-admin/tools.php:22 +msgid "" +"Categories have hierarchy, meaning that you can nest sub-categories. Tags do " +"not have hierarchy and cannot be nested. Sometimes people start out using " +"one on their posts, then later realize that the other would work better for " +"their content." +msgstr "" +"Les catégories disposent d’une hiérarchie, ce qui signifie que vous " +"pouvez leur donner des sous-catégories. Les mots-clés n’ont pas de " +"hiérarchie et ne peuvent être imbriqués. Parfois, des auteurs commencent par " +"utiliser une sorte de caractérisation, pour se rendre compte par la suite " +"qu’ils préfèrent l’autre." + +#: wp-admin/tools.php:23 +msgid "" +"The Categories and Tags Converter link on this screen will take you to the " +"Import screen, where that Converter is one of the plugins you can install. " +"Once that plugin is installed, the Activate Plugin & Run Importer link " +"will take you to a screen where you can choose to convert tags into " +"categories or vice versa." +msgstr "" +"Le lien « convertisseur de catégories et mots-clés » " +"vous mènera à la page d’import, où ledit convertisseur est l’une " +"des extensions que vous pouvez installer. Une fois installée, le lien «" +" Activer l’extension & lancer l’importateur » " +"vous mènera à l’écran d’où vous pourrez choisir de lancer une " +"conversion dans un sens ou dans l’autre." + +#: wp-admin/tools.php:28 +msgid "" +"Documentation on Tools" +msgstr "" +"Documentation sur les outils (en)" + +#: wp-admin/tools.php:61 +msgid "" +"If you want to convert your categories to tags (or vice versa), use the Categories and Tags Converter available from the Import " +"screen." +msgstr "" +"Si vous souhaitez convertir vos catégories en mots-clés (et vice versa), " +"utilisez le Convertisseur de catégories mots-clés, " +"disponible depuis l’écran des importateurs." + +#: wp-admin/update-core.php:22 wp-admin/update-core.php:529 +#: wp-admin/update-core.php:554 wp-admin/update-core.php:583 +#: wp-admin/update-core.php:612 +msgid "You do not have sufficient permissions to update this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour mettre à jour ce site." + +#: wp-admin/update-core.php:45 +msgid "" +"You are using a development version of WordPress. You can update to the " +"latest nightly build automatically or download the nightly build and install " +"it manually:" +msgstr "" +"Vous utilisez une version de développement de WordPress. Vous pouvez faire " +"une mise à jour automatique vers la toute dernière version quotidienne " +"(« nightly build »), ou télécharger cette " +"version quotidienne et l’installer vous-même :" + +#: wp-admin/update-core.php:46 +msgid "Download nightly build" +msgstr "Télécharger la dernière version de développement" + +#: wp-admin/update-core.php:49 +msgid "" +"If you need to re-install version %s, you can do so here or download the " +"package and re-install manually:" +msgstr "" +"Si vous souhaitez réinstaller la version %s, vous pouvez le faire ici, ou " +"télécharger l’archive pour la eéinstaller vous-même :" + +#: wp-admin/update-core.php:50 +msgid "Re-install Now" +msgstr "Ré-installer maintenant" + +#: wp-admin/update-core.php:60 wp-admin/upgrade.php:71 +msgid "" +"You cannot update because WordPress %1$s requires PHP version %2$s or higher and MySQL version " +"%3$s or higher. You are running PHP version %4$s and MySQL version %5$s." +msgstr "" +"Cette mise à jour ne peut être installée, car WordPress %1$s requiert une version de PHP " +"égale ou supérieure à la %2$s, et une version de MySQL égale ou supérieure à " +"la %3$s. Votre hébergement utilise PHP version %4$s et MySQL version %5$s." + +#: wp-admin/update-core.php:62 wp-admin/upgrade.php:73 +msgid "" +"You cannot update because WordPress %1$s requires PHP version %2$s or higher. You are running " +"version %3$s." +msgstr "" +"Cette mise à jour ne peut être installée, car WordPress %1$s requiert une version de PHP " +"égale ou supérieure à la %2$s. Votre hébergement utilise PHP version %3$s." + +#: wp-admin/update-core.php:64 wp-admin/upgrade.php:75 +msgid "" +"You cannot update because WordPress %1$s requires MySQL version %2$s or higher. You are running " +"version %3$s." +msgstr "" +"Cette mise à jour ne peut être installée, car WordPress %1$s requiert une version de " +"MySQL égale ou supérieure à la %2$s. Votre hébergement utilise MySQL version " +"%3$s." + +#: wp-admin/update-core.php:66 +msgid "" +"You can update to WordPress %2$s automatically or download the package and install it " +"manually:" +msgstr "" +"Vous pouvez faire la mise à jour vers WordPress %2$s automatiquement ou télécharger l’" +"archive complète et l’installer vous-même :" + +#: wp-admin/update-core.php:70 +msgid "Download %s" +msgstr "Télécharger la version %s" + +#: wp-admin/update-core.php:92 +msgid "Hide this update" +msgstr "Masquer cette mise à jour" + +#: wp-admin/update-core.php:94 +msgid "Bring back this update" +msgstr "Réafficher cette mise à jour" + +#: wp-admin/update-core.php:97 +msgid "" +"This localized version contains both the translation and various other " +"localization fixes. You can skip upgrading if you want to keep your current " +"translation." +msgstr "" +"Cette version localisée contient à la fois la traduction et divers " +"correctifs liés à la localisation. Si vous souhaitez conserver votre " +"traduction actuelle, vous pouvez ne pas utiliser cette version." + +#: wp-admin/update-core.php:100 +msgid "" +"You are about to install WordPress %s in English (US). " +"There is a chance this update will break your translation. You may prefer to " +"wait for the localized version to be released." +msgstr "" +"Vous êtes sur le point d’installer WordPress %s en anglais (US)" +". Il se peut que cette mise à jour ne fonctionne pas avec la " +"traduction de WordPress dont vous disposez. Vous devriez sans doute " +"patienter, le temps que la mise à jour soit officiellement traduite dans " +"votre langue." + +#: wp-admin/update-core.php:110 wp-admin/update-core.php:122 +msgid "Show hidden updates" +msgstr "Afficher les mises à jour cachées" + +#: wp-admin/update-core.php:111 +msgid "Hide hidden updates" +msgstr "Masquer les mises à jour cachées" + +#: wp-admin/update-core.php:147 +msgid "You have the latest version of WordPress." +msgstr "Vous avez la dernière version de WordPress." + +#: wp-admin/update-core.php:160 +msgid "Future security updates will be applied automatically." +msgstr "" +"Les prochaines mises à jour de sécurité seront appliquées automatiquement." + +#: wp-admin/update-core.php:165 +msgid "" +"Important: before updating, please back up your database and files. For " +"help with updates, visit the Updating WordPress Codex page." +msgstr "" +"Important : avant de faire une mise à jour, veillez à " +"faire une " +"sauvegarde de votre base de données et de vos fichiers. Pour obtenir de " +"l’aide sur les mises à jour, lisez la page Mettre à jour WordPress." + +#: wp-admin/update-core.php:169 +msgid "An updated version of WordPress is available." +msgstr "Une nouvelle version de WordPress est disponible." + +#: wp-admin/update-core.php:190 +msgid "" +"While your site is being updated, it will be in maintenance mode. As soon as " +"your updates are complete, your site will return to normal." +msgstr "" +"Durant le processus de mise à jour, votre site sera en mode de maintenance. " +"Dès que le processus sera achevé, votre site sera à nouveau accessible." + +#: wp-admin/update-core.php:193 +msgid "Learn more about WordPress %s." +msgstr "À propos de WordPress %s." + +#: wp-admin/update-core.php:207 +msgid "Your plugins are all up to date." +msgstr "Vos extensions sont toutes à jour." + +#: wp-admin/update-core.php:219 +msgid "" +"The following plugins have new versions available. Check the ones you want " +"to update and then click “Update Plugins”." +msgstr "" +"Les extensions suivantes disposent d’une nouvelle version. Cochez " +"celles que vous voulez mettre à jour, puis cliquez sur « Mettre à " +"jour les extensions »." + +#: wp-admin/update-core.php:243 +msgid "Compatibility with WordPress %1$s: 100%% (according to its author)" +msgstr "Compatibilité avec WordPress %1$s : 100%% (selon l’auteur)" + +#: wp-admin/update-core.php:246 wp-admin/update-core.php:254 +msgid "" +"Compatibility with WordPress %1$s: %2$d%% (%3$d \"works\" votes out of %4$d " +"total)" +msgstr "" +"Compatibilité avec WordPress %1$s : %2$d%% (%3$d votes « Ã§a " +"marche » sur un total de %4$d)" + +#: wp-admin/update-core.php:248 wp-admin/update-core.php:256 +msgid "Compatibility with WordPress %1$s: Unknown" +msgstr "Compatibilité avec WordPress %1$s : inconnue" + +#: wp-admin/update-core.php:267 +msgid "View version %1$s details" +msgstr "Voir les détails de la version %1$s" + +#: wp-admin/update-core.php:273 wp-admin/update-core.php:321 +msgid "You have version %1$s installed. Update to %2$s." +msgstr "Vous utilisez la version %1$s. Mettez à jour vers la version %2$s." + +#: wp-admin/update-core.php:288 +msgid "Your themes are all up to date." +msgstr "Vos thèmes sont tous à jour." + +#: wp-admin/update-core.php:296 +msgid "" +"The following themes have new versions available. Check the ones you want to " +"update and then click “Update Themes”." +msgstr "" +"Les thèmes suivants disposent d’une nouvelle version. Cochez ceux que " +"vous voulez mettre à jour, puis cliquez sur « Mettre à jour les " +"thèmes »." + +#: wp-admin/update-core.php:297 +msgid "" +"Please Note: Any customizations you have made to theme " +"files will be lost. Please consider using child themes " +"for modifications." +msgstr "" +"Notez bien : toutes les personnalisations que vous " +"pourriez avoir apportées aux fichiers des thèmes seront perdues. Pensez à " +"utiliser des thèmes enfants pour vos modifications." + +#: wp-admin/update-core.php:300 wp-admin/update-core.php:327 +#: wp-admin/update-core.php:599 wp-admin/update-core.php:604 +msgid "Update Themes" +msgstr "Mettre à jour les thèmes" + +#: wp-admin/update-core.php:336 wp-admin/update-core.php:344 +msgid "Translations" +msgstr "Traductions" + +#: wp-admin/update-core.php:337 +msgid "Your translations are all up to date." +msgstr "Vos traductions sont toutes à jour." + +#: wp-admin/update-core.php:346 +msgid "Some of your translations are out of date." +msgstr "Certaines de vos traductions ne sont pas à jour." + +#: wp-admin/update-core.php:380 +msgid "Update WordPress" +msgstr "Mettre à jour WordPress" + +#: wp-admin/update-core.php:464 wp-admin/update-core.php:496 +msgid "WordPress Updates" +msgstr "Mises à jour de WordPress" + +#: wp-admin/update-core.php:471 +msgid "" +"This screen lets you update to the latest version of WordPress as well as " +"update your themes and plugins from the WordPress.org repository. When " +"updates are available, the number of available updates will appear in a " +"bubble on the left hand menu as a notification." +msgstr "" +"Cet écran vous permet de mettre à jour WordPress vers sa dernière version, " +"ainsi que de mettre à jour les thèmes et extensions à partir du dépôt de " +"WordPress.org. Quand des mises à jour sont disponibles, leur nombre apparaît " +"dans une infobulle de notification, dans le menu situé à gauche." + +#: wp-admin/update-core.php:472 +msgid "" +"It is very important to keep your WordPress installation up to date for " +"security reasons, so when you see a number appear, make sure you take the " +"time to update, which is an easy process." +msgstr "" +"Il est impératif que votre installation de WordPress soit toujours à la " +"dernière version en date, pour raisons de sécurité. De fait, quand une " +"nouvelle version est annoncée, prenez le temps de faire une mise à " +"jour : le processus est très simple." + +#: wp-admin/update-core.php:477 +msgid "How to Update" +msgstr "Comment faire la mise à jour" + +#: wp-admin/update-core.php:479 +msgid "" +"Updating your WordPress installation is a simple one-click procedure; just " +"click on the Update button when it says a new version is available." +msgstr "" +"La mise à jour de votre version de WordPress se fait en un seul clic. " +"Cliquez simplement sur le bouton « Mettre à jour » " +"quand il indique qu’une nouvelle version est disponible." + +#: wp-admin/update-core.php:480 +msgid "" +"To update themes or plugins from this screen, use the checkboxes to make " +"your selection and click on the appropriate Update button. Check the box at " +"the top of the Themes or Plugins section to select all and update them all " +"at once." +msgstr "" +"Pour mettre à jour les thèmes ou extensions depuis cet écran, utilisez les " +"cases à cocher pour faire votre sélection, et cliquez sur le bouton " +"correspondant. Cochez la case en haut de la section Thèmes ou Extensions " +"pour tout sélectionner, et donc tout mettre à jour d’un clic." + +#: wp-admin/update-core.php:485 +msgid "" +"Documentation on Updating WordPress" +msgstr "" +"Documentation sur la mise à jour de WordPress (en)" + +#: wp-admin/update-core.php:501 +msgid "Please select one or more themes to update." +msgstr "Veuillez sélectionner un ou plusieurs thèmes à mettre à jour." + +#: wp-admin/update-core.php:503 +msgid "Please select one or more plugins to update." +msgstr "Veuillez sélectionner une ou plusieurs extensions à mettre à jour." + +#. translators: %1 date, %2 time. +#: wp-admin/update-core.php:509 +msgid "Last checked on %1$s at %2$s." +msgstr "Dernière vérification le %1$s à %2$s." + +#: wp-admin/update-core.php:510 +msgid "Check Again" +msgstr "Vérifier à nouveau" + +#: wp-admin/update.php:24 wp-admin/update.php:50 wp-admin/update.php:69 +msgid "You do not have sufficient permissions to update plugins for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour mettre à jour les " +"extensions de ce site." + +#: wp-admin/update.php:78 +msgid "Plugin Reactivation" +msgstr "Réactivation d’extension" + +#: wp-admin/update.php:80 +msgid "Plugin reactivated successfully." +msgstr "L’extension a bien été réactivée." + +#: wp-admin/update.php:83 +msgid "Plugin failed to reactivate due to a fatal error." +msgstr "" +"L’extension n’a pu être réactivée suite à une erreur fatale." + +#: wp-admin/update.php:108 +msgid "Installing Plugin: %s" +msgstr "Extension en cours d’installation : %s" + +# contexte? +#: wp-admin/update.php:130 +msgid "Upload Plugin" +msgstr "Mettre une extension en ligne" + +#: wp-admin/update.php:135 +msgid "Installing Plugin from uploaded file: %s" +msgstr "Installation de l’extension à partir du fichier : %s" + +#: wp-admin/update.php:151 wp-admin/update.php:171 +msgid "You do not have sufficient permissions to update themes for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour mettre à jour les thèmes de " +"ce site." + +#: wp-admin/update.php:214 +msgid "Installing Theme: %s" +msgstr "Installation du thème : %s" + +#: wp-admin/update.php:235 +msgid "Upload Theme" +msgstr "Mettre un thème en ligne" + +#: wp-admin/update.php:241 +msgid "Installing Theme from uploaded file: %s" +msgstr "Installation du thème à partir du fichier : %s" + +#: wp-admin/upgrade.php:54 +msgid "WordPress › Update" +msgstr "WordPress › Mise à jour" + +#: wp-admin/upgrade.php:65 +msgid "No Update Required" +msgstr "Pas de mise à jour requise" + +#: wp-admin/upgrade.php:66 +msgid "Your WordPress database is already up-to-date!" +msgstr "Votre base de données WordPress est déjà à jour !" + +#: wp-admin/upgrade.php:84 +msgid "Database Update Required" +msgstr "Mise à jour de la base de données requise" + +#: wp-admin/upgrade.php:85 +msgid "" +"WordPress has been updated! Before we send you on your way, we have to " +"update your database to the newest version." +msgstr "" +"WordPress a été mis à jour ! Avant de vous laisser continuer, nous " +"devons mettre à jour la base de données." + +#: wp-admin/upgrade.php:86 +msgid "The update process may take a little while, so please be patient." +msgstr "" +"Le processus de mise à jour peut prendre un certain temps, merci donc pour " +"votre patience." + +#: wp-admin/upgrade.php:87 +msgid "Update WordPress Database" +msgstr "Mettre à jour la base de données de WordPress" + +#: wp-admin/upgrade.php:97 +msgid "Update Complete" +msgstr "Mise à jour terminée" + +#: wp-admin/upgrade.php:98 +msgid "Your WordPress database has been successfully updated!" +msgstr "La base de données de WordPress a bien été mise à jour !" + +#: wp-admin/upgrade.php:103 +msgid "%s queries" +msgstr "%s requêtes" + +#: wp-admin/upgrade.php:105 +msgid "%s seconds" +msgstr "%s secondes" + +#: wp-admin/upload.php:42 +msgid "You are not allowed to scan for lost attachments." +msgstr "" +"Vous n’avez pas l’autorisation de chercher les fichiers attachés " +"perdus." + +#: wp-admin/upload.php:99 +msgid "You are not allowed to move this post to the trash." +msgstr "" +"Vous n’avez pas l’autorisation de déplacer cet article dans la " +"Corbeille." + +#: wp-admin/upload.php:102 +msgid "Error in moving to trash." +msgstr "Erreur lors du déplacement dans la Corbeille." + +#: wp-admin/upload.php:111 +msgid "You are not allowed to move this post out of the trash." +msgstr "" +"Vous n’avez pas l’autorisation de sortir cet article de la " +"Corbeille." + +#: wp-admin/upload.php:114 +msgid "Error in restoring from trash." +msgstr "Erreur pendant la récupération depuis la Corbeille." + +#: wp-admin/upload.php:123 +msgid "You are not allowed to delete this post." +msgstr "Vous n’avez pas l’autorisation de supprimer cet article." + +#: wp-admin/upload.php:148 +msgctxt "items per page (screen options)" +msgid "Media items" +msgstr "Fichiers média" + +#: wp-admin/upload.php:154 +msgid "" +"All the files you’ve uploaded are listed in the Media Library, with " +"the most recent uploads listed first. You can use the Screen Options tab to " +"customize the display of this screen." +msgstr "" +"Tous les fichiers que vous avez mis en ligne sont listés dans la " +"Bibliothèque de Médias, les plus récents en premier. Vous pouvez utiliser " +"l’onglet « Options de l’écran » pour " +"personnaliser l’affichage de cet écran." + +#: wp-admin/upload.php:155 +msgid "" +"You can narrow the list by file type/status using the text link filters at " +"the top of the screen. You also can refine the list by date using the " +"dropdown menu above the media table." +msgstr "" +"Vous pouvez limiter cette liste par type de fichier ou par état à l’" +"aide des filtres en haut de l’écran. Vous pouvez également affiner la " +"liste par défaut à l’aide du menu déroulant au dessus du tableau." + +#: wp-admin/upload.php:161 +msgid "" +"Hovering over a row reveals action links: Edit, Delete Permanently, and " +"View. Clicking Edit or on the media file’s name displays a simple " +"screen to edit that individual file’s metadata. Clicking Delete " +"Permanently will delete the file from the media library (as well as from any " +"posts to which it is currently attached). View will take you to the display " +"page for that file." +msgstr "" +"Le survol par la souris des lignes du tableau révèle des liens : «" +" Modifier », « Supprimer définitivement " +"» et « Afficher ». En cliquant sur « " +"Modifier » ou sur le nom d’un fichier média, vous " +"obtiendrez un écran où vous pourrez modifier les métadonnées du fichier. En " +"cliquant sur « Supprimer définitivement », vous " +"supprimerez le fichier de la bibliothèque (ainsi que de tous les articles " +"auxquels il était lié). « Afficher » vous enverra sur " +"la page d’affichage de ce fichier." + +#: wp-admin/upload.php:165 +msgid "Attaching Files" +msgstr "Fichiers des extensions" + +#: wp-admin/upload.php:167 +msgid "" +"If a media file has not been attached to any post, you will see that in the " +"Attached To column, and can click on Attach File to launch a small popup " +"that will allow you to search for a post and attach the file." +msgstr "" +"Si un fichier média n’est lié à aucun article, cela vous sera indiqué " +"dans la colonne « Attaché à », et vous pourrez cliquer " +"sur le lien « Joindre » pour afficher une petite " +"fenêtre vous permettant de trouver un article auquel attacher le fichier." + +#: wp-admin/upload.php:172 +msgid "" +"Documentation on Media Library" +msgstr "" +"Documentation sur la bibliothèque des médias (en)" + +#: wp-admin/upload.php:199 +msgid "Reattached %d attachment." +msgid_plural "Reattached %d attachments." +msgstr[0] "Rattachement de %d fichier attaché." +msgstr[1] "Rattachement de %d fichiers attachés." + +#: wp-admin/upload.php:204 +msgid "Media attachment permanently deleted." +msgid_plural "%d media attachments permanently deleted." +msgstr[0] "Média définitivement supprimé." +msgstr[1] "%d médias définitivement supprimés." + +#: wp-admin/upload.php:209 +msgid "Media attachment moved to the trash." +msgid_plural "%d media attachments moved to the trash." +msgstr[0] "Fichier média déplacé dans la Corbeille." +msgstr[1] "%d fichiers médias déplacés dans la Corbeille." + +#: wp-admin/upload.php:215 +msgid "Media attachment restored from the trash." +msgid_plural "%d media attachments restored from the trash." +msgstr[0] "Fichier média récupéré depuis la Corbeille." +msgstr[1] "%d fichiers médias récupérés depuis la Corbeille." + +#: wp-admin/upload.php:220 +msgid "Media permanently deleted." +msgstr "Média définitivement supprimé." + +#: wp-admin/upload.php:221 +msgid "Error saving media attachment." +msgstr "Erreur lors de la sauvegarde du fichier attaché." + +#: wp-admin/upload.php:222 +msgid "Media moved to the trash." +msgstr "Fichier média déplacé dans la Corbeille." + +#: wp-admin/upload.php:223 +msgid "Media restored from the trash." +msgstr "Fichier média récupéré depuis la Corbeille." + +#: wp-admin/user-edit.php:28 +msgid "Edit User" +msgstr "Modifier l’utilisateur" + +#: wp-admin/user-edit.php:39 +msgid "" +"Your profile contains information about you (your “account”) as " +"well as some personal options related to using WordPress." +msgstr "" +"Votre profil contient les informations à votre propos (votre « " +"compte »), ainsi que quelques options liées à votre utilisation " +"personnelle de WordPress." + +#: wp-admin/user-edit.php:40 +msgid "" +"You can change your password, turn on keyboard shortcuts, change the color " +"scheme of your WordPress administration screens, and turn off the WYSIWYG " +"(Visual) editor, among other things. You can hide the Toolbar (formerly " +"called the Admin Bar) from the front end of your site, however it cannot be " +"disabled on the admin screens." +msgstr "" +"Vous pouvez modifier votre mot de passe, activer les raccourcis clavier, " +"modifier la combinaison de couleurs des écrans de l’administration, et " +"désactiver l’éditeur visuel (WYSIWYG), entre autres choses. Vous " +"pouvez également cacher la barre d’outils (anciennement « " +"barre d’administration ») sur la partie publique de votre " +"site, mais elle ne peut pas être enlevée des écrans d’administration." + +#: wp-admin/user-edit.php:41 +msgid "" +"Your username cannot be changed, but you can use other fields to enter your " +"real name or a nickname, and change which name to display on your posts." +msgstr "" +"Votre identifiant ne peut être modifié, mais vous pouvez utiliser les autres " +"champs pour saisir votre nom complet ou un pseudonyme, et changer ensuite le " +"nom à afficher dans vos articles." + +#: wp-admin/user-edit.php:42 +msgid "" +"Required fields are indicated; the rest are optional. Profile information " +"will only be displayed if your theme is set up to do so." +msgstr "" +"Les champs obligatoires sont indiqués, les autres sont facultatifs. Les " +"informations du profil ne sont affichées que si votre thème a été conçu pour " +"les exploiter." + +#: wp-admin/user-edit.php:43 +msgid "Remember to click the Update Profile button when you are finished." +msgstr "" +"Pensez bien à cliquer sur le bouton « Mettre à jour le " +"profil » quand vous aurez terminé." + +#: wp-admin/user-edit.php:53 +msgid "" +"Documentation on User Profiles" +msgstr "" +"Documentation sur le Profil utilisateur (en)" + +#: wp-admin/user-edit.php:71 +msgid "Use https" +msgstr "Utiliser https" + +#: wp-admin/user-edit.php:72 +msgid "Always use https when visiting the admin" +msgstr "" +"Toujours utiliser https lors de l’utilisation de l’administration" + +#: wp-admin/user-edit.php:79 wp-admin/user-edit.php:107 +#: wp-admin/user-edit.php:154 +msgid "You do not have permission to edit this user." +msgstr "" +"Vous n’avez pas l’autorisation de modifier cet utilisateur." + +#: wp-admin/user-edit.php:160 +msgid "Important:" +msgstr "Important :" + +#: wp-admin/user-edit.php:160 +msgid "This user has super admin privileges." +msgstr "Cet utilisateur possède les privilèges de super-admin." + +#: wp-admin/user-edit.php:165 +msgid "Profile updated." +msgstr "Profil mis à jour." + +#: wp-admin/user-edit.php:167 +msgid "User updated." +msgstr "Utilisateur mis à jour." + +#: wp-admin/user-edit.php:170 +msgid "← Back to Users" +msgstr "← Retour aux utilisateurs" + +#: wp-admin/user-edit.php:187 wp-admin/users.php:435 +msgctxt "user" +msgid "Add Existing" +msgstr "Ajouter un utilisateur existant" + +#: wp-admin/user-edit.php:202 +msgid "Personal Options" +msgstr "Options personnelles" + +#: wp-admin/user-edit.php:207 +msgid "Visual Editor" +msgstr "Éditeur visuel" + +#: wp-admin/user-edit.php:208 +msgid "Disable the visual editor when writing" +msgstr "Désactiver l’éditeur visuel pour écrire" + +#: wp-admin/user-edit.php:220 +msgid "Keyboard Shortcuts" +msgstr "Raccourcis clavier" + +#: wp-admin/user-edit.php:221 +msgid "Enable keyboard shortcuts for comment moderation." +msgstr "Activer les raccourcis clavier pour la modération de commentaires." + +#: wp-admin/user-edit.php:221 +msgid "" +"More information" +msgstr "" +"Plus d’informations (en)" + +#: wp-admin/user-edit.php:229 +msgid "Show Toolbar when viewing site" +msgstr "Afficher la barre d’outils lorsque vous visitez le site" + +#: wp-admin/user-edit.php:245 +msgid "Usernames cannot be changed." +msgstr "Les identifiants ne peuvent être modifiés." + +#: wp-admin/user-edit.php:261 wp-admin/user-edit.php:263 +msgid "— No role for this site —" +msgstr "— Pas de rôle sur ce site —" + +#: wp-admin/user-edit.php:272 +msgid "Grant this user super admin privileges for the Network." +msgstr "Donner les privilèges de super-admin à cet utilisateur pour le réseau." + +#: wp-admin/user-edit.php:274 +msgid "" +"Super admin privileges cannot be removed because this user has the network " +"admin email." +msgstr "" +"Les privilèges de super-admin ne peuvent pas être enlevés, car cet " +"utilisateur est celui avec l’adresse de contact administratif du " +"réseau." + +#: wp-admin/user-edit.php:280 wp-admin/user-new.php:368 +msgid "First Name" +msgstr "Prénom" + +#: wp-admin/user-edit.php:285 wp-admin/user-new.php:372 +msgid "Last Name" +msgstr "Nom" + +#: wp-admin/user-edit.php:290 +msgid "Nickname" +msgstr "Pseudonyme" + +#: wp-admin/user-edit.php:295 +msgid "Display name publicly as" +msgstr "Nom à afficher publiquement" + +#: wp-admin/user-edit.php:331 +msgid "Contact Info" +msgstr "Informations de contact" + +#: wp-admin/user-edit.php:341 +msgid "" +"There is a pending change of your e-mail to %1$s. Cancel" +msgstr "" +"Il y a une modification de votre adresse de contact en cours, en faveur de " +"%1$s. Annuler" + +#: wp-admin/user-edit.php:364 +msgid "About Yourself" +msgstr "À propos de vous" + +#: wp-admin/user-edit.php:364 +msgid "About the user" +msgstr "À propos de l’utilisateur" + +#: wp-admin/user-edit.php:368 +msgid "Biographical Info" +msgstr "Renseignements biographiques" + +#: wp-admin/user-edit.php:370 +msgid "" +"Share a little biographical information to fill out your profile. This may " +"be shown publicly." +msgstr "" +"Donnez quelques informations biographiques pour remplir votre profil. Ceci " +"peut être affiché publiquement." + +#: wp-admin/user-edit.php:378 +msgid "New Password" +msgstr "Nouveau mot de passe" + +#: wp-admin/user-edit.php:381 +msgid "" +"If you would like to change the password type a new one. Otherwise leave " +"this blank." +msgstr "" +"Si vous souhaitez changer le mot de passe de l’utilisateur, tapez en " +"un nouveau deux fois de suite ci-dessous. Sinon, laissez les champs vides." + +#: wp-admin/user-edit.php:385 +msgid "Repeat New Password" +msgstr "Répétez le nouveau mot de passe" + +#: wp-admin/user-edit.php:387 +msgid "Type your new password again." +msgstr "Veuillez saisir une deuxième fois votre mot de passe." + +#: wp-admin/user-edit.php:404 +msgid "Additional Capabilities" +msgstr "Fonctionnalités complémentaires" + +#: wp-admin/user-edit.php:407 +msgid "Capabilities" +msgstr "Capacités" + +#: wp-admin/user-edit.php:415 +msgid "Denied: %s" +msgstr "Refusé : %s" + +#: wp-admin/user-edit.php:428 +msgid "Update Profile" +msgstr "Mettre à jour le profil" + +#: wp-admin/user-edit.php:428 +msgid "Update User" +msgstr "Mettre à jour l’utilisateur" + +# Pas d'entité HTML : texte envoyé par mail +#. translators: 1: Site name, 2: site URL, 3: role +#: wp-admin/user-new.php:24 +msgid "" +"Hi,\n" +"You've been invited to join '%1$s' at\n" +"%2$s with the role of %3$s.\n" +"If you do not want to join this site please ignore\n" +"this email. This invitation will expire in a few days.\n" +"\n" +"Please click the following link to activate your user account:\n" +"%%s" +msgstr "" +"Bonjour,\n" +"Vous avez été invité(e) à rejoindre « %1$s » sur\n" +"%2$s en tant que %3$s. \n" +"Si vous ne souhaitez pas rejoindre ce site, veuillez ignorer\n" +"ce message. L'invitation expirera dans quelques jours.\n" +"\n" +"Veuillez cliquer sur le lien suivant pour activer votre compte " +"utilisateur :\n" +"%%s" + +#: wp-admin/user-new.php:36 +msgid "[%s] Your site invite" +msgstr "[%s] Votre invitation sur le site" + +# Pas d'entité HTML : texte envoyé par mail +#. translators: 1: Site name, 2: site URL, 3: role, 4: activation URL +#: wp-admin/user-new.php:81 +msgid "" +"Hi,\n" +"\n" +"You've been invited to join '%1$s' at\n" +"%2$s with the role of %3$s.\n" +"\n" +"Please click the following link to confirm the invite:\n" +"%4$s" +msgstr "" +"Bonjour,\n" +"\n" +"Vous avez été invité(e) à rejoindre « %1$s » sur\n" +"%2$s en tant que %3$s. \n" +"Veuillez cliquer sur le lien suivant pour confirmer l'invitation :\n" +"%4$s" + +# Pas d'entité HTML : titre de mail +#: wp-admin/user-new.php:88 +msgid "[%s] Joining confirmation" +msgstr "[%s] Confirmation d'inscription" + +#: wp-admin/user-new.php:151 +msgid "" +"To add a new user to your site, fill in the form on this screen and click " +"the Add New User button at the bottom." +msgstr "" +"Pour ajouter un nouvel utilisateur à votre site, remplissez le formulaire de " +"cet écran et cliquez sur le bouton « Ajouter un nouvel " +"utilisateur » en bas de l’écran." + +#: wp-admin/user-new.php:154 +msgid "" +"Because this is a multisite installation, you may add accounts that already " +"exist on the Network by specifying a username or email, and defining a role. " +"For more options, such as specifying a password, you have to be a Network " +"Administrator and use the hover link under an existing user’s name to " +"Edit the user profile under Network Admin > All Users." +msgstr "" +"Parce qu’il s’agit d’une installation multisite, vous " +"pouvez ajouter des comptes qui existent déjà sur le Réseau, en indiquant un " +"nom d’utilisateur ou une adresse de messagerie, et en assignant un " +"rôle. Pour avoir plus d’options, telle que le choix du mot de passe, " +"vous devez être Administrateur du Réseau, et utiliser les liens qui " +"apparaissent au survol sous le nom de l’utilisateur pour modifier son " +"profil utilisateur, depuis l’écran « Tous les " +"utilisateurs »." + +#: wp-admin/user-new.php:155 +msgid "" +"New users will receive an email letting them know they’ve been added " +"as a user for your site. This email will also contain their password. Check " +"the box if you don’t want the user to receive a welcome email." +msgstr "" +"Les nouveaux utilisateurs reçoivent un message les informant qu’ils " +"ont été ajoutés aux utilisateurs de votre site. Ce message contient " +"également leur mot de passe. Décochez la case si vous ne voulez pas que " +"l’utilisateur reçoive ce message de bienvenue." + +#: wp-admin/user-new.php:157 +msgid "" +"You must assign a password to the new user, which they can change after " +"logging in. The username, however, cannot be changed." +msgstr "" +"Vous devez assigner un mot de passe au nouvel utilisateur, qu’il " +"pourra changer après s’être connecté. L’identifiant, en " +"revanche, ne peut être changé." + +#: wp-admin/user-new.php:158 +msgid "" +"New users will receive an email letting them know they’ve been added " +"as a user for your site. By default, this email will also contain their " +"password. Uncheck the box if you don’t want the password to be " +"included in the welcome email." +msgstr "" +"Les nouveaux utilisateurs reçoivent un message les informant qu’ils " +"ont été ajoutés aux utilisateurs de ce site. Par défaut, ce message contient " +"également leur mot de passe. Décochez la case si vous ne voulez pas que le " +"mot de passe y soit inclus." + +#: wp-admin/user-new.php:161 +msgid "" +"Remember to click the Add New User button at the bottom of this screen when " +"you are finished." +msgstr "" +"N’oubliez pas de cliquer sur le bouton « Ajouter un " +"utilisateur », en bas de cet écran, quand vous aurez terminé." + +#: wp-admin/user-new.php:171 +msgid "User Roles" +msgstr "Rôles utilisateurs" + +#: wp-admin/user-new.php:172 +msgid "" +"Here is a basic overview of the different user roles and the permissions " +"associated with each one:" +msgstr "" +"Voici un rapide survol des différents rôles assignables aux utilisateurs, et " +"des permissions qui leurs sont associées :" + +#: wp-admin/user-new.php:174 +msgid "Administrators have access to all the administration features." +msgstr "" +"Les administrateurs peuvent accéder à toutes les fonctionnalités de l’" +"administration ;" + +#: wp-admin/user-new.php:175 +msgid "" +"Editors can publish posts, manage posts as well as manage other people’" +"s posts, etc." +msgstr "" +"Les éditeurs peuvent publier et gérer leurs propres articles, ainsi que ceux " +"des autres membres ;" + +#: wp-admin/user-new.php:176 +msgid "" +"Authors can publish and manage their own posts, and are able to upload files." +msgstr "" +"Les auteurs peuvent publier et gérer leurs propres articles, ils peuvent " +"également envoyer des fichiers ;" + +#: wp-admin/user-new.php:177 +msgid "" +"Contributors can write and manage their posts but not publish posts or " +"upload media files." +msgstr "" +"Les contributeurs peuvent écrire et gérer leurs articles, mais ils ne " +"peuvent pas publier les articles ou envoyer des fichiers média ;" + +#: wp-admin/user-new.php:178 +msgid "" +"Subscribers can read comments/comment/receive newsletters, etc. but cannot " +"create regular site content." +msgstr "" +"Les abonnés peuvent lire les commentaires/commenter/recevoir les " +"newsletters, etc. Mais ils ne peuvent pas créer du contenu sur le site." + +#: wp-admin/user-new.php:184 +msgid "" +"Documentation on Adding New Users" +msgstr "" +"Documentation sur l’ajout de nouveaux utilisateurs (en)" + +#: wp-admin/user-new.php:211 +msgid "" +"Invitation email sent to new user. A confirmation link must be clicked " +"before their account is created." +msgstr "" +"Envoi d’un message d’invitation au nouvel utilisateur. Un lien " +"de confirmation devra d’abord être cliqué avant la création du compte." + +#: wp-admin/user-new.php:214 +msgid "" +"Invitation email sent to user. A confirmation link must be clicked for them " +"to be added to your site." +msgstr "" +"L’invitation a été envoyée à l’utilisateur sur son adresse de " +"messagerie. Il devra cliquer sur un lien de confirmation pour être ajouté à " +"votre site." + +#: wp-admin/user-new.php:217 +msgid "User has been added to your site." +msgstr "L’utilisateur a été ajouté à votre site." + +#: wp-admin/user-new.php:220 +msgid "That user is already a member of this site." +msgstr "Cet utilisateur est déjà membre de ce site." + +#: wp-admin/user-new.php:231 +msgid "User added." +msgstr "Utilisateur ajouté." + +#: wp-admin/user-new.php:239 +msgctxt "user" +msgid "Add New User" +msgstr "Ajouter un utilisateur" + +#: wp-admin/user-new.php:241 +msgctxt "user" +msgid "Add Existing User" +msgstr "Ajouter un utilisateur existant" + +#: wp-admin/user-new.php:274 +msgid "Add Existing User" +msgstr "Ajouter un utilisateur existant" + +#: wp-admin/user-new.php:276 +msgid "" +"Enter the email address of an existing user on this network to invite them " +"to this site. That person will be sent an email asking them to confirm the " +"invite." +msgstr "" +"Saisissez l’adresse de contact d’un utilisateur existant sur " +"votre réseau, afin de l’inviter sur ce site. Cette personne recevra un " +"message lui demandant de confirmer l’invitation." + +#: wp-admin/user-new.php:279 +msgid "" +"Enter the email address or username of an existing user on this network to " +"invite them to this site. That person will be sent an email asking them to " +"confirm the invite." +msgstr "" +"Pour inviter un utilisateur de ce réseau sur ce site, saisissez son adresse " +"de messagerie ou son identifiant. Cette personne recevra alors un message " +"lui proposant de confirmer son ajout." + +#: wp-admin/user-new.php:280 +msgid "E-mail or Username" +msgstr "E-mail ou identifiant" + +#: wp-admin/user-new.php:308 wp-admin/user-new.php:423 +msgid "Skip Confirmation Email" +msgstr "Passer la confirmation par e-mail" + +#: wp-admin/user-new.php:309 wp-admin/user-new.php:424 +msgid "Add the user without sending them a confirmation email." +msgstr "Ajouter un utilisateur sans envoyer un e-mail de confirmation." + +#: wp-admin/user-new.php:327 +msgid "Add Existing User " +msgstr "Ajouter un utilisateur existant" + +#: wp-admin/user-new.php:336 +msgid "Create a brand new user and add them to this site." +msgstr "Créer un nouvel utilisateur et l’ajouter à ce site." + +#: wp-admin/user-new.php:396 +msgid "Repeat Password" +msgstr "Répétez le mot de passe" + +#: wp-admin/user-new.php:405 +msgid "Send Password?" +msgstr "Envoyer le mot de passe ?" + +#: wp-admin/user-new.php:406 +msgid "Send this password to the new user by email." +msgstr "" +"Envoyer ce mot de passe au nouvel utilisateur sur son adresse de messagerie." + +#: wp-admin/user-new.php:434 +msgid "Add New User " +msgstr "Ajouter un utilisateur" + +#: wp-admin/users.php:20 +msgctxt "users per page (screen options)" +msgid "Users" +msgstr "Utilisateurs" + +#: wp-admin/users.php:26 +msgid "" +"This screen lists all the existing users for your site. Each user has one of " +"five defined roles as set by the site admin: Site Administrator, Editor, " +"Author, Contributor, or Subscriber. Users with roles other than " +"Administrator will see fewer options in the dashboard navigation when they " +"are logged in, based on their role." +msgstr "" +"Cet écran liste tous les utilisateurs actuels de votre site. Chaque " +"utilisateur a l’un des 5 rôles prédéfinis, tel qu’assigné par " +"l’administrateur du site : Administrateur, Éditeur, Auteur, " +"Contributeur ou Abonné. Les utilisateurs avec un rôle autre qu’" +"Administrateur verront moins d’options quand ils seront connectés, en " +"fonction de leur rôle." + +#: wp-admin/users.php:27 +msgid "" +"To add a new user for your site, click the Add New button at the top of the " +"screen or Add New in the Users menu section." +msgstr "" +"Pour ajouter un nouvel utilisateur à votre site, cliquez sur le bouton " +"« Ajouter » en haut de l’écran, ou l’" +"option « Ajouter » du menu « " +"Utilisateurs »." + +#: wp-admin/users.php:32 +msgid "Screen Display" +msgstr "Écran affiché" + +#: wp-admin/users.php:33 +msgid "You can customize the display of this screen in a number of ways:" +msgstr "" +"Vous pouvez personnaliser l’affichage de cet écran de plusieurs " +"manières :" + +#: wp-admin/users.php:35 +msgid "" +"You can hide/display columns based on your needs and decide how many users " +"to list per screen using the Screen Options tab." +msgstr "" +"Vous pouvez cacher/afficher les colonnes en fonction de vos besoins, et " +"décider du nombre d’articles à afficher par écran à l’aide de " +"l’onglet « Options de l’écran »." + +#: wp-admin/users.php:36 +msgid "" +"You can filter the list of users by User Role using the text links in the " +"upper left to show All, Administrator, Editor, Author, Contributor, or " +"Subscriber. The default view is to show all users. Unused User Roles are not " +"listed." +msgstr "" +"Vous pouvez filtrer la liste des utilisateurs par rôle, à l’aide des " +"liens textuels en haut à gauche, afin d’afficher tous les " +"utilisateurs, ou seulement les administrateurs, les éditeurs, les auteurs ou " +"les contributeurs. Par défaut, tous les utilisateurs sont affichés. Les " +"rôles sans utilisateurs ne sont pas listés." + +#: wp-admin/users.php:37 +msgid "" +"You can view all posts made by a user by clicking on the number under the " +"Posts column." +msgstr "" +"Vous pouvez afficher tous les articles faits par un même utilisateur en " +"cliquant sur le nombre sous la colonne « Articles »." + +#: wp-admin/users.php:41 +msgid "" +"Hovering over a row in the users list will display action links that allow " +"you to manage users. You can perform the following actions:" +msgstr "" +"Passer la souris au-dessus d’une ligne de la liste des utilisateurs, " +"fera s’afficher des liens vous permettant de gérer l’" +"utilisateur. Vous pouvez lancer les actions suivantes :" + +#: wp-admin/users.php:43 +msgid "" +"Edit takes you to the editable profile screen for that user. You can also " +"reach that screen by clicking on the username." +msgstr "" +"« Modifier » vous envoie sur l’écran de " +"modification de cet utilisateur. Vous pouvez également vous rendre sur cet " +"écran en cliquant sur le nom de l’utilisateur ;" + +#: wp-admin/users.php:46 +msgid "" +"Remove allows you to remove a user from your site. It does not delete their " +"posts. You can also remove multiple users at once by using Bulk Actions." +msgstr "" +"« Supprimer » vous permet de supprimer un utilisateur " +"de votre site. Cela n’efface pas ses articles. Vous pouvez également " +"supprimer plusieurs utilisateurs à la fois en utilisant les « " +"Actions groupées »." + +#: wp-admin/users.php:48 +msgid "" +"Delete brings you to the Delete Users screen for confirmation, where you can " +"permanently remove a user from your site and delete their posts. You can " +"also delete multiple users at once by using Bulk Actions." +msgstr "" +"« Effacer » vous amène à l’écran « " +"Effacer des utilisateurs » pour confirmation, d’où vous " +"pouvez définitivement supprimer un utilisateur de votre site et effacer ses " +"articles. Vous pouvez également effacer plusieurs utilisateurs à la fois en " +"utilisant les « Actions groupées »." + +#: wp-admin/users.php:61 +msgid "" +"Documentation on Managing Users" +msgstr "" +"Documentation sur l’ajout de nouveaux utilisateurs (en)" + +#: wp-admin/users.php:62 +msgid "" +"Descriptions of Roles and Capabilities" +msgstr "" +"Descriptions des rôles et permissions (en)" + +#: wp-admin/users.php:104 wp-admin/users.php:121 +msgid "You can’t edit that user." +msgstr "Vous ne pouvez pas modifier cet utilisateur." + +#: wp-admin/users.php:144 wp-admin/users.php:195 +msgid "User deletion is not allowed from this screen." +msgstr "" +"La suppression d’un utilisateur n’est pas autorisée depuis cet " +"écran." + +#: wp-admin/users.php:163 wp-admin/users.php:205 +msgid "You can’t delete users." +msgstr "Vous ne pouvez pas supprimer d’utilisateurs." + +#: wp-admin/users.php:170 +msgid "You can’t delete that user." +msgstr "Vous ne pouvez pas supprimer cet utilisateur." + +#: wp-admin/users.php:222 +msgid "Delete Users" +msgstr "Supprimer des utilisateurs" + +#: wp-admin/users.php:225 +msgid "Please select an option." +msgstr "Veuillez choisir une option." + +#: wp-admin/users.php:228 +msgid "You have specified this user for deletion:" +msgid_plural "You have specified these users for deletion:" +msgstr[0] "Vous avez choisi de supprimer cet utilisateur :" +msgstr[1] "Vous avez choisi de supprimer ces utilisateurs :" + +#: wp-admin/users.php:235 +msgid "ID #%1$s: %2$s The current user will not be deleted." +msgstr "" +"ID n°%1$s : %2$s L’utilisateur actuel ne sera pas " +"supprimé." + +#: wp-admin/users.php:237 wp-admin/users.php:340 +msgid "ID #%1$s: %2$s" +msgstr "ID n°%1$s : %2$s" + +#: wp-admin/users.php:244 +msgid "What should be done with posts owned by this user?" +msgid_plural "What should be done with posts owned by these users?" +msgstr[0] "Que voulez-vous faire des articles de cet utilisateur ?" +msgstr[1] "Que voulez-vous faire des articles de ces utilisateurs ?" + +#: wp-admin/users.php:247 +msgid "Delete all posts." +msgstr "Supprimer tous les articles." + +#: wp-admin/users.php:249 +msgid "Attribute all posts to:" +msgstr "Attribuer tous les articles à :" + +#: wp-admin/users.php:253 +msgid "Confirm Deletion" +msgstr "Confirmer la suppression" + +#: wp-admin/users.php:255 +msgid "There are no valid users selected for deletion." +msgstr "Aucun utilisateur valide n’est sélectionné pour la suppression." + +#: wp-admin/users.php:267 wp-admin/users.php:275 wp-admin/users.php:304 +#: wp-admin/users.php:312 +msgid "You can’t remove users." +msgstr "Vous ne pouvez pas supprimer ces utilisateurs." + +#: wp-admin/users.php:327 +msgid "Remove Users from Site" +msgstr "Supprimer des utilisateurs de ce site" + +#: wp-admin/users.php:328 +msgid "You have specified these users for removal:" +msgstr "Vous avez choisi de supprimer ces utilisateurs :" + +#: wp-admin/users.php:336 +msgid "ID #%1$s: %2$s The current user will not be removed." +msgstr "" +"ID n°%1$s : %2$s l’utilisateur actuel ne sera pas " +"supprimé." + +#: wp-admin/users.php:338 +msgid "" +"ID #%1$s: %2$s You don't have permission to remove this user." +msgstr "" +"ID n°%1$s : %2$s vous n’avez pas l’autorisation de " +"supprimer cet utilisateur." + +#: wp-admin/users.php:347 +msgid "Confirm Removal" +msgstr "Confirmer la suppression" + +#: wp-admin/users.php:349 +msgid "There are no valid users selected for removal." +msgstr "Aucun utilisateur valide n’est sélectionné pour la suppression." + +#: wp-admin/users.php:379 +msgid "User deleted." +msgid_plural "%s users deleted." +msgstr[0] "Utilisateur supprimé." +msgstr[1] "%s utilisateurs supprimés." + +#: wp-admin/users.php:383 +msgid "New user created. Edit user" +msgstr "" +"Nouvel utilisateur créé. Modifier l’utilisateur" + +#: wp-admin/users.php:387 +msgid "New user created." +msgstr "Le nouvel utilisateur a été créé." + +#: wp-admin/users.php:391 +msgid "Changed roles." +msgstr "Rôles modifiés." + +#: wp-admin/users.php:394 +msgid "The current user’s role must have user editing capabilities." +msgstr "" +"L’utilisateur courant doit avoir un niveau lui permettant de modifier " +"les utilisateurs." + +#: wp-admin/users.php:395 +msgid "Other user roles have been changed." +msgstr "Les rôles des autres utilisateurs ont été modifiés." + +#: wp-admin/users.php:398 +msgid "You can’t delete the current user." +msgstr "Vous ne pouvez pas supprimer l’utilisateur courant." + +#: wp-admin/users.php:399 +msgid "Other users have been deleted." +msgstr "Les autres utilisateurs ont été supprimés." + +#: wp-admin/users.php:402 +msgid "User removed from this site." +msgstr "Utilisateur supprimé de ce site." + +#: wp-admin/users.php:405 +msgid "You can't remove the current user." +msgstr "Vous ne pouvez pas supprimer l’utilisateur courant." + +#: wp-admin/users.php:406 +msgid "Other users have been removed." +msgstr "Les autres utilisateurs ont été supprimés." + +#: wp-admin/widgets.php:51 +msgid "" +"Widgets are independent sections of content that can be placed into any " +"widgetized area provided by your theme (commonly called sidebars). To " +"populate your sidebars/widget areas with individual widgets, drag and drop " +"the title bars into the desired area. By default, only the first widget area " +"is expanded. To populate additional widget areas, click on their title bars " +"to expand them." +msgstr "" +"Les widgets sont des conteneurs de contenu indépendants, qui peuvent être " +"placés dans n’importe quelle zone à widgets de votre thème (le plus " +"souvent, la barre latérale). Pour remplir les zones à widgets de votre barre " +"latérale, glissez/déposez les barres de titre dans la zone désirée. Par " +"défaut, seule la première zone de widgets sera ouverte. Pour remplir les " +"autres zones à widgets, cliquez sur leur barre de titre afin de les ouvrir." + +#: wp-admin/widgets.php:52 +msgid "" +"The Available Widgets section contains all the widgets you can choose from. " +"Once you drag a widget into a sidebar, it will open to allow you to " +"configure its settings. When you are happy with the widget settings, click " +"the Save button and the widget will go live on your site. If you click " +"Delete, it will remove the widget." +msgstr "" +"La section « Widgets disponibles » contient tous les " +"widgets que vous pouvez utiliser. Une fois le widget glissé dans la barre " +"latérale, il s’ouvrira pour vous permettre d’en modifier les " +"réglages. Quand vous êtes satisfait de vos réglages, cliquez sur le bouton " +"« Enregistrer » et le widget sera lancé sur votre " +"site. Si vous cliquez sur « Supprimer », le widget " +"sera enlevé du site." + +#: wp-admin/widgets.php:56 +msgid "Removing and Reusing" +msgstr "Retirer et réutiliser" + +#: wp-admin/widgets.php:58 +msgid "" +"If you want to remove the widget but save its setting for possible future " +"use, just drag it into the Inactive Widgets area. You can add them back " +"anytime from there. This is especially helpful when you switch to a theme " +"with fewer or different widget areas." +msgstr "" +"Si vous voulez enlever le widget, mais conserver ses réglages pour un " +"possible usage futur, glissez-le simplement dans la zone « " +"Widgets désactivés ». De là, vous pouvez les rajouter n’" +"importe quand. C’est particulièrement utile quand vous passez à un " +"thème avec moins de zones à widgets, ou des zones différentes." + +#: wp-admin/widgets.php:59 +msgid "" +"Widgets may be used multiple times. You can give each widget a title, to " +"display on your site, but it’s not required." +msgstr "" +"Les widgets peuvent être utilisés à plusieurs reprises. Vous pouvez donner " +"un titre pour chaque widget, afin de l’afficher sur votre site, mais " +"ce n’est pas obligatoire." + +#: wp-admin/widgets.php:60 +msgid "" +"Enabling Accessibility Mode, via Screen Options, allows you to use Add and " +"Edit buttons instead of using drag and drop." +msgstr "" +"En activant le mode « Accessibilité », via les options " +"d’écrans, vous autorisez l’utilisation des boutons « " +"Ajouter » et « Modifier » à la place du " +"glisser/déposer." + +#: wp-admin/widgets.php:64 +msgid "Missing Widgets" +msgstr "Widgets manquants" + +#: wp-admin/widgets.php:66 +msgid "" +"Many themes show some sidebar widgets by default until you edit your " +"sidebars, but they are not automatically displayed in your sidebar " +"management tool. After you make your first widget change, you can re-add the " +"default widgets by adding them from the Available Widgets area." +msgstr "" +"De nombreux thèmes affichent par défaut quelques widgets dans la barre " +"latérale, jusqu’à ce que vous la modifiez vous-mêmes. Ces widgets par " +"défaut ne sont pas automatiquement affichés dans le gestionnaire de barre " +"latérale. Après avoir fait vos propres modifications de widgets, vous pouvez " +"rajouter les widgets par défaut depuis la section « Widgets " +"Disponibles »." + +#: wp-admin/widgets.php:67 +msgid "" +"When changing themes, there is often some variation in the number and setup " +"of widget areas/sidebars and sometimes these conflicts make the transition a " +"bit less smooth. If you changed themes and seem to be missing widgets, " +"scroll down on this screen to the Inactive Widgets area, where all of your " +"widgets and their settings will have been saved." +msgstr "" +"En changeant de thèmes, il y a souvent des variations sur le nombre et " +"l’agencement des zones de widgets et des barres latérales, et parfois " +"tout cela entre en conflit, rendant la transition moins aisée. Si vous avec " +"changé de thème et que certains widgets semblent manquer, faites défiler cet " +"écran jusqu’en bas pour les retrouver dans la zone des widgets " +"inactifs, où ils ont été conservés avec leurs derniers réglages." + +#: wp-admin/widgets.php:72 +msgid "" +"Documentation on Widgets" +msgstr "" +"Documentation sur les widgets" + +#: wp-admin/widgets.php:77 +msgid "" +"The theme you are currently using isn’t widget-aware, meaning that it " +"has no sidebars that you are able to change. For information on making your " +"theme widget-aware, please follow these instructions." +msgstr "" +"Le thème que vous utilisez n’est pas conçu pour les widgets, ce qui " +"signifie qu’il ne dispose pas d’une colonne latérale que vous " +"pouvez modifier. Pour obtenir des informations sur la manière de rendre " +"votre thème compatible avec les widgets, lisez ces instructions." + +#: wp-admin/widgets.php:93 +msgid "Inactive Sidebar (not used)" +msgstr "Barre latérale inactive (inutilisée)" + +#: wp-admin/widgets.php:96 +msgid "" +"This sidebar is no longer available and does not show anywhere on your site. " +"Remove each of the widgets below to fully remove this inactive sidebar." +msgstr "" +"Cette barre latérale n’est plus disponible, et ne s’affiche " +"nulle part sur le site. Vous pouvez en retirer les widgets ci-dessous afin " +"de la supprimer totalement." + +#: wp-admin/widgets.php:110 +msgid "Inactive Widgets" +msgstr "Widgets désactivés" + +#: wp-admin/widgets.php:113 +msgid "" +"Drag widgets here to remove them from the sidebar but keep their settings." +msgstr "" +"Glissez ici les widgets que vous voulez retirer de la colonne latérale, tout " +"en conservant leurs réglages actuels." + +#: wp-admin/widgets.php:235 +msgid "Widget %s" +msgstr "Widget %s" + +#: wp-admin/widgets.php:246 +msgid "" +"Select both the sidebar for this widget and the position of the widget in " +"that sidebar." +msgstr "" +"Sélectionnez à la fois la colonne latérale pour ce widget, et la position du " +"widget dans cette colonne latérale." + +#: wp-admin/widgets.php:286 +msgid "Save Widget" +msgstr "Enregistrer le widget" + +#: wp-admin/widgets.php:302 +msgid "Changes saved." +msgstr "Modifications enregistrées." + +#: wp-admin/widgets.php:306 +msgid "Error while saving." +msgstr "Erreur lors de la sauvegarde." + +#: wp-admin/widgets.php:307 +msgid "Error in displaying the widget settings form." +msgstr "" +"Une erreur est survenue durant l’affichage du formulaire de " +"paramétrage du widget." + +#: wp-admin/widgets.php:336 +msgid "Available Widgets" +msgstr "Widgets disponibles" + +#: wp-admin/widgets.php:336 +msgctxt "removing-widget" +msgid "Deactivate" +msgstr "Désactiver" + +#: wp-admin/widgets.php:338 +msgid "" +"Drag widgets from here to a sidebar on the right to activate them. Drag " +"widgets back here to deactivate them and delete their settings." +msgstr "" +"Glissez les widgets d’ici vers une colonne latérale à droite pour les " +"activer. Remettez-les ici pour les désactiver et supprimer leurs réglages." + +#. Plugin URI of the plugin/theme +msgid "http://akismet.com/?return=true" +msgstr "http://akismet.com/?return=true" + +#. Description of the plugin/theme +msgid "" +"Used by millions, Akismet is quite possibly the best way in the world to " +"protect your blog from comment and trackback spam. 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) Sign up for an Akismet API key, and 3) Go " +"to your Akismet configuration page, and save your API key." +msgstr "" +"Utilisé par des millions de sites, Akismet est très probablement la " +"meilleure manière de protéger votre site des commentaires et " +"trackbacks indésirables (spam). Il vous protège même pendant votre " +"sommeil. Pour mettre sa protection en place : 1) Cliquez sur le lien " +"« Activer », à gauche de la description, 2) Abtenez une clé d’API Akismet, " +"et 3) Allez sur votre page de configuration d’Akismet et enregistrez-y " +"votre clé d’API." + +#. Author of the plugin/theme +msgid "Automattic" +msgstr "Automattic" + +#. Author URI of the plugin/theme +msgid "http://automattic.com/wordpress-plugins/" +msgstr "http://automattic.com/wordpress-plugins/" + +#. Plugin Name of the plugin/theme +msgid "Hello Dolly" +msgstr "Hello Dolly" + +#. Plugin URI of the plugin/theme +msgid "http://wordpress.org/plugins/hello-dolly/" +msgstr "http://wordpress.org/plugins/hello-dolly/" + +#. Description of the plugin/theme +msgid "" +"This is not just a plugin, it symbolizes the hope and enthusiasm of an " +"entire generation summed up in two words sung most famously by Louis " +"Armstrong: Hello, Dolly. When activated you will randomly see a lyric from " +"Hello, Dolly in the upper right of your admin screen on every " +"page." +msgstr "" +"Ce n'est pas qu'une extension. Elle symbolise l'espoir et l'enthousiasme de " +"toute une génération, résumé en deux mots, qu'a notamment chanté Louis " +"Armstrong : Hello, Dolly. Une fois activé, elle affichera une ligne " +"aléatoirement des paroles de la chanson Hello, Dolly, en haut à " +"droite de toutes les pages de l'administration." + +#. Author of the plugin/theme +msgid "Matt Mullenweg" +msgstr "Matt Mullenweg" + +#. Author URI of the plugin/theme +msgid "http://ma.tt/" +msgstr "http://ma.tt/" + +#~ msgid "" +#~ "Thank you for updating to the latest version. WordPress %s makes your " +#~ "writing experience even better." +#~ msgstr "" +#~ "Merci d’être passé à la dernière version. WordPress %s améliore " +#~ "grandement votre confort d’écriture." + +#~ msgid "Colorful New Theme" +#~ msgstr "Nouveau thème tout en couleurs" + +#~ msgid "Introducing Twenty Thirteen" +#~ msgstr "Arrivée de Twenty Thirteen" + +#~ msgid "" +#~ "The new default theme puts focus on your content with a colorful, single-" +#~ "column design made for media-rich blogging." +#~ msgstr "" +#~ "Le nouveau thème par défaut fait la part belle à votre contenu avec une " +#~ "mise en page colorée et sur une seule colonne, conçu pour la publication " +#~ "d’articles riches en médias." + +#~ msgid "" +#~ "Inspired by modern art, Twenty Thirteen features quirky details, " +#~ "beautiful typography, and bold, high-contrast colors — all with a " +#~ "flexible layout that looks great on any device, big or small." +#~ msgstr "" +#~ "Inspiré de l’art moderne, Twenty Thirteen comprend quelques détails " +#~ "décalés, une superbe typographie et des couleurs franches et contrastées " +#~ "— le tout avec une mise en page flexible qui s’affiche " +#~ "parfaitement sur n’importe quel écran, grand ou petit." + +#~ msgid "Write with Confidence" +#~ msgstr "Écrivez en toute confiance" + +#~ msgid "Explore Revisions" +#~ msgstr "Explorez les révisions" + +#~ msgid "" +#~ "From the first word you write, WordPress saves every change. Each " +#~ "revision is always at your fingertips. Text is highlighted as you scroll " +#~ "through revisions at lightning speed, so you can see what changes have " +#~ "been made along the way." +#~ msgstr "" +#~ "Dès le premier mot écrit, WordPress enregistre chacune de vos " +#~ "modifications. Les révisions sont accessibles en un coup de souris. " +#~ "Lorsque vous comparez les révisions entre elles, le texte s’affiche " +#~ "à la vitesse de la lumière, afin de vous aider à voir ce qui a changé " +#~ "entre chaque." + +#~ msgid "" +#~ "It’s easy to compare two revisions from any point in time, and to " +#~ "restore a revision and go back to writing. Now you can be confident that " +#~ "no mistake is permanent." +#~ msgstr "" +#~ "Vous pouvez facilement comparer deux révisions proches ou éloignées, " +#~ "rétablir une révision et vous remettre à écrire. Désormais, vous avez " +#~ "l’assurance qu’aucune erreur n’est définitive." + +#~ msgid "Improved Autosaves" +#~ msgstr "Sauvegardes automatiques améliorées" + +#~ msgid "" +#~ "Never lose a word you’ve written. Autosaving is now even better; " +#~ "whether your power goes out, your browser crashes, or you lose your " +#~ "internet connection, your content is safe." +#~ msgstr "" +#~ "Ne perdez jamais un mot écrit. La sauvegarde automatique est maintenant " +#~ "encore plus efficace ; qu’il y ait une coupure d’" +#~ "électricité, que votre navigateur plante ou que vous perdiez votre " +#~ "connexion Internet, votre contenu est en de bonnes mains." + +#~ msgid "Better Post Locking" +#~ msgstr "Meilleur verrouillage d’articles" + +#~ msgid "" +#~ "Always know who’s editing with live updates that appear in the list " +#~ "of posts. And if someone leaves for lunch with a post open, you can take " +#~ "over where they left off." +#~ msgstr "" +#~ "Vous pouvez toujours savoir qui est en train de faire des modifications, " +#~ "avec une notification en direct dans la liste des articles. Et si " +#~ "quelqu’un part déjeuner avec un article en cours, vous pouvez " +#~ "prendre leur suite." + +#~ msgid "Support for Audio and Video" +#~ msgstr "Utilisation de médias audio et vidéo" + +#~ msgid "New Media Player" +#~ msgstr "Nouveau lecteur de médias" + +#~ msgid "" +#~ "Share your audio and video with the new built-in HTML5 media player. " +#~ "Upload files using the media manager and embed them in your posts." +#~ msgstr "" +#~ "Partager vos sons et vos vidéos avec le nouveau lecteur de médias HTML5 " +#~ "intégré. Mettez vos fichiers en ligne avec le gestionnaire de médias, et " +#~ "ajoutez-les à vos articles." + +#~ msgid "Embed Music from Spotify, Rdio, and SoundCloud" +#~ msgstr "Intégrez de la musique de Spotify, Rdio et SoundCloud" + +#~ msgid "" +#~ "Embed songs and albums from your favorite artists, or playlists you’" +#~ "ve mixed yourself. It’s as simple as pasting a URL into a post on " +#~ "its own line." +#~ msgstr "" +#~ "Intégrez les chansons et les albums de vos artistes préférés, ou des " +#~ "listes de lectures que vous aurez créées. C’est aussi facile que " +#~ "d’ajouter un lien dans un article sur sa propre ligne." + +#~ msgid "" +#~ "(Love another service? Check out all of the embeds " +#~ "that WordPress supports.)" +#~ msgstr "" +#~ "(Vous préférez un autre service ? Voyez tous ceux que " +#~ "WordPress peut intégrer.)" + +#~ msgid "Audio/Video API" +#~ msgstr "API audio/vidéo" + +#~ msgid "" +#~ "The new audio/video APIs give developers access to powerful media " +#~ "metadata, like ID3 tags." +#~ msgstr "" +#~ "La nouvelle API audio/vidéo permet aux développeurs d’accéder à de " +#~ "puissantes métadonnées, comme les balises ID3." + +#~ msgid "Semantic Markup" +#~ msgstr "Balisage sémantique" + +#~ msgid "" +#~ "Themes can now choose improved HTML5 markup for comment forms, search " +#~ "forms, and comment lists." +#~ msgstr "" +#~ "Les thèmes peuvent maintenant choisir un balisage HTML5 amélioré pour les " +#~ "formulaires de commentaire et de recherche, et les listes de commentaires." + +#~ msgid "JavaScript Utilities" +#~ msgstr "Utilitaires JavaScript" + +#~ msgid "" +#~ "Handy JavaScript utilities ease common tasks like Ajax requests, " +#~ "templating, and Backbone view management." +#~ msgstr "" +#~ "Des utilitaires JavaScript pratiques simplifient les tâches courantes, " +#~ "comme les requêtes Ajax, la création de modèles ou la gestion de l’" +#~ "affichage Backbone." + +#~ msgid "" +#~ "Search content for shortcodes with has_shortcode() and " +#~ "adjust shortcode attributes with a new filter." +#~ msgstr "" +#~ "Cherchez les shortcodes dans vos contenus à l’aide de " +#~ "has_shortcode(), et ajustez leurs attributs à l’aide " +#~ "d’un nouveau filtre." + +#~ msgid "Revision Control" +#~ msgstr "Contrôle des révisions" + +#~ msgid "" +#~ "Fine-grained revision controls allow you to keep a different number of " +#~ "revisions for each post type." +#~ msgstr "" +#~ "Des contrôles de révisions détaillés vous permettent de conserver un " +#~ "nombre différent de révisions pour chaque type de contenu." + +#~ msgid "" +#~ "New and updated libraries: MediaElement.js, jQuery " +#~ "%2$s, jQuery UI %3$s, jQuery Migrate, Backbone %4$s." +#~ msgstr "" +#~ "Bibliothèques mises à jour ou ajoutées : MediaElement.js, jQuery %2$s, jQuery UI %3$s, jQuery Migrate et " +#~ "Backbone %4$s." + +#~ msgid "%1$s translation for the %2$s theme" +#~ msgstr "Traduction %1$s pour le thème %2$s" + +#~ msgid "Updating the %1$s translation for the %2$s plugin" +#~ msgstr "Mise à jour de la traduction de %s1$s pour l'extension %2$s" + +#~ msgid "%1$s translation for the %2$s plugin" +#~ msgstr "Traduction %1$s pour l'extension %2$s" + +#~ msgid "%s translation" +#~ msgstr "Traduction de %s" + +#~ msgid "" +#~ "Downloading language update from %s…" +#~ msgstr "" +#~ "Téléchargement de la mise à jour de la langue depuis " +#~ "%s…" + +#~ msgid "Language update failed." +#~ msgstr "La mise à jour de la langue a échoué." + +#~ msgid "Language updated successfully." +#~ msgstr "La langue a bien été mise à jour." + +#~ msgid "Global Dashboard" +#~ msgstr "Tableau de bord global" + +#~ msgid "Item moved to the Trash." +#~ msgid_plural "%s items moved to the Trash." +#~ msgstr[0] "Élément déplacé dans la corbeille." +#~ msgstr[1] "%s éléments déplacés dans la corbeille." + +#~ msgid "" +#~ "Warning! WordPress encrypts user cookies, but you must add the following " +#~ "lines to wp-config.php for it to be more secure." +#~ msgstr "" +#~ "Attention ! WordPress encrypte les cookies utilisés par les " +#~ "utilisateurs, mais pour que la sécurité soit améliorée vous devez ajouter " +#~ "les lignes suivantes dans le fichier wp-config.php." + +#~ msgid "" +#~ "Before the line /* That's all, stop editing! Happy blogging. */ please add this code:" +#~ msgstr "" +#~ "Veuillez ajouter ce code avant la ligne /* C'est tout, ne touchez " +#~ "pas à ce qui suit ! Bon blogging ! */ :" + +#~ msgid "" +#~ "The current theme does not natively support menus, but you can use the " +#~ "“Custom Menu” widget to add any menus you create here to the " +#~ "theme’s sidebar." +#~ msgstr "" +#~ "Le thème actuellement utilisé ne peut pas utiliser les menus nativement, " +#~ "mais vous pouvez utiliser le widget “Menu de Navigation” pour " +#~ "ajouter n’importe quel menu créé ici à la barre latérale du thème." + +#~ msgid "Select a menu to use within your theme." +#~ msgid_plural "Select the menus you will use in your theme." +#~ msgstr[0] "Sélectionnez un menu à utiliser dans votre thème." +#~ msgstr[1] "Sélectionnez les menus à utiliser dans votre thème." + +#~ msgid "Thumbnail linked to file" +#~ msgstr "Miniature liée au fichier" + +#~ msgid "Image linked to file" +#~ msgstr "Image liée au fichier" + +#~ msgid "Thumbnail linked to page" +#~ msgstr "Miniature liée à la page" + +#~ msgid "Image linked to page" +#~ msgstr "Image liée à la page" + +#~ msgid "Link to file" +#~ msgstr "Lier au fichier" + +#~ msgid "Link to page" +#~ msgstr "Lier à la page" + +#~ msgid "ERROR: %s" +#~ msgstr "Erreur : %s" + +#~ msgid "" +#~ "Your theme supports %s menu. Select which menu you would like to use " +#~ "below." +#~ msgid_plural "" +#~ "Your theme supports %s menus. Select a menu to use for each theme " +#~ "location below." +#~ msgstr[0] "" +#~ "Votre thème accepte %s menu. Sélectionnez le menu que vous souhaitez " +#~ "utiliser ci-dessous." +#~ msgstr[1] "" +#~ "Votre thème accepte %s menus. Sélectionnez un menu à utiliser pour chaque " +#~ "emplacement du thème ci-dessous." + +#~ msgid "An administrator must always approve the comment" +#~ msgstr "Un administrateur doit toujours approuver le commentaire" + +#~ msgctxt "Link used in suggestion to use child themes in GUU" +#~ msgid "http://codex.wordpress.org/Child_Themes" +#~ msgstr "http://codex.wordpress.org/fr:Thèmes_Enfant" + +#~ msgid "" +#~ "Thank you for updating to the latest version! WordPress %s is more " +#~ "polished and enjoyable than ever before. We hope you like it." +#~ msgstr "" +#~ "Merci d’être passé à la dernière version ! WordPress %s est " +#~ "mieux conçu et plus agréable que jamais. Il a tout pour vous plaire." + +#~ msgid "Beautiful Interface" +#~ msgstr "Une superbe interface" + +#~ msgid "" +#~ "Adding media has been streamlined with an all-new experience, making it a " +#~ "breeze to upload files and place them into your posts." +#~ msgstr "" +#~ "L’ajout de fichiers média a été repensé pour aboutir à une toute " +#~ "nouvelle approche, facilitant grandement la mise en ligne et l’" +#~ "insertion dans vos articles." + +#~ msgid "Picturesque Galleries" +#~ msgstr "Des galeries très visuelles" + +#~ msgid "" +#~ "Creating image galleries is faster with drag and drop reordering, inline " +#~ "caption editing, and simplified controls for layout." +#~ msgstr "" +#~ "La création de galeries d’images est plus rapide grâce à la " +#~ "réorganisation par glisser-déposer, la modification directe de la " +#~ "légende, et aux contrôles de mise en page simplifiés." + +#~ msgid "New Default Theme" +#~ msgstr "Nouveau thème par défaut" + +#~ msgid "" +#~ "The newest default theme for WordPress is simple, flexible, and elegant." +#~ msgstr "" +#~ "Le nouveau thème par défaut de WordPress est simple, flexible et élégant." + +#~ msgid "" +#~ "What makes it really shine are the design details, like the gorgeous Open " +#~ "Sans typeface and a fully responsive design that looks great on any " +#~ "device." +#~ msgstr "" +#~ "Il brille notamment par l’attention portée aux détails, comme la " +#~ "superbe police Open Sans et le design totalement souple qui s’" +#~ "adapte parfaitement à toutes les tailles d’écran." + +#~ msgid "" +#~ "Naturally, Twenty Twelve supports all the theme features you’ve come to " +#~ "know and love, but it is also designed to be as great for a website as it " +#~ "is for a blog." +#~ msgstr "" +#~ "Bien entendu, Twenty Twelve intègre toutes les fonctionnalités que vous " +#~ "avez connu et apprécié avec les thèmes précédents, mais il a en plus été " +#~ "conçu pour fonctionner aussi bien pour un site web que pour un blog." + +#~ msgid "Retina Ready" +#~ msgstr "Prêt pour le Retina" + +#~ msgid "So Sharp You Can’t See the Pixels" +#~ msgstr "Tellement net que vous ne verrez pas les pixels" + +#~ msgid "" +#~ "The WordPress dashboard now looks beautiful on high-resolution screens " +#~ "like those found on the iPad, Kindle Fire HD, Nexus 10, and MacBook Pro " +#~ "with Retina Display. Icons and other visual elements are crystal clear " +#~ "and full of detail." +#~ msgstr "" +#~ "Le tableau de bord de WordPress est magnifique sur les écrans haute-" +#~ "résolution, comme ceux de l’iPad, du Kindle Fire HD, du Nexus 10 et " +#~ "du MacBook Pro. Les icônes et autres éléments visuels sont clairs et très " +#~ "détaillés." + +#~ msgid "Smoother Experience" +#~ msgstr "Une utilisation plus harmonieuse" + +#~ msgid "Better Accessibility" +#~ msgstr "Une meilleure accessibilité" + +#~ msgid "" +#~ "WordPress supports more usage modes than ever before. Screenreaders, " +#~ "touch devices, and mouseless workflows all have improved ease of use and " +#~ "accessibility." +#~ msgstr "" +#~ "WordPress reconnaît plus de modes d’utilisation qu’" +#~ "auparavant. Les lecteurs d’écrans, les appareils tactiles et les " +#~ "utilisations sans souris fonctionnent tous plus simplement et avec une " +#~ "meilleure accessibilité." + +#~ msgid "More Polish" +#~ msgstr "Un coup d’éclat" + +#~ msgid "" +#~ "A number of screens and controls have been refined. For example, a new " +#~ "color picker makes it easier for you to choose that perfect shade of blue." +#~ msgstr "" +#~ "Un grand nombre d’écrans et de contrôleurs ont été repensés. Par " +#~ "exemple, le nouveau sélecteur de couleur vous permet de trouver plus " +#~ "simplement cette teinte de bleu si particulière." + +#~ msgid "Meta Query Additions" +#~ msgstr "Support des Meta Queries" + +#~ msgid "" +#~ "The WP_Comment_Query and WP_User_Query classes " +#~ "now support meta queries just like WP_Query. Meta queries " +#~ "now support querying for objects without a particular meta key." +#~ msgstr "" +#~ "Les classes WP_Comment_Query et WP_User_Query " +#~ "reconnaissent désormais les requêtes méta, tout comme WP_Query. Les requêtes méta peuvent maintenant lancer une requête sur un " +#~ "objet sans nécessite de clé méta." + +#~ msgid "Post Objects" +#~ msgstr "Objets d’articles" + +#~ msgid "" +#~ "Post objects are now instances of a WP_Post class, which " +#~ "improves performance by loading selected properties on demand." +#~ msgstr "" +#~ "Les objets d’articles sont dorénavant des instances de la classe " +#~ "WP_Post, qui améliore les performances en chargeant à la " +#~ "demande les propriétés sélectionnées." + +#~ msgid "Image Editing API" +#~ msgstr "L’API de modification d’image" + +#~ msgid "" +#~ "The WP_Image_Editor class abstracts image editing " +#~ "functionality such as cropping and scaling, and uses ImageMagick when " +#~ "available." +#~ msgstr "" +#~ "La classe WP_Image_Editor est une abstraction de la " +#~ "fonctionnalité de modification d’image, comme le cadrage et le " +#~ "changement d’échelle. Elle utilise ImageMagick si cette " +#~ "bibliothèque est disponible." + +#~ msgid "" +#~ "switch_to_blog() is now significantly faster and more " +#~ "reliable." +#~ msgstr "" +#~ "switch_to_blog() est sensiblement plus rapide et fiable." + +#~ msgid "XML-RPC API" +#~ msgstr "L’API XML-RPC" + +#~ msgid "" +#~ "The WordPress API is now always enabled, and supports " +#~ "fetching users, editing profiles, managing post revisions, and searching " +#~ "posts." +#~ msgstr "" +#~ "L’API de WordPress est dorénavant toujours " +#~ "activée, et autorise la récupération des utilisateurs, la modification " +#~ "des profils, la gestion des révisions d’articles, et la recherche " +#~ "d’articles." + +#~ msgid "http://codex.wordpress.org/XML-RPC_WordPress_API" +#~ msgstr "http://codex.wordpress.org/XML-RPC_WordPress_API" + +#~ msgid "" +#~ "WordPress now includes the Underscore and Backbone JavaScript libraries. TinyMCE, jQuery, jQuery UI, " +#~ "and SimplePie have all been updated to the latest versions." +#~ msgstr "" +#~ "WordPress inclus aujourd’hui les bibliothèques Underscore et Backbone. TinyMCE, jQuery, " +#~ "jQuery UI, et SimplePie ont tous été mis à jour à la dernière version" + +#~ msgid "" +#~ "You have lost your connection with the server, and saving has been " +#~ "disabled. This message will vanish once you've reconnected." +#~ msgstr "" +#~ "Vous avez perdu votre connexion avec le serveur, et l'enregistrement a " +#~ "été désactivé. Ce message disparaîtra une fois que vous serez à nouveau " +#~ "connecté." + +#~ msgid "“%1$s” from %2$s." +#~ msgstr "%1$s tiré de %2$s." + +#~ msgid "“%1$s” by %2$s." +#~ msgstr "%1$s par %2$s." + +#~ msgid "“%s”." +#~ msgstr "%s." + +#~ msgid "Length:" +#~ msgstr "Durée :" + +#~ msgctxt "post type general name: Posts, Pages, etc." +#~ msgid "Go to All %s" +#~ msgstr "Aller à l'ensemble des %s" + +#~ msgid "" +#~ "Menus can be displayed in locations defined by your theme, even used in " +#~ "sidebars by adding a “Custom Menus” widget on the Widgets screen. " +#~ msgstr "" +#~ "Les menus peuvent être affichés dans certains emplacements prédéfinis de " +#~ "votre thème, et même être utilisés dans les barre latérales à l'aide du " +#~ "widget « Menus personnalisés » depuis l'écran Widgets. " + +#~ msgid "Go to All Posts" +#~ msgstr "Aller à Tous les articles" + +#~ msgid "No difference" +#~ msgstr "Aucune différence" + +#~ msgid "Settings saved." +#~ msgstr "Options enregistrées." + +#~ msgid "Standard" +#~ msgstr "Par défaut" + +#~ msgid "(twice, required)" +#~ msgstr "(deux fois, obligatoire)" + +#~ msgid "Save Changes" +#~ msgstr "Enregistrer les modifications" + +#~ msgid "F j, Y" +#~ msgstr "j F Y" + +#~ msgid "g:i a" +#~ msgstr "G \\h i \\m\\i\\n" + +#~ msgid "F j, Y g:i a" +#~ msgstr "j F Y, G \\h i \\m\\i\\n" + +#~ msgid "Use the editor below to compose your post." +#~ msgstr "Utilisez l'éditeur ci-dessous pour rédiger votre article." + +#~ msgid "Select or upload an image for your post." +#~ msgstr "Sélectionnez ou mettez en ligne une image pour votre article." + +#~ msgid "" +#~ "Use the Add Media button to select or upload images for your gallery." +#~ msgstr "" +#~ "Utilisez le bouton Ajouter un média pour sélectionner ou mettre en ligne " +#~ "des images pour votre galerie." + +#~ msgid "" +#~ "Add a link title and destination URL. Use the editor to compose optional " +#~ "text to accompany the link." +#~ msgstr "" +#~ "Ajoutez un titre au lien et une adresse de destination. Utilisez " +#~ "l'éditeur pour rédiger un text facultatif pour accompagner le lien." + +#~ msgid "Select or upload a video, or paste a video embed code into the box." +#~ msgstr "" +#~ "Sélectionnez ou mettez en ligne une vidéo, ou collez son code d'inclusion " +#~ "(embed) dans le champ texte." + +#~ msgid "" +#~ "Select or upload an audio file, or paste an audio embed code into the box." +#~ msgstr "" +#~ "Sélectionnez ou mettez en ligne un fichier audio, ou collez son code " +#~ "d'inclusion (embed) dans le champ texte." + +#~ msgid "Copy a chat or Q&A transcript into the editor." +#~ msgstr "" +#~ "Copiez dans l'éditeur une retranscription de discussion ou de question-" +#~ "réponse." + +#~ msgid "Use the editor to compose a status update. What’s new?" +#~ msgstr "" +#~ "Utilisez l'éditeur pour rédiger une mise à jour d'état. Quoi de " +#~ "neuf ?" + +#~ msgid "" +#~ "Add a source name and link if you have them. Use the editor to compose " +#~ "the quote." +#~ msgstr "" +#~ "Ajoutez le nom et le lien de votre source si vous les connaissez. " +#~ "Utilisez l'éditeur pour rédiger votre article." + +#~ msgid "Use the editor to share a quick thought or side topic." +#~ msgstr "" +#~ "Utilisez l'éditeur pour partager une rapide réflexion ou un sujet annexe." + +#~ msgid "Y/m/d \\a\\t g:i A" +#~ msgstr "d/m/Y \\à G \\h i \\m\\i\\n" + +#~ msgid "Quote source" +#~ msgstr "Source de la citation" + +#~ msgid "Drop image file to upload" +#~ msgstr "Déposez le fichier de l'image à mettre en ligne" + +#~ msgid "Choose an Image" +#~ msgstr "Choisissez une image" + +#~ msgid "Select / Upload Image" +#~ msgstr "Sélectionner une image à mettre en ligne" + +#~ msgid "Image URL or HTML" +#~ msgstr "Adresse ou code HTML de l'image" + +#~ msgid "(or use an image URL or HTML)" +#~ msgstr "" +#~ "(ou utilisez l'adresse ou le code HTML d'une image)" + +#~ msgid "(or use an image URL)" +#~ msgstr "(ou indiquez l'adresse web d'une image)" + +#~ msgid "(or select/upload an image)" +#~ msgstr "(or sélectionner une image à mettre en ligne)" + +#~ msgid "Quote source link" +#~ msgstr "Lien de la source de la citation" + +#~ msgid "Image click-through link" +#~ msgstr "Lien vers lequel mène l'image" + +#~ msgid "Video embed code or URL" +#~ msgstr "Adresse ou code d'insertion de la vidéo" + +#~ msgid "Video URL" +#~ msgstr "Adresse web de la vidéo" + +#~ msgid "Choose a Video" +#~ msgstr "Choisissez une vidéo" + +#~ msgid "Select Video" +#~ msgstr "Sélectionner la vidéo" + +#~ msgid "Select Video From Media Library" +#~ msgstr "Sélectionner une vidéo depuis la bibliothèque de médias" + +#~ msgid "Audio embed code or URL" +#~ msgstr "Adresse ou code d'insertion du son" + +#~ msgid "Audio URL" +#~ msgstr "Adresse web du fichier audio" + +#~ msgid "Choose Audio" +#~ msgstr "Choisissez le fichier audio" + +#~ msgid "Select Audio" +#~ msgstr "Sélectionner un fichier audio" + +#~ msgid "Select Audio From Media Library" +#~ msgstr "Sélectionner un fichier audio depuis la bibliothèque de médias" + +#~ msgid "Error in deleting..." +#~ msgstr "Erreur pendant la suppression…" + +#~ msgid "" +#~ "ALERT: You are logged out! Could not save draft. Please log in again." +#~ msgstr "" +#~ "ALERTE : vous êtes déconnecté(e) ! Impossible " +#~ "d’enregistrer le brouillon. Veuillez vous reconnecter." + +#~ msgid "No tags found!" +#~ msgstr "Aucun mot-clé trouvé !" + +#~ msgid "" +#~ "Your login has expired. Please open a new browser window and log in again. " +#~ msgstr "" +#~ "Votre connexion a expiré. Veuillez ouvrir une nouvelle fenêtre de votre " +#~ "navigateur et vous reconnecter. " + +#~ msgid "" +#~ "%s is currently editing this article. If you update it, you will " +#~ "overwrite the changes." +#~ msgstr "" +#~ "%s est en train de modifier cet article. Si vous le modifiez, vous " +#~ "annulerez ses modifications." + +#~ msgid "[more]" +#~ msgstr "[plus]" + +#~ msgid "[less]" +#~ msgstr "[moins]" + +#~ msgid "Custom Links" +#~ msgstr "Liens personnalisés" + +#~ msgid "Label" +#~ msgstr "Titre" + +#~ msgid "" +#~ "Select menu items (pages, categories, links) from the boxes at left to " +#~ "begin building your custom menu." +#~ msgstr "" +#~ "Sélectionner les entrées du menu (pages, catégories, liens) depuis les " +#~ "blocs situés à gauche pour commencer à construire votre menu personnalisé." + +#~ msgid "Warning: %s is currently editing this post" +#~ msgstr "Attention : %s modifie actuellement cet article" + +#~ msgid "Warning: %s is currently editing this page" +#~ msgstr "Attention : %s modifie actuellement cette page" + +#~ msgid "%1$s%2$s, %3$s @ %4$s : %5$s" +#~ msgstr "%2$s %1$s %3$s à %4$s h %5$s min" + +#~ msgid "The %s menu has been successfully created." +#~ msgstr "Le menu %s a bien été créé." + +#~ msgid "" +#~ "This feature allows you to use a custom menu in place of your theme’" +#~ "s default menus." +#~ msgstr "" +#~ "Cette fonctionnalité vous permet d’utiliser un menu personnaliser " +#~ "en lieu et place du menu par défaut de votre thème." + +#~ msgid "" +#~ "Custom menus may contain links to pages, categories, custom links or " +#~ "other content types (use the Screen Options tab to decide which ones to " +#~ "show on the screen). You can specify a different navigation label for a " +#~ "menu item as well as other attributes. You can create multiple menus. If " +#~ "your theme includes more than one menu location, you can choose which " +#~ "custom menu to associate with each. You can also use custom menus in " +#~ "conjunction with the Custom Menus widget." +#~ msgstr "" +#~ "Les menus personnalisés peuvent contenir des liens vers des pages, des " +#~ "catégories, des liens personnalisés ou d’autres types de contenus " +#~ "(utilisez l’onglet « Options de l’écran " +#~ "» pour décider lesquels afficher). Vous pouvez choisir un titre de " +#~ "navigation différent pour le menu ainsi que ses autres attributs. Vous " +#~ "pouvez créer plusieurs menus. Si votre thème peut prendre en compte " +#~ "plusieurs menus, vous pouvez choisir quel menu associer à chaque " +#~ "emplacement. Vous pouvez également utiliser les menus personnalisés par " +#~ "le biais du widget « Menu Personnalisé »." + +#~ msgid "Create Menus" +#~ msgstr "Créer des menus" + +#~ msgid "" +#~ "To create a new custom menu, click on the + tab, give the menu a name, " +#~ "and click Create Menu. Next, add menu items from the appropriate boxes. " +#~ "You’ll be able to edit the information for each menu item, and can " +#~ "drag and drop to change their order. You can also drag a menu item a " +#~ "little to the right to make it a submenu. Don’t forget to click " +#~ "Save Menu when you’re finished." +#~ msgstr "" +#~ "Pour créer un nouveau menu personnalisé, cliquez sur l’onglet " +#~ "« + », nommez le menu puis cliquez sur « " +#~ "Créer un menu ». Ensuite, ajoutez-y des éléments à partir des " +#~ "blocs appropriés. Vous pourrez modifier les informations pour chaque " +#~ "élément de menu, et les glisser/déposer afin d’en changer l’" +#~ "ordre. Vous pouvez également glisser un élément de menu un peu plus vers " +#~ "la droite afin d’en faire un sous-menu. N’oubliez pas de " +#~ "cliquer sur « Enregistrer le menu » quand vous avez " +#~ "terminé." + +#~ msgid "Add New Menu" +#~ msgstr "Ajouter un nouveau menu" + +#~ msgid "Add menu" +#~ msgstr "Ajouter un menu" + +#~ msgid "" +#~ "To create a custom menu, give it a name above and click Create Menu. Then " +#~ "choose items like pages, categories or custom links from the left column " +#~ "to add to this menu." +#~ msgstr "" +#~ "Pour créer un menu personnalisé, donnez-lui un nom ci-dessus et cliquez " +#~ "sur « Créer un menu ». Ensuite, ajoutez-y des " +#~ "entrées (des pages, des catégories ou des liens personnalisés) depuis la " +#~ "colonne de gauche." + +#~ msgid "" +#~ "When you have finished building your custom menu, make sure you click the " +#~ "Save Menu button." +#~ msgstr "" +#~ "Une fois que vous avez terminé de construire votre menu, n’oubliez " +#~ "pas de cliquer sur le bouton « Enregister le menu »." + +#~ msgid "WordPress Address (URL)" +#~ msgstr "Adresse web de WordPress (URL)" + +#~ msgid "Site Address (URL)" +#~ msgstr "Adresse web du site (URL)" + +#~ msgid "Loading..." +#~ msgstr "Chargement..." + +#~ msgid "These revisions are identical." +#~ msgstr "Ces 2 versions sont identiques." + +#~ msgid "Function Name..." +#~ msgstr "Nom de fonction..." + +#~ msgid "Invalid user ID." +#~ msgstr "Identifiant utilisateur invalide." + +#~ msgid "Insert Multiple Images" +#~ msgstr "Insérez plusieurs images" + +#~ msgid "" +#~ "Have a need for speed? You can now insert multiple images at once and " +#~ "then compose your words around them." +#~ msgstr "" +#~ "Besoin de vélocité ? Vous pouvez désormais insérer plusieurs images " +#~ "en même temps, puis les entourer de votre texte." + +#~ msgid "Attachment Page Content" +#~ msgstr "Contenu de la page du fichier attaché" + +#~ msgid "Description" +#~ msgstr "Description" + +#~ msgid "Arrow: move by 10px" +#~ msgstr "Flèche : déplacer de 10 px" + +#~ msgid "Shift + arrow: move by 1px" +#~ msgstr "Shit + Flèche : déplacer de 1 px" + +#~ msgid "Ctrl + arrow: resize by 10px" +#~ msgstr "Ctrl + Flèche : ajuster de 10 px" + +#~ msgid "Ctrl + Shift + arrow: resize by 1px" +#~ msgstr "Ctrl + shift + Flèche : ajuster de 1 px" + +#~ msgid "Shift + drag: lock aspect ratio" +#~ msgstr "Shift + clic/déplacement : fixer une proportion de taille" + +#~ msgid "Refresh" +#~ msgstr "Rafraîchir" + +#~ msgid "No items found." +#~ msgstr "Aucun élément trouvé." + +#~ msgid "Choose a Featured Image" +#~ msgstr "Choisissez une image à mettre à la une" + +#~ msgid "Update Featured Image" +#~ msgstr "Mettre à jour l'image à la Une" + +#~ msgid "Remove Featured Image" +#~ msgstr "Supprimer l’image à la une" + +#~ msgid "Set featured image" +#~ msgstr "Mettre une image à la une" + +#~ msgid "Media attachment updated" +#~ msgstr "Fichier attaché mis à jour." + +#~ msgid "Delete Permanently" +#~ msgstr "Supprimer définitivement" + +#~ msgid "Sorry, that file cannot be edited." +#~ msgstr "Désolé, ce fichier ne peut être modifié." + +#~ msgid "New Feature: Plugin Favorites" +#~ msgstr "Nouvelle fonctionnalité : extensions favorites" + +#~ msgid "" +#~ "If you have favorited plugins on WordPress.org, you can now install them " +#~ "directly from this tab." +#~ msgstr "" +#~ "Si vous avez mis des extensions en favoris sur WordPress.org, vous pouvez " +#~ "les installer directement depuis cet onglet." + +#~ msgid "widgets" +#~ msgstr "widgets" + +#~ msgid "menus" +#~ msgstr "menus" + +#~ msgid "Live Theme Previews" +#~ msgstr "La prévisualisation des thèmes" + +#~ msgid "" +#~ "Gone are the days of rushing to update your header, background, and the " +#~ "like as soon as you activate a new theme. You can now customize these " +#~ "options before activating a new theme. Note: this " +#~ "feature is available for installed themes only." +#~ msgstr "" +#~ "Qu’ils sont loin les jours où, juste après avoir activé un nouveau " +#~ "thème, vous deviez vous dépêcher de modifier l’en-tête, le fond et " +#~ "le reste ! Désormais, vous pouvez personnaliser ces options " +#~ "avant d’activer un nouveau thème. Attention : " +#~ "cette fonctionnalité n’est disponible que pour les thèmes installés." + +#~ msgid "Customize Current Theme" +#~ msgstr "Personnalisez votre thème actuel" + +#~ msgid "" +#~ "Satisfy your curiosity and try on a fresh coat of paint — you can " +#~ "also use the live preview mode to customize your current theme. Look for " +#~ "the Customize link on the Themes screen." +#~ msgstr "" +#~ "Succombez à la curiosité et voyez la vie en technicolor : avec le " +#~ "mode de prévisualisation, vous pouvez également personnaliser votre thème " +#~ "actuel. Cliquez sur le lien « Personnaliser » dans " +#~ "l’écran des thèmes." + +#~ msgid "Custom Headers" +#~ msgstr "Des en-têtes personnalisés" + +#~ msgid "Flexible Sizes" +#~ msgstr "Tailles flexible" + +#~ msgid "" +#~ "You can decide for yourself how tall or wide your custom header image " +#~ "should be. From now on, themes will provide a recommended image size for " +#~ "custom headers rather than a fixed requirement. Note: this feature " +#~ "requires theme " +#~ "support." +#~ msgstr "" +#~ "Vous pouvez décider de la taille de votre image d’en-tête, en " +#~ "hauteur comme en largeur. Désormais, les thèmes proposeront une taille " +#~ "recommandée pour les en-têtes personnalisés plutôt que de l’" +#~ "imposer. Attention : cette fonctionnalité ne fonctionne qu’avec les thèmes qui " +#~ "l’implémentent (en)." + +#~ msgid "" +#~ "Tired of re-uploading the same custom header image every time you check " +#~ "out a new theme? Now you can choose header images from your media library " +#~ "for easier customization." +#~ msgstr "" +#~ "La lassitude vous étreint-elle quand vous devez remettre en ligne la même " +#~ "image d’en-tête chaque fois que vous testez un nouveau thème ? Pour " +#~ "simplifier cette personnalisation, vous pouvez maintenant choisir une " +#~ "image d’en-tête directement dans votre bibliothèque de médias." + +#~ msgid "Twitter Embeds" +#~ msgstr "Twitter est dans la place" + +#~ msgid "Share Tweets with Style" +#~ msgstr "Partager vos tweets avec classe" + +#~ msgid "" +#~ "You can now embed individual tweets in posts. It includes action links " +#~ "that allow readers to reply to, retweet, and favorite the tweet without " +#~ "leaving your site. Just paste a tweet URL on its own line." +#~ msgstr "" +#~ "Vous pouvez maintenant inclure des tweets individuels dans vos articles, " +#~ "WordPress se chargera d’ajouter les liens permettant à vos lecteurs " +#~ "de répondre, retweeter ou ajouter le tweet en favoris directement depuis " +#~ "votre site. Collez simplement le lien du tweet dans sa propre ligne." + +#~ msgid "" +#~ "This works with URLs from some other sites, too. For more, see the Codex " +#~ "article on Embeds." +#~ msgstr "" +#~ "Notez que cela marche également avec les liens d’autres sites. Pour " +#~ "en savoir plus, lisez l’article Embeds (en) du " +#~ "Codex." + +#~ msgid "http://codex.wordpress.org/Embeds" +#~ msgstr "http://codex.wordpress.org/Embeds" + +#~ msgid "Better Captions" +#~ msgstr "De plus belles légendes" + +#~ msgid "HTML Support" +#~ msgstr "Support HTML" + +#~ msgid "" +#~ "Basic HTML support has been added to the caption field in the image " +#~ "uploader. This allows you to add links — great for photo credits or " +#~ "licensing details — and basic formatting such as bold and " +#~ "italicized text." +#~ msgstr "" +#~ "Nous avons ajouté un support HTML de base au champ de légende d’" +#~ "image dans l’outil de mise en ligne. Cela vous permet d’" +#~ "ajouter des liens ; très utile pour faire un lien vers l’auteur de " +#~ "la photo ou vers les détails de la licence d’utilisation, ainsi que " +#~ "vous mettre en place une mise en forme simple, comme un texte en gras ou " +#~ "en italique." + +#~ msgid "Faster WP_Query" +#~ msgstr "Des requêtes WP_Query plus rapides" + +#~ msgid "" +#~ "Post queries have been optimized to improve performance, especially for " +#~ "sites with large databases." +#~ msgstr "" +#~ " Les requêtes d’écriture ont été optimisées pour améliorer les " +#~ "performances, notamment sur les sites ayant beaucoup de contenu." + +#~ msgid "" +#~ "The number of strings loaded on the front end was greatly reduced, " +#~ "resulting in faster front page load times for localized installations." +#~ msgstr "" +#~ "Le nombre de chaînes chargées pour le thème a été grandement réduit, ce " +#~ "qui donne des pages qui se chargent plus vite même avec les fichiers de " +#~ "traduction." + +#~ msgid "" +#~ "Also, better support for East Asian languages, right-to-left languages, " +#~ "theme translations, and more." +#~ msgstr "" +#~ "Par ailleurs, WordPress gère désormais mieux les langues d’Asie " +#~ "orientale, celles qui s’écrivent de droite à gauche (RTL), la " +#~ "traduction des thèmes, et plus encore." + +#~ msgid "Themes API" +#~ msgstr "L’API des thèmes" + +#~ msgid "" +#~ "WP_Theme, wp_get_themes(), wp_get_theme(). Faster, uses less memory, " +#~ "makes use of persistent caching." +#~ msgstr "" +#~ "WP_Theme, wp_get_themes() et wp_get_theme() sont plus rapides, utilisent " +#~ "moins de mémoire, et font un meilleur usage du cache persistant." + +#~ msgid "Custom Header and Background API" +#~ msgstr "" +#~ "L’API de gestion des en-têtes personnalisés et des images de fond" + +#~ msgid "" +#~ "Custom header and background API relocated into the theme support API." +#~ msgstr "" +#~ "L’API de gestion des en-têtes personnalisés et des images de fond a " +#~ "été déplacée dans l’API de support du thème." + +#~ msgid "" +#~ "A new WordPress API that supports custom content types " +#~ "and taxonomies, as well as dozens of other bug fixes and improvements." +#~ msgstr "" +#~ "Une nouvelle API pour WordPress, qui fonctionne avec " +#~ "les types de contenus et les taxinomies, et profite également d’une " +#~ "douzaine de correctifs et d’améliorations." + +#~ msgid "" +#~ "jQuery, jQuery UI, TinyMCE, Plupload, PHPMailer, SimplePie, and other " +#~ "libraries were updated. jQuery UI Touch Punch was introduced." +#~ msgstr "" +#~ "jQuery, jQuery UI, TinyMCE, Plupload, PHPMailer, SimplePie et d’" +#~ "autres bibliothèques ont été mises à jour. Introduction de jQuery UI " +#~ "Touch Punch." + +#~ msgid "Reset Text Color" +#~ msgstr "Réinitialiser la couleur du texte" + +#~ msgid "" +#~ "This will restore the original header text. You will not be able to " +#~ "restore any customizations." +#~ msgstr "" +#~ "Ceci remettra en place l’image d’en-tête d’origine. Il " +#~ "ne vous sera pas possible de récupérer vos personnalisations." + +#~ msgid "Restore Original Header Text" +#~ msgstr "Remettre le texte l’en-tête d’origine" + +#~ msgid "Publish Box" +#~ msgstr "Boite de publication" + +#~ msgctxt "column name" +#~ msgid "Attached to" +#~ msgstr "Attaché à" + +#~ msgid "Upload/Insert %s" +#~ msgstr "Envoyer/Insérer %s" + +#~ msgid "Maximum upload file size: %d%s." +#~ msgstr "Taille maximale des fichiers : %d%s." + +#~ msgid "After a file has been uploaded, you can add titles and descriptions." +#~ msgstr "" +#~ "Une fois le fichier envoyé, vous pourrez lui ajouter titre et " +#~ "descriptions." + +#~ msgid "Images" +#~ msgstr "Images" + +#~ msgid "Manage Images" +#~ msgstr "Gérer les images" + +#~ msgid "Image (%s)" +#~ msgid_plural "Images (%s)" +#~ msgstr[0] "Image (%s)" +#~ msgstr[1] "Images (%s)" + +#~ msgid "Manage Audio" +#~ msgstr "Gérer les sons" + +#~ msgid "Audio (%s)" +#~ msgid_plural "Audio (%s)" +#~ msgstr[0] "Fichier audio (%s)" +#~ msgstr[1] "Fichiers audio (%s)" + +#~ msgid "Manage Video" +#~ msgstr "Gérer les vidéos" + +#~ msgid "Video (%s)" +#~ msgid_plural "Video (%s)" +#~ msgstr[0] "Vidéos (%s)" +#~ msgstr[1] "Vidéos (%s)" + +#~ msgid "Located at" +#~ msgstr "Situé dans" + +#~ msgid "You must select a page to set a static front page." +#~ msgstr "" +#~ "Vous devez sélectionner une page pour configurer une page d'accueil " +#~ "statique." + +#~ msgid "Updated Media Uploader" +#~ msgstr "Outil d’envoi de fichiers mis à jour" + +#~ msgid "" +#~ "The single media icon now launches the uploader for all file types, and " +#~ "the new drag and drop interface makes uploading a breeze." +#~ msgstr "" +#~ "Il n’y a désormais plus qu’une seule icône d’envoi de " +#~ "fichier, pour tous les types de fichier. Elle mène à l’interface de " +#~ "glisser/déposer de fichier, beaucoup plus simple." + +#~ msgid "" +#~ "Basic image editing is available after upload is complete. Make sure you " +#~ "click Save before leaving this screen." +#~ msgstr "" +#~ "Un petit outil de retouche très basique est disponible une fois que la " +#~ "mise en ligne est validée. Prenez garde à bien cliquer sur «" +#~ " Enregistrer » en quitter cet écran." + +#~ msgctxt "default page for posts title" +#~ msgid "Blog" +#~ msgstr "Blog" + +#~ msgid "Enable a static front page" +#~ msgstr "Mettre en place une page d'accueil statique" + +#~ msgid "Show a page instead of your latest posts" +#~ msgstr "" +#~ "Afficher une page plutôt que les derniers articles" + +#~ msgid "Add new page titled:" +#~ msgstr "Ajouter une nouvelle page intitulée :" + +#~ msgid "— Add new page —" +#~ msgstr "— Ajouter un nouvelle page —" + +#~ msgid "titled:" +#~ msgstr "intitulée :" + +#~ msgctxt "default page on front title" +#~ msgid "Home" +#~ msgstr "Accueil" + +#~ msgid "Show latest posts on a separate page" +#~ msgstr "Afficher les derniers articles sur une page séparée" + +#~ msgid "Page title:" +#~ msgstr "Titre de la page :" + +#~ msgid "" +#~ "You can also choose a background color. If you know the hexadecimal code " +#~ "for the color you want, enter it in the Background Color field. If not, " +#~ "click on the Select a Color link, and a color picker will allow you to " +#~ "choose the exact shade you want." +#~ msgstr "" +#~ "Vous pouvez également choisir une couleur de fond. Si vous connaissez le " +#~ "code hexadécimal de la couleur voulue, saisissez-la dans le champ «" +#~ " Couleur ». Sinon, cliquez sur le lien « " +#~ "Sélecteur de Couleur », et vous pourrez choisir la teinte " +#~ "exacte que vous recherchez." + +#~ msgid "Media Library" +#~ msgstr "Bibliothèque" + +#~ msgid "Large" +#~ msgstr "Large" + +#~ msgid "Select" +#~ msgstr "Sélectionner" + +#~ msgid "First, tweak the look of your site:" +#~ msgstr "Pour commencer, retouchez l'apparence de votre site :" + +#~ msgid "Learn How To" +#~ msgstr "Apprenez à" + +#~ msgid "Add image/media" +#~ msgstr "Ajouter une image/un média" + +#~ msgid "Add/remove widgets" +#~ msgstr "Ajouter/enlever des widgets" + +#~ msgid "Edit your navigation menu" +#~ msgstr "Modifier votre menu de navigation" + +#~ msgid "Gallery Settings" +#~ msgstr "Réglages de galerie" + +#~ msgid "Insert gallery" +#~ msgstr "Insérer une galerie" + +#~ msgid "Columns" +#~ msgstr "Colonnes" + +#~ msgid "Already Installed" +#~ msgstr "Déjà installé" + +#~ msgid "" +#~ "You appear to have already installed WordPress. To reinstall please clear " +#~ "your old database tables first." +#~ msgstr "" +#~ "Il semblerait que WordPress soit déjà installé. Pour le réinstaller, " +#~ "commencez par vider les tables de la base de données." + +#~ msgid "" +#~ "Due to security issues, you cannot use Post By Email on Multisite " +#~ "Installs." +#~ msgstr "" +#~ "Suite à des problèmes de sécurité, vous ne pouvez pas utiliser la " +#~ "publication par e-mail sur les installations multisite." + +#~ msgid "Remote Publishing" +#~ msgstr "Publication à distance" + +#~ msgid "" +#~ "Remote Publishing allows you to use an external editor (like the iOS or " +#~ "Android app) to write your posts." +#~ msgstr "" +#~ "La publication à distance vous permet d’utiliser un éditeur externe " +#~ "(tel qu’une application iOS ou Android) pour écrire vos articles." + +#~ msgid "" +#~ "You do not have sufficient permissions to install plugins for this site." +#~ msgstr "" +#~ "Vous n’avez pas les droits suffisants pour installer des extensions " +#~ "sur ce site." + +#~ msgid "" +#~ "You do not have sufficient permissions to install themes for this site." +#~ msgstr "" +#~ "Vous n’avez pas les droits suffisants pour installer des thèmes sur " +#~ "ce site." + +#~ msgid "" +#~ "The description is not prominent by default, however some themes may show " +#~ "it." +#~ msgstr "" +#~ "La description n’est pas très utilisée par défaut, cependant de " +#~ "plus en plus de thèmes l’affichent." + +#~ msgid "Attachment Page" +#~ msgstr "Page de fichier attaché" + +#~ msgid "Select a Color" +#~ msgstr "Sélecteur de couleur" + +#~ msgid "Clear" +#~ msgstr "Effacer" + +#~ msgid "No Tags" +#~ msgstr "Aucun mot-clé" + +#~ msgid "" +#~ "The template files are located in %2$s. The stylesheet files " +#~ "are located in %3$s. %4$s uses templates " +#~ "from %5$s. Changes made to the templates will affect " +#~ "both themes." +#~ msgstr "" +#~ "Les fichiers du thème se trouvent dans %2$s. Les " +#~ "feuilles de style sont dans %3$s. %4$s " +#~ "utilise les modèles de %5$s. Tout changement dans les " +#~ "modèles affectera les deux thèmes." + +#~ msgid "All of this theme’s files are located in %2$s." +#~ msgstr "Tous les fichiers de ce thème se trouvent dans %2$s." + +#~ msgid "on %4$s" +#~ msgstr "le %4$s" + +#~ msgid "Welcome to your new WordPress site!" +#~ msgstr "Bienvenue dans votre nouveau site WordPress !" + +#~ msgid "" +#~ "If you need help getting started, check out our documentation on First Steps " +#~ "with WordPress. If you’d rather dive right in, here are a few " +#~ "things most people do first when they set up a new WordPress site. If you " +#~ "need help, use the Help tabs in the upper right corner to get information " +#~ "on how to use your current screen and where to go for more assistance." +#~ msgstr "" +#~ "Si vous avez besoin d’aide pour vous lancer, jeter un œil à " +#~ "notre documentation, « Premiers pas avec WordPress " +#~ "». Si vous préférez faire le grand saut directement, voici quelques " +#~ "indications sur ce que la plupart des utilisateurs font quand ils mettent " +#~ "en place un nouveau site WordPress. Si vous avez besoin d’" +#~ "assistance, utilisez les onglets d’aide, situés dans le coin " +#~ "supérieur droit, pour obtenir des informations sur la manière d’" +#~ "utiliser l’écran courant, et où trouver plus d’information." + +#~ msgid "Basic Settings" +#~ msgstr "Réglages de base" + +#~ msgid "" +#~ "Here are a few easy things you can do to get your feet wet. Make sure to " +#~ "click Save on each Settings screen." +#~ msgstr "" +#~ "Voici quelques idées pour vous jeter à l’eau. Assurez-vous bien de " +#~ "cliquer sur « Enregistrer » sur chaque écran de " +#~ "réglages." + +#~ msgid "Choose your privacy setting" +#~ msgstr "Choisissez vos réglages de vie privée" + +#~ msgid "Select your tagline and time zone" +#~ msgstr "" +#~ "Réglez votre fuseau horaire et le slogan de votre site" + +#~ msgid "Fill in your profile" +#~ msgstr "Remplissez votre profil" + +#~ msgid "Add Real Content" +#~ msgstr "Ajouter votre propre contenu" + +#~ msgid "" +#~ "Check out the sample page & post editors to see how it all works, then " +#~ "delete the default content and write your own!" +#~ msgstr "" +#~ "Allez voir l’article et la page de démo dans leurs éditeurs " +#~ "respectifs, afin d’apprendre comment tout est mis en place, puis " +#~ "effacez ce contenu par défaut et écrivez le vôtre !" + +#~ msgid "" +#~ "Delete the sample page and post" +#~ msgstr "" +#~ "Effacez la page d’exemple et l’article d’exemple" + +#~ msgid "" +#~ "Install a theme to get started customizing your site." +#~ msgstr "" +#~ "Installez un thème pour commencer à personnaliser " +#~ "votre site." + +#~ msgid "Choose light or dark" +#~ msgstr "Choisissez un jeu de couleurs (clair ou foncé)" + +#~ msgid "Set a background color" +#~ msgstr "Choisissez une couleur de fond" + +#~ msgid "Add some widgets" +#~ msgstr "Ajoutez quelques widgets" + +#~ msgid "" +#~ "Use the current theme — %1$s — or choose a " +#~ "new one. If you stick with %1$s, here are a few ways to make your " +#~ "site look unique." +#~ msgstr "" +#~ "Utilisez le thème actuel — %1$s — ou choisissez-en un nouveau. Si vous préférez conserver %1$s, voici " +#~ "quelques techniques pour le rendre plus « unique »." + +#~ msgid "" +#~ "Use the current theme — %1$s — or choose a " +#~ "new one." +#~ msgstr "" +#~ "Utilisez le thème actuel — %1$s — ou choisissez-en un nouveau." + +#~ msgid "" +#~ "Already know what you’re doing? Dismiss this " +#~ "message." +#~ msgstr "" +#~ "Vous savez déjà ce que vous faites ? Fermez ce message." + +#~ msgid "ERROR: The e-mail address isn't correct." +#~ msgstr "" +#~ "ERREUR : l’adresse e-mail est incorrecte" + +#~ msgid "" +#~ "The %1$s file is deprecated. Please remove it and update " +#~ "your server rewrite rules to use %2$s instead." +#~ msgstr "" +#~ "Le fichier %1$s est obsolète. Veuillez l’enlever et " +#~ "mettre à jour les règles de réécriture de votre serveur, afin d’" +#~ "utiliser %2$s à la place." + +#~ msgid "You are not allowed to create pages as this user." +#~ msgstr "" +#~ "Vous n’avez pas l’autorisation de créer des pages sous cet " +#~ "identifiant." + +#~ msgid "You are not allowed to post as this user." +#~ msgstr "" +#~ "Vous n’avez pas l’autorisation de publier sous cet " +#~ "identifiant." + +#~ msgctxt "Default link category slug" +#~ msgid "Blogroll" +#~ msgstr "Liens" + +#~ msgctxt "default link" +#~ msgid "Support Forums" +#~ msgstr "Forums d’entraide en français" + +#~ msgctxt "Default link to wordpress.org/extend/plugins/" +#~ msgid "Plugins" +#~ msgstr "Extensions" + +#~ msgctxt "Default link to wordpress.org/extend/themes/" +#~ msgid "Themes" +#~ msgstr "Thèmes" + +#~ msgid "WordPress Planet" +#~ msgstr "La planète WordPress" + +#~ msgid "" +#~ "ERROR: This username is already registered. Please " +#~ "choose another one." +#~ msgstr "" +#~ "ERREUR : cet identifiant existe déjà. Merci d’" +#~ "en choisir un autre." + +#~ msgid "ERROR: The e-mail address isn’t correct." +#~ msgstr "ERREUR : adresse de messagerie incorrecte." + +#~ msgid "Don’t show Avatars" +#~ msgstr "Ne pas afficher les avatars" + +#~ msgid "" +#~ "The Embed option allows you embed a video, image, or other media content " +#~ "into your content automatically by typing the URL (of the web page where " +#~ "the file lives) on its own line when you create your content." +#~ msgstr "" +#~ "L’option « Affichage automatique » tentera de " +#~ "convertir tout lien vers une image, une image ou un autre type de média, " +#~ "en code qui affichera effectivement le fichier dans l’article ou la " +#~ "page. Saisissez simplement l’adresse web du contenu dans sa propre " +#~ "ligne quand vous écrivez le contenu." + +#~ msgid "" +#~ "If you do not set the maximum embed size, it will be automatically sized " +#~ "to fit into your content area." +#~ msgstr "" +#~ "Si vous n’indiquez pas taille maximale d’affichage, le " +#~ "fichier sera automatiquement ajusté à la taille de votre zone de contenu." + +#~ msgid "Auto-embeds" +#~ msgstr "Affichage automatique" + +#~ msgid "" +#~ "When possible, embed the media content from a URL directly onto the page. " +#~ "For example: links to Flickr and YouTube." +#~ msgstr "" +#~ "Si vous en avez la possibilité, pensez à inclure votre contenu multimédia " +#~ "dans votre page directement à partir de son URL. Par exemple, des liens " +#~ "vers Flickr, YouTube ou Dailymotion." + +#~ msgid "Maximum embed size" +#~ msgstr "Taille maximale d’affichage" + +#~ msgid "" +#~ "If the width value is left blank, embeds will default to the max width of " +#~ "your theme." +#~ msgstr "" +#~ "Si la largeur est laissée vide, les affichages utiliseront par défaut la " +#~ "largeur maximale de votre thème." + +#~ msgid "Privacy Settings" +#~ msgstr "Options de vie privée" + +#~ msgid "" +#~ "Documentation on Privacy Settings" +#~ msgstr "" +#~ "Documentation sur les réglages de vie privée (en)" + +#~ msgid "Size of the post box" +#~ msgstr "Taille du champ de saisie" + +#~ msgid "lines" +#~ msgstr "lignes" + +#~ msgid "" +#~ "To post to WordPress from a desktop blogging client or remote website " +#~ "that uses the Atom Publishing Protocol or one of the XML-RPC publishing " +#~ "interfaces you must enable them below." +#~ msgstr "" +#~ "Pour publier avec WordPress depuis un client de bureau ou un site " +#~ "distant, vous devez activer la méthode ci-dessous, que ce soit le " +#~ "protocole de publication Atom ou l’une des interfaces de " +#~ "publication XML-RPC." + +#~ msgid "Atom Publishing Protocol" +#~ msgstr "Protocole de publication Atom" + +#~ msgid "Enable the Atom Publishing Protocol." +#~ msgstr "Activer le protocole de publication Atom." + +#~ msgid "" +#~ "Enable the WordPress, Movable Type, MetaWeblog and Blogger XML-RPC " +#~ "publishing protocols." +#~ msgstr "" +#~ "Activer les protocoles XML-RPC (WordPress, Movable Type, MetaWeblog, " +#~ "Blogger XML-RPC)." + +#~ msgid "Try Again" +#~ msgstr "Recommencez" + +#~ msgid "" +#~ "New theme activated. This theme supports widgets, please visit the widgets settings screen to configure them." +#~ msgstr "" +#~ "Le nouveau thème a été activé. Ce thème est compatible avec les " +#~ "widgets ; veuillez vous rendre sur l’écran de réglage des widgets pour les configurer." + +#~ msgid "Role:" +#~ msgstr "Rôle :" + +#~ msgid "The requested user does not exist." +#~ msgstr "L’utilisateur demandé n’existe pas." + +#~ msgid "Please enter a valid email address." +#~ msgstr "Veuillez saisir une adresse de messagerie valide." + +#~ msgid "No Sidebars Defined" +#~ msgstr "Aucune colonne latérale définie" + +#~ msgid "" +#~ "Thank you for updating to the latest version! Using WordPress %s will " +#~ "improve your looks, personality, and web publishing experience. Okay, " +#~ "just the last one, but still. :)" +#~ msgstr "" +#~ "Merci d’avoir fait une mise à jour ! Grâce à WordPress %s, votre " +#~ "sourire sera plus blanc, votre chevelure plus soyeuse, et vos " +#~ "publications en ligne plus efficaces. Bon, d’accord, seulement le " +#~ "dernier point. Mais tout de même ! :)" + +#~ msgid "" +#~ "The web browser on your device cannot be used to upload files. You may be " +#~ "able to use the native " +#~ "app for your device instead." +#~ msgstr "" +#~ "Le navigateur de votre système ne permet pas de mettre en ligne des " +#~ "fichiers. Vous pourrez sûrement y arriver en passant par l'application native pour votre système." + +#~ msgid "Post query optimized to avoid table scans." +#~ msgstr "" +#~ "Les requêtes d'écriture ont été optimisées pour limiter la lecture des " +#~ "tables." + +#~ msgid "← Return to %s" +#~ msgstr "← Retour à %s" + +#~ msgctxt "" +#~ "Custom Background: Choose an image from your computer - or - Choose from " +#~ "image library" +#~ msgid "or" +#~ msgstr "ou" + +#~ msgctxt "" +#~ "Custom Header: Choose an image from your computer - or - Choose from " +#~ "image library" +#~ msgid "or" +#~ msgstr "ou" + +#~ msgid "Colors" +#~ msgstr "Couleurs" + +#~ msgid "5 stars" +#~ msgstr "5 étoiles" + +#~ msgid "4 stars" +#~ msgstr "4 étoiles" + +#~ msgid "3 stars" +#~ msgstr "3 étoiles" + +#~ msgid "2 stars" +#~ msgstr "2 étoiles" + +#~ msgid "1 star" +#~ msgstr "1 étoile" + +#~ msgid "Deactivating the plugin…" +#~ msgstr "Désactivation de l’extension…" + +#~ msgid "Reactivating the plugin…" +#~ msgstr "Réactivation de l’extension…" + +#~ msgid "An Unexpected HTTP Error occurred during the API request." +#~ msgstr "" +#~ "Une erreur HTTP inattendue est survenue lors de la requête sur l’" +#~ "API." + +#~ msgid "An unknown error occurred during the API request." +#~ msgstr "" +#~ "Une erreur HTTP inattendue est survenue lors de la requête sur l’" +#~ "API." diff --git a/sources/wp-content/languages/admin-network-fr_FR.mo b/sources/wp-content/languages/admin-network-fr_FR.mo new file mode 100644 index 0000000000000000000000000000000000000000..86797df940751e7cc298be7537ee50394b470167 GIT binary patch literal 51161 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

    RBldo_)%}Vy>mF;0)MOTu zx`8hd8<-U7m1-g%k=!|_V$ubud}B;>*LcRf;uQH2+jndYx$Y>ixxWMsk7WI^(3fRR z%sApa;u0Xz(yDnC+q~;!N2|3}CT%a4N)jzu8%n{d6@){vEXDfdfXzHcdp1IB6Uxrk zJoR21H#ZjoFQTdZV13r4$E>oT898sL7Dp98Mnnx_;^rJ;*KVA=$$m%R0Ao(etjU5z zkmaio7$OAgi{~xOMUTvd$Yh%igkp3h?AdlmG}F=A6qrh_=Fn|I5|Z(Y^_q=Pn5R(t zY?H`qjT6f=KJ})vy9rHT+q>CIT1|)RzDOD zC5JTvL};glpp@-m-Yc;B##+%WgSU4SkPVzLPg=EgizFI^gt|5?L$(QFgX9IV4Kn3HT?46pDaUyx{$LbRW|bjJ$P!t&A71DM z0Wx#C?LFuEnHfoQJ@xvz1?<_+k@oQ3Qpb$ac|PLpaLuyWfGtJ7_2yvp8dWL*NlQvx z!4TcRG+BF^m@0!EjN_w>2a+YShzCPt%8dzgZ_1y?owf99V@SrUovX?&6AKlZ3QHaKk#G+El}|SZtIj z>Fnfxw)K1S5@tA#lT9|>)wrOB8&6C&&s!%d%fck+?GA?Hc#d3(VJntjwO%A| z9$9OJ7KyP%Tj0G#CuI^JlQ8^3=EK8ul)dqH;A!JtvE};?J68AoXtjDsQorIxE$w9p2ZM($7y!;&mh!>}k2TJv03?o`=fb_qmcmZL1U-ieZ5 za;q%bH#Z@hHT&U=WXT!(q(9zt_2i|^nvl_vZ$P!?2_)Pc*9B3h+-(s%~x}Ws`AVA!Nm3K4KtB>PA;|E5Jlf+Wm3YV#z;92>o>Xi zu759k6cM?8ivy}N-0Xj(7VB~VcY)N#MoE*wB|Mf)eobUkY#BI0&nincF*O++8F6X- zTnb>Bn@BQ*iiym25S@!QY*~sW1tx~uP(Qk4IOZ-#F_A`XEel~!8TE-TVqG<54dDXt zoR=sYZA{!6E0t@eXRA~(MR%(#@oA2$c)<#AwelFVWmXbyW~T~`o)Sa+;)&|25HMeD zt!%g#yjp4OxHDxL4b;UN=QpaYMI^b*&S83LEh!Lfb?G&M>^oLfOJ>i^Q&&=PNhdYp z$z$hxBO6v~+<2M>ce`tcf z&j`|Q+nOZJoXUp-%hVOvu2Q7?y$$wanYiFTQKD6gdZ5}!(nC)F*^*lqEecHQIjLN`!T>3@1=Sn#la>BbNoEKSrNa@J_-&IlgHNJfR}LGH zr{qhTMCNy&v&gK)OL?xA6q+dpwwKSN8X%QQNew~DW*R{p9zt<%yYV~&j&77>U35R& zRTr;48~AT>x6z!$$hOoAvcVN1Y@0X=SnG1F3qa{L$%>AHj$ zC1))YM`$YV08N*Eg~fR%R)iE6_%KbM$mF2KBmYE_hW7XomWib_UKVYR+m_$zo|rGE z#7wGRX-Rt#BG10aklASL3zaasEb|5RD%WLg{&C%lV5X_WirqP1nF^b0OK8E{b-%jC zb4kuq6QKr^Ks1*xKz8PWsucTjw5nn)(2ehCqw_pZEevY511&90q&hpCpPX<=zXvnf zPgM{!)23LF2?)H(L^dS3oF|sB4xm1Ufd65rzTSzzxIn9o0E8?GqfCdw=BCnP*wpX zwN*=Sf24q7UCZaP{X(D4-O;8mn>HFq^5(;6I8#Di)?5t3W)8NYyOO4iJw1%H`~E!H zne*CA57(2PN+C>k8m)~;q}E(xFFP`fBvUI5(B~KNvd+T<)a?)cedFZ^1*J7tG=>{p z(G^ zbc)h+$8DUm(F_SFWhE1Sq%LRsEXMo(@J^S1a!8&w=zIBCVoyk6)V7l+YF`*Ww3l6ua(OaD=Y zWj~;zgrtll#8%SsZWWCq5nl5w@}IMz)N(@z>N4GwfVEO|o{{9_ZAvHFkP;@(Iiw3~ zu_g;1No5k4y{TcsrM-Sp=4W*aHl zpt--3H(76@Qi{fl%=(d@D5216MZ;xH qKev;97hIX7$}hKH>B+yuQ-4t7X#Va_eo$XEe|9JJf6QNuFa9rT<9S~I literal 0 HcmV?d00001 diff --git a/sources/wp-content/languages/admin-network-fr_FR.po b/sources/wp-content/languages/admin-network-fr_FR.po new file mode 100644 index 0000000..34b619f --- /dev/null +++ b/sources/wp-content/languages/admin-network-fr_FR.po @@ -0,0 +1,1809 @@ +# Translation of multisite strings in WordPress 3.1-alpha. +# Copyright (C) 2010 WordPress +# This file is distributed under the same license as the WordPress package. +# FIRST AUTHOR , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: WordPress 3.7\n" +"Report-Msgid-Bugs-To: http://wppolyglots.wordpress.com\n" +"POT-Creation-Date: 2013-10-18 08:55:54+00:00\n" +"PO-Revision-Date: 2013-10-24 14:05+0100\n" +"Last-Translator: Xavier B. \n" +"Language-Team: WordPress Francophone \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n>1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 1.5.7\n" + +#: wp-admin/network/index.php:20 wp-admin/network/settings.php:17 +#: wp-admin/network/site-info.php:43 wp-admin/network/site-new.php:37 +#: wp-admin/network/site-settings.php:43 wp-admin/network/site-themes.php:56 +#: wp-admin/network/site-users.php:49 wp-admin/network/sites.php:17 +#: wp-admin/network/sites.php:106 wp-admin/network/upgrade.php:39 +#: wp-admin/network/user-new.php:36 wp-admin/network/users.php:17 +#: wp-admin/network/users.php:95 wp-admin/network/users.php:117 +#: wp-admin/network/users.php:130 wp-admin/network/users.php:181 +msgid "You do not have permission to access this page." +msgstr "Vous n’avez pas les droits suffisants pour accéder à cette page." + +#: wp-admin/network/index.php:25 +msgid "" +"Welcome to your Network Admin. This area of the Administration Screens is " +"used for managing all aspects of your Multisite Network." +msgstr "" +"Bienvenu dans l’administration de votre réseau ! Cette partie des " +"écrans d’administration sert à gérer tous les aspects de votre réseau " +"multisite." + +#: wp-admin/network/index.php:26 +msgid "From here you can:" +msgstr "D’ici, vous pouvez :" + +#: wp-admin/network/index.php:27 +msgid "Add and manage sites or users" +msgstr "Ajouter et gérer des sites ou des utilisateurs" + +#: wp-admin/network/index.php:28 +msgid "Install and activate themes or plugins" +msgstr "Installer et activer des thèmes ou des extensions" + +#: wp-admin/network/index.php:29 +msgid "Update your network" +msgstr "Mettre à jour votre réseau" + +#: wp-admin/network/index.php:30 +msgid "Modify global network settings" +msgstr "Modifier les réglages globaux du réseau" + +#: wp-admin/network/index.php:38 +msgid "" +"The Right Now widget on this screen provides current user and site counts on " +"your network." +msgstr "" +"Le widget Aujourd’hui de cet écran vous donne le nombre actuel d’" +"utilisateurs et de sites sur votre réseau." + +#: wp-admin/network/index.php:39 +msgid "To add a new user, click Create a New User." +msgstr "" +"Pour ajouter un nouvel utilisateur, cliquez sur Créer un nouvel " +"utilisateur." + +#: wp-admin/network/index.php:40 +msgid "To add a new site, click Create a New Site." +msgstr "" +"Pour ajouter un nouveau site, cliquez sur Créer un nouveau site." + +#: wp-admin/network/index.php:41 +msgid "To search for a user or site, use the search boxes." +msgstr "" +"Pour chercher un utilisateur ou un site, utilisez les champs de recherche." + +#: wp-admin/network/index.php:42 +msgid "" +"To search for a user, enter an email address or username. " +"Use a wildcard to search for a partial username, such as user*." +msgstr "" +"Pour chercher un utilisateur, saisissez une adresse de messagerie ou " +"un identifiant. Utilisez le signe étoile (*) pour lancer une " +"recherche sur un identifiant partiel, par exemple utilisa*." + +#: wp-admin/network/index.php:43 +msgid "To search for a site, enter the path or domain." +msgstr "" +"Pour chercher un site, saisissez son chemin ou son domaine." + +#: wp-admin/network/index.php:47 +msgid "Quick Tasks" +msgstr "Tâches rapides" + +#: wp-admin/network/index.php:53 +msgid "" +"Documentation on the Network Admin" +msgstr "" +"Documentation sur l’administration du réseau (en)" + +#: wp-admin/network/index.php:54 wp-admin/network/site-info.php:33 +#: wp-admin/network/site-new.php:30 wp-admin/network/site-settings.php:33 +#: wp-admin/network/site-themes.php:33 wp-admin/network/site-users.php:36 +#: wp-admin/network/sites.php:46 wp-admin/network/user-new.php:30 +#: wp-admin/network/users.php:245 +msgid "" +"Support Forums" +msgstr "" +"Forums " +"d’entraide" + +#: wp-admin/network/menu.php:17 +msgid "All Sites" +msgstr "Tous les sites" + +# contexte +#: wp-admin/network/menu.php:18 wp-admin/network/sites.php:236 +msgctxt "site" +msgid "Add New" +msgstr "Ajouter" + +#: wp-admin/network/menu.php:27 +msgid "Themes %s" +msgstr "Thèmes %s" + +#: wp-admin/network/menu.php:31 +msgid "Installed Themes" +msgstr "Thèmes installés" + +# contexte +#: wp-admin/network/menu.php:32 wp-admin/network/themes.php:231 +msgctxt "theme" +msgid "Add New" +msgstr "Ajouter" + +#: wp-admin/network/menu.php:46 wp-admin/network/settings.php:19 +msgid "Network Settings" +msgstr "Réglages du réseau" + +#: wp-admin/network/menu.php:53 +msgid "Updates" +msgstr "Mises à jour" + +#: wp-admin/network/menu.php:58 +msgid "Available Updates" +msgstr "Mises à jour disponibles" + +#: wp-admin/network/menu.php:59 wp-admin/network/upgrade.php:18 +#: wp-admin/network/upgrade.php:43 wp-admin/network/upgrade.php:94 +msgid "Upgrade Network" +msgstr "Mettre à jour le réseau" + +#: wp-admin/network/settings.php:26 +msgid "" +"This screen sets and changes options for the network as a whole. The first " +"site is the main site in the network and network options are pulled from " +"that original site’s options." +msgstr "" +"Cet écran vous donne accès aux options régissant l’ensemble du réseau. " +"Le premier site est le site principal du réseau, et les options du réseau " +"sont tirées des options de ce premier site." + +#: wp-admin/network/settings.php:27 +msgid "" +"Operational settings has fields for the network’s name and admin email." +msgstr "" +"Les réglages de fonctionnement permettent de modifier le nom du réseau, et " +"l’adresse de messagerie de l’administrateur." + +#: wp-admin/network/settings.php:28 +msgid "" +"Registration settings can disable/enable public signups. If you let others " +"sign up for a site, install spam plugins. Spaces, not commas, should " +"separate names banned as sites for this network." +msgstr "" +"Les réglages d’inscription permettent d’ouvrir ou fermer les " +"inscriptions au public. Si vous ouvrez les inscriptions, veillez à installer " +"des extensions antispam. Les domaines bannis devraient être indiqués séparés " +"d’un espace, non d’une virgule." + +#: wp-admin/network/settings.php:29 +msgid "" +"New site settings are defaults applied when a new site is created in the " +"network. These include welcome email for when a new site or user account is " +"registered, and what᾿s put in the first post, page, comment, comment " +"author, and comment URL." +msgstr "" +"Les réglages des nouveaux sites sont les réglages par défaut appliqués à " +"tout nouveau site créé sur le réseau. Cela comprend le message d’" +"accueil quand un nouvel utilisateur ou un nouveau site est enregistré, ainsi " +"que le contenu du premier article, de la première page et du premier " +"commentaire (dont le nom et l’adresse web du commentateur)." + +#: wp-admin/network/settings.php:30 +msgid "" +"Upload settings control the size of the uploaded files and the amount of " +"available upload space for each site. You can change the default value for " +"specific sites when you edit a particular site. Allowed file types are also " +"listed (space separated only)." +msgstr "" +"Les réglages d’envoi des fichiers permettent de limiter la taille des " +"fichiers mis en ligne et l’espace disponible pour chaque site. Vous " +"pouvez préciser la valeur pour chaque site individuellement. Vous pouvez " +"également préciser les types de fichiers acceptés (séparés par des espaces)." + +#: wp-admin/network/settings.php:31 +msgid "" +"Menu setting enables/disables the plugin menus from appearing for non super " +"admins, so that only super admins, not site admins, have access to activate " +"plugins." +msgstr "" +"Le réglage du menu (dés)active la section « Extensions " +"» du menu pour les utilisateurs normaux, de telle sorte que seuls les " +"super-admins peuvent y accéder pour activer une extension." + +#: wp-admin/network/settings.php:32 +msgid "" +"Super admins can no longer be added on the Options screen. You must now go " +"to the list of existing users on Network Admin > Users and click on Username " +"or the Edit action link below that name. This goes to an Edit User page " +"where you can check a box to grant super admin privileges." +msgstr "" +"Les super-admins ne peuvent plus être ajoutés via l’écran des options. " +"Vous devez aller à la liste des utilisateurs (option « " +"Utilisateurs » du menu « Admin du réseau ») " +"et cliquer sur un identifiant ou sur le lien « Modifier " +"» qui s’affiche en dessous. Vous arriverez alors à un écran vous " +"permettant de modifier ce compte utilisateur, où une case à cocher donne les " +"droits de super-admin." + +#: wp-admin/network/settings.php:37 +msgid "" +"Documentation on Network Settings" +msgstr "" +"Documentation sur les réglages du réseau (en)" + +#: wp-admin/network/settings.php:77 +msgid "Options saved." +msgstr "Options enregistrées." + +#: wp-admin/network/settings.php:86 +msgid "Operational Settings" +msgstr "Réglages de fonctionnement" + +#: wp-admin/network/settings.php:89 +msgid "Network Name" +msgstr "Nom du réseau" + +#: wp-admin/network/settings.php:93 +msgid "What you would like to call this network." +msgstr "Quel nom voulez-vous donner à ce réseau ?" + +#: wp-admin/network/settings.php:98 +msgid "Network Admin Email" +msgstr "Adresse de contact de l’administrateur du réseau" + +#: wp-admin/network/settings.php:102 +msgid "" +"Registration and support emails will come from this address. An address such " +"as support@%s is recommended." +msgstr "" +"Les messages de confirmations d’enregistrement et ceux du support " +"proviendront de cette adresse. Nous vous suggérons d’utiliser une " +"adresse comme support@%s." + +#: wp-admin/network/settings.php:106 +msgid "Registration Settings" +msgstr "Réglages d’inscription" + +#: wp-admin/network/settings.php:109 +msgid "Allow new registrations" +msgstr "Autoriser les nouvelles inscriptions" + +#: wp-admin/network/settings.php:116 +msgid "Registration is disabled." +msgstr "Les inscriptions ne sont pas autorisées pour le moment." + +#: wp-admin/network/settings.php:117 +msgid "User accounts may be registered." +msgstr "Seuls les comptes utilisateurs peuvent être créés." + +#: wp-admin/network/settings.php:118 +msgid "Logged in users may register new sites." +msgstr "Seuls les utilisateurs connectés peuvent créer de nouveaux sites." + +#: wp-admin/network/settings.php:119 +msgid "Both sites and user accounts can be registered." +msgstr "La création de sites et d’utilisateurs est autorisée." + +#: wp-admin/network/settings.php:121 +msgid "" +"If registration is disabled, please set NOBLOGREDIRECT in " +"wp-config.php to a URL you will redirect visitors to if they " +"visit a non-existent site." +msgstr "" +"Si l’enregistrement est désactivé, veuillez configurer l’entrée " +"NOBLOGREDIRECT dans le fichier wp-config.php pour " +"qu’il pointe sur l’adresse internet vers laquelle vous souhaitez " +"que vos visiteurs soient redirigés s’ils demandent un site qui n’" +"existe pas. " + +#: wp-admin/network/settings.php:127 +msgid "Registration notification" +msgstr "Notification d’inscription" + +#: wp-admin/network/settings.php:133 +msgid "" +"Send the network admin an email notification every time someone registers a " +"site or user account." +msgstr "" +"Envoyer un message à l’administrateur du réseau à chaque inscription " +"de site ou d’utilisateurs." + +#: wp-admin/network/settings.php:138 +msgid "Add New Users" +msgstr "Ajouter de nouveaux utilisateurs" + +#: wp-admin/network/settings.php:140 +msgid "" +"Allow site administrators to add new users to their site via the \"Users " +"→ Add New\" page." +msgstr "" +"Autoriser les administrateurs de sites à ajouter de nouveaux utilisateurs à " +"leurs sites via la page « Utilisateurs → Ajouter " +"»." + +#: wp-admin/network/settings.php:145 +msgid "Banned Names" +msgstr "Noms bannis" + +#: wp-admin/network/settings.php:149 +msgid "" +"Users are not allowed to register these sites. Separate names by spaces." +msgstr "" +"Les utilisateurs ne sont pas autorisés à créer un site avec l’un de " +"ces noms. Séparez les noms par un espace." + +#: wp-admin/network/settings.php:154 +msgid "Limited Email Registrations" +msgstr "Enregistrement réservé aux noms de domaines" + +#: wp-admin/network/settings.php:161 +msgid "" +"If you want to limit site registrations to certain domains. One domain per " +"line." +msgstr "" +"Si vous souhaitez que les seules personnes habilitées à créer un site soient " +"celles disposant d’une adresse de messagerie liée à certains noms de " +"domaines. Un domaine par ligne." + +#: wp-admin/network/settings.php:166 +msgid "Banned Email Domains" +msgstr "Noms de domaines bannis" + +#: wp-admin/network/settings.php:171 +msgid "" +"If you want to ban domains from site registrations. One domain per line." +msgstr "" +"Si vous souhaitez interdire la création de sites aux personnes dont l’" +"adresse de messagerie est liée à certains noms de domaines. Un domaine par " +"ligne." + +#: wp-admin/network/settings.php:176 +msgid "New Site Settings" +msgstr "Réglages des nouveaux sites" + +#: wp-admin/network/settings.php:180 +msgid "Welcome Email" +msgstr "Message de bienvenue" + +#: wp-admin/network/settings.php:185 +msgid "The welcome email sent to new site owners." +msgstr "" +"Ce message de bienvenue sera envoyé aux propriétaires de nouveaux sites." + +#: wp-admin/network/settings.php:189 +msgid "Welcome User Email" +msgstr "Message de bienvenue des utilisateurs" + +#: wp-admin/network/settings.php:194 +msgid "The welcome email sent to new users." +msgstr "Ce message de bienvenue sera envoyé aux nouveaux utilisateurs." + +#: wp-admin/network/settings.php:203 +msgid "The first post on a new site." +msgstr "Le premier article sur tout nouveau site." + +#: wp-admin/network/settings.php:207 +msgid "First Page" +msgstr "Première page" + +#: wp-admin/network/settings.php:212 +msgid "The first page on a new site." +msgstr "La première page sur tout nouveau site." + +#: wp-admin/network/settings.php:216 +msgid "First Comment" +msgstr "Premier commentaire" + +#: wp-admin/network/settings.php:221 +msgid "The first comment on a new site." +msgstr "Le premier commentaire sur tout nouveau site." + +#: wp-admin/network/settings.php:225 +msgid "First Comment Author" +msgstr "Auteur du premier commentaire" + +#: wp-admin/network/settings.php:229 +msgid "The author of the first comment on a new site." +msgstr "L’auteur du premier commentaire sur tout nouveau site." + +#: wp-admin/network/settings.php:233 +msgid "First Comment URL" +msgstr "Adresse du premier commentaire" + +#: wp-admin/network/settings.php:237 +msgid "The URL for the first comment on a new site." +msgstr "L’adresse web du premier commentaire sur tout nouveau site." + +#: wp-admin/network/settings.php:241 +msgid "Upload Settings" +msgstr "Réglages d’envoi des fichiers" + +#: wp-admin/network/settings.php:244 +msgid "Site upload space" +msgstr "Espace de stockage du site" + +#: wp-admin/network/settings.php:246 +msgid "Limit total size of files uploaded to %s MB" +msgstr "La taille totale des fichiers envoyés est limitée à %s Mo" + +#: wp-admin/network/settings.php:251 +msgid "Upload file types" +msgstr "Types de fichiers " + +#: wp-admin/network/settings.php:256 +msgid "Max upload file size" +msgstr "Taille maximale des fichiers" + +#: wp-admin/network/settings.php:257 +msgctxt "File size in kilobytes" +msgid "%s KB" +msgstr "%s Ko" + +#: wp-admin/network/settings.php:266 +msgid "Language Settings" +msgstr "Réglages de langue" + +#: wp-admin/network/settings.php:269 +msgid "Default Language" +msgstr "Langue par défaut" + +#: wp-admin/network/settings.php:284 +msgid "Enable administration menus" +msgstr "Activer les menus d’administration" + +#: wp-admin/network/site-info.php:17 wp-admin/network/site-settings.php:17 +#: wp-admin/network/site-users.php:17 +msgid "You do not have sufficient permissions to edit this site." +msgstr "Vous n’avez pas les droits suffisants pour modifier ce site." + +#: wp-admin/network/site-info.php:23 wp-admin/network/site-settings.php:23 +#: wp-admin/network/site-themes.php:23 wp-admin/network/site-users.php:26 +msgid "" +"The menu is for editing information specific to individual sites, " +"particularly if the admin area of a site is unavailable." +msgstr "" +"Ce menu sert à modifier les informations relatives à un site individuel, en " +"particulier si sa zone d’administration est indisponible." + +#: wp-admin/network/site-info.php:24 wp-admin/network/site-settings.php:24 +#: wp-admin/network/site-themes.php:24 wp-admin/network/site-users.php:27 +msgid "" +"Info - The domain and path are rarely edited as this can " +"cause the site to not work properly. The Registered date and Last Updated " +"date are displayed. Network admins can mark a site as archived, spam, " +"deleted and mature, to remove from public listings or disable." +msgstr "" +"Infos - Il n’est pas recommandé de modifier le " +"domaine ou le chemin d’accès, car cela pourrait rendre le site non " +"fonctionnel. Les dates de création et de dernière mise à jour sont " +"affichées. Les administrateurs réseau peuvent indiquer qu’un site est " +"archivé, indésirable, pour adulte et effacé, afin de le retirer de la liste " +"publique ou le désactiver." + +#: wp-admin/network/site-info.php:25 wp-admin/network/site-settings.php:25 +#: wp-admin/network/site-themes.php:25 wp-admin/network/site-users.php:28 +msgid "" +"Users - This displays the users associated with this site. " +"You can also change their role, reset their password, or remove them from " +"the site. Removing the user from the site does not remove the user from the " +"network." +msgstr "" +"Utilisateurs - Affiche les utilisateurs associés à ce site. " +"Vous pouvez également modifier leur rôle, réinitialiser leur mot de passe ou " +"les enlever du site. Enlever un utilisateur d’un site ne l’" +"enlève pas du réseau." + +#: wp-admin/network/site-info.php:26 wp-admin/network/site-settings.php:26 +#: wp-admin/network/site-themes.php:26 wp-admin/network/site-users.php:29 +msgid "" +"Themes - This area shows themes that are not already " +"enabled across the network. Enabling a theme in this menu makes it " +"accessible to this site. It does not activate the theme, but allows it to " +"show in the site’s Appearance menu. To enable a theme for the entire " +"network, see the Network Themes screen." +msgstr "" +"Thèmes - Cette zone affiche les thèmes qui n’ont pas " +"déjà été activés pour l’ensemble du réseau. En activant un thème avec " +"ce menu, vous le rendez disponible pour ce site. Cela ne l’active pas, " +"mais l’affichera dans le menu Apparence du site. Pour activer un thème " +"pour l’ensemble du réseau, rendez-vous sur l’écran Thèmes du réseau." + +#: wp-admin/network/site-info.php:27 wp-admin/network/site-settings.php:27 +#: wp-admin/network/site-themes.php:27 wp-admin/network/site-users.php:30 +msgid "" +"Settings - This page shows a list of all settings " +"associated with this site. Some are created by WordPress and others are " +"created by plugins you activate. Note that some fields are grayed out and " +"say Serialized Data. You cannot modify these values due to the way the " +"setting is stored in the database." +msgstr "" +"Réglages - Cette page affiche la liste de tous les réglages " +"associés à ce site. Certains sont créés par WordPress, d’autres par " +"des extensions que vous activez. Notez que certains champs sont grisés et " +"indiquent données sérialisées (Serialized Data). Vous ne pouvez pas modifier " +"ces valeurs, du fait de la manière dont ils sont stockés dans la base de " +"données." + +#: wp-admin/network/site-info.php:32 wp-admin/network/site-new.php:29 +#: wp-admin/network/site-settings.php:32 wp-admin/network/site-themes.php:32 +#: wp-admin/network/site-users.php:35 wp-admin/network/sites.php:45 +msgid "" +"Documentation on Site Management" +msgstr "" +"Documentation sur la gestion de site (en)" + +#: wp-admin/network/site-info.php:39 wp-admin/network/site-settings.php:39 +#: wp-admin/network/site-themes.php:50 wp-admin/network/site-users.php:45 +msgid "Invalid site ID." +msgstr "Identifiant du site invalide." + +#: wp-admin/network/site-info.php:84 +msgid "Site info updated." +msgstr "Les infos du site ont été mises à jour." + +#: wp-admin/network/site-info.php:88 wp-admin/network/site-settings.php:74 +#: wp-admin/network/site-themes.php:129 wp-admin/network/site-users.php:161 +msgid "Edit Site: %2$s" +msgstr "Modifier le site : %2$s." + +#: wp-admin/network/site-info.php:89 wp-admin/network/site-settings.php:75 +#: wp-admin/network/site-themes.php:130 wp-admin/network/site-users.php:162 +msgid "Edit Site: %s" +msgstr "Modifier le site : %s" + +#: wp-admin/network/site-info.php:104 wp-admin/network/site-settings.php:90 +#: wp-admin/network/site-themes.php:143 wp-admin/network/site-users.php:185 +msgid "Info" +msgstr "Infos" + +#: wp-admin/network/site-info.php:143 +msgid "Update siteurl and home as well." +msgstr "" +"Mettez également à jour les options siteurl et home." + +#: wp-admin/network/site-new.php:17 +msgid "You do not have sufficient permissions to add sites to this network." +msgstr "" +"Vous n’avez pas les droits suffisants pour ajouter des sites à ce " +"réseau." + +#: wp-admin/network/site-new.php:23 +msgid "" +"This screen is for Super Admins to add new sites to the network. This is not " +"affected by the registration settings." +msgstr "" +"Cet écran permet aux super-admins d’ajouter de nouveaux sites au " +"réseau. Il n’est pas limité par les réglages d’inscription." + +#: wp-admin/network/site-new.php:24 +msgid "" +"If the admin email for the new site does not exist in the database, a new " +"user will also be created." +msgstr "" +"Si l’adresse de contact du nouveau site n’existe pas dans la " +"base de données, un nouvel utilisateur sera créé pour l’occasion." + +#: wp-admin/network/site-new.php:40 +msgid "Can’t create an empty site." +msgstr "Impossible de créer un site vide." + +#: wp-admin/network/site-new.php:50 +msgid "" +"The following words are reserved for use by WordPress functions and cannot " +"be used as blog names: %s" +msgstr "" +"Les mots suivants sont réservés pour l’usage de fonctions WordPress et " +"ne peuvent pas être utilisés comme nom de site : %s" + +#: wp-admin/network/site-new.php:57 +msgid "Missing or invalid site address." +msgstr "Adresse de site manquante ou non valide." + +#: wp-admin/network/site-new.php:59 +msgid "Missing email address." +msgstr "Adresse de messagerie manquante." + +#: wp-admin/network/site-new.php:61 +msgid "Invalid email address." +msgstr "Adresse de messagerie invalide." + +#: wp-admin/network/site-new.php:77 +msgid "There was an error creating the user." +msgstr "" +"Une erreur s’est produite lors de la création d’un utilisateur." + +#: wp-admin/network/site-new.php:88 +msgid "" +"New site created by %1$s\n" +"\n" +"Address: %2$s\n" +"Name: %3$s" +msgstr "" +"Nouveau site créé par %1$s\n" +"\n" +"Adresse : %2$s\n" +"Nom : %3$s" + +#: wp-admin/network/site-new.php:92 +msgid "[%s] New Site Created" +msgstr "[%s] Nouveau site créé" + +#: wp-admin/network/site-new.php:104 +msgid "" +"Site added. Visit Dashboard or Edit " +"Site" +msgstr "" +"Site ajouté. Afficher le tableau de bord | Modifier le site" + +#: wp-admin/network/site-new.php:107 wp-admin/network/site-new.php:116 +msgid "Add New Site" +msgstr "Ajouter un nouveau site" + +#: wp-admin/network/site-new.php:126 +msgid "Site Address" +msgstr "Adresse du site" + +#: wp-admin/network/site-new.php:142 +msgid "Admin Email" +msgstr "Adresse de contact de l’administrateur" + +#: wp-admin/network/site-new.php:146 +msgid "" +"A new user will be created if the above email address is not in the database." +msgstr "" +"Un nouvel utilisateur sera créé si l’adresse de contact n’existe " +"pas dans la base de données." + +#: wp-admin/network/site-new.php:146 +msgid "The username and password will be mailed to this email address." +msgstr "" +"L’identifiant et le mot de passe seront envoyés sur l’adresse de " +"contact indiquée." + +#: wp-admin/network/site-new.php:149 +msgid "Add Site" +msgstr "Ajouter un site" + +#: wp-admin/network/site-settings.php:70 +msgid "Site options updated." +msgstr "Les réglages du site ont été mis à jour." + +#: wp-admin/network/site-themes.php:17 +msgid "You do not have sufficient permissions to manage themes for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour gérer les thèmes de ce site." + +#: wp-admin/network/site-themes.php:126 wp-admin/network/themes.php:203 +msgctxt "themes per page (screen options)" +msgid "Themes" +msgstr "Thèmes" + +#: wp-admin/network/site-themes.php:157 wp-admin/network/themes.php:239 +msgid "Theme enabled." +msgid_plural "%s themes enabled." +msgstr[0] "Thème activé." +msgstr[1] "%s thèmes activés." + +#: wp-admin/network/site-themes.php:160 wp-admin/network/themes.php:242 +msgid "Theme disabled." +msgid_plural "%s themes disabled." +msgstr[0] "Thème désactivé." +msgstr[1] "%s thèmes désactivés." + +#: wp-admin/network/site-themes.php:162 wp-admin/network/themes.php:247 +msgid "No theme selected." +msgstr "Aucun thème sélectionné." + +#: wp-admin/network/site-themes.php:165 +msgid "Network enabled themes are not shown on this screen." +msgstr "Les thèmes activés pour le réseau ne sont pas visibles sur cet écran." + +#: wp-admin/network/site-users.php:203 +msgid "User is already a member of this site." +msgstr "Cet utilisateur est déjà membre de ce site." + +#: wp-admin/network/site-users.php:206 +msgid "Enter the username of an existing user." +msgstr "Saisir l’identifiant d’un utilisateur existant." + +#: wp-admin/network/site-users.php:212 +msgid "Select a user to change role." +msgstr "Sélectionnez un utilisateur dont vous voulez changer le rôle." + +#: wp-admin/network/site-users.php:218 +msgid "Select a user to remove." +msgstr "Sélectionnez un utilisateur à enlever." + +#: wp-admin/network/site-users.php:221 +msgid "User created." +msgstr "L’utilisateur a été créé." + +#: wp-admin/network/site-users.php:224 +msgid "Enter the username and email." +msgstr "Saisir l’identifiant et l’adresse de messagerie." + +#: wp-admin/network/site-users.php:227 +msgid "Duplicated username or email address." +msgstr "Identifiant ou adresse de messagerie déjà utilisé(e)." + +#: wp-admin/network/site-users.php:271 wp-admin/network/user-new.php:103 +msgid "Add User" +msgstr "Ajouter un utilisateur" + +#: wp-admin/network/site-users.php:301 wp-admin/network/user-new.php:99 +msgid "Username and password will be mailed to the above email address." +msgstr "" +"L’identifiant et le mot de passe seront envoyés à l’adresse de " +"contact précisée." + +#: wp-admin/network/sites.php:25 +msgctxt "sites per page (screen options)" +msgid "Sites" +msgstr "Sites" + +#: wp-admin/network/sites.php:31 +msgid "" +"Add New takes you to the Add New Site screen. You can search for a site by " +"Name, ID number, or IP address. Screen Options allows you to choose how many " +"sites to display on one page." +msgstr "" +"Ajouter vous envoie au formulaire en bas de cette page. Vous pouvez chercher " +"un site par le nom, l’identifiant ou l’adresse IP. Les options " +"d’écran vous permettent de choisir le nombre de sites à afficher sur " +"une même page." + +#: wp-admin/network/sites.php:32 +msgid "" +"This is the main table of all sites on this network. Switch between list and " +"excerpt views by using the icons above the right side of the table." +msgstr "" +"Voici la liste de tous les sites de ce réseau. Vous pouvez changer de vue " +"(liste avec ou sans extrait) en utilisant les icônes présentes en haut à " +"droite de la liste." + +#: wp-admin/network/sites.php:33 +msgid "" +"Hovering over each site reveals seven options (three for the primary site):" +msgstr "" +"Survoler chaque site avec la souris révèle sept options (trois pour le site " +"principal) :" + +#: wp-admin/network/sites.php:34 +msgid "An Edit link to a separate Edit Site screen." +msgstr "" +"Un lien « Modifier » vers un nouvel écran de " +"modification de site." + +#: wp-admin/network/sites.php:35 +msgid "Dashboard leads to the Dashboard for that site." +msgstr "" +"« Tableau de bord » mène au tableau de bord pour ce " +"site." + +#: wp-admin/network/sites.php:36 +msgid "" +"Deactivate, Archive, and Spam which lead to confirmation screens. These " +"actions can be reversed later." +msgstr "" +"« Désactiver », « Archiver » et " +"« Indésirable » envoient chacun à des écrans de " +"confirmation. Ces actions peuvent être annulées par la suite ." + +#: wp-admin/network/sites.php:37 +msgid "Delete which is a permanent action after the confirmation screens." +msgstr "" +"« Supprimer » est une action irréversible une fois " +"passé l’écran de confirmation." + +#: wp-admin/network/sites.php:38 +msgid "Visit to go to the frontend site live." +msgstr "" +"« Afficher » envoie vers la page d’accueil du " +"site." + +#: wp-admin/network/sites.php:39 +msgid "" +"The site ID is used internally, and is not shown on the front end of the " +"site or to users/viewers." +msgstr "" +"L’identifiant du site est utilisé en interne et n’est pas affiché dans " +"la partie publique du site, ni aux utilisateurs/visiteurs." + +#: wp-admin/network/sites.php:40 +msgid "Clicking on bold headings can re-sort this table." +msgstr "Cliquez sur les en-têtes en gras afin de retrier ce tableau." + +#: wp-admin/network/sites.php:62 wp-admin/network/sites.php:137 +msgid "You are not allowed to change the current site." +msgstr "Vous n’êtes pas autorisé à modifier le site actuel." + +#: wp-admin/network/sites.php:67 +msgid "WordPress › Confirm your action" +msgstr "WordPress › Confirmer votre action" + +#: wp-admin/network/sites.php:83 +msgid "Confirm" +msgstr "Confirmer" + +#: wp-admin/network/sites.php:124 +msgid "You are not allowed to delete the site." +msgstr "Vous n’avez pas l’autorisation d’effacer ce site." + +#: wp-admin/network/sites.php:185 +msgid "Sites removed from spam." +msgstr "Sites marqués comme sains." + +#: wp-admin/network/sites.php:188 +msgid "Sites marked as spam." +msgstr "Sites marqués comme indésirables." + +#: wp-admin/network/sites.php:191 +msgid "Sites deleted." +msgstr "Sites effacés." + +#: wp-admin/network/sites.php:194 +msgid "Site deleted." +msgstr "Site effacé." + +#: wp-admin/network/sites.php:197 +msgid "You do not have permission to delete that site." +msgstr "Vous n’avez pas l’autorisation de supprimer ce site." + +#: wp-admin/network/sites.php:200 +msgid "Site archived." +msgstr "Site archivé." + +#: wp-admin/network/sites.php:203 +msgid "Site unarchived." +msgstr "Site désarchivé." + +#: wp-admin/network/sites.php:206 +msgid "Site activated." +msgstr "Site activé." + +#: wp-admin/network/sites.php:209 +msgid "Site deactivated." +msgstr "Site désactivé." + +#: wp-admin/network/sites.php:212 +msgid "Site removed from spam." +msgstr "Site marqué comme sain." + +#: wp-admin/network/sites.php:215 +msgid "Site marked as spam." +msgstr "Site marqué comme indésirable." + +#: wp-admin/network/themes.php:17 +msgid "You do not have sufficient permissions to manage network themes." +msgstr "" +"Vous n’avez pas les droits suffisants pour gérer les thèmes du réseau." + +#: wp-admin/network/themes.php:106 +msgid "You do not have sufficient permissions to delete themes for this site." +msgstr "" +"Vous n’avez pas les droits suffisants pour effacer les thèmes de ce " +"site." + +# Ne pas mettre d'entité HTML ( ...) : chaîne affichée dans l'éditeur visuel. +#: wp-admin/network/themes.php:141 +msgid "Delete Theme" +msgid_plural "Delete Themes" +msgstr[0] "Supprimer le thème" +msgstr[1] "Supprimer les thèmes" + +#: wp-admin/network/themes.php:143 +msgid "This theme may be active on other sites in the network." +msgid_plural "These themes may be active on other sites in the network." +msgstr[0] "Ce thème est peut-être activé sur d’autres sites du réseau" +msgstr[1] "" +"Ces thèmes sont peut-être activés sur d’autres sites du réseau" + +#: wp-admin/network/themes.php:144 +msgid "You are about to remove the following theme:" +msgid_plural "You are about to remove the following themes:" +msgstr[0] "Vous êtes sur le point de supprimer le thème suivant :" +msgstr[1] "Vous êtes sur le point de supprimer les thèmes suivants :" + +#. translators: 1: theme name, 2: theme author +#: wp-admin/network/themes.php:149 +msgid "Are you sure you wish to delete these themes?" +msgstr "Êtes-vous certain(e) de vouloir supprimer ces thèmes ?" + +#: wp-admin/network/themes.php:158 +msgid "Yes, Delete this theme" +msgid_plural "Yes, Delete these themes" +msgstr[0] "Oui, supprimer ce thème" +msgstr[1] "Oui, supprimer ces thèmes" + +#: wp-admin/network/themes.php:161 +msgid "No, Return me to the theme list" +msgstr "Non, retourner à la liste des thèmes." + +#: wp-admin/network/themes.php:209 +msgid "" +"This screen enables and disables the inclusion of themes available to choose " +"in the Appearance menu for each site. It does not activate or deactivate " +"which theme a site is currently using." +msgstr "" +"Cet écran permet d’activer ou désactiver la disponibilité des thèmes " +"pour tous les sites du réseau. Il ne permet pas d’activer ou activer " +"le thème actuellement utilisé ce site." + +#: wp-admin/network/themes.php:210 +msgid "" +"If the network admin disables a theme that is in use, it can still remain " +"selected on that site. If another theme is chosen, the disabled theme will " +"not appear in the site’s Appearance > Themes screen." +msgstr "" +"Si l’administrateur du réseau désactive un thème en cours d’" +"utilisation par un site, ce thème restera en place pour ce site. Si le site " +"change de thème, le thème désactivé n’apparaîtra plus dans l’" +"écran de sélection des thèmes de ce site." + +#: wp-admin/network/themes.php:211 +msgid "" +"Themes can be enabled on a site by site basis by the network admin on the " +"Edit Site screen (which has a Themes tab); get there via the Edit action " +"link on the All Sites screen. Only network admins are able to install or " +"edit themes." +msgstr "" +"Les thèmes peuvent être activés par l’administrateur du réseau pour " +"chaque site, individuellement, par le biais de l’écran de modification " +"d’un site (et de son onglet « Thèmes »), " +"accessible via le lien « Modifier » de la liste des " +"sites. Seuls les administrateurs du réseau peuvent installer ou modifier des " +"thèmes." + +#: wp-admin/network/themes.php:216 +msgid "" +"Documentation on Network Themes" +msgstr "" +"Documentation sur les thèmes du réseau" + +#: wp-admin/network/themes.php:245 +msgctxt "network" +msgid "Theme deleted." +msgid_plural "%s themes deleted." +msgstr[0] "Thème supprimé." +msgstr[1] "%s thèmes supprimés." + +#: wp-admin/network/themes.php:249 +msgid "You cannot delete a theme while it is active on the main site." +msgstr "" +"Vous ne pouvez pas effacer un thème s’il est activé sur le site " +"principal." + +#: wp-admin/network/upgrade.php:25 +msgid "" +"Only use this screen once you have updated to a new version of WordPress " +"through Updates/Available Updates (via the Network Administration navigation " +"menu or the Toolbar). Clicking the Upgrade Network button will step through " +"each site in the network, five at a time, and make sure any database updates " +"are applied." +msgstr "" +"N’utilisez cet écran que quand vous avez mis à jour cette installation " +"de WordPress (au moyen de la fonction de mise à jour automatique ou la barre " +"d’outils). En cliquant sur « Mettre à jour le réseau " +"», WordPress s’occupera de tous les sites du réseau, par groupes " +"de cinq, et s’assurera que toutes les mises à jour de bases de données " +"sont appliquées." + +#: wp-admin/network/upgrade.php:26 +msgid "" +"If a version update to core has not happened, clicking this button won’" +"t affect anything." +msgstr "" +"S’il n’y a pas eu de mise à jour de l’installation de " +"WordPress récemment, cliquer sur ce bouton n’aura aucun effet." + +#: wp-admin/network/upgrade.php:27 +msgid "" +"If this process fails for any reason, users logging in to their sites will " +"force the same update." +msgstr "" +"Si ce processus échoue pour n’importe quelles raisons, les " +"utilisateurs se connectant à leurs sites déclencheront la même mise à jour." + +#: wp-admin/network/upgrade.php:32 +msgid "" +"Documentation on Upgrade Network" +msgstr "" +"Documentation sur la mise à jour du réseau (en)" + +#: wp-admin/network/upgrade.php:58 +msgid "All done!" +msgstr "Terminé !" + +#: wp-admin/network/upgrade.php:70 +msgid "" +"Warning! Problem updating %1$s. Your server may not be able to connect to " +"sites running on it. Error message: %2$s" +msgstr "" +"Attention ! Problème lors de la mise à jour de %1$s. Votre serveur peut " +"ne pas être capable de se connecter aux sites qu’il gère. Message " +"d’erreur : %2$s" + +#: wp-admin/network/upgrade.php:75 +msgid "" +"If your browser doesn’t start loading the next page automatically, " +"click this link:" +msgstr "" +"Si votre navigateur ne lance pas automatiquement la page suivante, cliquez " +"sur ce lien :" + +#: wp-admin/network/upgrade.php:75 +msgid "Next Sites" +msgstr "Sites suivants" + +#: wp-admin/network/upgrade.php:89 +msgid "Database Upgrade Required" +msgstr "Il faut mettre à jour la base de données" + +#: wp-admin/network/upgrade.php:90 +msgid "" +"WordPress has been updated! Before we send you on your way, we need to " +"individually upgrade the sites in your network." +msgstr "" +"WordPress a été mis à jour ! Avant de vous laisser continuer, nous " +"devons mettre à jour chaque site de votre réseau." + +#: wp-admin/network/upgrade.php:93 +msgid "" +"The database upgrade process may take a little while, so please be patient." +msgstr "" +"Le processus de mise à jour peut prendre un long moment. Merci pour votre " +"patience." + +#: wp-admin/network/user-new.php:17 +msgid "You do not have sufficient permissions to add users to this network." +msgstr "" +"Vous n’avez pas les droits suffisants pour ajouter des utilisateurs à " +"ce réseau." + +#: wp-admin/network/user-new.php:23 +msgid "" +"Add User will set up a new user account on the network and send that person " +"an email with username and password." +msgstr "" +"« Ajouter un utilisateur » créera un nouveau compte " +"utilisateur sur le réseau, et enverra un message contenant son identifiant " +"et son mot de passe au destinataire." + +#: wp-admin/network/user-new.php:24 +msgid "" +"Users who are signed up to the network without a site are added as " +"subscribers to the main or primary dashboard site, giving them profile pages " +"to manage their accounts. These users will only see Dashboard and My Sites " +"in the main navigation until a site is created for them." +msgstr "" +"Les utilisateurs qui se sont inscrits sur le réseau sans créer de site " +"deviennent abonnés du site d’accueil. Celui-ci leur permet d’" +"accéder à leur compte. Ces utilisateurs ne voient dans la navigation " +"principale que les options « Tableau de bord » et " +"« Mes sites », jusqu’à ce qu’un site leur " +"soit créé." + +#: wp-admin/network/user-new.php:29 wp-admin/network/users.php:244 +msgid "" +"Documentation on Network Users" +msgstr "" +"Documentation sur les utilisateurs du réseau" + +#: wp-admin/network/user-new.php:39 +msgid "Cannot create an empty user." +msgstr "Impossible de créer un utilisateur vide." + +#: wp-admin/network/user-new.php:51 +msgid "Cannot add user." +msgstr "Impossible d’ajouter l’utilisateur." + +#: wp-admin/network/users.php:27 +msgid "Transfer or delete posts before deleting users." +msgstr "" +"Transférer ou effacer les articles avant d’effacer les utilisateurs." + +#: wp-admin/network/users.php:40 +msgid "Warning! User %s cannot be deleted." +msgstr "" +"Attention ! L’utilisateur %s n’a pas pu être supprimé." + +#: wp-admin/network/users.php:43 +msgid "" +"Warning! User cannot be deleted. The user %s is a network administrator." +msgstr "" +"Attention ! L’utilisateur %s ne peut être effacé car il est un " +"administrateur du réseau." + +#: wp-admin/network/users.php:50 +msgid "What should be done with posts owned by %s?" +msgstr "Que voulez-vous faire des articles appartenant à %s ?" + +#: wp-admin/network/users.php:68 +msgid "Site: %s" +msgstr "Site : %s" + +#: wp-admin/network/users.php:144 +msgid "" +"Warning! User cannot be modified. The user %s is a network administrator." +msgstr "" +"Attention ! L’utilisateur %s ne peut être modifié car il est un " +"administrateur du réseau." + +#: wp-admin/network/users.php:234 +msgid "" +"This table shows all users across the network and the sites to which they " +"are assigned." +msgstr "" +"Ce tableau affiche tous les utilisateurs appartenant au réseau, et les sites " +"auxquels ils sont assignés." + +#: wp-admin/network/users.php:235 +msgid "" +"Hover over any user on the list to make the edit links appear. The Edit link " +"on the left will take you to his or her Edit User profile page; the Edit " +"link on the right by any site name goes to an Edit Site screen for that site." +msgstr "" +"Survolez n’importe quel utilisateur de cette liste avec la souris pour " +"faire apparaître ses liens connexes. Le lien « Modifier " +"» à gauche vous permet de modifier son profil ; celui tout à " +"droite, à côté de l’adresse du site, permet de modifier le site." + +#: wp-admin/network/users.php:236 +msgid "" +"You can also go to the user’s profile page by clicking on the " +"individual username." +msgstr "" +"Vous pouvez également aller sur la page de profil d’un utilisateur en " +"cliquant sur son identifiant." + +#: wp-admin/network/users.php:237 +msgid "" +"You can sort the table by clicking on any of the bold headings and switch " +"between list and excerpt views by using the icons in the upper right." +msgstr "" +"Un clic sur le titre d’une colonne permet de changer le tri du " +"tableau. Les icônes en haut à droit permettent d’afficher des extraits " +"ou non." + +#: wp-admin/network/users.php:238 +msgid "" +"The bulk action will permanently delete selected users, or mark/unmark those " +"selected as spam. Spam users will have posts removed and will be unable to " +"sign up again with the same email addresses." +msgstr "" +"Le menu « Actions groupées » permet d’effacer " +"définitivement plusieurs utilisateurs d’un coup, ou de les marquer " +"comme sains ou indésirables. Les utilisateurs indésirables verront leurs " +"articles supprimés, et ne pourront plus se connecter avec leur adresse de " +"messagerie." + +#: wp-admin/network/users.php:239 +msgid "" +"You can make an existing user an additional super admin by going to the Edit " +"User profile page and checking the box to grant that privilege." +msgstr "" +"Vous pouvez promouvoir un utilisateur existant en super-admin en allant sur " +"leur page de profil, et en cochant la case correspondante." + +#: wp-admin/network/users.php:259 +msgid "Users marked as spam." +msgstr "Utilisateurs marqués comme indésirables." + +#: wp-admin/network/users.php:262 +msgid "Users removed from spam." +msgstr "Utilisateurs marqués comme sains." + +#: wp-admin/network/users.php:265 +msgid "Users deleted." +msgstr "Utilisateurs supprimés." + +#: wp-admin/network.php:27 +msgid "The Network creation panel is not for WordPress MU networks." +msgstr "" +"Le panneau de création de réseau n’est pas conçu pour les réseaux " +"WordPress MU." + +#: wp-admin/network.php:103 +msgid "" +"You must define the WP_ALLOW_MULTISITE constant as true in your " +"wp-config.php file to allow creation of a Network." +msgstr "" +"Afin d’autoriser la création d’un réseau, vous devez définir la " +"constante WP_ALLOW_MULTISITE comme « true " +"» dans votre fichier wp-config.php." + +#: wp-admin/network.php:109 +msgid "Create a Network of WordPress Sites" +msgstr "Créer un réseau de sites WordPress" + +#: wp-admin/network.php:113 +msgid "" +"This screen allows you to configure a network as having subdomains " +"(site1.example.com) or subdirectories (example.com/site1). Subdomains require wildcard subdomains to be enabled in Apache and " +"DNS records, if your host allows it." +msgstr "" +"Cet écran vous permet de configurer un réseau, sous la forme sous-domaines " +"(site1.example.com) ou sous-dossiers (example.com/site1). La forme sous-domaines nécessite une entrée de sous-domaine " +"générique (wildcard) dans les enregistrements DNS et la configuration " +"Apache, si votre hébergeur le permet." + +#: wp-admin/network.php:114 +msgid "" +"Choose subdomains or subdirectories; this can only be switched afterwards by " +"reconfiguring your install. Fill out the network details, and click install. " +"If this does not work, you may have to add a wildcard DNS record (for " +"subdomains) or change to another setting in Permalinks (for subdirectories)." +msgstr "" +"Faites le choix entre sous-domaines ou sous-dossiers. Une fois l’" +"installation configurée, vous ne pourrez pas revenir en arrière sans " +"recommencer à zéro. Saisissez tous les détails, et cliquez sur « " +"Installer ». Si cela ne marche pas, vous devrez sans doute " +"ajouter une entrée de sous-domaine générique (wildcard) dans vos " +"enregistrements DNS, ou passer à un réglage différent pour vos permaliens " +"(si en mode sous-dossiers)." + +#: wp-admin/network.php:115 +msgid "" +"The next screen for Network Setup will give you individually-generated lines " +"of code to add to your wp-config.php and .htaccess files. Make sure the " +"settings of your FTP client make files starting with a dot visible, so that " +"you can find .htaccess; you may have to create this file if it really is not " +"there. Make backup copies of those two files." +msgstr "" +"L’écran suivant vous présentera un ensemble de lignes de code générées " +"à partir de votre configuration, qu’il vous faudra ajouter à vos " +"fichiers wp-config.php et .htaccess. Veillez bien " +"à ce que votre client FTP soit configuré pour afficher les fichiers " +"commençant par un point, afin que vous puissiez trouver le fichier ." +"htaccess. Il est possible que vous ayez à créer ce fichier s’il " +"n’est pas déjà présent. Avant toute modification de wp-config." +"php et .htaccess, faites-en une copie de sauvegarde." + +#: wp-admin/network.php:116 +msgid "" +"Add the designated lines of code to wp-config.php (just before /*..." +"stop editing...*/) and .htaccess (replacing the existing " +"WordPress rules)." +msgstr "" +"Ajoutez les lignes de code désignées dans le fichier wp-config.php (juste avant /*...stop editing...*/) et le fichier ." +"htaccess (en remplaçant les règles existantes de WordPress)." + +#: wp-admin/network.php:117 +msgid "" +"Once you add this code and refresh your browser, multisite should be " +"enabled. This screen, now in the Network Admin navigation menu, will keep an " +"archive of the added code. You can toggle between Network Admin and Site " +"Admin by clicking on the Network Admin or an individual site name under the " +"My Sites dropdown in the Toolbar." +msgstr "" +"Une fois que vous aurez ajouté ce code et rafraîchi la page dans votre " +"navigateur, le mode multisite devrait être activé. Cet écran, désormais " +"placé dans le menu de navigation Admin du Réseau, conservera une archive du " +"code ajouté. Vous pouvez basculer de l’administration du réseau à " +"l’administration du site en cliquant sur « Admin du " +"réseau », ou en cliquant sur le nom d’un site individuel " +"dans le menu déroulant « Mes Sites » de la barre " +"d’outils." + +#: wp-admin/network.php:118 +msgid "" +"The choice of subdirectory sites is disabled if this setup is more than a " +"month old because of permalink problems with “/blog/” from the " +"main site. This disabling will be addressed in a future version." +msgstr "" +"Le choix d’avoir des sites en mode sous-répertoire est désactivé si le " +"réseau a été installé il y a un mois ou plus, afin de pallier les problèmes " +"de permaliens avec l’ajout de « /blog/ » sur les " +"adresses du site principal. Cette limitation sera corrigée dans une " +"prochaine version." + +#: wp-admin/network.php:120 wp-admin/network.php:131 +msgid "" +"Documentation on Creating a Network" +msgstr "" +"Documentation sur la création d’un réseau de sites" + +#: wp-admin/network.php:121 wp-admin/network.php:132 +msgid "" +"Documentation on the Network Screen" +msgstr "" +"Documentation sur l’écran Outils > Réseau (en)" + +#: wp-admin/network.php:125 +msgid "Network" +msgstr "Réseau" + +#: wp-admin/network.php:155 +msgid "" +"The constant DO_NOT_UPGRADE_GLOBAL_TABLES cannot be defined when creating a " +"network." +msgstr "" +"La constante DO_NOT_UPGRADE_GLOBAL_TABLES ne doit pas être définie lors de " +"la création du réseau." + +#: wp-admin/network.php:163 wp-admin/network.php:351 wp-admin/network.php:471 +#: wp-admin/network.php:505 +msgid "Warning:" +msgstr "Attention :" + +#: wp-admin/network.php:163 +msgid "" +"Please deactivate your plugins before enabling the " +"Network feature." +msgstr "" +"Veuillez désactiver vos extensions avant la mise en place " +"de votre réseau de sites." + +#: wp-admin/network.php:163 +msgid "Once the network is created, you may reactivate your plugins." +msgstr "Une fois le réseau créé, vous pourrez réactiver vos extensions." + +#: wp-admin/network.php:172 +msgid "You cannot install a network of sites with your server address." +msgstr "" +"Vous ne pouvez pas installer de réseau de sites avec cette adresse serveur." + +#: wp-admin/network.php:173 +msgid "You cannot use port numbers such as %s." +msgstr "" +"Vous ne pouvez pas utiliser de numéros de port tels que %s." + +#: wp-admin/network.php:174 +msgid "Return to Dashboard" +msgstr "Revenir au tableau de bord" + +#: wp-admin/network.php:186 +msgid "ERROR: The network could not be created." +msgstr "ERREUR : le réseau n’a pas pu être créé." + +# Nom par défaut du réseau de sites. +#: wp-admin/network.php:193 +msgctxt "Default network name" +msgid "%s Sites" +msgstr "Réseau %s" + +#: wp-admin/network.php:196 +msgid "Welcome to the Network installation process!" +msgstr "Bienvenue dans le processus d’installation du réseau !" + +#: wp-admin/network.php:197 +msgid "" +"Fill in the information below and you’ll be on your way to creating a " +"network of WordPress sites. We will create configuration files in the next " +"step." +msgstr "" +"Complétez le formulaire ci-dessous et vous serez prêt à créer un réseau de " +"sites WordPress. Nous créerons les fichiers de configurations à l’" +"étape suivante." + +#: wp-admin/network.php:209 +msgid "Note:" +msgstr "Note :" + +#: wp-admin/network.php:209 +msgid "" +"Please make sure the Apache mod_rewrite module is installed as " +"it will be used at the end of this installation." +msgstr "" +"Vérifiez bien que le module Apache mod_rewrite est installé, " +"car il sera nécessaire à la fin de cette installation." + +#: wp-admin/network.php:211 wp-admin/network.php:236 wp-admin/network.php:262 +#: wp-admin/network.php:272 +msgid "Warning!" +msgstr "Attention !" + +#: wp-admin/network.php:211 +msgid "" +"It looks like the Apache mod_rewrite module is not installed." +msgstr "" +"Il semble que le module Apache mod_rewrite n’est pas " +"installé." + +#: wp-admin/network.php:213 +msgid "" +"If mod_rewrite is disabled, ask your administrator to enable " +"that module, or look at the Apache documentation or elsewhere for help setting it up." +msgstr "" +"Si le module mod_rewrite est désactivé, contactez votre " +"administrateur pour l’activer, ou lisez la documentation Apache officielle " +"ou non, " +"pour comprendre comment le mettre en place." + +#: wp-admin/network.php:217 +msgid "Addresses of Sites in your Network" +msgstr "Adresse des sites dans votre réseau" + +#: wp-admin/network.php:218 +msgid "" +"Please choose whether you would like sites in your WordPress network to use " +"sub-domains or sub-directories. You cannot change this later." +msgstr "" +"Veuillez décider si vous voulez que les sites de votre installation " +"WordPress utilisent des sous-domaines ou des sous-dossiers. Ce " +"réglage est définitif, vous ne pourrez pas revenir en arrière." + +#: wp-admin/network.php:219 +msgid "" +"You will need a wildcard DNS record if you are going to use the virtual host " +"(sub-domain) functionality." +msgstr "" +"Vous aurez besoin d’un enregistrement DNS générique (wildcard) pour " +"permettre l’utilisation de la forme sous-domaine (hôte virtuel)." + +#: wp-admin/network.php:223 +msgid "Sub-domains" +msgstr "Sous-domaines" + +#: wp-admin/network.php:224 +msgctxt "subdomain examples" +msgid "like site1.%1$s and site2.%1$s" +msgstr "comme site1.%1$s et site2.%1$s" + +#: wp-admin/network.php:227 +msgid "Sub-directories" +msgstr "Sous-dossiers" + +#: wp-admin/network.php:228 +msgctxt "subdirectory examples" +msgid "like %1$s/site1 and %1$s/site2" +msgstr "comme %1$s/site1 et %1$s/site2" + +#: wp-admin/network.php:236 wp-admin/network.php:471 wp-admin/network.php:505 +msgid "" +"Subdirectory networks may not be fully compatible with custom wp-content " +"directories." +msgstr "" +"Les réseaux dans un sous-dossier peuvent ne pas être complètement " +"compatibles avec les dossiers /wp-content personnalisés." + +#: wp-admin/network.php:241 wp-admin/network.php:245 wp-admin/network.php:285 +msgid "Server Address" +msgstr "Adresse du serveur" + +#: wp-admin/network.php:242 +msgid "" +"We recommend you change your siteurl to %1$s before enabling " +"the network feature. It will still be possible to visit your site using the " +"www prefix with an address like %2$s but any links " +"will not have the www prefix." +msgstr "" +"Nous vous recommandons de modifier votre réglage « siteurl " +"» pour %1$s avec d’activer la fonctionnalité de " +"réseau. Il sera toujours possible de se rendre sur votre site par le biais " +"du préfixe « www » avec une adresse comme %2$s, mais les liens n’auront pas le préfixe « www " +"»." + +#: wp-admin/network.php:247 wp-admin/network.php:287 +msgid "The internet address of your network will be %s." +msgstr "L’adresse internet de votre réseau sera %s." + +#: wp-admin/network.php:253 +msgid "Network Details" +msgstr "Détails du réseau" + +#: wp-admin/network.php:257 wp-admin/network.php:267 +msgid "Sub-directory Install" +msgstr "Installation dans un sous-dossier" + +#: wp-admin/network.php:259 +msgid "" +"Because you are using localhost, the sites in your WordPress " +"network must use sub-directories. Consider using localhost." +"localdomain if you wish to use sub-domains." +msgstr "" +"Vous utilisez localhost, donc les sites de votre réseau " +"WordPress doivent utiliser des sous-dossiers. Songez à utiliser " +"localhost.localdomain si vous préférez utiliser des sous-" +"domaines." + +#: wp-admin/network.php:262 wp-admin/network.php:272 wp-admin/network.php:279 +msgid "" +"The main site in a sub-directory install will need to use a modified " +"permalink structure, potentially breaking existing links." +msgstr "" +"Le site principal installé dans un sous-dossier aura besoin d’utiliser " +"une structure de permaliens personnalisés, ce qui pourra potentiellement " +"casser des liens existants." + +#: wp-admin/network.php:269 +msgid "" +"Because your install is in a directory, the sites in your WordPress network " +"must use sub-directories." +msgstr "" +"Votre installation est située dans un dossier, donc les sites de votre " +"réseau WordPress doivent forcément utiliser des sous-dossiers." + +#: wp-admin/network.php:277 +msgid "Sub-domain Install" +msgstr "Installation sous-domaine" + +#: wp-admin/network.php:278 +msgid "" +"Because your install is not new, the sites in your WordPress network must " +"use sub-domains." +msgstr "" +"Votre installation n’est pas récente, donc les sites de votre réseau " +"WordPress doivent utiliser les sous-domaines." + +#: wp-admin/network.php:292 +msgid "Network Title" +msgstr "Nom du réseau" + +#: wp-admin/network.php:295 +msgid "What would you like to call your network?" +msgstr "Quel nom voulez-vous donner à votre réseau ?" + +#: wp-admin/network.php:299 +msgid "Admin E-mail Address" +msgstr "Adresse de contact de l’administrateur" + +#: wp-admin/network.php:302 +msgid "Your email address." +msgstr "Votre adresse de contact." + +#: wp-admin/network.php:346 +msgid "The original configuration steps are shown here for reference." +msgstr "Pour rappel, voici les étapes de configuration originelles." + +#: wp-admin/network.php:351 +msgid "An existing WordPress network was detected." +msgstr "Un réseau WordPress existant a été détecté." + +#: wp-admin/network.php:352 +msgid "" +"Please complete the configuration steps. To create a new network, you will " +"need to empty or remove the network database tables." +msgstr "" +"Veuillez effectuer les étapes de configuration. Pour créer un nouveau " +"réseau, vous devrez vider ou effacer les tables de la base de données du " +"réseau." + +#: wp-admin/network.php:363 +msgid "Enabling the Network" +msgstr "Activer le réseau de sites" + +#: wp-admin/network.php:364 +msgid "" +"Complete the following steps to enable the features for creating a network " +"of sites." +msgstr "" +"Suivez les étapes ci-après pour activer les fonctionnalités permettant la " +"création d’un réseau de sites." + +#: wp-admin/network.php:367 wp-admin/network.php:369 +msgid "" +"Caution: We recommend you back up your existing wp-" +"config.php and %s files." +msgstr "" +"Attention : nous vous recommandons de faire une copie " +"de sauvegarde de vos fichiers wp-config.php et %s " +"actuels." + +#: wp-admin/network.php:371 +msgid "" +"Caution: We recommend you back up your existing wp-" +"config.php file." +msgstr "" +"Attention : nous vous recommandons de faire une copie " +"de sauvegarde de votre fichier wp-config.php actuel." + +#: wp-admin/network.php:377 +msgid "" +"Add the following to your wp-config.php file in %s " +"above the line reading /* That’s all, stop " +"editing! Happy blogging. */:" +msgstr "" +"Ajoutez les lignes suivantes à votre fichier wp-config.php, " +"dans %s, au-dessus de la ligne /* C’est tout, ne " +"touchez pas à ce qui suit ! Bon blogging ! */ :" + +#: wp-admin/network.php:408 +msgid "" +"This unique authentication key is also missing from your wp-config." +"php file." +msgid_plural "" +"These unique authentication keys are also missing from your wp-config." +"php file." +msgstr[0] "" +"Cette clé d’authentification unique ne se trouve pas non plus dans " +"votre fichier wp-config.php." +msgstr[1] "" +"Ces clés d’authentification uniques ne se trouvent pas non plus dans " +"votre fichier wp-config.php." + +#: wp-admin/network.php:408 +msgid "To make your installation more secure, you should also add:" +msgstr "" +"Pour mieux sécuriser votre installation, vous devriez également " +"ajouter :" + +#: wp-admin/network.php:468 +msgid "" +"Add the following to your web.config file in %s, " +"replacing other WordPress rules:" +msgstr "" +"Ajoutez les lignes suivantes à votre fichier web.config, dans " +"%s, en remplacement des autres règles liées à WordPress :" + +#: wp-admin/network.php:502 +msgid "" +"Add the following to your .htaccess file in %s, " +"replacing other WordPress rules:" +msgstr "" +"Ajoutez les lignes suivantes à votre fichier .htaccess, dans " +"%s, en remplacement des autres règles liées à WordPress :" + +#: wp-admin/network.php:514 +msgid "" +"Once you complete these steps, your network is enabled and configured. You " +"will have to log in again." +msgstr "" +"Une fois les étapes effectuées, votre réseau sera activé et configuré. Vous " +"devez maintenant vous reconnecter." + +#~ msgid "" +#~ "To search for a user enter all or part of a username or " +#~ "email address" +#~ msgstr "" +#~ "Pour chercher un utilisateur, saisissez tout ou partie " +#~ "de son idenfiant ou de adresse de messagerie" + +#~ msgid "" +#~ "Dashboard Site is an option to give a site to users who do not have a " +#~ "site on the system. Their default role is Subscriber, but that default " +#~ "can be changed. The Admin Notice Feed can provide a notice on all " +#~ "dashboards of the latest post via RSS or Atom, or provide no such notice " +#~ "if left blank." +#~ msgstr "" +#~ "L’option « Site d’accueil » permet " +#~ "d’afficher un site aux utilisateurs qui n’en ont pas encore " +#~ "un. Leur rôle par défaut à « Abonné », mais vous " +#~ "pouvez le modifier. Le flux d’annonce de l’administrateur permet d’" +#~ "afficher une information sur tous les tableaux de bord, tirée du dernier " +#~ "article d’un flux RSS ou Atom. Aucune information ne sera affichée " +#~ "si le champ est laissé vide." + +#~ msgid "" +#~ "Until WordPress 3.0, running multiple sites required using WordPress MU " +#~ "instead of regular WordPress. In version 3.0, these applications have " +#~ "merged. If you are a former MU user, you should be aware of the following " +#~ "changes:" +#~ msgstr "" +#~ "Avant WordPress 3.0, la gestion de plusieurs sites requérait l’" +#~ "utilisation de WordPress MU plutôt que le WordPress habituel. Dans la " +#~ "version 3.0, ces deux éditions ont fusionné. Si vous étiez un utilisateur " +#~ "de MU, il vous faut garder en tête les modifications suivantes :" + +#~ msgid "" +#~ "Site Admin is now Super Admin (we highly encourage you to get yourself a " +#~ "cape!)." +#~ msgstr "" +#~ "L’administrateur du site est désormais appelé super-admin (nous " +#~ "vous encourageons vivement à vous trouver une cape !) ;" + +#~ msgid "Blogs are now called Sites; Site is now called Network." +#~ msgstr "" +#~ "Les blogs sont maintenant appelés des sites. Le site global est " +#~ "maintenant nommé « le réseau »." + +#~ msgid "" +#~ "The Right Now box provides the network administrator with links to the " +#~ "screens to either create a new site or user, or to search existing users " +#~ "and sites. Screens for Sites and Users are also accessible through the " +#~ "left-hand navigation in the Network Admin section." +#~ msgstr "" +#~ "Le bloc « Aujourd’hui » permet à l’" +#~ "administrateur du réseau de se rendre à l’écran de création de " +#~ "sites et celui de création d’utilisateurs, ou de lancer une " +#~ "recherche sur l’ensemble des sites et utilisateurs. Ces écrans sont " +#~ "également accessibles via la navigation de l’administration du " +#~ "réseau de sites." + +#~ msgid "Menu Settings" +#~ msgstr "Réglages du menu" + +#~ msgid "" +#~ "You can update all the sites on your network through this page. It works " +#~ "by calling the update script of each site automatically. Hit the link " +#~ "below to update." +#~ msgstr "" +#~ "Vous pouvez mettre à jour tous les sites de votre réseau par le biais de " +#~ "cette page. Le processus consiste à appeler le script de mise à jour pour " +#~ "chaque site, automatiquement. Cliquez sur le lien ci-dessous pour lancer " +#~ "la mise à jour." + +#~ msgctxt "plugin editor" +#~ msgid "Add New" +#~ msgstr "Ajouter" + +#~ msgid "Only the characters a-z and 0-9 recommended." +#~ msgstr "" +#~ "N’utilisez de préférence que des lettres (de a à z) et des chiffres " +#~ "(de 0 à 9)." + +#~ msgid "Add User to This Site" +#~ msgstr "Ajouter un utilisateur à ce site" + +#~ msgid "" +#~ "You may add from existing network users, or set up a new user to add to " +#~ "this site." +#~ msgstr "" +#~ "Vous pouvez ajouter des utilisateurs en provenance du réseau, ou créer un " +#~ "nouvel utilisateur à ajouter à ce site." + +#~ msgid "You may add from existing network users to this site." +#~ msgstr "" +#~ "Vous pouvez ajouter à ce site des utilisateurs existant sur le réseau de " +#~ "sites." + +#~ msgid "" +#~ "Your WordPress address must match your Site " +#~ "address before creating a Network. See General " +#~ "Settings." +#~ msgstr "" +#~ "Votre adresse WordPress doit correspondre à votre " +#~ "adresse de site avant de pouvoir créer un réseau. Voir " +#~ "les réglages généraux." + +#~ msgid "" +#~ "Create a blogs.dir directory at %s/blogs.dir. " +#~ "This directory is used to store uploaded media for your additional sites " +#~ "and must be writeable by the web server." +#~ msgstr "" +#~ "Créez le dossier blogs.dir à l’emplacement %s/" +#~ "blogs.dir. Ce dossier sera utilisé pour stocker les fichiers mis " +#~ "en ligne pour les sites additionnels ; il doit être accessible en " +#~ "écriture par votre serveur web." + +#~ msgid "" +#~ "Checkboxes for media upload buttons set which are shown in the visual " +#~ "editor. If unchecked, a generic upload button is still visible; other " +#~ "media types can still be uploaded if on the allowed file types list." +#~ msgstr "" +#~ "Les cases à cocher pour les boutons du gestionnaire de médias déterminent " +#~ "lesquels sont affichés dans l’éditeur visuel. Si aucun n’est " +#~ "coché, un bouton générique sera utilisé. Les autres types de fichiers " +#~ "peuvent toujours être mis en ligne s’ils sont indiqués dans la " +#~ "liste." diff --git a/sources/wp-content/languages/continents-cities-fr_FR.mo b/sources/wp-content/languages/continents-cities-fr_FR.mo new file mode 100644 index 0000000000000000000000000000000000000000..2ea779f7b7d5fec70cc53ed2ddd17d10fc7b96c1 GIT binary patch literal 9301 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 DFDbT) literal 0 HcmV?d00001 diff --git a/sources/wp-content/languages/continents-cities-fr_FR.po b/sources/wp-content/languages/continents-cities-fr_FR.po new file mode 100644 index 0000000..d3fbb1e --- /dev/null +++ b/sources/wp-content/languages/continents-cities-fr_FR.po @@ -0,0 +1,1985 @@ +# Translation of timezone strings in WordPress 3.1-alpha. +# Copyright (C) 2010 WordPress +# This file is distributed under the same license as the WordPress package. +# FIRST AUTHOR , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: WordPress 3.7\n" +"Report-Msgid-Bugs-To: http://wppolyglots.wordpress.com\n" +"POT-Creation-Date: 2013-01-01 00:19:07+00:00\n" +"PO-Revision-Date: 2013-10-24 14:05+0100\n" +"Last-Translator: Xavier B. \n" +"Language-Team: WordPress Francophone \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 1.5.7\n" + +#: wp-admin/includes/continents-cities.php:7 +msgid "Africa" +msgstr "Afrique" + +#: wp-admin/includes/continents-cities.php:8 +msgid "Abidjan" +msgstr "" + +#: wp-admin/includes/continents-cities.php:9 +msgid "Accra" +msgstr "" + +#: wp-admin/includes/continents-cities.php:10 +msgid "Addis Ababa" +msgstr "Addis-Abeba" + +#: wp-admin/includes/continents-cities.php:11 +msgid "Algiers" +msgstr "Alger" + +#: wp-admin/includes/continents-cities.php:12 +msgid "Asmara" +msgstr "" + +#: wp-admin/includes/continents-cities.php:13 +msgid "Asmera" +msgstr "Asmara" + +#: wp-admin/includes/continents-cities.php:14 +msgid "Bamako" +msgstr "" + +#: wp-admin/includes/continents-cities.php:15 +msgid "Bangui" +msgstr "" + +#: wp-admin/includes/continents-cities.php:16 +msgid "Banjul" +msgstr "" + +#: wp-admin/includes/continents-cities.php:17 +msgid "Bissau" +msgstr "" + +#: wp-admin/includes/continents-cities.php:18 +msgid "Blantyre" +msgstr "" + +#: wp-admin/includes/continents-cities.php:19 +msgid "Brazzaville" +msgstr "" + +#: wp-admin/includes/continents-cities.php:20 +msgid "Bujumbura" +msgstr "" + +#: wp-admin/includes/continents-cities.php:21 +msgid "Cairo" +msgstr "Le Caire" + +#: wp-admin/includes/continents-cities.php:22 +msgid "Casablanca" +msgstr "" + +#: wp-admin/includes/continents-cities.php:23 +msgid "Ceuta" +msgstr "" + +#: wp-admin/includes/continents-cities.php:24 +msgid "Conakry" +msgstr "" + +#: wp-admin/includes/continents-cities.php:25 +msgid "Dakar" +msgstr "" + +#: wp-admin/includes/continents-cities.php:26 +msgid "Dar es Salaam" +msgstr "" + +#: wp-admin/includes/continents-cities.php:27 +msgid "Djibouti" +msgstr "" + +#: wp-admin/includes/continents-cities.php:28 +msgid "Douala" +msgstr "" + +#: wp-admin/includes/continents-cities.php:29 +msgid "El Aaiun" +msgstr "Laâyoune" + +#: wp-admin/includes/continents-cities.php:30 +msgid "Freetown" +msgstr "" + +#: wp-admin/includes/continents-cities.php:31 +msgid "Gaborone" +msgstr "" + +#: wp-admin/includes/continents-cities.php:32 +msgid "Harare" +msgstr "" + +#: wp-admin/includes/continents-cities.php:33 +msgid "Johannesburg" +msgstr "" + +#: wp-admin/includes/continents-cities.php:34 +msgid "Kampala" +msgstr "" + +#: wp-admin/includes/continents-cities.php:35 +msgid "Khartoum" +msgstr "" + +#: wp-admin/includes/continents-cities.php:36 +msgid "Kigali" +msgstr "" + +#: wp-admin/includes/continents-cities.php:37 +msgid "Kinshasa" +msgstr "" + +#: wp-admin/includes/continents-cities.php:38 +msgid "Lagos" +msgstr "" + +#: wp-admin/includes/continents-cities.php:39 +msgid "Libreville" +msgstr "" + +#: wp-admin/includes/continents-cities.php:40 +msgid "Lome" +msgstr "Lomé" + +#: wp-admin/includes/continents-cities.php:41 +msgid "Luanda" +msgstr "" + +#: wp-admin/includes/continents-cities.php:42 +msgid "Lubumbashi" +msgstr "" + +#: wp-admin/includes/continents-cities.php:43 +msgid "Lusaka" +msgstr "" + +#: wp-admin/includes/continents-cities.php:44 +msgid "Malabo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:45 +msgid "Maputo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:46 +msgid "Maseru" +msgstr "" + +#: wp-admin/includes/continents-cities.php:47 +msgid "Mbabane" +msgstr "" + +#: wp-admin/includes/continents-cities.php:48 +msgid "Mogadishu" +msgstr "Mogadiscio" + +#: wp-admin/includes/continents-cities.php:49 +msgid "Monrovia" +msgstr "" + +#: wp-admin/includes/continents-cities.php:50 +msgid "Nairobi" +msgstr "" + +#: wp-admin/includes/continents-cities.php:51 +msgid "Ndjamena" +msgstr "N'Djamena" + +#: wp-admin/includes/continents-cities.php:52 +msgid "Niamey" +msgstr "" + +#: wp-admin/includes/continents-cities.php:53 +msgid "Nouakchott" +msgstr "" + +#: wp-admin/includes/continents-cities.php:54 +msgid "Ouagadougou" +msgstr "" + +#: wp-admin/includes/continents-cities.php:55 +msgid "Porto-Novo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:56 +msgid "Sao Tome" +msgstr "São Tomé" + +#: wp-admin/includes/continents-cities.php:57 +msgid "Timbuktu" +msgstr "Tombouctou" + +#: wp-admin/includes/continents-cities.php:58 +msgid "Tripoli" +msgstr "" + +#: wp-admin/includes/continents-cities.php:59 +msgid "Tunis" +msgstr "" + +#: wp-admin/includes/continents-cities.php:60 +msgid "Windhoek" +msgstr "" + +#: wp-admin/includes/continents-cities.php:61 +msgid "America" +msgstr "Amériques" + +#: wp-admin/includes/continents-cities.php:62 +msgid "Adak" +msgstr "" + +#: wp-admin/includes/continents-cities.php:63 +msgid "Anchorage" +msgstr "" + +#: wp-admin/includes/continents-cities.php:64 +msgid "Anguilla" +msgstr "" + +#: wp-admin/includes/continents-cities.php:65 +msgid "Antigua" +msgstr "" + +#: wp-admin/includes/continents-cities.php:66 +msgid "Araguaina" +msgstr "Araguaína" + +#: wp-admin/includes/continents-cities.php:67 +msgid "Argentina" +msgstr "Argentine" + +#: wp-admin/includes/continents-cities.php:68 +msgid "Buenos Aires" +msgstr "" + +#: wp-admin/includes/continents-cities.php:69 +msgid "Catamarca" +msgstr "" + +#: wp-admin/includes/continents-cities.php:70 +msgid "ComodRivadavia" +msgstr "Comodoro Rivadavia" + +#: wp-admin/includes/continents-cities.php:71 +msgid "Cordoba" +msgstr "Córdoba" + +#: wp-admin/includes/continents-cities.php:72 +msgid "Jujuy" +msgstr "San Salvador de Jujuy" + +#: wp-admin/includes/continents-cities.php:73 +msgid "La Rioja" +msgstr "" + +#: wp-admin/includes/continents-cities.php:74 +msgid "Mendoza" +msgstr "" + +#: wp-admin/includes/continents-cities.php:75 +msgid "Rio Gallegos" +msgstr "Rio Gallegos" + +#: wp-admin/includes/continents-cities.php:76 +#, fuzzy +msgid "San Juan" +msgstr "Saint-Marin" + +#: wp-admin/includes/continents-cities.php:77 +#, fuzzy +msgid "San Luis" +msgstr "Saint-Marin" + +#: wp-admin/includes/continents-cities.php:78 +msgid "Tucuman" +msgstr "San Miguel de Tucumán" + +#: wp-admin/includes/continents-cities.php:79 +msgid "Ushuaia" +msgstr "Ushuaïa" + +#: wp-admin/includes/continents-cities.php:80 +msgid "Aruba" +msgstr "" + +#: wp-admin/includes/continents-cities.php:81 +msgid "Asuncion" +msgstr "Asunción" + +#: wp-admin/includes/continents-cities.php:82 +msgid "Atikokan" +msgstr "" + +#: wp-admin/includes/continents-cities.php:83 +msgid "Atka" +msgstr "" + +#: wp-admin/includes/continents-cities.php:84 +msgid "Bahia" +msgstr "" + +#: wp-admin/includes/continents-cities.php:85 +msgid "Barbados" +msgstr "Barbade" + +#: wp-admin/includes/continents-cities.php:86 +msgid "Belem" +msgstr "Belém" + +#: wp-admin/includes/continents-cities.php:87 +msgid "Belize" +msgstr "" + +#: wp-admin/includes/continents-cities.php:88 +msgid "Blanc-Sablon" +msgstr "" + +#: wp-admin/includes/continents-cities.php:89 +msgid "Boa Vista" +msgstr "" + +#: wp-admin/includes/continents-cities.php:90 +msgid "Bogota" +msgstr "Bogotá" + +#: wp-admin/includes/continents-cities.php:91 +msgid "Boise" +msgstr "" + +#: wp-admin/includes/continents-cities.php:92 +msgid "Cambridge Bay" +msgstr "Ikaluktutiak" + +#: wp-admin/includes/continents-cities.php:93 +msgid "Campo Grande" +msgstr "" + +#: wp-admin/includes/continents-cities.php:94 +msgid "Cancun" +msgstr "Cancún" + +#: wp-admin/includes/continents-cities.php:95 +msgid "Caracas" +msgstr "" + +#: wp-admin/includes/continents-cities.php:96 +msgid "Cayenne" +msgstr "" + +#: wp-admin/includes/continents-cities.php:97 +msgid "Cayman" +msgstr "ÃŽles Caïmans" + +#: wp-admin/includes/continents-cities.php:98 +msgid "Chicago" +msgstr "" + +#: wp-admin/includes/continents-cities.php:99 +msgid "Chihuahua" +msgstr "Etat de Chihuahua" + +#: wp-admin/includes/continents-cities.php:100 +msgid "Coral Harbour" +msgstr "" + +#: wp-admin/includes/continents-cities.php:101 +msgid "Costa Rica" +msgstr "" + +#: wp-admin/includes/continents-cities.php:102 +msgid "Cuiaba" +msgstr "Cuiabá" + +#: wp-admin/includes/continents-cities.php:103 +msgid "Curacao" +msgstr "Curaçao" + +#: wp-admin/includes/continents-cities.php:104 +msgid "Danmarkshavn" +msgstr "" + +#: wp-admin/includes/continents-cities.php:105 +msgid "Dawson" +msgstr "" + +#: wp-admin/includes/continents-cities.php:106 +msgid "Dawson Creek" +msgstr "" + +#: wp-admin/includes/continents-cities.php:107 +msgid "Denver" +msgstr "" + +#: wp-admin/includes/continents-cities.php:108 +msgid "Detroit" +msgstr "" + +#: wp-admin/includes/continents-cities.php:109 +msgid "Dominica" +msgstr "Dominique" + +#: wp-admin/includes/continents-cities.php:110 +msgid "Edmonton" +msgstr "" + +#: wp-admin/includes/continents-cities.php:111 +msgid "Eirunepe" +msgstr "Eirunepé" + +#: wp-admin/includes/continents-cities.php:112 +msgid "El Salvador" +msgstr "Salvador" + +#: wp-admin/includes/continents-cities.php:113 +msgid "Ensenada" +msgstr "" + +#: wp-admin/includes/continents-cities.php:114 +msgid "Fort Wayne" +msgstr "" + +#: wp-admin/includes/continents-cities.php:115 +msgid "Fortaleza" +msgstr "" + +#: wp-admin/includes/continents-cities.php:116 +#, fuzzy +msgid "Glace Bay" +msgstr "Ikaluktutiak" + +#: wp-admin/includes/continents-cities.php:117 +msgid "Godthab" +msgstr "Nuuk (GodthÃ¥b)" + +#: wp-admin/includes/continents-cities.php:118 +#, fuzzy +msgid "Goose Bay" +msgstr "Ikaluktutiak" + +#: wp-admin/includes/continents-cities.php:119 +msgid "Grand Turk" +msgstr "" + +#: wp-admin/includes/continents-cities.php:120 +msgid "Grenada" +msgstr "Grenade" + +#: wp-admin/includes/continents-cities.php:121 +msgid "Guadeloupe" +msgstr "" + +#: wp-admin/includes/continents-cities.php:122 +msgid "Guatemala" +msgstr "" + +#: wp-admin/includes/continents-cities.php:123 +msgid "Guayaquil" +msgstr "" + +#: wp-admin/includes/continents-cities.php:124 +msgid "Guyana" +msgstr "Guyane" + +#: wp-admin/includes/continents-cities.php:125 +msgid "Halifax" +msgstr "" + +#: wp-admin/includes/continents-cities.php:126 +msgid "Havana" +msgstr "La Havane" + +#: wp-admin/includes/continents-cities.php:127 +msgid "Hermosillo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:128 +msgid "Indiana" +msgstr "" + +#: wp-admin/includes/continents-cities.php:129 +msgid "Indianapolis" +msgstr "" + +#: wp-admin/includes/continents-cities.php:130 +#, fuzzy +msgid "Knox" +msgstr "Knox (Indiana)" + +#: wp-admin/includes/continents-cities.php:131 +msgid "Marengo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:132 +msgid "Petersburg" +msgstr "" + +#: wp-admin/includes/continents-cities.php:133 +#, fuzzy +msgid "Tell City" +msgstr "Ville/Localité" + +#: wp-admin/includes/continents-cities.php:134 +msgid "Vevay" +msgstr "" + +#: wp-admin/includes/continents-cities.php:135 +msgid "Vincennes" +msgstr "" + +#: wp-admin/includes/continents-cities.php:136 +msgid "Winamac" +msgstr "" + +#: wp-admin/includes/continents-cities.php:137 +msgid "Inuvik" +msgstr "" + +#: wp-admin/includes/continents-cities.php:138 +msgid "Iqaluit" +msgstr "" + +#: wp-admin/includes/continents-cities.php:139 +msgid "Jamaica" +msgstr "Jamaïque" + +#: wp-admin/includes/continents-cities.php:140 +msgid "Juneau" +msgstr "" + +#: wp-admin/includes/continents-cities.php:141 +msgid "Kentucky" +msgstr "" + +#: wp-admin/includes/continents-cities.php:142 +msgid "Louisville" +msgstr "" + +#: wp-admin/includes/continents-cities.php:143 +msgid "Monticello" +msgstr "" + +#: wp-admin/includes/continents-cities.php:144 +msgid "Knox IN" +msgstr "Knox (Indiana)" + +#: wp-admin/includes/continents-cities.php:145 +msgid "La Paz" +msgstr "" + +#: wp-admin/includes/continents-cities.php:146 +msgid "Lima" +msgstr "" + +#: wp-admin/includes/continents-cities.php:147 +msgid "Los Angeles" +msgstr "" + +#: wp-admin/includes/continents-cities.php:148 +msgid "Maceio" +msgstr "Maceió" + +#: wp-admin/includes/continents-cities.php:149 +msgid "Managua" +msgstr "" + +#: wp-admin/includes/continents-cities.php:150 +msgid "Manaus" +msgstr "" + +#: wp-admin/includes/continents-cities.php:151 +msgid "Marigot" +msgstr "" + +#: wp-admin/includes/continents-cities.php:152 +msgid "Martinique" +msgstr "" + +#: wp-admin/includes/continents-cities.php:153 +msgid "Mazatlan" +msgstr "" + +#: wp-admin/includes/continents-cities.php:154 +msgid "Menominee" +msgstr "" + +#: wp-admin/includes/continents-cities.php:155 +msgid "Merida" +msgstr "" + +#: wp-admin/includes/continents-cities.php:156 +msgid "Mexico City" +msgstr "Mexico" + +#: wp-admin/includes/continents-cities.php:157 +msgid "Miquelon" +msgstr "" + +#: wp-admin/includes/continents-cities.php:158 +msgid "Moncton" +msgstr "" + +#: wp-admin/includes/continents-cities.php:159 +msgid "Monterrey" +msgstr "" + +#: wp-admin/includes/continents-cities.php:160 +msgid "Montevideo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:161 +msgid "Montreal" +msgstr "Montréal" + +#: wp-admin/includes/continents-cities.php:162 +msgid "Montserrat" +msgstr "" + +#: wp-admin/includes/continents-cities.php:163 +msgid "Nassau" +msgstr "" + +#: wp-admin/includes/continents-cities.php:164 +#, fuzzy +msgid "New York" +msgstr "%d nouveau courrier." + +#: wp-admin/includes/continents-cities.php:165 +msgid "Nipigon" +msgstr "" + +#: wp-admin/includes/continents-cities.php:166 +msgid "Nome" +msgstr "" + +#: wp-admin/includes/continents-cities.php:167 +msgid "Noronha" +msgstr "" + +#: wp-admin/includes/continents-cities.php:168 +msgid "North Dakota" +msgstr "Dakota du Nord" + +#: wp-admin/includes/continents-cities.php:169 +#, fuzzy +msgid "Center" +msgstr "Centre" + +#: wp-admin/includes/continents-cities.php:170 +#, fuzzy +msgid "New Salem" +msgstr "%d nouveau courrier." + +#: wp-admin/includes/continents-cities.php:171 +msgid "Panama" +msgstr "" + +#: wp-admin/includes/continents-cities.php:172 +msgid "Pangnirtung" +msgstr "" + +#: wp-admin/includes/continents-cities.php:173 +msgid "Paramaribo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:174 +msgid "Phoenix" +msgstr "" + +#: wp-admin/includes/continents-cities.php:175 +#, fuzzy +msgid "Port-au-Prince" +msgstr "Port de transfert de fichiers" + +#: wp-admin/includes/continents-cities.php:176 +msgid "Port of Spain" +msgstr "Port-d'Espagne" + +#: wp-admin/includes/continents-cities.php:177 +msgid "Porto Acre" +msgstr "" + +#: wp-admin/includes/continents-cities.php:178 +msgid "Porto Velho" +msgstr "" + +#: wp-admin/includes/continents-cities.php:179 +msgid "Puerto Rico" +msgstr "Porto Rico" + +#: wp-admin/includes/continents-cities.php:180 +msgid "Rainy River" +msgstr "" + +#: wp-admin/includes/continents-cities.php:181 +msgid "Rankin Inlet" +msgstr "Kangiqtiniq (Rankin Inlet)" + +#: wp-admin/includes/continents-cities.php:182 +msgid "Recife" +msgstr "" + +#: wp-admin/includes/continents-cities.php:183 +msgid "Regina" +msgstr "" + +#: wp-admin/includes/continents-cities.php:184 +msgid "Resolute" +msgstr "" + +#: wp-admin/includes/continents-cities.php:185 +#, fuzzy +msgid "Rio Branco" +msgstr "Rio Gallegos" + +#: wp-admin/includes/continents-cities.php:186 +msgid "Rosario" +msgstr "" + +#: wp-admin/includes/continents-cities.php:187 +msgid "Santiago" +msgstr "Santiago du Chili" + +#: wp-admin/includes/continents-cities.php:188 +msgid "Santo Domingo" +msgstr "Saint-Domingue" + +#: wp-admin/includes/continents-cities.php:189 +msgid "Sao Paulo" +msgstr "São Paulo" + +#: wp-admin/includes/continents-cities.php:190 +msgid "Scoresbysund" +msgstr "Ittoqqortoormiit (Scoresbysund)" + +#: wp-admin/includes/continents-cities.php:191 +msgid "Shiprock" +msgstr "" + +#: wp-admin/includes/continents-cities.php:192 +msgid "St Barthelemy" +msgstr "Saint-Barthélemy" + +#: wp-admin/includes/continents-cities.php:193 +msgid "St Johns" +msgstr "Saint John's" + +#: wp-admin/includes/continents-cities.php:194 +msgid "St Kitts" +msgstr "ÃŽle Saint-Christophe" + +#: wp-admin/includes/continents-cities.php:195 +msgid "St Lucia" +msgstr "Sainte-Lucie" + +#: wp-admin/includes/continents-cities.php:196 +msgid "St Thomas" +msgstr "Saint Thomas" + +#: wp-admin/includes/continents-cities.php:197 +msgid "St Vincent" +msgstr "Saint Vincent" + +#: wp-admin/includes/continents-cities.php:198 +#, fuzzy +msgid "Swift Current" +msgstr "Codeurs" + +#: wp-admin/includes/continents-cities.php:199 +msgid "Tegucigalpa" +msgstr "" + +#: wp-admin/includes/continents-cities.php:200 +msgid "Thule" +msgstr "" + +#: wp-admin/includes/continents-cities.php:201 +#, fuzzy +msgid "Thunder Bay" +msgstr "Ikaluktutiak" + +#: wp-admin/includes/continents-cities.php:202 +msgid "Tijuana" +msgstr "" + +#: wp-admin/includes/continents-cities.php:203 +msgid "Toronto" +msgstr "" + +#: wp-admin/includes/continents-cities.php:204 +msgid "Tortola" +msgstr "" + +#: wp-admin/includes/continents-cities.php:205 +msgid "Vancouver" +msgstr "" + +#: wp-admin/includes/continents-cities.php:206 +msgid "Virgin" +msgstr "" + +#: wp-admin/includes/continents-cities.php:207 +msgid "Whitehorse" +msgstr "" + +#: wp-admin/includes/continents-cities.php:208 +msgid "Winnipeg" +msgstr "" + +#: wp-admin/includes/continents-cities.php:209 +msgid "Yakutat" +msgstr "" + +#: wp-admin/includes/continents-cities.php:210 +msgid "Yellowknife" +msgstr "" + +#: wp-admin/includes/continents-cities.php:211 +msgid "Antarctica" +msgstr "Antartique" + +#: wp-admin/includes/continents-cities.php:212 +msgid "Casey" +msgstr "" + +#: wp-admin/includes/continents-cities.php:213 +msgid "Davis" +msgstr "" + +#: wp-admin/includes/continents-cities.php:214 +msgid "DumontDUrville" +msgstr "Dumont d'Urville" + +#: wp-admin/includes/continents-cities.php:215 +msgid "Mawson" +msgstr "" + +#: wp-admin/includes/continents-cities.php:216 +msgid "McMurdo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:217 +msgid "Palmer" +msgstr "" + +#: wp-admin/includes/continents-cities.php:218 +msgid "Rothera" +msgstr "" + +#: wp-admin/includes/continents-cities.php:219 +msgid "South Pole" +msgstr "Pôle Sud" + +#: wp-admin/includes/continents-cities.php:220 +msgid "Syowa" +msgstr "" + +#: wp-admin/includes/continents-cities.php:221 +msgid "Vostok" +msgstr "" + +#: wp-admin/includes/continents-cities.php:222 +msgid "Arctic" +msgstr "Arctique" + +#: wp-admin/includes/continents-cities.php:223 +msgid "Longyearbyen" +msgstr "" + +#: wp-admin/includes/continents-cities.php:224 +msgid "Asia" +msgstr "Asie" + +#: wp-admin/includes/continents-cities.php:225 +msgid "Aden" +msgstr "" + +#: wp-admin/includes/continents-cities.php:226 +msgid "Almaty" +msgstr "" + +#: wp-admin/includes/continents-cities.php:227 +msgid "Amman" +msgstr "" + +#: wp-admin/includes/continents-cities.php:228 +msgid "Anadyr" +msgstr "" + +#: wp-admin/includes/continents-cities.php:229 +msgid "Aqtau" +msgstr "Aqtou" + +#: wp-admin/includes/continents-cities.php:230 +msgid "Aqtobe" +msgstr "Aktioubé" + +#: wp-admin/includes/continents-cities.php:231 +msgid "Ashgabat" +msgstr "Achgabat" + +#: wp-admin/includes/continents-cities.php:232 +msgid "Ashkhabad" +msgstr "Achgabat" + +#: wp-admin/includes/continents-cities.php:233 +msgid "Baghdad" +msgstr "Bagdad" + +#: wp-admin/includes/continents-cities.php:234 +msgid "Bahrain" +msgstr "Bahreïn" + +#: wp-admin/includes/continents-cities.php:235 +msgid "Baku" +msgstr "Bakou" + +#: wp-admin/includes/continents-cities.php:236 +msgid "Bangkok" +msgstr "" + +#: wp-admin/includes/continents-cities.php:237 +msgid "Beirut" +msgstr "Beyrouth" + +#: wp-admin/includes/continents-cities.php:238 +msgid "Bishkek" +msgstr "Bichkek" + +#: wp-admin/includes/continents-cities.php:239 +msgid "Brunei" +msgstr "" + +#: wp-admin/includes/continents-cities.php:240 +msgid "Calcutta" +msgstr "" + +#: wp-admin/includes/continents-cities.php:241 +msgid "Choibalsan" +msgstr "Choybalsan" + +#: wp-admin/includes/continents-cities.php:242 +msgid "Chongqing" +msgstr "" + +#: wp-admin/includes/continents-cities.php:243 +msgid "Chungking" +msgstr "" + +#: wp-admin/includes/continents-cities.php:244 +msgid "Colombo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:245 +msgid "Dacca" +msgstr "Dhâkâ (Dacca)" + +#: wp-admin/includes/continents-cities.php:246 +msgid "Damascus" +msgstr "Damas" + +#: wp-admin/includes/continents-cities.php:247 +msgid "Dhaka" +msgstr "Dhâkâ (Dacca)" + +#: wp-admin/includes/continents-cities.php:248 +msgid "Dili" +msgstr "" + +#: wp-admin/includes/continents-cities.php:249 +msgid "Dubai" +msgstr "Dubaï" + +#: wp-admin/includes/continents-cities.php:250 +msgid "Dushanbe" +msgstr "Douchanbé" + +#: wp-admin/includes/continents-cities.php:251 +msgid "Gaza" +msgstr "" + +#: wp-admin/includes/continents-cities.php:252 +msgid "Harbin" +msgstr "" + +#: wp-admin/includes/continents-cities.php:253 +msgid "Ho Chi Minh" +msgstr "Hô-Chi-Minh-Ville" + +#: wp-admin/includes/continents-cities.php:254 +#, fuzzy +msgid "Hong Kong" +msgstr "Chinois de Hong-Kong" + +#: wp-admin/includes/continents-cities.php:255 +msgid "Hovd" +msgstr "" + +#: wp-admin/includes/continents-cities.php:256 +msgid "Irkutsk" +msgstr "Irkoutsk" + +#: wp-admin/includes/continents-cities.php:257 +msgid "Istanbul" +msgstr "" + +#: wp-admin/includes/continents-cities.php:258 +msgid "Jakarta" +msgstr "" + +#: wp-admin/includes/continents-cities.php:259 +msgid "Jayapura" +msgstr "" + +#: wp-admin/includes/continents-cities.php:260 +msgid "Jerusalem" +msgstr "Jérusalem" + +#: wp-admin/includes/continents-cities.php:261 +msgid "Kabul" +msgstr "Kaboul" + +#: wp-admin/includes/continents-cities.php:262 +msgid "Kamchatka" +msgstr "Kamtchatka" + +#: wp-admin/includes/continents-cities.php:263 +msgid "Karachi" +msgstr "" + +#: wp-admin/includes/continents-cities.php:264 +msgid "Kashgar" +msgstr "Kachgar" + +#: wp-admin/includes/continents-cities.php:265 +msgid "Katmandu" +msgstr "Katmandou" + +#: wp-admin/includes/continents-cities.php:266 +msgid "Kolkata" +msgstr "Calcutta" + +#: wp-admin/includes/continents-cities.php:267 +msgid "Krasnoyarsk" +msgstr "Krasnoïarsk" + +#: wp-admin/includes/continents-cities.php:268 +msgid "Kuala Lumpur" +msgstr "" + +#: wp-admin/includes/continents-cities.php:269 +msgid "Kuching" +msgstr "" + +#: wp-admin/includes/continents-cities.php:270 +msgid "Kuwait" +msgstr "Koweït" + +#: wp-admin/includes/continents-cities.php:271 +msgid "Macao" +msgstr "" + +#: wp-admin/includes/continents-cities.php:272 +msgid "Macau" +msgstr "Macao" + +#: wp-admin/includes/continents-cities.php:273 +msgid "Magadan" +msgstr "" + +#: wp-admin/includes/continents-cities.php:274 +msgid "Makassar" +msgstr "" + +#: wp-admin/includes/continents-cities.php:275 +msgid "Manila" +msgstr "Manille" + +#: wp-admin/includes/continents-cities.php:276 +msgid "Muscat" +msgstr "Mascate" + +#: wp-admin/includes/continents-cities.php:277 +msgid "Nicosia" +msgstr "Nicosie" + +#: wp-admin/includes/continents-cities.php:278 +msgid "Novosibirsk" +msgstr "Novossibirsk" + +#: wp-admin/includes/continents-cities.php:279 +msgid "Omsk" +msgstr "" + +#: wp-admin/includes/continents-cities.php:280 +msgid "Oral" +msgstr "Oural" + +#: wp-admin/includes/continents-cities.php:281 +msgid "Phnom Penh" +msgstr "" + +#: wp-admin/includes/continents-cities.php:282 +msgid "Pontianak" +msgstr "" + +#: wp-admin/includes/continents-cities.php:283 +msgid "Pyongyang" +msgstr "" + +#: wp-admin/includes/continents-cities.php:284 +msgid "Qatar" +msgstr "" + +#: wp-admin/includes/continents-cities.php:285 +msgid "Qyzylorda" +msgstr "Kyzylorda" + +#: wp-admin/includes/continents-cities.php:286 +msgid "Rangoon" +msgstr "" + +#: wp-admin/includes/continents-cities.php:287 +msgid "Riyadh" +msgstr "Riyad" + +#: wp-admin/includes/continents-cities.php:288 +msgid "Saigon" +msgstr "Hô-Chi-Minh-Ville (Saigon)" + +#: wp-admin/includes/continents-cities.php:289 +msgid "Sakhalin" +msgstr "Sakhaline" + +#: wp-admin/includes/continents-cities.php:290 +msgid "Samarkand" +msgstr "Samarcande" + +#: wp-admin/includes/continents-cities.php:291 +msgid "Seoul" +msgstr "Séoul" + +#: wp-admin/includes/continents-cities.php:292 +msgid "Shanghai" +msgstr "" + +#: wp-admin/includes/continents-cities.php:293 +msgid "Singapore" +msgstr "Singapour" + +#: wp-admin/includes/continents-cities.php:294 +msgid "Taipei" +msgstr "" + +#: wp-admin/includes/continents-cities.php:295 +msgid "Tashkent" +msgstr "Tachkent" + +#: wp-admin/includes/continents-cities.php:296 +msgid "Tbilisi" +msgstr "Tbilissi" + +#: wp-admin/includes/continents-cities.php:297 +msgid "Tehran" +msgstr "Téhéran" + +#: wp-admin/includes/continents-cities.php:298 +msgid "Tel Aviv" +msgstr "Tel Aviv-Jaffa" + +#: wp-admin/includes/continents-cities.php:299 +msgid "Thimbu" +msgstr "Thimphou" + +#: wp-admin/includes/continents-cities.php:300 +msgid "Thimphu" +msgstr "Thimphou" + +#: wp-admin/includes/continents-cities.php:301 +msgid "Tokyo" +msgstr "TÅkyÅ" + +#: wp-admin/includes/continents-cities.php:302 +msgid "Ujung Pandang" +msgstr "Makassar (Ujung Pandang)" + +#: wp-admin/includes/continents-cities.php:303 +msgid "Ulaanbaatar" +msgstr "Oulan-Bator (Ulaanbaatar)" + +#: wp-admin/includes/continents-cities.php:304 +msgid "Ulan Bator" +msgstr "Oulan-Bator (Ulaanbaatar)" + +#: wp-admin/includes/continents-cities.php:305 +msgid "Urumqi" +msgstr "Ürümqi" + +#: wp-admin/includes/continents-cities.php:306 +msgid "Vientiane" +msgstr "" + +#: wp-admin/includes/continents-cities.php:307 +msgid "Vladivostok" +msgstr "" + +#: wp-admin/includes/continents-cities.php:308 +msgid "Yakutsk" +msgstr "Iakoutsk" + +#: wp-admin/includes/continents-cities.php:309 +msgid "Yekaterinburg" +msgstr "Iekaterinbourg" + +#: wp-admin/includes/continents-cities.php:310 +msgid "Yerevan" +msgstr "Yerevan (Erevan)" + +#: wp-admin/includes/continents-cities.php:311 +msgid "Atlantic" +msgstr "Atlantique" + +#: wp-admin/includes/continents-cities.php:312 +msgid "Azores" +msgstr "Açores" + +#: wp-admin/includes/continents-cities.php:313 +msgid "Bermuda" +msgstr "Bermudes" + +#: wp-admin/includes/continents-cities.php:314 +msgid "Canary" +msgstr "ÃŽles Canaries" + +#: wp-admin/includes/continents-cities.php:315 +msgid "Cape Verde" +msgstr "Cap-Vert" + +#: wp-admin/includes/continents-cities.php:316 +msgid "Faeroe" +msgstr "ÃŽles Féroé" + +#: wp-admin/includes/continents-cities.php:317 +msgid "Faroe" +msgstr "ÃŽles Féroé" + +#: wp-admin/includes/continents-cities.php:318 +msgid "Jan Mayen" +msgstr "ÃŽle Jan Mayen" + +#: wp-admin/includes/continents-cities.php:319 +msgid "Madeira" +msgstr "Madère" + +#: wp-admin/includes/continents-cities.php:320 +msgid "Reykjavik" +msgstr "Reykjavík" + +#: wp-admin/includes/continents-cities.php:321 +msgid "South Georgia" +msgstr "ÃŽle de Géorgie du Sud" + +#: wp-admin/includes/continents-cities.php:322 +msgid "St Helena" +msgstr "Sainte-Hélène" + +#: wp-admin/includes/continents-cities.php:323 +msgid "Stanley" +msgstr "" + +#: wp-admin/includes/continents-cities.php:324 +msgid "Australia" +msgstr "Australie" + +#: wp-admin/includes/continents-cities.php:325 +msgid "ACT" +msgstr "Territoire de la capitale australienne (ACT)" + +#: wp-admin/includes/continents-cities.php:326 +msgid "Adelaide" +msgstr "Adélaïde" + +#: wp-admin/includes/continents-cities.php:327 +msgid "Brisbane" +msgstr "" + +#: wp-admin/includes/continents-cities.php:328 +#, fuzzy +msgid "Broken Hill" +msgstr "Thèmes endommagés" + +#: wp-admin/includes/continents-cities.php:329 +msgid "Canberra" +msgstr "" + +#: wp-admin/includes/continents-cities.php:330 +msgid "Currie" +msgstr "" + +#: wp-admin/includes/continents-cities.php:331 +msgid "Darwin" +msgstr "" + +#: wp-admin/includes/continents-cities.php:332 +msgid "Eucla" +msgstr "" + +#: wp-admin/includes/continents-cities.php:333 +msgid "Hobart" +msgstr "" + +#: wp-admin/includes/continents-cities.php:334 +msgid "LHI" +msgstr "ÃŽle Lord Howe (LHI)" + +#: wp-admin/includes/continents-cities.php:335 +msgid "Lindeman" +msgstr "" + +#: wp-admin/includes/continents-cities.php:336 +msgid "Lord Howe" +msgstr "ÃŽle Lord Howe (LHI)" + +#: wp-admin/includes/continents-cities.php:337 +msgid "Melbourne" +msgstr "" + +#: wp-admin/includes/continents-cities.php:338 +msgid "North" +msgstr "Nord" + +#: wp-admin/includes/continents-cities.php:339 +msgid "NSW" +msgstr "Nouvelle-Galles du Sud (NSW)" + +#: wp-admin/includes/continents-cities.php:340 +msgid "Perth" +msgstr "" + +#: wp-admin/includes/continents-cities.php:341 +msgid "Queensland" +msgstr "" + +#: wp-admin/includes/continents-cities.php:342 +msgid "South" +msgstr "Sud" + +#: wp-admin/includes/continents-cities.php:343 +msgid "Sydney" +msgstr "" + +#: wp-admin/includes/continents-cities.php:344 +msgid "Tasmania" +msgstr "Tasmanie" + +#: wp-admin/includes/continents-cities.php:345 +msgid "Victoria" +msgstr "" + +#: wp-admin/includes/continents-cities.php:346 +msgid "West" +msgstr "Ouest" + +#: wp-admin/includes/continents-cities.php:347 +msgid "Yancowinna" +msgstr "" + +#: wp-admin/includes/continents-cities.php:348 +msgid "Etc" +msgstr "Etc." + +#: wp-admin/includes/continents-cities.php:349 +msgid "GMT" +msgstr "UTC" + +#: wp-admin/includes/continents-cities.php:350 +msgid "GMT+0" +msgstr "UTC+0" + +#: wp-admin/includes/continents-cities.php:351 +msgid "GMT+1" +msgstr "UTC+1" + +#: wp-admin/includes/continents-cities.php:352 +msgid "GMT+10" +msgstr "UTC+10" + +#: wp-admin/includes/continents-cities.php:353 +msgid "GMT+11" +msgstr "UTC+11" + +#: wp-admin/includes/continents-cities.php:354 +msgid "GMT+12" +msgstr "UTC+12" + +#: wp-admin/includes/continents-cities.php:355 +msgid "GMT+2" +msgstr "UTC+2" + +#: wp-admin/includes/continents-cities.php:356 +msgid "GMT+3" +msgstr "UTC+3" + +#: wp-admin/includes/continents-cities.php:357 +msgid "GMT+4" +msgstr "UTC+4" + +#: wp-admin/includes/continents-cities.php:358 +msgid "GMT+5" +msgstr "UTC+5" + +#: wp-admin/includes/continents-cities.php:359 +msgid "GMT+6" +msgstr "UTC+6" + +#: wp-admin/includes/continents-cities.php:360 +msgid "GMT+7" +msgstr "UTC+7" + +#: wp-admin/includes/continents-cities.php:361 +msgid "GMT+8" +msgstr "UTC+8" + +#: wp-admin/includes/continents-cities.php:362 +msgid "GMT+9" +msgstr "UTC+9" + +#: wp-admin/includes/continents-cities.php:363 +msgid "GMT-0" +msgstr "UTC-0" + +#: wp-admin/includes/continents-cities.php:364 +msgid "GMT-1" +msgstr "UTC-1" + +#: wp-admin/includes/continents-cities.php:365 +msgid "GMT-10" +msgstr "UTC-10" + +#: wp-admin/includes/continents-cities.php:366 +msgid "GMT-11" +msgstr "UTC-11" + +#: wp-admin/includes/continents-cities.php:367 +msgid "GMT-12" +msgstr "UTC-12" + +#: wp-admin/includes/continents-cities.php:368 +msgid "GMT-13" +msgstr "UTC-13" + +#: wp-admin/includes/continents-cities.php:369 +msgid "GMT-14" +msgstr "UTC-14" + +#: wp-admin/includes/continents-cities.php:370 +msgid "GMT-2" +msgstr "UTC-2" + +#: wp-admin/includes/continents-cities.php:371 +msgid "GMT-3" +msgstr "UTC-3" + +#: wp-admin/includes/continents-cities.php:372 +msgid "GMT-4" +msgstr "UTC-4" + +#: wp-admin/includes/continents-cities.php:373 +msgid "GMT-5" +msgstr "UTC-5" + +#: wp-admin/includes/continents-cities.php:374 +msgid "GMT-6" +msgstr "UTC-6" + +#: wp-admin/includes/continents-cities.php:375 +msgid "GMT-7" +msgstr "UTC-7" + +#: wp-admin/includes/continents-cities.php:376 +msgid "GMT-8" +msgstr "UTC-8" + +#: wp-admin/includes/continents-cities.php:377 +msgid "GMT-9" +msgstr "UTC-9" + +#: wp-admin/includes/continents-cities.php:378 +msgid "GMT0" +msgstr "UTC0" + +#: wp-admin/includes/continents-cities.php:379 +msgid "Greenwich" +msgstr "" + +#: wp-admin/includes/continents-cities.php:380 +msgid "UCT" +msgstr "UTC" + +#: wp-admin/includes/continents-cities.php:381 +msgid "Universal" +msgstr "Universel" + +#: wp-admin/includes/continents-cities.php:382 +#, fuzzy +msgid "UTC" +msgstr "UTC" + +#: wp-admin/includes/continents-cities.php:383 +msgid "Zulu" +msgstr "" + +#: wp-admin/includes/continents-cities.php:384 +msgid "Europe" +msgstr "" + +#: wp-admin/includes/continents-cities.php:385 +msgid "Amsterdam" +msgstr "" + +#: wp-admin/includes/continents-cities.php:386 +msgid "Andorra" +msgstr "Andorre" + +#: wp-admin/includes/continents-cities.php:387 +msgid "Athens" +msgstr "Athènes" + +#: wp-admin/includes/continents-cities.php:388 +msgid "Belfast" +msgstr "" + +#: wp-admin/includes/continents-cities.php:389 +msgid "Belgrade" +msgstr "" + +#: wp-admin/includes/continents-cities.php:390 +msgid "Berlin" +msgstr "" + +#: wp-admin/includes/continents-cities.php:391 +msgid "Bratislava" +msgstr "" + +#: wp-admin/includes/continents-cities.php:392 +msgid "Brussels" +msgstr "Bruxelles" + +#: wp-admin/includes/continents-cities.php:393 +msgid "Bucharest" +msgstr "Bucarest" + +#: wp-admin/includes/continents-cities.php:394 +msgid "Budapest" +msgstr "" + +#: wp-admin/includes/continents-cities.php:395 +msgid "Chisinau" +msgstr "ChiÅŸinău (Kichinev)" + +#: wp-admin/includes/continents-cities.php:396 +msgid "Copenhagen" +msgstr "Copenhague" + +#: wp-admin/includes/continents-cities.php:397 +msgid "Dublin" +msgstr "" + +#: wp-admin/includes/continents-cities.php:398 +msgid "Gibraltar" +msgstr "" + +#: wp-admin/includes/continents-cities.php:399 +msgid "Guernsey" +msgstr "" + +#: wp-admin/includes/continents-cities.php:400 +msgid "Helsinki" +msgstr "" + +#: wp-admin/includes/continents-cities.php:401 +msgid "Isle of Man" +msgstr "ÃŽle de Man" + +#: wp-admin/includes/continents-cities.php:402 +msgid "Jersey" +msgstr "" + +#: wp-admin/includes/continents-cities.php:403 +msgid "Kaliningrad" +msgstr "" + +#: wp-admin/includes/continents-cities.php:404 +msgid "Kiev" +msgstr "" + +#: wp-admin/includes/continents-cities.php:405 +msgid "Lisbon" +msgstr "Lisbonne" + +#: wp-admin/includes/continents-cities.php:406 +msgid "Ljubljana" +msgstr "" + +#: wp-admin/includes/continents-cities.php:407 +msgid "London" +msgstr "Londres" + +#: wp-admin/includes/continents-cities.php:408 +msgid "Luxembourg" +msgstr "" + +#: wp-admin/includes/continents-cities.php:409 +msgid "Madrid" +msgstr "" + +#: wp-admin/includes/continents-cities.php:410 +msgid "Malta" +msgstr "Malte" + +#: wp-admin/includes/continents-cities.php:411 +msgid "Mariehamn" +msgstr "" + +#: wp-admin/includes/continents-cities.php:412 +msgid "Minsk" +msgstr "" + +#: wp-admin/includes/continents-cities.php:413 +msgid "Monaco" +msgstr "" + +#: wp-admin/includes/continents-cities.php:414 +msgid "Moscow" +msgstr "Moscou" + +#: wp-admin/includes/continents-cities.php:415 +msgid "Oslo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:416 +msgid "Paris" +msgstr "" + +#: wp-admin/includes/continents-cities.php:417 +msgid "Podgorica" +msgstr "" + +#: wp-admin/includes/continents-cities.php:418 +msgid "Prague" +msgstr "" + +#: wp-admin/includes/continents-cities.php:419 +msgid "Riga" +msgstr "" + +#: wp-admin/includes/continents-cities.php:420 +msgid "Rome" +msgstr "" + +#: wp-admin/includes/continents-cities.php:421 +msgid "Samara" +msgstr "" + +#: wp-admin/includes/continents-cities.php:422 +msgid "San Marino" +msgstr "Saint-Marin" + +#: wp-admin/includes/continents-cities.php:423 +msgid "Sarajevo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:424 +msgid "Simferopol" +msgstr "" + +#: wp-admin/includes/continents-cities.php:425 +msgid "Skopje" +msgstr "" + +#: wp-admin/includes/continents-cities.php:426 +msgid "Sofia" +msgstr "" + +#: wp-admin/includes/continents-cities.php:427 +msgid "Stockholm" +msgstr "" + +#: wp-admin/includes/continents-cities.php:428 +msgid "Tallinn" +msgstr "" + +#: wp-admin/includes/continents-cities.php:429 +msgid "Tirane" +msgstr "Tirana" + +#: wp-admin/includes/continents-cities.php:430 +msgid "Tiraspol" +msgstr "" + +#: wp-admin/includes/continents-cities.php:431 +msgid "Uzhgorod" +msgstr "Oujhorod (Uzhgorod)" + +#: wp-admin/includes/continents-cities.php:432 +msgid "Vaduz" +msgstr "" + +#: wp-admin/includes/continents-cities.php:433 +msgid "Vatican" +msgstr "" + +#: wp-admin/includes/continents-cities.php:434 +msgid "Vienna" +msgstr "Vienne" + +#: wp-admin/includes/continents-cities.php:435 +msgid "Vilnius" +msgstr "" + +#: wp-admin/includes/continents-cities.php:436 +msgid "Volgograd" +msgstr "" + +#: wp-admin/includes/continents-cities.php:437 +msgid "Warsaw" +msgstr "Varsovie" + +#: wp-admin/includes/continents-cities.php:438 +msgid "Zagreb" +msgstr "" + +#: wp-admin/includes/continents-cities.php:439 +msgid "Zaporozhye" +msgstr "Zaporojie" + +#: wp-admin/includes/continents-cities.php:440 +msgid "Zurich" +msgstr "" + +#: wp-admin/includes/continents-cities.php:441 +msgid "Indian" +msgstr "Océan Indien" + +#: wp-admin/includes/continents-cities.php:442 +msgid "Antananarivo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:443 +msgid "Chagos" +msgstr "Archipel des Chagos" + +#: wp-admin/includes/continents-cities.php:444 +msgid "Christmas" +msgstr "ÃŽle Christmas" + +#: wp-admin/includes/continents-cities.php:445 +msgid "Cocos" +msgstr "ÃŽles Cocos" + +#: wp-admin/includes/continents-cities.php:446 +msgid "Comoro" +msgstr "Archipel des Comores" + +#: wp-admin/includes/continents-cities.php:447 +msgid "Kerguelen" +msgstr "ÃŽles Kerguelen" + +#: wp-admin/includes/continents-cities.php:448 +msgid "Mahe" +msgstr "Mahé" + +#: wp-admin/includes/continents-cities.php:449 +msgid "Maldives" +msgstr "" + +#: wp-admin/includes/continents-cities.php:450 +msgid "Mauritius" +msgstr "ÃŽle Maurice" + +#: wp-admin/includes/continents-cities.php:451 +msgid "Mayotte" +msgstr "Mayotte" + +#: wp-admin/includes/continents-cities.php:452 +msgid "Reunion" +msgstr "ÃŽle de la Réunion" + +#: wp-admin/includes/continents-cities.php:453 +msgid "Pacific" +msgstr "Océan Pacifique" + +#: wp-admin/includes/continents-cities.php:454 +msgid "Apia" +msgstr "" + +#: wp-admin/includes/continents-cities.php:455 +msgid "Auckland" +msgstr "" + +#: wp-admin/includes/continents-cities.php:456 +msgid "Chatham" +msgstr "ÃŽles Chatham" + +#: wp-admin/includes/continents-cities.php:457 +msgid "Easter" +msgstr "ÃŽle de Pâques" + +#: wp-admin/includes/continents-cities.php:458 +msgid "Efate" +msgstr "Éfaté" + +#: wp-admin/includes/continents-cities.php:459 +msgid "Enderbury" +msgstr "" + +#: wp-admin/includes/continents-cities.php:460 +msgid "Fakaofo" +msgstr "" + +#: wp-admin/includes/continents-cities.php:461 +msgid "Fiji" +msgstr "Fidji" + +#: wp-admin/includes/continents-cities.php:462 +msgid "Funafuti" +msgstr "" + +#: wp-admin/includes/continents-cities.php:463 +msgid "Galapagos" +msgstr "ÃŽles Galápagos" + +#: wp-admin/includes/continents-cities.php:464 +msgid "Gambier" +msgstr "ÃŽles Gambier" + +#: wp-admin/includes/continents-cities.php:465 +msgid "Guadalcanal" +msgstr "" + +#: wp-admin/includes/continents-cities.php:466 +msgid "Guam" +msgstr "" + +#: wp-admin/includes/continents-cities.php:467 +msgid "Honolulu" +msgstr "" + +#: wp-admin/includes/continents-cities.php:468 +msgid "Johnston" +msgstr "Atoll de Johnston" + +#: wp-admin/includes/continents-cities.php:469 +msgid "Kiritimati" +msgstr "ÃŽle Christmas (Kiribati)" + +#: wp-admin/includes/continents-cities.php:470 +msgid "Kosrae" +msgstr "" + +#: wp-admin/includes/continents-cities.php:471 +msgid "Kwajalein" +msgstr "" + +#: wp-admin/includes/continents-cities.php:472 +msgid "Majuro" +msgstr "" + +#: wp-admin/includes/continents-cities.php:473 +msgid "Marquesas" +msgstr "ÃŽles Marquises" + +#: wp-admin/includes/continents-cities.php:474 +msgid "Midway" +msgstr "Atoll de Midway" + +#: wp-admin/includes/continents-cities.php:475 +msgid "Nauru" +msgstr "" + +#: wp-admin/includes/continents-cities.php:476 +msgid "Niue" +msgstr "Niué" + +#: wp-admin/includes/continents-cities.php:477 +msgid "Norfolk" +msgstr "" + +#: wp-admin/includes/continents-cities.php:478 +msgid "Noumea" +msgstr "Nouméa" + +#: wp-admin/includes/continents-cities.php:479 +msgid "Pago Pago" +msgstr "" + +#: wp-admin/includes/continents-cities.php:480 +msgid "Palau" +msgstr "Palaos" + +#: wp-admin/includes/continents-cities.php:481 +msgid "Pitcairn" +msgstr "ÃŽles Pitcairn" + +#: wp-admin/includes/continents-cities.php:482 +msgid "Ponape" +msgstr "Pohnpei (Ponape)" + +#: wp-admin/includes/continents-cities.php:483 +#, fuzzy +msgid "Port Moresby" +msgstr "Port de connexion" + +#: wp-admin/includes/continents-cities.php:484 +msgid "Rarotonga" +msgstr "" + +#: wp-admin/includes/continents-cities.php:485 +msgid "Saipan" +msgstr "" + +#: wp-admin/includes/continents-cities.php:486 +msgid "Samoa" +msgstr "" + +#: wp-admin/includes/continents-cities.php:487 +msgid "Tahiti" +msgstr "" + +#: wp-admin/includes/continents-cities.php:488 +msgid "Tarawa" +msgstr "" + +#: wp-admin/includes/continents-cities.php:489 +msgid "Tongatapu" +msgstr "" + +#: wp-admin/includes/continents-cities.php:490 +msgid "Truk" +msgstr "Chuuk (Truk)" + +#: wp-admin/includes/continents-cities.php:491 +msgid "Wake" +msgstr "ÃŽle Wake" + +#: wp-admin/includes/continents-cities.php:492 +msgid "Wallis" +msgstr "Wallis-et-Futuna" + +#: wp-admin/includes/continents-cities.php:493 +msgid "Yap" +msgstr "" diff --git a/sources/wp-content/languages/fr_FR.mo b/sources/wp-content/languages/fr_FR.mo new file mode 100644 index 0000000000000000000000000000000000000000..53d0fbf4d689fcf22ee4d40f44cdf4d7b32e8510 GIT binary patch literal 178928 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, 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: WordPress 3.7\n" +"Report-Msgid-Bugs-To: http://wppolyglots.wordpress.com\n" +"POT-Creation-Date: 2013-10-22 23:05:29+00:00\n" +"PO-Revision-Date: 2013-10-24 14:02+0100\n" +"Last-Translator: Xavier B. \n" +"Language-Team: WordPress Francophone \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n>1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-Bookmarks: -1,430,-1,-1,-1,-1,-1,-1,-1,-1\n" +"X-Generator: Poedit 1.5.7\n" + +#: wp-activate.php:73 +msgid "Activation Key Required" +msgstr "Clé d’activation requise" + +#: wp-activate.php:76 +msgid "Activation Key:" +msgstr "Clé d’activation :" + +#: wp-activate.php:80 +msgid "Activate" +msgstr "Activer" + +#: wp-activate.php:92 wp-activate.php:112 +msgid "Your account is now active!" +msgstr "Votre compte est maintenant activé !" + +#: wp-activate.php:96 +msgid "" +"Your account has been activated. You may now log in to " +"the site using your chosen username of “%2$s”. Please check your " +"email inbox at %3$s for your password and login instructions. If you do not " +"receive an email, please check your junk or spam folder. If you still do not " +"receive an email within an hour, you can reset your " +"password." +msgstr "" +"Votre compte vient d’être activé. Vous pouvez dès maintenant vous connecter à votre site en utilisant votre identifiant " +"« %2$s ». Vous trouverez dans votre messagerie (sur " +"%3$s) un message vous donnant votre mot de passe et identifiant, ainsi que " +"les instructions pour vous connecter. Si vous ne recevez pas d’e-mail, " +"pensez à consulter le dossier « spam » de votre client " +"de messagerie. Si vous ne recevez pas votre mot de passe dans moins d’" +"une heure, vous pouvez réinitialiser votre mot de passe." + +#: wp-activate.php:98 +msgid "" +"Your site at %2$s is active. You may now log in to your " +"site using your chosen username of “%3$s”. Please check your " +"email inbox at %4$s for your password and login instructions. If you do not " +"receive an email, please check your junk or spam folder. If you still do not " +"receive an email within an hour, you can reset your " +"password." +msgstr "" +"Votre site est activé à %2$s. Vous pouvez dès " +"maintenant vous connecter à ce site en utilisant l’identifiant choisi " +"« %3$s ». Vous trouverez dans votre messagerie (sur " +"%4$s) un message vous donnant votre mot de passe et identifiant, ainsi que " +"les instructions pour vous connecter. Si vous ne recevez pas d’e-mail, " +"pensez à consulter le dossier « spam » de votre client " +"de messagerie. Si vous ne recevez pas votre mot de passe dans moins d’" +"une heure, vous pouvez réinitialiser votre mot de passe." + +#: wp-activate.php:103 +msgid "An error occurred during the activation" +msgstr "Une erreur est survenue lors de l’activation" + +#: wp-activate.php:115 wp-signup.php:179 +msgid "Username:" +msgstr "Identifiant :" + +#: wp-activate.php:116 wp-includes/post-template.php:1251 +msgid "Password:" +msgstr "Mot de passe :" + +#: wp-activate.php:120 +msgid "" +"Your account is now activated. View your site or Log in" +msgstr "" +"Votre compte est maintenant activé. Consultez votre site ou connectez-vous" + +#: wp-activate.php:122 +msgid "" +"Your account is now activated. Log in or go back to the " +"homepage." +msgstr "" +"Votre compte est maintenant activé. Connectez-vous ou " +"retournez sur la page d’accueil de votre site." + +#: wp-comments-post.php:48 +msgid "Sorry, comments are closed for this item." +msgstr "Désolé, les commentaires sont fermés pour cet article." + +#: wp-comments-post.php:109 +msgid "Sorry, you must be logged in to post a comment." +msgstr "Désolé, vous devez être connecté(e) pour rédiger un commentaire." + +#: wp-comments-post.php:116 +msgid "ERROR: please fill the required fields (name, email)." +msgstr "" +"ERREUR : veuillez renseigner les champs obligatoires " +"(nom, e-mail)." + +#: wp-comments-post.php:118 +msgid "ERROR: please enter a valid email address." +msgstr "" +"ERREUR : veuillez saisir une adresse de messagerie " +"valide." + +#: wp-comments-post.php:122 +msgid "ERROR: please type a comment." +msgstr "ERREUR : veuillez saisir un commentaire." + +#: wp-content/plugins/akismet/admin.php:14 +msgid "Akismet %s requires WordPress 3.0 or higher." +msgstr "Akismet %s nécessite la version 3.0 de WordPress ou supérieure." + +#: wp-content/plugins/akismet/admin.php:14 +msgid "" +"Please upgrade WordPress to a current version, or downgrade to version 2.4 of the Akismet plugin." +msgstr "" +"Veuillez mettre à jour WordPress à la version actuelle, " +"ou restaurer la version 2.4 du plugin Akismet." + +#: wp-content/plugins/akismet/admin.php:26 +msgid "Comment History" +msgstr "Voir l’historique du commentaire" + +#: wp-content/plugins/akismet/admin.php:59 +#: wp-content/plugins/akismet/admin.php:225 +#: wp-content/plugins/akismet/admin.php:227 +msgid "Settings" +msgstr "Réglages" + +#: wp-content/plugins/akismet/admin.php:83 +#: wp-includes/class-wp-customize-manager.php:83 +#: wp-includes/script-loader.php:373 +msgid "Cheatin’ uh?" +msgstr "Alors, on triche ?" + +#: wp-content/plugins/akismet/admin.php:166 +msgid "Empty" +msgstr "Vide" + +#: wp-content/plugins/akismet/admin.php:167 +msgid "Valid" +msgstr "Valide" + +#: wp-content/plugins/akismet/admin.php:168 +msgid "Invalid" +msgstr "Invalide" + +#: wp-content/plugins/akismet/admin.php:169 +msgid "Failed" +msgstr "Échoué" + +#: wp-content/plugins/akismet/admin.php:173 +msgid "Your key has been cleared." +msgstr "Votre clé a été vidée." + +#: wp-content/plugins/akismet/admin.php:174 +msgid "" +"Your Akismet account has been successfully set up and activated. Happy " +"blogging!" +msgstr "" +"Votre compte Akismet a bien été configuré et activé. Écrivez sans " +"limites !" + +#: wp-content/plugins/akismet/admin.php:175 +msgid "The key you entered is invalid. Please double-check it." +msgstr "Votre clé ne semble pas être valide. Veuillez la vérifier." + +#: wp-content/plugins/akismet/admin.php:176 +msgid "" +"The key you entered could not be verified because a connection to akismet." +"com could not be established. Please check your server configuration." +msgstr "" +"La clé que vous avez entrée n’a pas pu être vérifiée, car la connexion " +"à akismet.com n’a pas pu être établie. Veuillez vérifier la " +"configuration de votre serveur." + +#: wp-content/plugins/akismet/admin.php:177 +msgid "" +"There was a problem connecting to the Akismet server. Please check your " +"server configuration." +msgstr "" +"Il y a eu un problème lors de la connexion au serveur Akismet. Veuillez " +"vérifier la configuration de votre serveur." + +#: wp-content/plugins/akismet/admin.php:178 +msgid "Please enter an API key" +msgstr "Veuillez saisir une clé d’API" + +#: wp-content/plugins/akismet/admin.php:179 +msgid "This key is invalid." +msgstr "Cette clé n’est pas valide." + +#: wp-content/plugins/akismet/admin.php:180 +msgid "" +"The key below was previously validated but a connection to akismet.com can " +"not be established at this time. Please check your server configuration." +msgstr "" +"La clé ci-dessous a déjà été validée, mais la connexion à akismet.com ne " +"peut être établie pour le moment. Veuillez vérifier la configuration de " +"votre serveur." + +#: wp-content/plugins/akismet/admin.php:181 +msgid "" +"Your WordPress home URL %s is invalid. Please fix the home " +"option." +msgstr "" +"L’adresse de votre accueil WordPress (%s) n’est pas valide. " +"Veuillez la corriger l’option de l’accueil." + +#: wp-content/plugins/akismet/admin.php:188 +#: wp-content/plugins/akismet/admin.php:500 +#: wp-content/plugins/akismet/admin.php:919 +#: wp-content/plugins/akismet/admin.php:922 +msgid "Akismet" +msgstr "Akismet" + +#: wp-content/plugins/akismet/admin.php:190 +msgid "Akismet Stats" +msgstr "Stats Akismet" + +#: wp-content/plugins/akismet/admin.php:193 +msgid "" +"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." +msgstr "" +"Akismet élimine les commentaires et trackbacks indésirables (spam) de votre " +"site. Pour utiliser Akismet, vous pouvez devoir vous inscrire afin d’" +"obtenir une clé d’API. Cliquez sur le bouton ci-dessous pour vous " +"lancer." + +#: wp-content/plugins/akismet/admin.php:198 +msgid "Create a new Akismet Key" +msgstr "Créer une nouvelle clé Akismet" + +#: wp-content/plugins/akismet/admin.php:201 +msgid "I already have a key" +msgstr "J’ai déjà une clé." + +#: wp-content/plugins/akismet/admin.php:205 +msgid "Settings saved." +msgstr "Réglages enregistrés." + +#: wp-content/plugins/akismet/admin.php:208 +msgid "" +"Sign up success! Please check your email for your Akismet " +"API Key and enter it below." +msgstr "" +"Vous êtes bien enregistré ! Une fois votre clé pour " +"l’API Akismet reçue, veuillez la saisir ci-dessous." + +#: wp-content/plugins/akismet/admin.php:217 +msgid "Akismet API Key" +msgstr "Clé pour l’API Akismet" + +#: wp-content/plugins/akismet/admin.php:220 +msgid "" +"You must enter a valid Akismet API key here. If you need an API key, you can " +"create one here" +msgstr "" +"Vous devez saisir ici une clé d’API Akismet valide. Si vous avez " +"besoin d’une clé d’API, vous pouvez en créer une " +"ici." + +#: wp-content/plugins/akismet/admin.php:228 +msgid "Auto-detete old spam" +msgstr "Supprimer automatiquement les anciens indésirables" + +#: wp-content/plugins/akismet/admin.php:228 +msgid "Auto-delete spam submitted on posts more than a month old." +msgstr "" +"Supprimer automatiquement les commentaires indésirables sur les articles " +"datant de plus d’un mois." + +#: wp-content/plugins/akismet/admin.php:229 +msgid "Show approved comments" +msgstr "Afficher les commentaires approuvés" + +#: wp-content/plugins/akismet/admin.php:229 +msgid "Show the number of comments you've approved beside each comment author." +msgstr "" +"Afficher le nombre de commentaires que vous avez validés à côté de chaque " +"auteur de commentaire." + +#: wp-content/plugins/akismet/admin.php:238 +msgid "Save Changes" +msgstr "Enregistrer les modifications" + +#: wp-content/plugins/akismet/admin.php:243 +msgid "Server Connectivity" +msgstr "Connectivité serveur" + +#: wp-content/plugins/akismet/admin.php:248 +msgid "Server Status" +msgstr "État du serveur" + +#: wp-content/plugins/akismet/admin.php:251 +msgid "Network functions are disabled." +msgstr "Les fonctionnalités réseau sont désactivées." + +#: wp-content/plugins/akismet/admin.php:252 +msgid "" +"Your web host or server administrator has disabled PHP's fsockopen or gethostbynamel functions. Akismet cannot work " +"correctly until this is fixed. Please contact your web host or " +"firewall administrator and give them this " +"information about Akismet's system requirements." +msgstr "" +"Votre hébergeur web ou votre administrateur système a désactivé les " +"fonctions fsockopen ou gethostbynamel de PHP. " +"Akismet ne pourra pas fonctionner correctement tant que ce problème " +"ne sera pas résolu. Veuillez contacter votre hébergeur ou votre " +"administrateur réseau avec ces informations " +"à propos des pré-requis systèmes." + +#: wp-content/plugins/akismet/admin.php:258 +msgid "Unable to reach some Akismet servers." +msgstr "Impossible d’atteindre certains serveurs d’Akismet." + +#: wp-content/plugins/akismet/admin.php:259 +msgid "" +"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 this " +"information about Akismet and firewalls." +msgstr "" +"Un problème réseau ou un pare-feu bloque une partie des connexions vers le " +"serveur d’Akismet.com. Akismet fonctionne, mais des problèmes peuvent " +"survenir en cas de congestion réseau. Veuillez contacter votre hébergeur ou " +"votre administrateur réseau avec ces " +"informations (en anglais)." + +#: wp-content/plugins/akismet/admin.php:261 +msgid "Unable to reach any Akismet servers." +msgstr "Impossible d’atteindre les serveurs d’Akismet." + +#: wp-content/plugins/akismet/admin.php:262 +msgid "" +"A network problem or firewall is blocking all connections from your web " +"server to Akismet.com. Akismet cannot work correctly until this is " +"fixed. Please contact your web host or firewall administrator and " +"give them this information about Akismet " +"and firewalls." +msgstr "" +"Un problème réseau ou un pare-feu bloque toutes les connexions vers le " +"serveur d’Akismet.com. Akismet ne pourra pas fonctionner " +"correctement tant que ce problème ne sera pas résolu. Veuillez " +"contacter votre hébergeur ou votre administrateur réseau avec ces informations (en anglais)." + +#: wp-content/plugins/akismet/admin.php:264 +msgid "All Akismet servers are available." +msgstr "Tous les serveurs Akismet sont disponibles." + +#: wp-content/plugins/akismet/admin.php:265 +msgid "Akismet is working correctly. All servers are accessible." +msgstr "Akismet fonctionne correctement. Tous les serveurs sont accessibles." + +#: wp-content/plugins/akismet/admin.php:268 +msgid "Unable to find Akismet servers." +msgstr "Impossible de trouver les serveurs d’Akismet." + +#: wp-content/plugins/akismet/admin.php:269 +msgid "" +"A DNS problem or firewall is preventing all access from your web server to " +"Akismet.com. Akismet cannot work correctly until this is fixed. Please contact your web host or firewall administrator and give " +"them this information about Akismet and " +"firewalls." +msgstr "" +"Un problème de DNS ou de pare-feu empêche tout accès au serveur d’" +"Akismet.com. Akismet ne pourra pas fonctionner correctement tant que " +"ce problème ne sera pas résolu. Veuillez contacter votre hébergeur " +"ou votre administrateur réseau avec ces " +"informations (en anglais)." + +#: wp-content/plugins/akismet/admin.php:276 +#: wp-content/plugins/akismet/admin.php:280 +msgid "Network Status" +msgstr "État du réseau" + +#: wp-content/plugins/akismet/admin.php:280 +msgid "Akismet server" +msgstr "Serveur Akismet" + +#: wp-content/plugins/akismet/admin.php:288 +msgid "Accessible" +msgstr "Accessible" + +#: wp-content/plugins/akismet/admin.php:288 +msgid "Re-trying" +msgstr "Nouvelle tentative" + +#: wp-content/plugins/akismet/admin.php:294 +msgid "Check Network Status" +msgstr "Vérifier l’état du réseau" + +#: wp-content/plugins/akismet/admin.php:299 +msgid "Last Checked" +msgstr "Vérifié pour la dernière fois" + +#: wp-content/plugins/akismet/admin.php:301 +msgid "%s Ago" +msgstr "Il y a %s" + +#: wp-content/plugins/akismet/admin.php:301 +msgid "Not yet" +msgstr "Pas encore" + +#: wp-content/plugins/akismet/admin.php:302 +msgid "" +"You can confirm that Akismet.com is up by clicking here." +msgstr "" +"Vous pouvez confirmer qu’Akismet.com fonctionne en cliquant ici." + +#: wp-content/plugins/akismet/admin.php:323 +msgid "Akismet is almost ready." +msgstr "Akismet est presque prêt." + +#: wp-content/plugins/akismet/admin.php:323 +msgid "" +"You must enter your Akismet API key for it to work." +msgstr "" +"Vous devez saisir votre clé d’API Akismet pour " +"que cela fonctionne." + +#: wp-content/plugins/akismet/admin.php:336 +msgctxt "comments" +msgid "Spam" +msgstr "Indésirable" + +#: wp-content/plugins/akismet/admin.php:342 +msgid "" +"Akismet has protected your site from " +"%3$s spam comments." +msgid_plural "" +"Akismet has protected your site from " +"%3$s spam comments." +msgstr[0] "" +"Akismet a protégé votre site de %3$s " +"commentaire indésirable." +msgstr[1] "" +"Akismet a protégé votre site de %3$s " +"commentaires indésirables." + +#: wp-content/plugins/akismet/admin.php:362 +msgid "Akismet Error Code" +msgstr "Code d’erreur Akismet" + +#: wp-content/plugins/akismet/admin.php:393 +msgid "Activate your Akismet account" +msgstr "Activez votre compte Akismet" + +#: wp-content/plugins/akismet/admin.php:396 +msgid "" +"Almost done - activate your account and say goodbye to " +"comment spam" +msgstr "" +"Presque terminé - activez votre compte et dites adieu aux " +"commentaires indésirables" + +#: wp-content/plugins/akismet/admin.php:414 +msgid "Akismet has detected a problem." +msgstr "Akismet a détecté un problème." + +#: wp-content/plugins/akismet/admin.php:414 +msgid "" +"Some comments have not yet been checked for spam by Akismet. They have been " +"temporarily held for moderation. Please check your Akismet " +"configuration and contact your web host if problems persist." +msgstr "" +"Certaines commentaires n’ont pas encore été vérifiés par Akismet. En " +"attendant, ils ont été mis dans la file de modération. Veuillez vérifier " +"votre configuration Akismet, et contacter votre hébergeur " +"si le problème persiste." + +#: wp-content/plugins/akismet/admin.php:436 +msgid "Awaiting spam check" +msgstr "En attente de vérification" + +#: wp-content/plugins/akismet/admin.php:440 +msgid "Flagged as spam by Akismet" +msgstr "Marqué comme indésirable par Akismet" + +#: wp-content/plugins/akismet/admin.php:442 +msgid "Cleared by Akismet" +msgstr "Validé par Akismet" + +#: wp-content/plugins/akismet/admin.php:446 +msgid "Flagged as spam by %s" +msgstr "Marqué comme indésirable par %s" + +#: wp-content/plugins/akismet/admin.php:448 +msgid "Un-spammed by %s" +msgstr "Marqué comme légitime par %s" + +#: wp-content/plugins/akismet/admin.php:460 +#: wp-content/plugins/akismet/admin.php:468 +msgid "View comment history" +msgstr "Voir l’historique du commentaire" + +#: wp-content/plugins/akismet/admin.php:460 +msgid "History" +msgstr "Historique" + +#: wp-content/plugins/akismet/admin.php:473 +msgid "%s approved" +msgid_plural "%s approved" +msgstr[0] "%s approuvé" +msgstr[1] "%s approuvés" + +#: wp-content/plugins/akismet/admin.php:488 +#: wp-content/plugins/akismet/admin.php:516 +msgid "%s ago" +msgstr "il y a %s" + +#: wp-content/plugins/akismet/admin.php:556 +msgid "" +"Akismet has protected your site from %2$s spam comment " +"already. " +msgid_plural "" +"Akismet has protected your site from %2$s spam comments " +"already. " +msgstr[0] "" +"Akismet a déjà protégé votre site de %2$s commentaire " +"indésirable." +msgstr[1] "" +"Akismet a déjà protégé votre site de %2$s commentaires " +"indésirables." + +#: wp-content/plugins/akismet/admin.php:562 +msgid "Akismet blocks spam from getting to your blog. " +msgstr "" +"Akismet empêche les commentaires indésirables d’" +"arriver sur votre site," + +#: wp-content/plugins/akismet/admin.php:567 +msgid "There's %1$s comment in your spam queue right now." +msgid_plural "" +"There are %1$s comments in your spam queue right now." +msgstr[0] "" +"Il y a actuellement %1$s commentaire dans votre file de " +"commentaires indésirables." +msgstr[1] "" +"Il y a actuellement %1$s commentaires dans votre file de " +"commentaires indésirables." + +#: wp-content/plugins/akismet/admin.php:573 +msgid "There's nothing in your spam queue at the moment." +msgstr "" +"Il n’y a rien dans votre file d’indésirables " +"actuellement." + +#: wp-content/plugins/akismet/admin.php:591 +msgid "Check for Spam" +msgstr "Vérifier les commentaires indésirables" + +#: wp-content/plugins/akismet/admin.php:636 +msgid "%s reported this comment as not spam" +msgstr "%s a marqué ce commentaire comme n’étant pas un indésirable" + +#: wp-content/plugins/akismet/admin.php:687 +msgid "%s reported this comment as spam" +msgstr "%s a marqué ce commentaire comme indésirable" + +#: wp-content/plugins/akismet/admin.php:735 +msgid "%s changed the comment status to %s" +msgstr "%s a changé le statut du commentaire en %s" + +#: wp-content/plugins/akismet/admin.php:804 +msgid "Akismet re-checked and caught this comment as spam" +msgstr "" +"Akismet a revérifié ce commentaire et considéré qu’il s’agit " +"d’un indésirable" + +#: wp-content/plugins/akismet/admin.php:809 +msgid "Akismet re-checked and cleared this comment" +msgstr "Akismet a revérifié et validé ce commentaire" + +#: wp-content/plugins/akismet/admin.php:813 +msgid "Akismet was unable to re-check this comment (response: %s)" +msgstr "Akismet n’a pas pu revérifier ce commentaire (réponse : %s)" + +#: wp-content/plugins/akismet/admin.php:920 +#: wp-content/plugins/akismet/admin.php:923 +msgid "Akismet Stats" +msgstr "Statistiques Akismet" + +#: wp-content/plugins/akismet/akismet.php:292 +msgid "Akismet caught this comment as spam" +msgstr "Akismet a considéré que ce commentaire est un indésirable" + +#: wp-content/plugins/akismet/akismet.php:294 +#: wp-content/plugins/akismet/akismet.php:302 +msgid "Comment status was changed to %s" +msgstr "L’état du commentaire a été changé en %s" + +#: wp-content/plugins/akismet/akismet.php:297 +msgid "Akismet cleared this comment" +msgstr "Akismet a revérifié et validé ce commentaire" + +#: wp-content/plugins/akismet/akismet.php:300 +msgid "Comment was caught by wp_blacklist_check" +msgstr "Un commentaire a été arrêté par wp_blacklist_check" + +#: wp-content/plugins/akismet/akismet.php:307 +msgid "" +"Akismet was unable to check this comment (response: %s), will automatically " +"retry again later." +msgstr "" +"Akismet n’a pas pu revérifier ce commentaire (réponse : %s)" +" ; il fera une nouvelle tentative plus tard." + +#: wp-content/plugins/akismet/akismet.php:541 +msgid "Akismet caught this comment as spam during an automatic retry." +msgstr "" +"Akismet a revérifié ce commentaire et considéré qu’il s’agit " +"d’un indésirable." + +#: wp-content/plugins/akismet/akismet.php:543 +msgid "Akismet cleared this comment during an automatic retry." +msgstr "" +"Akismet a validé ce commentaire suite à une revérification automatique." + +#: wp-content/plugins/akismet/legacy.php:47 +msgid "Akismet Spam (%s)" +msgstr "Commentaires indésirables Akismet (%s)" + +#: wp-content/plugins/akismet/legacy.php:49 +#: wp-content/plugins/akismet/legacy.php:51 +msgid "Akismet Spam" +msgstr "Commentaire indésirable Akismet" + +#: wp-content/plugins/akismet/legacy.php:61 +#: wp-content/plugins/akismet/legacy.php:80 +msgid "You do not have sufficient permission to moderate comments." +msgstr "" +"Vous n’avez pas les droits suffisants pour modérer les commentaires." + +#: wp-content/plugins/akismet/legacy.php:96 +msgid "%1$s comments recovered." +msgstr "%s commentaires récupérés." + +#: wp-content/plugins/akismet/legacy.php:100 +msgid "All spam deleted." +msgstr "Tous les commentaires indésirables ont été supprimés." + +#: wp-content/plugins/akismet/legacy.php:148 +msgid "Caught Spam" +msgstr "Commentaires indésirables bloqués" + +#: wp-content/plugins/akismet/legacy.php:153 +msgid "" +"Akismet has caught %1$s spam for you since you first " +"installed it." +msgstr "" +"Akismet a bloqué %1$s commentaires indésirables pour vous " +"depuis que vous l’avez installé." + +#: wp-content/plugins/akismet/legacy.php:160 +msgid "You have no spam currently in the queue. Must be your lucky day. :)" +msgstr "" +"Aucun commentaire indésirable dans la file d’attente actuellement. Ce " +"doit être votre jour de chance :)" + +#: wp-content/plugins/akismet/legacy.php:163 +msgid "" +"You can delete all of the spam from your database with a single click. This " +"operation cannot be undone, so you may wish to check to ensure that no " +"legitimate comments got through first. Spam is automatically deleted after " +"15 days, so don’t sweat it." +msgstr "" +"Vous pouvez supprimer tous les commentaires indésirables de votre base de " +"données en un seul clic. Cette opération est irréversible, donc vous devez " +"vérifier qu’aucun commentaire légitime n’y a été placé par " +"mégarde. Dans tous les cas, ces commentaires indésirables sont " +"automatiquement supprimés après 15 jours." + +#: wp-content/plugins/akismet/legacy.php:169 +#: wp-content/plugins/akismet/legacy.php:347 +msgid "There are currently %1$s comments identified as spam." +msgstr "" +"Il y a actuellement %1$s commentaire(s) identifié(s) comme indésirable(s)." + +#: wp-content/plugins/akismet/legacy.php:169 +#: wp-content/plugins/akismet/legacy.php:347 +msgid "Delete all" +msgstr "Tout supprimer " + +#: wp-content/plugins/akismet/legacy.php:176 wp-includes/admin-bar.php:674 +#: wp-includes/class-wp-editor.php:887 wp-includes/default-widgets.php:194 +#: wp-includes/media.php:1888 +msgid "Search" +msgstr "Recherche" + +#: wp-content/plugins/akismet/legacy.php:178 +msgid "" +"These are the latest comments identified as spam by Akismet. If you see any " +"mistakes, simply mark the comment as \"not spam\" and Akismet will learn " +"from the submission. If you wish to recover a comment from spam, simply " +"select the comment, and click Not Spam. After 15 days we clean out the junk " +"for you." +msgstr "" +"Voici les derniers commentaires identifiés comme indésirables par Akismet. " +"Si vous voyez une erreur, changez le marquage du commentaire en cliquant sur " +"« N’est pas indésirable » et Askimet s’en " +"souviendra. Si vous souhaitez récupérer un commentaire marqué comme " +"indésirable, sélectionnez-le et cliquez sur le bouton « Marquer " +"les commentaires cochés comme légitimes ». Au bout de 15 jours, " +"nous supprimons de toute façon tous les indésirables." + +#: wp-content/plugins/akismet/legacy.php:209 +msgid "All" +msgstr "Tous" + +#: wp-content/plugins/akismet/legacy.php:214 +#: wp-includes/theme-compat/comments-popup.php:33 +msgid "Comments" +msgstr "Commentaires" + +#: wp-content/plugins/akismet/legacy.php:232 +msgid "Search Spam »" +msgstr "Chercher dans les commentaires indésirables »" + +#: wp-content/plugins/akismet/legacy.php:239 +#: wp-content/plugins/akismet/legacy.php:306 +#: wp-includes/link-template.php:1663 wp-includes/link-template.php:1699 +msgid "« Previous Page" +msgstr "« Page précédente" + +#: wp-content/plugins/akismet/legacy.php:260 +#: wp-content/plugins/akismet/legacy.php:327 +#: wp-includes/link-template.php:1592 wp-includes/link-template.php:1700 +msgid "Next Page »" +msgstr "Page suivante »" + +#: wp-content/plugins/akismet/legacy.php:282 +msgid "IP:" +msgstr "IP :" + +#: wp-content/plugins/akismet/legacy.php:288 +msgid "Not Spam" +msgstr "N’est pas un commentaire indésirable" + +#: wp-content/plugins/akismet/legacy.php:294 wp-includes/post.php:1488 +msgid "View Post" +msgstr "Afficher l’article" + +#: wp-content/plugins/akismet/legacy.php:333 +msgid "De-spam marked comments »" +msgstr "Marquer les commentaires cochés comme légitimes »" + +#: wp-content/plugins/akismet/legacy.php:335 +msgid "" +"Comments you de-spam will be submitted to Akismet as mistakes so it can " +"learn and get better." +msgstr "" +"Les commentaires que vous marquez comme légitimes seront envoyés à Akismet " +"pour qu’il puisse apprendre de ses erreurs." + +#: wp-content/plugins/akismet/legacy.php:340 +msgid "No results found." +msgstr "Aucun résultat." + +#: wp-content/plugins/akismet/legacy.php:385 +msgid "Recheck Queue for Spam" +msgstr "Revérifier la file de commentaires indésirables" + +#: wp-content/plugins/akismet/widget.php:10 +msgid "Akismet Widget" +msgstr "Widget Akismet" + +#: wp-content/plugins/akismet/widget.php:11 +msgid "Display the number of spam comments Akismet has caught" +msgstr "Affiche le nombre de commentaires indésirables repérés par Akismet" + +#: wp-content/plugins/akismet/widget.php:67 +msgid "Spam Blocked" +msgstr "Indésirable bloqué" + +#: wp-content/plugins/akismet/widget.php:72 wp-includes/default-widgets.php:66 +#: wp-includes/default-widgets.php:215 wp-includes/default-widgets.php:281 +#: wp-includes/default-widgets.php:340 wp-includes/default-widgets.php:380 +#: wp-includes/default-widgets.php:426 wp-includes/default-widgets.php:512 +#: wp-includes/default-widgets.php:618 wp-includes/default-widgets.php:728 +#: wp-includes/default-widgets.php:1073 wp-includes/default-widgets.php:1146 +msgid "Title:" +msgstr "Titre :" + +#: wp-content/plugins/akismet/widget.php:96 +msgid "" +"%1$s spam blocked by Akismet" +msgid_plural "" +"%1$s spam blocked by Akismet" +msgstr[0] "" +"%1$s indésirable bloqué par " +"Akismet" +msgstr[1] "" +"%1$s indésirables bloqués par " +"Akismet" + +#: wp-includes/admin-bar.php:84 wp-includes/admin-bar.php:93 +msgid "About WordPress" +msgstr "À propos de WordPress" + +#: wp-includes/admin-bar.php:102 +msgid "WordPress.org" +msgstr "Site de WordPress-FR" + +#: wp-includes/admin-bar.php:103 wp-includes/default-widgets.php:319 +#: wp-login.php:95 +msgid "http://wordpress.org/" +msgstr "http://www.wordpress-fr.net/" + +#: wp-includes/admin-bar.php:110 +msgid "Documentation" +msgstr "Documentation" + +#: wp-includes/admin-bar.php:111 +msgid "http://codex.wordpress.org/" +msgstr "http://codex.wordpress.org/" + +#: wp-includes/admin-bar.php:118 +msgid "Support Forums" +msgstr "Forums d’entraide" + +#: wp-includes/admin-bar.php:119 +msgid "http://wordpress.org/support/" +msgstr "http://www.wordpress-fr.net/support/" + +#: wp-includes/admin-bar.php:126 +msgid "Feedback" +msgstr "Remarque" + +#: wp-includes/admin-bar.php:127 +msgid "http://wordpress.org/support/forum/requests-and-feedback" +msgstr "http://wordpress.org/support/forum/requests-and-feedback" + +#: wp-includes/admin-bar.php:147 +msgid "Howdy, %1$s" +msgstr "Salutations, %1$s" + +#: wp-includes/admin-bar.php:157 +msgid "My Account" +msgstr "Mon compte" + +#: wp-includes/admin-bar.php:200 +msgid "Edit My Profile" +msgstr "Modifier mon profil" + +#: wp-includes/admin-bar.php:206 wp-includes/class-wp-admin-bar.php:367 +msgid "Log Out" +msgstr "Se déconnecter" + +#: wp-includes/admin-bar.php:235 +msgid "Network Admin: %s" +msgstr "Admin du réseau : %s" + +#: wp-includes/admin-bar.php:237 +msgid "Global Dashboard: %s" +msgstr "Tableau de bord global : %s" + +#: wp-includes/admin-bar.php:255 wp-includes/admin-bar.php:401 +#: wp-includes/deprecated.php:2833 +msgid "Visit Site" +msgstr "Aller sur le site" + +#: wp-includes/admin-bar.php:263 +msgid "Edit Site" +msgstr "Modifier le site" + +#: wp-includes/admin-bar.php:273 wp-includes/admin-bar.php:320 +#: wp-includes/admin-bar.php:376 wp-includes/deprecated.php:2835 +#: wp-includes/deprecated.php:2837 +msgid "Dashboard" +msgstr "Tableau de bord" + +#: wp-includes/admin-bar.php:300 +msgid "My Sites" +msgstr "Mes sites" + +#: wp-includes/admin-bar.php:313 +msgid "Network Admin" +msgstr "Admin du réseau" + +#: wp-includes/admin-bar.php:326 +msgid "Sites" +msgstr "Sites" + +#: wp-includes/admin-bar.php:332 +msgid "Users" +msgstr "Utilisateurs" + +#: wp-includes/admin-bar.php:338 wp-includes/admin-bar.php:604 +msgid "Themes" +msgstr "Thèmes" + +#: wp-includes/admin-bar.php:344 wp-includes/js/tinymce/langs/wp-langs.php:340 +msgid "Plugins" +msgstr "Extensions" + +#: wp-includes/admin-bar.php:384 wp-includes/post.php:1487 +msgid "New Post" +msgstr "Nouvel article" + +#: wp-includes/admin-bar.php:393 +msgid "Manage Comments" +msgstr "Gérer les commentaires" + +#: wp-includes/admin-bar.php:427 +msgid "Shortlink" +msgstr "Lien court" + +#: wp-includes/admin-bar.php:519 +msgctxt "add new from admin bar" +msgid "Link" +msgstr "Lien" + +#: wp-includes/admin-bar.php:539 +msgctxt "add new from admin bar" +msgid "User" +msgstr "Utilisateur" + +#: wp-includes/admin-bar.php:544 +msgctxt "admin bar menu group label" +msgid "New" +msgstr "Créer" + +# contexte +#: wp-includes/admin-bar.php:551 +msgctxt "admin bar menu group label" +msgid "Add New" +msgstr "Créer" + +#: wp-includes/admin-bar.php:580 +msgid "%s comment awaiting moderation" +msgid_plural "%s comments awaiting moderation" +msgstr[0] "%s commentaire en attente de modération" +msgstr[1] "%s commentaires en attente de modération" + +#: wp-includes/admin-bar.php:613 +msgid "Customize" +msgstr "Personnaliser" + +#: wp-includes/admin-bar.php:622 wp-includes/functions.php:2770 +msgid "Widgets" +msgstr "Widgets" + +#: wp-includes/admin-bar.php:625 +msgid "Menus" +msgstr "Menus" + +#: wp-includes/admin-bar.php:628 wp-includes/js/tinymce/langs/wp-langs.php:413 +msgid "Background" +msgstr "Arrière-plan" + +#: wp-includes/admin-bar.php:631 +msgid "Header" +msgstr "En-tête" + +#: wp-includes/atomlib.php:133 +msgid "XML error: %s at line %d" +msgstr "Erreur XML : %s à la ligne %d" + +#: wp-includes/author-template.php:62 +msgid "" +"Use get_the_author() instead if you do not want the value " +"echoed." +msgstr "" +"Utilisez plutôt get_the_author() si vous préférez que la valeur " +"ne soit pas affichée." + +#: wp-includes/author-template.php:174 +msgid "Visit %s’s website" +msgstr "Aller sur le site de %s" + +#: wp-includes/author-template.php:241 wp-includes/author-template.php:372 +msgid "Posts by %s" +msgstr "Articles par %s" + +#: wp-includes/bookmark-template.php:81 +msgid "Last updated: %s" +msgstr "Dernière mise à jour : %s" + +#: wp-includes/bookmark-template.php:205 +msgid "Bookmarks" +msgstr "Favoris" + +#: wp-includes/capabilities.php:595 wp-includes/capabilities.php:615 +#: wp-includes/capabilities.php:641 +msgid "Use WP_User->ID instead." +msgstr "Utilisez plutôt WP_User->ID." + +#: wp-includes/capabilities.php:930 +msgid "" +"Usage of user levels by plugins and themes is deprecated. Use roles and " +"capabilities instead." +msgstr "" +"L’utilisation des niveaux d’utilisateur par les extensions et " +"thèmes est désormais interdite. Utiliser les rôles et capacités à la place." + +#: wp-includes/category-template.php:59 wp-includes/category-template.php:174 +#: wp-includes/category-template.php:177 wp-includes/category-template.php:184 +#: wp-includes/category-template.php:197 wp-includes/category-template.php:200 +#: wp-includes/category-template.php:207 +msgid "View all posts in %s" +msgstr "Voir tous les articles dans %s" + +#: wp-includes/category-template.php:161 +msgid "Uncategorized" +msgstr "Non classé" + +#: wp-includes/category-template.php:412 +msgid "No categories" +msgstr "Pas de catégorie" + +#: wp-includes/category-template.php:420 wp-includes/default-widgets.php:445 +#: wp-includes/default-widgets.php:451 wp-includes/theme-compat/sidebar.php:63 +msgid "Categories" +msgstr "Catégories" + +#: wp-includes/category-template.php:561 +msgid "%s topic" +msgid_plural "%s topics" +msgstr[0] "%s sujet" +msgstr[1] "%s sujets" + +#: wp-includes/category-template.php:844 +msgid "View all posts filed under %s" +msgstr "Voir tous les articles classés dans %s" + +#: wp-includes/category-template.php:859 +msgid "Feed for all posts filed under %s" +msgstr "Flux pour tous les articles classés dans %s" + +#: wp-includes/category-template.php:1035 +msgid "Tags: " +msgstr "Mots-clés : " + +#: wp-includes/class-http.php:118 wp-includes/class-wp-xmlrpc-server.php:5326 +msgid "A valid URL was not provided." +msgstr "L’URL fournie est invalide." + +#: wp-includes/class-http.php:121 +msgid "User has blocked requests through HTTP." +msgstr "L’utilisateur a bloqué les requêtes HTTP." + +#: wp-includes/class-http.php:141 +msgid "" +"Destination directory for file streaming does not exist or is not writable." +msgstr "" +"Le dossier de destination pour la diffusion de fichier n’existe pas ou " +"n’est pas accessible en écriture." + +#: wp-includes/class-http.php:260 +msgid "" +"There are no HTTP transports available which can complete the requested " +"request." +msgstr "" +"Il n’y a pas de transport HTTP disponible pour mener à bien la requête " +"demandée." + +#: wp-includes/class-http.php:615 wp-includes/class-http.php:1242 +#: wp-includes/class-http.php:1270 +msgid "Too many redirects." +msgstr "Trop de redirections." + +#: wp-includes/class-http.php:793 wp-includes/class-http.php:801 +msgid "The SSL certificate for the host could not be verified." +msgstr "Le certificat SSL de l’hôte n’a pas pu être vérifié." + +#: wp-includes/class-http.php:861 wp-includes/class-http.php:1209 +msgid "Could not open handle for fopen() to %s" +msgstr "Impossible d’ouvrir le gestionnaire de fopen() pour %s" + +#: wp-includes/class-http.php:887 wp-includes/class-http.php:1262 +msgid "Failed to write request to temporary file." +msgstr "Impossible d’écrire la requête dans un fichier temporaire." + +#: wp-includes/class-pop3.php:82 +msgid "No server specified" +msgstr "Aucun serveur spécifié" + +#: wp-includes/class-pop3.php:90 wp-includes/class-pop3.php:102 +#: wp-includes/class-pop3.php:123 wp-includes/class-pop3.php:246 +#: wp-includes/class-pop3.php:300 wp-includes/class-pop3.php:311 +#: wp-includes/class-pop3.php:359 wp-includes/class-pop3.php:393 +#: wp-includes/class-pop3.php:426 wp-includes/class-pop3.php:525 +#: wp-includes/class-pop3.php:548 +msgid "Error " +msgstr "Erreur " + +#: wp-includes/class-pop3.php:115 +msgid "no login ID submitted" +msgstr "pas d’identifiant de connexion envoyé" + +#: wp-includes/class-pop3.php:118 wp-includes/class-pop3.php:138 +msgid "connection not established" +msgstr "la connexion n’est pas établie" + +#: wp-includes/class-pop3.php:135 wp-includes/class-pop3.php:171 +msgid "No password submitted" +msgstr "Pas de mot de passe envoyé" + +#: wp-includes/class-pop3.php:143 +msgid "Authentication failed" +msgstr "L’authentification a échoué" + +#: wp-includes/class-pop3.php:162 wp-includes/class-pop3.php:205 +#: wp-includes/class-pop3.php:230 wp-includes/class-pop3.php:272 +#: wp-includes/class-pop3.php:346 wp-includes/class-pop3.php:386 +#: wp-includes/class-pop3.php:416 wp-includes/class-pop3.php:450 +#: wp-includes/class-pop3.php:513 wp-includes/class-pop3.php:578 +msgid "No connection to server" +msgstr "Pas de connexion au serveur" + +#: wp-includes/class-pop3.php:168 +msgid "No login ID submitted" +msgstr "Pas d’identifiant de connexion envoyé" + +#: wp-includes/class-pop3.php:176 +msgid "No server banner" +msgstr "Pas de blocage serveur" + +#: wp-includes/class-pop3.php:176 wp-includes/class-pop3.php:186 +msgid "abort" +msgstr "abandonner" + +#: wp-includes/class-pop3.php:186 +msgid "apop authentication failed" +msgstr "l’identification APOP a échoué" + +#: wp-includes/class-pop3.php:323 +msgid "Premature end of list" +msgstr "Fin de liste inattendue" + +#: wp-includes/class-pop3.php:456 +msgid "Empty command string" +msgstr "Chaîne de commande vide" + +#: wp-includes/class-pop3.php:476 +msgid "connection does not exist" +msgstr "la connexion n’existe pas" + +#: wp-includes/class-pop3.php:583 +msgid "No msg number submitted" +msgstr "Pas de numéro de message envoyé" + +#: wp-includes/class-pop3.php:589 +msgid "Command failed " +msgstr "Échec de la commande " + +#: wp-includes/class-wp-admin-bar.php:105 +msgid "The menu ID should not be empty." +msgstr "L’identifiant du menu ne devrait pas être vide." + +#: wp-includes/class-wp-admin-bar.php:360 +msgid "Skip to toolbar" +msgstr "Aller à la barre d’outils" + +#: wp-includes/class-wp-admin-bar.php:361 +msgid "Top navigation toolbar." +msgstr "Barre de navigation supérieure." + +#: wp-includes/class-wp-customize-control.php:292 +#: wp-includes/class-wp-customize-manager.php:900 +msgid "— Select —" +msgstr "— Sélectionner —" + +#: wp-includes/class-wp-customize-control.php:344 +#: wp-includes/class-wp-customize-control.php:661 +#: wp-includes/class-wp-customize-control.php:737 +#: wp-includes/class-wp-customize-control.php:766 +#: wp-includes/js/tinymce/langs/wp-langs.php:249 +#: wp-includes/script-loader.php:482 +msgid "Default" +msgstr "Valeur par défaut" + +#: wp-includes/class-wp-customize-control.php:387 +msgid "Hex Value" +msgstr "Valeur hexadécimale" + +#: wp-includes/class-wp-customize-control.php:444 +msgid "Upload" +msgstr "Envoyer" + +#: wp-includes/class-wp-customize-control.php:445 +#: wp-includes/media-template.php:148 +msgid "Remove" +msgstr "Supprimer" + +#: wp-includes/class-wp-customize-control.php:480 +#: wp-includes/class-wp-customize-control.php:738 +msgid "No Image" +msgstr "Aucune image" + +#: wp-includes/class-wp-customize-control.php:484 +msgid "Upload New" +msgstr "Mettre en ligne" + +#: wp-includes/class-wp-customize-control.php:485 +msgid "Uploaded" +msgstr "Mis en ligne" + +#: wp-includes/class-wp-customize-control.php:558 +msgid "Remove Image" +msgstr "Retirer l’image" + +#: wp-includes/class-wp-customize-control.php:596 +#: wp-includes/media-template.php:51 +msgid "" +"The web browser on your device cannot be used to upload files. You may be " +"able to use the native app for your device instead." +msgstr "" +"Le navigateur web de votre système ne permet pas de mettre des fichiers en " +"ligne. Vous devriez pouvoir le faire en passant par une " +"application native." + +#: wp-includes/class-wp-customize-control.php:600 +msgid "Drop a file here or select a file." +msgstr "" +"Glissez un fichier ici ou sélectionnez un " +"fichier" + +#: wp-includes/class-wp-customize-control.php:603 +msgid "Select File" +msgstr "Sélectionner un fichier" + +#: wp-includes/class-wp-customize-control.php:654 +#: wp-includes/class-wp-customize-manager.php:813 +msgid "Background Image" +msgstr "Image d’arrière-plan" + +#: wp-includes/class-wp-customize-control.php:727 +#: wp-includes/class-wp-customize-manager.php:793 +msgid "Header Image" +msgstr "Image d’en-tête" + +# Ne pas mettre d'entité HTML ( ...) : chaîne affichée dans l'éditeur visuel. +#: wp-includes/class-wp-customize-control.php:739 +msgid "Random Default Image" +msgstr "Images par défaut aléatoire" + +#: wp-includes/class-wp-customize-control.php:740 +msgid "Random Uploaded Image" +msgstr "Image mise en ligne aléatoire" + +#: wp-includes/class-wp-customize-manager.php:719 +msgid "Site Title & Tagline" +msgstr "Titre de site et description" + +#: wp-includes/class-wp-customize-manager.php:730 +#: wp-includes/class-wp-xmlrpc-server.php:372 +msgid "Site Title" +msgstr "Titre du site" + +#: wp-includes/class-wp-customize-manager.php:741 +msgid "Tagline" +msgstr "Slogan" + +#: wp-includes/class-wp-customize-manager.php:748 +msgid "Colors" +msgstr "Couleurs" + +#: wp-includes/class-wp-customize-manager.php:764 +msgid "Display Header Text" +msgstr "Afficher le texte d’en-tête" + +#: wp-includes/class-wp-customize-manager.php:770 +msgid "Header Text Color" +msgstr "Couleur du texte d’en-tête" + +#: wp-includes/class-wp-customize-manager.php:785 +msgid "Background Color" +msgstr "Couleur d’arrière-plan" + +#: wp-includes/class-wp-customize-manager.php:835 +msgid "Background Repeat" +msgstr "Répétition de l’arrière-plan" + +#: wp-includes/class-wp-customize-manager.php:839 +msgid "No Repeat" +msgstr "Pas de répétition" + +#: wp-includes/class-wp-customize-manager.php:840 +msgid "Tile" +msgstr "Motif répété" + +#: wp-includes/class-wp-customize-manager.php:841 +msgid "Tile Horizontally" +msgstr "Répétition horizontale" + +#: wp-includes/class-wp-customize-manager.php:842 +msgid "Tile Vertically" +msgstr "Répétition verticale" + +#: wp-includes/class-wp-customize-manager.php:852 +msgid "Background Position" +msgstr "Position d’arrière-plan" + +#. translators: alignment +#: wp-includes/class-wp-customize-manager.php:856 +#: wp-includes/js/tinymce/langs/wp-langs.php:82 +#: wp-includes/js/tinymce/langs/wp-langs.php:375 +#: wp-includes/js/tinymce/langs/wp-langs.php:474 +#: wp-includes/media-template.php:271 wp-includes/media-template.php:435 +msgid "Left" +msgstr "Gauche" + +#. translators: alignment +#: wp-includes/class-wp-customize-manager.php:857 +#: wp-includes/js/tinymce/langs/wp-langs.php:83 +#: wp-includes/js/tinymce/langs/wp-langs.php:454 +#: wp-includes/js/tinymce/langs/wp-langs.php:475 +#: wp-includes/media-template.php:274 wp-includes/media-template.php:438 +msgid "Center" +msgstr "Centre" + +#. translators: alignment +#: wp-includes/class-wp-customize-manager.php:858 +#: wp-includes/js/tinymce/langs/wp-langs.php:84 +#: wp-includes/js/tinymce/langs/wp-langs.php:376 +#: wp-includes/js/tinymce/langs/wp-langs.php:472 +#: wp-includes/media-template.php:277 wp-includes/media-template.php:441 +msgid "Right" +msgstr "Droite" + +#: wp-includes/class-wp-customize-manager.php:868 +msgid "Background Attachment" +msgstr "Image d’arrière-plan" + +#: wp-includes/class-wp-customize-manager.php:872 +msgid "Fixed" +msgstr "Fixe" + +#: wp-includes/class-wp-customize-manager.php:873 +msgid "Scroll" +msgstr "Défilant" + +#: wp-includes/class-wp-customize-manager.php:893 +msgid "Navigation" +msgstr "Navigation" + +#: wp-includes/class-wp-customize-manager.php:896 +msgid "Your theme supports %s menu. Select which menu you would like to use." +msgid_plural "" +"Your theme supports %s menus. Select which menu appears in each location." +msgstr[0] "" +"Votre thème peut utiliser %s menu. Sélectionnez le menu que vous voudriez " +"utiliser." +msgstr[1] "" +"Votre thème peut utiliser %s menus. Sélectionnez le menu que vous voudriez " +"utiliser pour chaque emplacement." + +#: wp-includes/class-wp-customize-manager.php:896 +msgid "" +"You can edit your menu content on the Menus screen in the Appearance section." +msgstr "" +"Vous pouvez modifier le contenu de votre menu par le biais de l’écran " +"Menus, dans la section Apparence." + +#: wp-includes/class-wp-customize-manager.php:926 +msgid "Static Front Page" +msgstr "Page d’accueil statique" + +#: wp-includes/class-wp-customize-manager.php:929 +msgid "Your theme supports a static front page." +msgstr "Le thème actuel accepte les pages statiques." + +#: wp-includes/class-wp-customize-manager.php:940 +msgid "Front page displays" +msgstr "La page d’accueil affiche" + +#: wp-includes/class-wp-customize-manager.php:944 +msgid "Your latest posts" +msgstr "Les derniers articles" + +#: wp-includes/class-wp-customize-manager.php:945 +msgid "A static page" +msgstr "Une page statique" + +#: wp-includes/class-wp-customize-manager.php:956 +msgid "Front page" +msgstr "Page d’accueil" + +#: wp-includes/class-wp-customize-manager.php:968 +msgid "Posts page" +msgstr "Page des articles" + +#: wp-includes/class-wp-editor.php:114 wp-includes/class-wp-editor.php:698 +msgctxt "Name for the Text editor tab (formerly HTML)" +msgid "Text" +msgstr "Texte" + +#: wp-includes/class-wp-editor.php:115 wp-includes/class-wp-editor.php:697 +msgid "Visual" +msgstr "Visuel" + +#. translators: These languages show up in the spellchecker drop-down menu, in +#. the order specified, and with the first +#. language listed being the default language. They must be +#. comma-separated and take the format of name=code, where name +#. is the language name (which you may internationalize), and code is a +#. valid ISO 639 language code. Please test the +#. spellchecker with your values. +#: wp-includes/class-wp-editor.php:295 +msgid "" +"English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it," +"Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv" +msgstr "" +"French=fr,Anglais=en,Danois=da,Néerlandais=nl,Finnois=fi,Allemand=de," +"Italien=it,Polonais=pl,Portuguais=pt,Espagnol=es,Suédois=sv" + +#: wp-includes/class-wp-editor.php:688 +#: wp-includes/js/tinymce/langs/wp-langs.php:21 +#: wp-includes/script-loader.php:342 wp-includes/script-loader.php:428 +msgid "Update" +msgstr "Mettre à jour" + +#: wp-includes/class-wp-editor.php:688 +#: wp-includes/js/tinymce/langs/wp-langs.php:121 +msgid "Save" +msgstr "Enregistrer" + +#: wp-includes/class-wp-editor.php:693 +msgid "Exit fullscreen" +msgstr "Sortir du plein écran" + +#: wp-includes/class-wp-editor.php:706 +#: wp-includes/js/tinymce/langs/wp-langs.php:289 +msgid "Bold (Ctrl + B)" +msgstr "Gras (Ctrl + B)" + +#: wp-includes/class-wp-editor.php:707 +#: wp-includes/js/tinymce/langs/wp-langs.php:290 +msgid "Italic (Ctrl + I)" +msgstr "Italique (Ctrl + I)" + +#: wp-includes/class-wp-editor.php:709 +#: wp-includes/js/tinymce/langs/wp-langs.php:297 +msgid "Unordered list (Alt + Shift + U)" +msgstr "Liste non ordonnée (Alt + Shift + U)" + +#: wp-includes/class-wp-editor.php:710 +#: wp-includes/js/tinymce/langs/wp-langs.php:298 +msgid "Ordered list (Alt + Shift + O)" +msgstr "Liste ordonnée (Alt + Maj. + O)" + +#: wp-includes/class-wp-editor.php:712 +#: wp-includes/js/tinymce/langs/wp-langs.php:323 +msgid "Blockquote (Alt + Shift + Q)" +msgstr "Bloc de citation (Alt + Maj. + Q)" + +#: wp-includes/class-wp-editor.php:713 +#: wp-includes/js/tinymce/langs/wp-langs.php:305 +msgid "Insert/edit image (Alt + Shift + M)" +msgstr "Insérer/modifier une image (Alt + Shift + M)" + +#: wp-includes/class-wp-editor.php:715 +#: wp-includes/js/tinymce/langs/wp-langs.php:303 +msgid "Insert/edit link (Alt + Shift + A)" +msgstr "Insérer/modifier un lien (Alt + Shift + A)" + +#: wp-includes/class-wp-editor.php:716 +#: wp-includes/js/tinymce/langs/wp-langs.php:304 +msgid "Unlink (Alt + Shift + S)" +msgstr "Défaire le lien (Alt + Maj. + S)" + +#: wp-includes/class-wp-editor.php:718 +#: wp-includes/js/tinymce/langs/wp-langs.php:504 +msgid "Help (Alt + Shift + H)" +msgstr "Aide (Alt + Maj. + H)" + +#: wp-includes/class-wp-editor.php:742 +msgid "Updated." +msgstr "Mis à jour." + +#: wp-includes/class-wp-editor.php:742 wp-includes/media-template.php:180 +msgid "Saved." +msgstr "Enregistré." + +#: wp-includes/class-wp-editor.php:751 +msgid "Enter title here" +msgstr "Saisissez le titre ici" + +#: wp-includes/class-wp-editor.php:760 +msgid "Word count: %s" +msgstr "Compteur de mots : %s" + +#: wp-includes/class-wp-editor.php:761 +msgid "Just write." +msgstr "Il ne reste plus qu’à écrire." + +#: wp-includes/class-wp-editor.php:825 +msgid "Y/m/d" +msgstr "d/m/Y" + +# Pas d'entité HTML : utilisé dans un alert(). +#: wp-includes/class-wp-editor.php:871 +msgid "Enter the destination URL" +msgstr "Saisissez l’adresse de destination" + +#: wp-includes/class-wp-editor.php:873 wp-includes/media.php:1886 +msgid "URL" +msgstr "Adresse web" + +#: wp-includes/class-wp-editor.php:876 +#: wp-includes/js/tinymce/langs/wp-langs.php:382 +#: wp-includes/js/tinymce/langs/wp-langs.php:547 +#: wp-includes/media-template.php:226 wp-includes/media-template.php:409 +#: wp-includes/revision.php:31 +msgid "Title" +msgstr "Titre" + +#: wp-includes/class-wp-editor.php:879 +msgid "Open link in a new window/tab" +msgstr "Ouvrir le lien dans une nouvelle fenêtre/un nouvel onglet" + +#: wp-includes/class-wp-editor.php:883 +msgid "Or link to existing content" +msgstr "Ou alors, faites un lien vers l’un des contenus de votre site" + +#: wp-includes/class-wp-editor.php:899 +msgid "No search term specified. Showing recent items." +msgstr "" +"Aucun mot n’a été donné pour cette recherche. Voici les recherches " +"précédentes." + +#: wp-includes/class-wp-editor.php:909 wp-includes/script-loader.php:343 +msgid "Add Link" +msgstr "Ajouter un lien" + +#: wp-includes/class-wp-editor.php:912 +#: wp-includes/js/tinymce/langs/wp-langs.php:22 wp-includes/media.php:1890 +#: wp-includes/script-loader.php:371 wp-includes/script-loader.php:418 +msgid "Cancel" +msgstr "Annuler" + +#: wp-includes/class-wp-image-editor-gd.php:87 +#: wp-includes/class-wp-image-editor-imagick.php:120 +msgid "File doesn’t exist?" +msgstr "Le fichier n’existe pas ?" + +#: wp-includes/class-wp-image-editor-gd.php:94 +#: wp-includes/class-wp-image-editor-imagick.php:129 +msgid "File is not an image." +msgstr "Le fichier n’est pas une image." + +#: wp-includes/class-wp-image-editor-gd.php:98 +msgid "Could not read image size." +msgstr "Impossible de lire la taille de l’image." + +#: wp-includes/class-wp-image-editor-gd.php:156 +#: wp-includes/class-wp-image-editor-gd.php:174 +msgid "Image resize failed." +msgstr "Le redimensionnement de l’image a échoué." + +#: wp-includes/class-wp-image-editor-gd.php:162 +#: wp-includes/class-wp-image-editor-imagick.php:223 +msgid "Could not calculate resized image dimensions" +msgstr "Impossible de lire la taille de l’image redimensionnée" + +#: wp-includes/class-wp-image-editor-gd.php:267 +msgid "Image crop failed." +msgstr "Le recadrage de l’image a échoué." + +#: wp-includes/class-wp-image-editor-gd.php:291 +msgid "Image rotate failed." +msgstr "La rotation de l’image a échoué." + +#: wp-includes/class-wp-image-editor-gd.php:321 +msgid "Image flip failed." +msgstr "Le retournement de l’image a échoué." + +#: wp-includes/class-wp-image-editor-gd.php:353 +#: wp-includes/class-wp-image-editor-gd.php:361 +#: wp-includes/class-wp-image-editor-gd.php:365 +#: wp-includes/class-wp-image-editor-gd.php:368 +msgid "Image Editor Save Failed" +msgstr "L’enregistrement de l’éditeur d’images a échoué." + +#: wp-includes/class-wp-image-editor-imagick.php:193 +msgid "Could not read image size" +msgstr "Impossible de lire la taille de l’image" + +#: wp-includes/class-wp-theme.php:209 +msgid "The theme directory \"%s\" does not exist." +msgstr "" +"Le répertoire du thème « %s » n’existe pas." + +#: wp-includes/class-wp-theme.php:211 +msgid "Stylesheet is missing." +msgstr "La feuille de style manque." + +#: wp-includes/class-wp-theme.php:215 +msgid "" +"ERROR: The themes directory is either empty or doesn’t exist. Please " +"check your installation." +msgstr "" +"ERREUR : le répertoire des thèmes est soit vide, ou n’existe pas. " +"Veuillez vérifier votre installation." + +#: wp-includes/class-wp-theme.php:219 +msgid "Stylesheet is not readable." +msgstr "Impossible de lire la feuille de style." + +#: wp-includes/class-wp-theme.php:237 +msgid "Template is missing." +msgstr "Le modèle est manquant." + +#: wp-includes/class-wp-theme.php:256 +msgid "The parent theme is missing. Please install the \"%s\" parent theme." +msgstr "" +"Le thème parent est manquant. Merci d’installer le thème parent «" +" %s »." + +#: wp-includes/class-wp-theme.php:268 wp-includes/class-wp-theme.php:272 +msgid "The \"%s\" theme is not a valid parent theme." +msgstr "" +"Le thème « %s » n’est un thème parent valide." + +#: wp-includes/class-wp-theme.php:654 +msgid "Visit author homepage" +msgstr "Aller sur la page de l’auteur" + +#: wp-includes/class-wp-theme.php:657 wp-includes/comment-template.php:29 +msgid "Anonymous" +msgstr "Anonyme" + +#. translators: used between list items, there is a space after the comma +#: wp-includes/class-wp-theme.php:664 wp-includes/formatting.php:3108 +msgid ", " +msgstr ", " + +#: wp-includes/class-wp-xmlrpc-server.php:181 +msgid "XML-RPC services are disabled on this site." +msgstr "Les services XML-RPC sont désactivés sur ce site." + +#: wp-includes/class-wp-xmlrpc-server.php:188 +msgid "Incorrect username or password." +msgstr "Identifiant ou mot de passe incorrect." + +#: wp-includes/class-wp-xmlrpc-server.php:305 +msgid "Software Name" +msgstr "Nom du logiciel" + +#: wp-includes/class-wp-xmlrpc-server.php:310 +msgid "Software Version" +msgstr "Version du logiciel" + +#: wp-includes/class-wp-xmlrpc-server.php:315 +msgid "WordPress Address (URL)" +msgstr "Adresse web de WordPress (URL)" + +#: wp-includes/class-wp-xmlrpc-server.php:320 +msgid "Site Address (URL)" +msgstr "Adresse web du site (URL)" + +#: wp-includes/class-wp-xmlrpc-server.php:325 +msgid "Login Address (URL)" +msgstr "Adresse de connexion (URL)" + +#: wp-includes/class-wp-xmlrpc-server.php:330 +msgid "The URL to the admin area" +msgstr "L’adresse web de la zone d’administration" + +#: wp-includes/class-wp-xmlrpc-server.php:335 +msgid "Image default link type" +msgstr "Type du lien par défaut vers l’image" + +#: wp-includes/class-wp-xmlrpc-server.php:340 +msgid "Image default size" +msgstr "Taille de l’image par défaut" + +#: wp-includes/class-wp-xmlrpc-server.php:345 +msgid "Image default align" +msgstr "Alignement par défaut de l’image" + +#: wp-includes/class-wp-xmlrpc-server.php:350 +msgid "Template" +msgstr "Modèle" + +#: wp-includes/class-wp-xmlrpc-server.php:355 +msgid "Stylesheet" +msgstr "Feuille de style" + +#: wp-includes/class-wp-xmlrpc-server.php:360 +msgid "Post Thumbnail" +msgstr "Miniature d’article" + +#: wp-includes/class-wp-xmlrpc-server.php:367 +msgid "Time Zone" +msgstr "Fuseau horaire" + +#: wp-includes/class-wp-xmlrpc-server.php:377 +msgid "Site Tagline" +msgstr "Slogan du site" + +#: wp-includes/class-wp-xmlrpc-server.php:382 +msgid "Date Format" +msgstr "Format de date" + +#: wp-includes/class-wp-xmlrpc-server.php:387 +msgid "Time Format" +msgstr "Format d’heure" + +#: wp-includes/class-wp-xmlrpc-server.php:392 +msgid "Allow new users to sign up" +msgstr "Autoriser les nouveaux utilisateurs à s’inscrire" + +#: wp-includes/class-wp-xmlrpc-server.php:397 +msgid "Thumbnail Width" +msgstr "Largeur des miniatures" + +#: wp-includes/class-wp-xmlrpc-server.php:402 +msgid "Thumbnail Height" +msgstr "Hauteur des miniatures" + +#: wp-includes/class-wp-xmlrpc-server.php:407 +msgid "Crop thumbnail to exact dimensions" +msgstr "Recadrer les images pour parvenir aux dimensions exactes" + +#: wp-includes/class-wp-xmlrpc-server.php:412 +msgid "Medium size image width" +msgstr "Largeur de l’image en taille moyenne" + +#: wp-includes/class-wp-xmlrpc-server.php:417 +msgid "Medium size image height" +msgstr "Hauteur de l’image en taille moyenne" + +#: wp-includes/class-wp-xmlrpc-server.php:422 +msgid "Large size image width" +msgstr "Largeur de l’image en grande taille" + +#: wp-includes/class-wp-xmlrpc-server.php:427 +msgid "Large size image height" +msgstr "Hauteur de l’image en grande taille" + +#: wp-includes/class-wp-xmlrpc-server.php:432 +msgid "Allow people to post comments on new articles" +msgstr "" +"Autoriser les visiteurs à publier des commentaires sur les derniers articles" + +#: wp-includes/class-wp-xmlrpc-server.php:437 +msgid "Allow link notifications from other blogs (pingbacks and trackbacks)" +msgstr "" +"Autoriser les liens de notifications depuis les autres sites (notifications " +"par pings et rétroliens)" + +#: wp-includes/class-wp-xmlrpc-server.php:518 +msgid "Insufficient arguments passed to this XML-RPC method." +msgstr "Arguments insuffisants passés à cette méthode XML-RPC." + +#: wp-includes/class-wp-xmlrpc-server.php:1010 +#: wp-includes/class-wp-xmlrpc-server.php:3440 +#: wp-includes/class-wp-xmlrpc-server.php:4081 +#: wp-includes/class-wp-xmlrpc-server.php:4139 +#: wp-includes/class-wp-xmlrpc-server.php:4389 +#: wp-includes/class-wp-xmlrpc-server.php:4441 +msgid "Invalid post type" +msgstr "Type d’article invalide" + +#: wp-includes/class-wp-xmlrpc-server.php:1016 +#: wp-includes/class-wp-xmlrpc-server.php:1265 +#: wp-includes/class-wp-xmlrpc-server.php:1325 +#: wp-includes/class-wp-xmlrpc-server.php:1406 +#: wp-includes/class-wp-xmlrpc-server.php:2269 +#: wp-includes/class-wp-xmlrpc-server.php:2977 +#: wp-includes/class-wp-xmlrpc-server.php:2980 +#: wp-includes/class-wp-xmlrpc-server.php:3748 +#: wp-includes/class-wp-xmlrpc-server.php:4382 +#: wp-includes/class-wp-xmlrpc-server.php:4643 +#: wp-includes/class-wp-xmlrpc-server.php:5121 +#: wp-includes/class-wp-xmlrpc-server.php:5167 +#: wp-includes/class-wp-xmlrpc-server.php:5279 wp-includes/post.php:2728 +#: wp-includes/post.php:2984 +msgid "Invalid post ID." +msgstr "Identifiant de l’article non valide." + +#: wp-includes/class-wp-xmlrpc-server.php:1018 +msgid "Sorry, you are not allowed to edit this post." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de modifier cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:1020 +#: wp-includes/class-wp-xmlrpc-server.php:4393 +msgid "The post type may not be changed." +msgstr "Ce type de contenu ne peut pas être supprimé." + +#: wp-includes/class-wp-xmlrpc-server.php:1023 +#: wp-includes/class-wp-xmlrpc-server.php:3880 +msgid "Sorry, you are not allowed to post on this site." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de publier sur ce site." + +#: wp-includes/class-wp-xmlrpc-server.php:1032 +msgid "Sorry, you are not allowed to create private posts in this post type" +msgstr "" +"Désolé, vous n’avez pas l’autorisation de créer des contenus " +"privés avec ce type de contenu" + +#: wp-includes/class-wp-xmlrpc-server.php:1037 +msgid "Sorry, you are not allowed to publish posts in this post type" +msgstr "" +"Désolé, vous n’avez pas l’autorisation de publier des contenus " +"avec ce type de contenu" + +#: wp-includes/class-wp-xmlrpc-server.php:1046 +msgid "" +"Sorry, you are not allowed to create password protected posts in this post " +"type" +msgstr "" +"Désolé, vous n’avez pas l’autorisation de créer des contenus " +"protégés par mot de passe avec ce type de contenu" + +#: wp-includes/class-wp-xmlrpc-server.php:1051 +#: wp-includes/class-wp-xmlrpc-server.php:4132 +msgid "You are not allowed to create posts as this user." +msgstr "" +"Vous n’avez pas l’autorisation de créer des contenus sous cet " +"identifiant." + +#: wp-includes/class-wp-xmlrpc-server.php:1056 +#: wp-includes/class-wp-xmlrpc-server.php:4144 +msgid "Invalid author ID." +msgstr "Identifiant utilisateur non valable." + +#: wp-includes/class-wp-xmlrpc-server.php:1089 +msgid "Sorry, you cannot stick a private post." +msgstr "Désolé, vous ne pouvez pas mettre en avant un article privé." + +#: wp-includes/class-wp-xmlrpc-server.php:1094 +msgid "Sorry, you are not allowed to stick this post." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de mettre cet article en " +"avant." + +#: wp-includes/class-wp-xmlrpc-server.php:1107 +#: wp-includes/class-wp-xmlrpc-server.php:3291 +#: wp-includes/class-wp-xmlrpc-server.php:4286 +#: wp-includes/class-wp-xmlrpc-server.php:4601 +msgid "Invalid attachment ID." +msgstr "Identifiant du fichier invalide." + +#: wp-includes/class-wp-xmlrpc-server.php:1128 +#: wp-includes/class-wp-xmlrpc-server.php:1151 +msgid "Sorry, one of the given taxonomies is not supported by the post type." +msgstr "" +"Désolé, l’une des taxinomies données n’est pas reconnue par ce " +"type de contenu." + +#: wp-includes/class-wp-xmlrpc-server.php:1131 +#: wp-includes/class-wp-xmlrpc-server.php:1154 +msgid "" +"Sorry, you are not allowed to assign a term to one of the given taxonomies." +msgstr "" +"Désolé, vous n’avez pas l’autorisation d’assigner un terme " +"à l’une des taxinomies indiquées." + +#: wp-includes/class-wp-xmlrpc-server.php:1138 +#: wp-includes/class-wp-xmlrpc-server.php:1655 +#: wp-includes/class-wp-xmlrpc-server.php:1742 +#: wp-includes/class-wp-xmlrpc-server.php:1809 wp-includes/taxonomy.php:2120 +msgid "Invalid term ID" +msgstr "l’ID du terme est invalide" + +#: wp-includes/class-wp-xmlrpc-server.php:1173 +msgid "" +"Ambiguous term name used in a hierarchical taxonomy. Please use term ID " +"instead." +msgstr "" +"Un nom de terme est ambigu pour cette taxinomie hiérarchisée. Veuillez " +"utiliser l’identifiant du terme à la place." + +#: wp-includes/class-wp-xmlrpc-server.php:1180 +msgid "" +"Sorry, you are not allowed to add a term to one of the given taxonomies." +msgstr "" +"Désolé, vous n’avez pas l’autorisation d’ajouter un terme " +"à l’une des taxinomies indiquées." + +#: wp-includes/class-wp-xmlrpc-server.php:1224 +#: wp-includes/class-wp-xmlrpc-server.php:3900 +#: wp-includes/class-wp-xmlrpc-server.php:4307 +msgid "Sorry, your entry could not be posted. Something wrong happened." +msgstr "" +"Désolé, votre entrée n’a pas pu être publiée. Une erreur est survenue." + +#: wp-includes/class-wp-xmlrpc-server.php:1270 +msgid "There is a revision of this post that is more recent." +msgstr "Ce contenu a déjà une révision plus récente." + +#: wp-includes/class-wp-xmlrpc-server.php:1328 +msgid "Sorry, you are not allowed to delete this post." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de supprimer cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:1333 +msgid "The post cannot be deleted." +msgstr "Cet article ne peut pas être supprimé." + +#: wp-includes/class-wp-xmlrpc-server.php:1409 +#: wp-includes/class-wp-xmlrpc-server.php:3610 +#: wp-includes/class-wp-xmlrpc-server.php:3751 +#: wp-includes/class-wp-xmlrpc-server.php:4646 +#: wp-includes/class-wp-xmlrpc-server.php:4973 +#: wp-includes/class-wp-xmlrpc-server.php:5170 +msgid "Sorry, you cannot edit this post." +msgstr "Désolé, vous ne pouvez pas modifier cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:1464 +msgid "The post type specified is not valid" +msgstr "Le type de contenu spécifié n’est pas valable" + +#: wp-includes/class-wp-xmlrpc-server.php:1470 +msgid "Sorry, you are not allowed to edit posts in this post type" +msgstr "" +"Désolé, vous n’avez pas l’autorisation de modifier des entrées " +"dans ce type de contenu" + +#: wp-includes/class-wp-xmlrpc-server.php:1549 +#: wp-includes/class-wp-xmlrpc-server.php:1637 +#: wp-includes/class-wp-xmlrpc-server.php:1729 +#: wp-includes/class-wp-xmlrpc-server.php:1796 +#: wp-includes/class-wp-xmlrpc-server.php:1849 +#: wp-includes/class-wp-xmlrpc-server.php:1928 wp-includes/taxonomy.php:579 +#: wp-includes/taxonomy.php:941 wp-includes/taxonomy.php:1073 +#: wp-includes/taxonomy.php:1264 wp-includes/taxonomy.php:1977 +#: wp-includes/taxonomy.php:2113 wp-includes/taxonomy.php:2244 +#: wp-includes/taxonomy.php:2505 +msgid "Invalid taxonomy" +msgstr "La taxinomie est invalide" + +#: wp-includes/class-wp-xmlrpc-server.php:1554 +msgid "You are not allowed to create terms in this taxonomy." +msgstr "" +"Vous n’avez pas l’autorisation de créer des termes dans cette " +"taxinomie." + +#: wp-includes/class-wp-xmlrpc-server.php:1563 +#: wp-includes/class-wp-xmlrpc-server.php:1661 +msgid "The term name cannot be empty." +msgstr "Le nom du terme ne peut être vide." + +#: wp-includes/class-wp-xmlrpc-server.php:1567 +msgid "This taxonomy is not hierarchical." +msgstr "Cette taxinomie n’est pas hiérarchique." + +#: wp-includes/class-wp-xmlrpc-server.php:1576 +#: wp-includes/class-wp-xmlrpc-server.php:1675 +msgid "Parent term does not exist." +msgstr "Le terme parent n’existe pas." + +#: wp-includes/class-wp-xmlrpc-server.php:1593 +msgid "Sorry, your term could not be created. Something wrong happened." +msgstr "Désolé, votre terme n’a pu être créé. Une erreur est survenue." + +#: wp-includes/class-wp-xmlrpc-server.php:1642 +msgid "You are not allowed to edit terms in this taxonomy." +msgstr "" +"Vous n’avez pas l’autorisation de modifier les termes de cette " +"taxinomie." + +#: wp-includes/class-wp-xmlrpc-server.php:1666 +msgid "This taxonomy is not hierarchical so you can't set a parent." +msgstr "" +"Cette taxinomie n’est pas hiérarchisée, donc vous ne pouvez créer de " +"parent." + +#: wp-includes/class-wp-xmlrpc-server.php:1692 +msgid "Sorry, editing the term failed." +msgstr "Désolé, la modification du terme a échoué." + +#: wp-includes/class-wp-xmlrpc-server.php:1734 +msgid "You are not allowed to delete terms in this taxonomy." +msgstr "" +"Vous n’avez pas l’autorisation de supprimer les termes de cette " +"taxinomie." + +#: wp-includes/class-wp-xmlrpc-server.php:1750 +msgid "Sorry, deleting the term failed." +msgstr "Désolé, la suppression du terme a échoué." + +#: wp-includes/class-wp-xmlrpc-server.php:1801 +#: wp-includes/class-wp-xmlrpc-server.php:1854 +#: wp-includes/class-wp-xmlrpc-server.php:1933 +msgid "You are not allowed to assign terms in this taxonomy." +msgstr "" +"Désolé, vous n’avez pas l’autorisation d’assigner des " +"termes à cette taxinomie." + +#: wp-includes/class-wp-xmlrpc-server.php:2041 +msgid "Sorry, you cannot edit users." +msgstr "Désolé, vous ne pouvez pas modifier les utilisateurs." + +#: wp-includes/class-wp-xmlrpc-server.php:2046 +msgid "Invalid user ID" +msgstr "Indentifiant utilisateur non valide" + +#: wp-includes/class-wp-xmlrpc-server.php:2094 +msgid "Sorry, you cannot list users." +msgstr "Désolé, vous ne pouvez pas lister les utilisateurs." + +#: wp-includes/class-wp-xmlrpc-server.php:2110 +msgid "The role specified is not valid" +msgstr "Le rôle spécifié n’est pas valable" + +#: wp-includes/class-wp-xmlrpc-server.php:2161 +#: wp-includes/class-wp-xmlrpc-server.php:2204 +msgid "Sorry, you cannot edit your profile." +msgstr "Désolé, vous ne pouvez pas modifier votre profil." + +#: wp-includes/class-wp-xmlrpc-server.php:2238 +msgid "Sorry, the user cannot be updated." +msgstr "Désolé, cet utilisateur ne peut pas être mis à jour." + +#: wp-includes/class-wp-xmlrpc-server.php:2272 +msgid "Sorry, you cannot edit this page." +msgstr "Désolé, vous ne pouvez pas modifier cette page." + +#: wp-includes/class-wp-xmlrpc-server.php:2282 +#: wp-includes/class-wp-xmlrpc-server.php:2386 +#: wp-includes/class-wp-xmlrpc-server.php:2427 +msgid "Sorry, no such page." +msgstr "Désolé, aucune page ne correspond." + +#: wp-includes/class-wp-xmlrpc-server.php:2310 +#: wp-includes/class-wp-xmlrpc-server.php:2470 +msgid "Sorry, you cannot edit pages." +msgstr "Désolé, vous ne pouvez pas modifier les pages." + +#: wp-includes/class-wp-xmlrpc-server.php:2390 +msgid "Sorry, you do not have the right to delete this page." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de supprimer cette page." + +#: wp-includes/class-wp-xmlrpc-server.php:2395 +msgid "Failed to delete the page." +msgstr "Échec lors de la suppression de la page." + +#: wp-includes/class-wp-xmlrpc-server.php:2431 +msgid "Sorry, you do not have the right to edit this page." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de modifier cette page." + +#: wp-includes/class-wp-xmlrpc-server.php:2521 +#: wp-includes/class-wp-xmlrpc-server.php:3796 +#: wp-includes/class-wp-xmlrpc-server.php:4770 +msgid "Sorry, you cannot edit posts on this site." +msgstr "Désolé, vous ne pouvez pas modifier les articles de ce site." + +#: wp-includes/class-wp-xmlrpc-server.php:2556 +msgid "" +"Sorry, you must be able to edit posts on this site in order to view tags." +msgstr "" +"Désolé, vous devez avoir le droit de modifier des articles sur ce site si " +"vous voulez visualiser les mots-clés." + +#: wp-includes/class-wp-xmlrpc-server.php:2601 +msgid "Sorry, you do not have the right to add a category." +msgstr "Désolé, vous n’avez pas les droits pour ajouter une catégorie." + +#: wp-includes/class-wp-xmlrpc-server.php:2629 +#: wp-includes/class-wp-xmlrpc-server.php:2631 +msgid "Sorry, the new category failed." +msgstr "Désolé, la création de la catégorie a échoué." + +#: wp-includes/class-wp-xmlrpc-server.php:2661 +msgid "Sorry, you do not have the right to delete a category." +msgstr "Désolé, vous n’avez pas les droits pour supprimer une catégorie." + +#: wp-includes/class-wp-xmlrpc-server.php:2692 +msgid "" +"Sorry, you must be able to edit posts to this site in order to view " +"categories." +msgstr "" +"Désolé, vous devez avoir le droit d’écrire des articles pour ce site " +"si vous voulez visualiser les catégories." + +#: wp-includes/class-wp-xmlrpc-server.php:2728 +#: wp-includes/class-wp-xmlrpc-server.php:2829 +#: wp-includes/class-wp-xmlrpc-server.php:2835 +#: wp-includes/class-wp-xmlrpc-server.php:2884 +#: wp-includes/class-wp-xmlrpc-server.php:2890 +msgid "You are not allowed to moderate comments on this site." +msgstr "" +"Vous n’avez pas l’autorisation de modérer les commentaires de ce " +"site." + +#: wp-includes/class-wp-xmlrpc-server.php:2733 +#: wp-includes/class-wp-xmlrpc-server.php:2832 +#: wp-includes/class-wp-xmlrpc-server.php:2887 +msgid "Invalid comment ID." +msgstr "Identifiant commentaire invalide." + +#: wp-includes/class-wp-xmlrpc-server.php:2769 +msgid "Sorry, you cannot edit comments." +msgstr "Désolé, vous ne pouvez pas modifier les commentaires." + +#: wp-includes/class-wp-xmlrpc-server.php:2899 +msgid "Invalid comment status." +msgstr "Statut du commentaire non valide." + +#: wp-includes/class-wp-xmlrpc-server.php:2931 +msgid "Sorry, the comment could not be edited. Something wrong happened." +msgstr "" +"Désolé, votre commentaire n’a pu être modifié. Une erreur est survenue." + +#: wp-includes/class-wp-xmlrpc-server.php:2964 +msgid "You must be registered to comment" +msgstr "Vous devez être enregistré pour laisser un commentaire" + +#: wp-includes/class-wp-xmlrpc-server.php:3006 +msgid "Comment author name and email are required" +msgstr "" +"L’auteur d’un commentaire doit renseigner son nom et son adresse " +"de messagerie" + +#: wp-includes/class-wp-xmlrpc-server.php:3008 +msgid "A valid email address is required" +msgstr "Une adresse de messagerie valide est requise" + +#: wp-includes/class-wp-xmlrpc-server.php:3044 +#: wp-includes/class-wp-xmlrpc-server.php:3103 +#: wp-includes/class-wp-xmlrpc-server.php:3129 +#: wp-includes/class-wp-xmlrpc-server.php:3155 +#: wp-includes/class-wp-xmlrpc-server.php:3372 +msgid "You are not allowed access to details about this site." +msgstr "" +"Vous n’avez pas l’autorisation d’accéder aux détails de ce " +"site." + +#: wp-includes/class-wp-xmlrpc-server.php:3071 +msgid "You are not allowed access to details about comments." +msgstr "" +"Vous n’avez pas l’autorisation d’accéder aux détails des " +"commentaires." + +#: wp-includes/class-wp-xmlrpc-server.php:3237 +msgid "You are not allowed to update options." +msgstr "" +"Vous n’avez pas l’autorisation de mettre à jour les options." + +#: wp-includes/class-wp-xmlrpc-server.php:3286 +#: wp-includes/class-wp-xmlrpc-server.php:3331 +#: wp-includes/class-wp-xmlrpc-server.php:4937 +msgid "You do not have permission to upload files." +msgstr "" +"Vous n’avez pas l’autorisation d’envoyer des fichiers." + +#: wp-includes/class-wp-xmlrpc-server.php:3445 +msgid "Sorry, you are not allowed to edit this post type." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de modifier ce type de " +"contenu." + +#: wp-includes/class-wp-xmlrpc-server.php:3540 +#: wp-includes/class-wp-xmlrpc-server.php:3601 +#: wp-includes/class-wp-xmlrpc-server.php:3604 +#: wp-includes/class-wp-xmlrpc-server.php:3607 +msgid "Invalid post ID" +msgstr "Identifiant de l’article non valable" + +#: wp-includes/class-wp-xmlrpc-server.php:3543 +msgid "Sorry, you are not allowed to edit posts." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de modifier les articles." + +#: wp-includes/class-wp-xmlrpc-server.php:3547 +#: wp-includes/class-wp-xmlrpc-server.php:3614 +msgid "Sorry, revisions are disabled." +msgstr "Désolé, les révisions sont désactivées." + +#: wp-includes/class-wp-xmlrpc-server.php:3712 +msgid "Sorry, you do not have access to user data on this site." +msgstr "" +"Vous n’avez pas l’autorisation d’accéder aux données " +"utilisateurs de ce site." + +#: wp-includes/class-wp-xmlrpc-server.php:3803 +#: wp-includes/class-wp-xmlrpc-server.php:5031 +msgid "Either there are no posts, or something went wrong." +msgstr "" +"Soit il n’y a pas d’articles, soit une erreur s’est " +"produite." + +#: wp-includes/class-wp-xmlrpc-server.php:3842 +#: wp-includes/class-wp-xmlrpc-server.php:3852 +msgid "Sorry, that file cannot be edited." +msgstr "Désolé, ce fichier ne peut pas être modifié." + +#: wp-includes/class-wp-xmlrpc-server.php:3935 +#: wp-includes/class-wp-xmlrpc-server.php:3989 +#: wp-includes/class-wp-xmlrpc-server.php:4742 +#: wp-includes/class-wp-xmlrpc-server.php:5233 +msgid "Sorry, no such post." +msgstr "Désolé, aucun article ne correspond." + +#: wp-includes/class-wp-xmlrpc-server.php:3940 +#: wp-includes/class-wp-xmlrpc-server.php:4385 +msgid "Sorry, you do not have the right to edit this post." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de modifier cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:3945 +#: wp-includes/class-wp-xmlrpc-server.php:4546 +msgid "Sorry, you do not have the right to publish this post." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de publier cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:3956 +msgid "" +"For some strange yet very annoying reason, this post could not be edited." +msgstr "Pour une bien étrange raison, cet article n’a pu être modifié." + +#: wp-includes/class-wp-xmlrpc-server.php:3992 +msgid "Sorry, you do not have the right to delete this post." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de supprimer cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:3997 +msgid "" +"For some strange yet very annoying reason, this post could not be deleted." +msgstr "Pour une bien étrange raison, cet article n’a pu être supprimé." + +#: wp-includes/class-wp-xmlrpc-server.php:4066 +msgid "Sorry, you are not allowed to publish pages on this site." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de publier des pages sur " +"ce site." + +#: wp-includes/class-wp-xmlrpc-server.php:4077 +#: wp-includes/class-wp-xmlrpc-server.php:4090 +#: wp-includes/class-wp-xmlrpc-server.php:4095 +msgid "Sorry, you are not allowed to publish posts on this site." +msgstr "" +"Désolé, vous n’avez pas l’autorisation de publier des articles " +"sur ce site." + +#: wp-includes/class-wp-xmlrpc-server.php:4103 +#: wp-includes/class-wp-xmlrpc-server.php:4399 +msgid "Invalid post format" +msgstr "Format d’article invalide" + +#: wp-includes/class-wp-xmlrpc-server.php:4136 +msgid "You are not allowed to create pages as this user." +msgstr "" +"Vous n’avez pas l’autorisation de créer des pages sous cet " +"identifiant." + +#: wp-includes/class-wp-xmlrpc-server.php:4434 +msgid "You are not allowed to change the post author as this user." +msgstr "" +"Vous n’avez pas l’autorisation de modifier des articles sous cet " +"identifiant." + +#: wp-includes/class-wp-xmlrpc-server.php:4438 +msgid "You are not allowed to change the page author as this user." +msgstr "" +"Vous n’avez pas l’autorisation de modifier des pages sous cet " +"identifiant." + +#: wp-includes/class-wp-xmlrpc-server.php:4544 +msgid "Sorry, you do not have the right to publish this page." +msgstr "Désolé, vous n’avez pas le droit de publier cette page." + +#: wp-includes/class-wp-xmlrpc-server.php:4582 +msgid "Sorry, your entry could not be edited. Something wrong happened." +msgstr "" +"Désolé, votre entrée n’a pu être modifiée. Une erreur est survenue." + +#: wp-includes/class-wp-xmlrpc-server.php:4884 +#: wp-includes/class-wp-xmlrpc-server.php:5083 +msgid "" +"Sorry, you must be able to edit posts on this site in order to view " +"categories." +msgstr "" +"Désolé, vous devez avoir le droit d’écrire des articles sur ce site si " +"vous vous visualisez les catégories." + +#: wp-includes/class-wp-xmlrpc-server.php:4964 +msgid "Could not write file %1$s (%2$s)" +msgstr "Impossible d’écrire le fichier %1$s (%2$s)" + +#: wp-includes/class-wp-xmlrpc-server.php:5124 +msgid "Sorry, you can not edit this post." +msgstr "Désolé, vous ne pouvez pas modifier cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:5282 +msgid "Sorry, you cannot publish this post." +msgstr "Désolé, vous ne pouvez pas publier cet article." + +#: wp-includes/class-wp-xmlrpc-server.php:5331 +msgid "Is there no link to us?" +msgstr "N’y a-t-il aucun lien vers nous ?" + +#: wp-includes/class-wp-xmlrpc-server.php:5371 +#: wp-includes/class-wp-xmlrpc-server.php:5378 +#: wp-includes/class-wp-xmlrpc-server.php:5385 +#: wp-includes/class-wp-xmlrpc-server.php:5498 +msgid "" +"The specified target URL cannot be used as a target. It either doesn’t " +"exist, or it is not a pingback-enabled resource." +msgstr "" +"L’adresse web spécifiée ne peut être utilisée comme cible. Soit elle " +"n’existe pas, ou il ne s’agit pas d’une ressource " +"reconnaissant les pings." + +#: wp-includes/class-wp-xmlrpc-server.php:5381 +msgid "" +"The source URL and the target URL cannot both point to the same resource." +msgstr "" +"L’adresse source et l’adresse cible ne peuvent pointer vers la " +"même ressource." + +#: wp-includes/class-wp-xmlrpc-server.php:5389 +msgid "The pingback has already been registered." +msgstr "Le ping a déjà été enregistré." + +#: wp-includes/class-wp-xmlrpc-server.php:5403 +msgid "The source URL does not exist." +msgstr "L’adresse d’origine n’existe pas." + +#: wp-includes/class-wp-xmlrpc-server.php:5415 +msgid "We cannot find a title on that page." +msgstr "Nous ne trouvons pas du titre pour cette page." + +#: wp-includes/class-wp-xmlrpc-server.php:5451 +msgid "" +"The source URL does not contain a link to the target URL, and so cannot be " +"used as a source." +msgstr "" +"L’adresse source ne contient pas de lien vers l’adresse cible, " +"et ne peut donc pas être utilisée comme source." + +#: wp-includes/class-wp-xmlrpc-server.php:5472 +msgid "Pingback from %1$s to %2$s registered. Keep the web talking! :-)" +msgstr "" +"Réception d’un ping de %1$s pour %2$s. Continuons la " +"conversation ! :-)" + +#: wp-includes/class-wp-xmlrpc-server.php:5505 +msgid "The specified target URL does not exist." +msgstr "L’adresse cible spécifiée n’existe pas." + +#: wp-includes/comment-template.php:688 wp-includes/comment-template.php:1154 +msgid "% Comments" +msgstr "% commentaires" + +#: wp-includes/comment-template.php:690 wp-includes/comment-template.php:1152 +msgid "No Comments" +msgstr "Pas de commentaire" + +#: wp-includes/comment-template.php:692 wp-includes/comment-template.php:1153 +msgid "1 Comment" +msgstr "Un commentaire" + +#: wp-includes/comment-template.php:830 wp-includes/comment-template.php:1974 +msgctxt "noun" +msgid "Comment" +msgstr "Commentaire" + +#: wp-includes/comment-template.php:831 +msgid "Trackback" +msgstr "Rétrolien" + +#: wp-includes/comment-template.php:832 +msgid "Pingback" +msgstr "Ping" + +#: wp-includes/comment-template.php:883 +msgid "" +"Use get_trackback_url() instead if you do not want the value " +"echoed." +msgstr "" +"Utilisez plutôt get_trackback_url() si vous préférez que la " +"valeur ne soit pas affichée." + +#: wp-includes/comment-template.php:1155 +msgid "Comments Off" +msgstr "Commentaires fermés" + +#: wp-includes/comment-template.php:1165 +msgid "Enter your password to view comments." +msgstr "Saisissez votre mot de passe pour accéder aux commentaires." + +#: wp-includes/comment-template.php:1200 +msgid "Comment on %s" +msgstr "Commentaire sur %s" + +#: wp-includes/comment-template.php:1235 wp-includes/script-loader.php:408 +msgid "Reply" +msgstr "Répondre" + +#: wp-includes/comment-template.php:1236 +msgid "Log in to Reply" +msgstr "Connectez-vous pour répondre" + +#: wp-includes/comment-template.php:1318 +msgid "Leave a Comment" +msgstr "Laisser un commentaire" + +#: wp-includes/comment-template.php:1319 +msgid "Log in to leave a Comment" +msgstr "Connectez-vous pour laisser un commentaire" + +#: wp-includes/comment-template.php:1370 +msgid "Click here to cancel reply." +msgstr "Cliquez ici pour annuler la réponse." + +#: wp-includes/comment-template.php:1453 wp-includes/comment-template.php:1981 +#: wp-includes/theme-compat/comments.php:58 +msgid "Leave a Reply" +msgstr "Laisser un commentaire" + +#: wp-includes/comment-template.php:1454 wp-includes/comment-template.php:1982 +#: wp-includes/theme-compat/comments.php:58 +msgid "Leave a Reply to %s" +msgstr "Répondre à %s" + +#: wp-includes/comment-template.php:1670 +msgid "Pingback:" +msgstr "Ping :" + +#: wp-includes/comment-template.php:1670 wp-includes/comment-template.php:1752 +#: wp-includes/media-template.php:249 +msgid "Edit" +msgstr "Modifier" + +#: wp-includes/comment-template.php:1700 +msgid "%s says:" +msgstr "%s dit :" + +#: wp-includes/comment-template.php:1703 wp-includes/comment-template.php:1756 +msgid "Your comment is awaiting moderation." +msgstr "Votre commentaire est en attente de modération" + +#. translators: 1: date, 2: time +#: wp-includes/comment-template.php:1710 +msgid "%1$s at %2$s" +msgstr "%1$s à %2$s" + +#: wp-includes/comment-template.php:1710 +msgid "(Edit)" +msgstr "(Modifier)" + +#: wp-includes/comment-template.php:1743 +msgid "%s says:" +msgstr "%s dit :" + +#: wp-includes/comment-template.php:1749 +msgctxt "1: date, 2: time" +msgid "%1$s at %2$s" +msgstr "%1$s à %2$s" + +#: wp-includes/comment-template.php:1954 +#: wp-includes/theme-compat/comments-popup.php:75 +#: wp-includes/theme-compat/comments.php:77 +msgid "Name" +msgstr "Nom" + +#: wp-includes/comment-template.php:1956 +msgid "Email" +msgstr "Adresse de contact" + +#: wp-includes/comment-template.php:1958 +#: wp-includes/theme-compat/comments.php:83 +msgid "Website" +msgstr "Site web" + +#: wp-includes/comment-template.php:1962 +msgid "Required fields are marked %s" +msgstr "Les champs obligatoires sont indiqués avec %s" + +#: wp-includes/comment-template.php:1975 +#: wp-includes/theme-compat/comments.php:65 +msgid "You must be logged in to post a comment." +msgstr "" +"Vous devez être connecté pour rédiger un commentaire." + +#: wp-includes/comment-template.php:1976 +msgid "" +"Logged in as %2$s. Log out?" +msgstr "" +"Connecté en tant que %2$s. Se déconnecter ?" + +#: wp-includes/comment-template.php:1977 +msgid "Your email address will not be published." +msgstr "Votre adresse de messagerie ne sera pas publiée." + +#: wp-includes/comment-template.php:1978 +msgid "" +"You may use these HTML tags " +"and attributes: %s" +msgstr "" +"Vous pouvez utiliser ces balises et attributs HTML : %s" + +#: wp-includes/comment-template.php:1983 +msgid "Cancel reply" +msgstr "Annuler la réponse." + +#: wp-includes/comment-template.php:1984 +msgid "Post Comment" +msgstr "Laisser un commentaire" + +#: wp-includes/comment.php:434 +msgid "Unapproved" +msgstr "Désapprouvé" + +#. translators: comment status +#: wp-includes/comment.php:436 +msgctxt "adjective" +msgid "Approved" +msgstr "Approuvé" + +#. translators: comment status +#: wp-includes/comment.php:438 +msgctxt "adjective" +msgid "Spam" +msgstr "Indésirable" + +#: wp-includes/comment.php:693 wp-includes/comment.php:695 +msgid "" +"Duplicate comment detected; it looks as though you’ve already said " +"that!" +msgstr "" +"Détection d’un doublon : il semble que vous avez déjà envoyé ce " +"commentaire !" + +#: wp-includes/comment.php:752 wp-includes/comment.php:754 +msgid "You are posting comments too quickly. Slow down." +msgstr "Vous envoyez vos commentaires trop rapidement. Prenez votre temps." + +#: wp-includes/comment.php:1474 +msgid "Could not update comment status" +msgstr "Impossible de mettre à jour le statut du commentaire" + +#: wp-includes/cron.php:159 +msgid "" +"This argument has changed to an array to match the behavior of the other " +"cron functions." +msgstr "" +"Cet argument a été transformé en un tableau, afin de mieux correspondre au " +"comportement des autres fonctions de cron." + +#: wp-includes/cron.php:321 +msgid "Once Hourly" +msgstr "Une fois par heure" + +#: wp-includes/cron.php:322 +msgid "Twice Daily" +msgstr "Deux fois par jour" + +#: wp-includes/cron.php:323 +msgid "Once Daily" +msgstr "Une fois par jour" + +#: wp-includes/default-widgets.php:17 +msgid "Your site’s WordPress Pages" +msgstr "Les pages statiques de votre site WordPress" + +#: wp-includes/default-widgets.php:18 wp-includes/default-widgets.php:24 +#: wp-includes/post-template.php:829 wp-includes/theme-compat/sidebar.php:55 +msgid "Pages" +msgstr "Pages" + +#: wp-includes/default-widgets.php:68 wp-includes/default-widgets.php:159 +msgid "Sort by:" +msgstr "Trier par :" + +#: wp-includes/default-widgets.php:70 +msgid "Page title" +msgstr "Titre de la page" + +#: wp-includes/default-widgets.php:71 +msgid "Page order" +msgstr "Ordre de la page" + +#: wp-includes/default-widgets.php:72 +msgid "Page ID" +msgstr "ID de la page" + +#: wp-includes/default-widgets.php:76 +msgid "Exclude:" +msgstr "Exclure :" + +#: wp-includes/default-widgets.php:78 +msgid "Page IDs, separated by commas." +msgstr "IDs de pages, séparés par une virgule." + +#: wp-includes/default-widgets.php:93 +msgid "Your blogroll" +msgstr "Vos liens préférés" + +#: wp-includes/default-widgets.php:94 +msgid "Links" +msgstr "Liens" + +#: wp-includes/default-widgets.php:148 +msgid "Select Link Category:" +msgstr "Sélectionner la catégorie de liens :" + +#: wp-includes/default-widgets.php:150 +msgctxt "links widget" +msgid "All Links" +msgstr "Tous les liens" + +#: wp-includes/default-widgets.php:161 +msgid "Link title" +msgstr "Titre du lien" + +#: wp-includes/default-widgets.php:162 +msgid "Link rating" +msgstr "Note du lien" + +#: wp-includes/default-widgets.php:163 +msgid "Link ID" +msgstr "ID du lien" + +#: wp-includes/default-widgets.php:164 +msgctxt "Links widget" +msgid "Random" +msgstr "Aléatoire" + +#: wp-includes/default-widgets.php:169 +msgid "Show Link Image" +msgstr "Afficher l’image du lien" + +#: wp-includes/default-widgets.php:171 +msgid "Show Link Name" +msgstr "Afficher le nom du lien" + +#: wp-includes/default-widgets.php:173 +msgid "Show Link Description" +msgstr "Afficher la description du lien" + +#: wp-includes/default-widgets.php:175 +msgid "Show Link Rating" +msgstr "Afficher la note du lien" + +#: wp-includes/default-widgets.php:178 +msgid "Number of links to show:" +msgstr "Nombre de liens à afficher :" + +#: wp-includes/default-widgets.php:193 +msgid "A search form for your site" +msgstr "Un formulaire de recherche pour votre site" + +#: wp-includes/default-widgets.php:236 +msgid "A monthly archive of your site’s posts" +msgstr "Une archive mensuelle des articles de votre site" + +#: wp-includes/default-widgets.php:237 wp-includes/default-widgets.php:244 +#: wp-includes/theme-compat/sidebar.php:57 +msgid "Archives" +msgstr "Archives" + +#: wp-includes/default-widgets.php:252 +msgid "Select Month" +msgstr "Choisir un mois" + +#: wp-includes/default-widgets.php:283 wp-includes/default-widgets.php:516 +msgid "Display as dropdown" +msgstr "Afficher comme liste déroulante" + +#: wp-includes/default-widgets.php:285 wp-includes/default-widgets.php:519 +msgid "Show post counts" +msgstr "Afficher le nombre d’articles" + +#: wp-includes/default-widgets.php:301 +msgid "Log in/out, admin, feed and WordPress links" +msgstr "" +"(Dé)connexion, administration, flux et autres liens internes à WordPress" + +#: wp-includes/default-widgets.php:302 wp-includes/default-widgets.php:307 +#: wp-includes/theme-compat/sidebar.php:69 +msgid "Meta" +msgstr "Méta" + +#: wp-includes/default-widgets.php:316 +msgid "Syndicate this site using RSS 2.0" +msgstr "Suivez ce site par syndication RSS 2.0" + +#: wp-includes/default-widgets.php:316 +msgid "Entries RSS" +msgstr "Flux RSS des articles" + +#: wp-includes/default-widgets.php:317 +msgid "The latest comments to all posts in RSS" +msgstr "Les derniers commentaires pour tous les articles, au format RSS" + +#: wp-includes/default-widgets.php:317 +msgid "Comments RSS" +msgstr "RSS des commentaires" + +#: wp-includes/default-widgets.php:320 wp-includes/theme-compat/sidebar.php:75 +msgid "" +"Powered by WordPress, state-of-the-art semantic personal publishing platform." +msgstr "" +"Propulsé par WordPress, plate-forme de publication personnelle sémantique de " +"pointe." + +#: wp-includes/default-widgets.php:321 +msgctxt "meta widget link text" +msgid "WordPress.org" +msgstr "Site de WordPress-FR" + +#: wp-includes/default-widgets.php:353 +msgid "A calendar of your site’s posts" +msgstr "Un calendrier des articles de votre site" + +#: wp-includes/default-widgets.php:354 +msgid "Calendar" +msgstr "Calendrier" + +#: wp-includes/default-widgets.php:394 +msgid "Arbitrary text or HTML" +msgstr "Texte ou code HTML arbitraire" + +#: wp-includes/default-widgets.php:396 +msgid "Text" +msgstr "Texte" + +#: wp-includes/default-widgets.php:431 +msgid "Automatically add paragraphs" +msgstr "Créer automatiquement les paragraphes" + +#: wp-includes/default-widgets.php:444 +msgid "A list or dropdown of categories" +msgstr "Une liste ou un menu déroulant des catégories" + +#: wp-includes/default-widgets.php:463 +msgid "Select Category" +msgstr "Choisir une catégorie" + +#: wp-includes/default-widgets.php:522 +msgid "Show hierarchy" +msgstr "Afficher la hiérarchie" + +#: wp-includes/default-widgets.php:536 +msgid "The most recent posts on your site" +msgstr "Les articles les plus récents de votre site" + +#: wp-includes/default-widgets.php:537 wp-includes/default-widgets.php:562 +msgid "Recent Posts" +msgstr "Articles récents" + +#: wp-includes/default-widgets.php:621 +msgid "Number of posts to show:" +msgstr "Nombre d’articles à afficher :" + +#: wp-includes/default-widgets.php:625 +msgid "Display post date?" +msgstr "Afficher la date du contenu ?" + +#: wp-includes/default-widgets.php:638 +msgid "The most recent comments" +msgstr "Les commentaires les plus récents" + +#: wp-includes/default-widgets.php:639 wp-includes/default-widgets.php:682 +msgid "Recent Comments" +msgstr "Commentaires récents" + +#. translators: comments widget: 1: comment author, 2: post link +#: wp-includes/default-widgets.php:700 +msgctxt "widgets" +msgid "%1$s on %2$s" +msgstr "%1$s dans %2$s" + +#: wp-includes/default-widgets.php:731 +msgid "Number of comments to show:" +msgstr "Nombre de commentaires à afficher :" + +#: wp-includes/default-widgets.php:745 +msgid "Entries from any RSS or Atom feed" +msgstr "Articles en provenance de n’importe lequel flux RSS ou ATOM" + +#: wp-includes/default-widgets.php:747 +msgid "RSS" +msgstr "Flux" + +#: wp-includes/default-widgets.php:783 +msgid "Unknown Feed" +msgstr "Flux inconnu" + +#: wp-includes/default-widgets.php:789 +msgid "Syndicate this content" +msgstr "Suivez ce contenu par syndication RSS" + +#: wp-includes/default-widgets.php:837 +msgid "RSS Error: %s" +msgstr "Erreur RSS : %s" + +#: wp-includes/default-widgets.php:853 wp-includes/rss.php:899 +msgid "" +"An error has occurred, which probably means the feed is down. Try again " +"later." +msgstr "" +"Une erreur est survenue, le flux est probablement indisponible. Veuillez " +"réessayer plus tard." + +#: wp-includes/default-widgets.php:867 +msgid "Untitled" +msgstr "Sans titre" + +#: wp-includes/default-widgets.php:945 +msgid "RSS Error: %s" +msgstr "Erreur RSS : %s" + +#: wp-includes/default-widgets.php:949 +msgid "Enter the RSS feed URL here:" +msgstr "Saisissez l’adresse web du flux RSS ici :" + +#: wp-includes/default-widgets.php:952 +msgid "Give the feed a title (optional):" +msgstr "Donnez un titre au flux (facultatif) :" + +#: wp-includes/default-widgets.php:955 +msgid "How many items would you like to display?" +msgstr "Combien d’entrées souhaitez-vous afficher ?" + +#: wp-includes/default-widgets.php:964 +msgid "Display item content?" +msgstr "Afficher le contenu de l’élément ?" + +#: wp-includes/default-widgets.php:967 +msgid "Display item author if available?" +msgstr "Afficher l’auteur de l’élément si disponible ?" + +#: wp-includes/default-widgets.php:970 +msgid "Display item date?" +msgstr "Afficher la date de l’élément ?" + +#: wp-includes/default-widgets.php:1036 +msgid "Your most used tags in cloud format" +msgstr "Vos mots-clés les plus utilisés, au format « nuage »" + +#: wp-includes/default-widgets.php:1037 +msgid "Tag Cloud" +msgstr "Nuage de mots-clés" + +#: wp-includes/default-widgets.php:1047 +msgid "Tags" +msgstr "Mots-clés" + +#: wp-includes/default-widgets.php:1075 +msgid "Taxonomy:" +msgstr "Taxinomie :" + +#: wp-includes/default-widgets.php:1103 +msgid "Use this widget to add one of your custom menus as a widget." +msgstr "" +"Utilisez ce widget pour ajouter l’un de vos menus en tant que widget." + +#: wp-includes/default-widgets.php:1104 +msgid "Custom Menu" +msgstr "Menu personnalisé" + +#: wp-includes/default-widgets.php:1141 +msgid "No menus have been created yet. Create some." +msgstr "" +"Aucun menu n’a été créé pour le moment. En créer un." + +#: wp-includes/default-widgets.php:1150 +msgid "Select Menu:" +msgstr "Sélectionner le menu :" + +#: wp-includes/deprecated.php:62 +msgid "new WordPress Loop" +msgstr "Nouvelle boucle WordPress" + +#: wp-includes/deprecated.php:707 +#: wp-includes/js/tinymce/langs/wp-langs.php:520 +#: wp-includes/media-template.php:280 wp-includes/media-template.php:326 +#: wp-includes/media-template.php:384 wp-includes/media-template.php:444 +#: wp-includes/media-template.php:459 wp-includes/script-loader.php:300 +msgid "None" +msgstr "Aucun" + +#: wp-includes/deprecated.php:987 +msgid "Last updated" +msgstr "Mis à jour récemment" + +#: wp-includes/deprecated.php:1884 wp-includes/post-template.php:1190 +msgid "Missing Attachment" +msgstr "Fichier attaché manquant" + +#: wp-includes/deprecated.php:2718 +msgid "First Post" +msgstr "Premier article" + +#: wp-includes/deprecated.php:2718 +msgid "Last Post" +msgstr "Dernier article" + +#: wp-includes/deprecated.php:3161 wp-includes/functions.php:2081 +msgid "Are you sure you want to do this?" +msgstr "Voulez-vous vraiment faire cela ?" + +#: wp-includes/deprecated.php:3211 +msgid "File “%s” doesn’t exist?" +msgstr "Le fichier « %s » n’existe pas ?" + +#: wp-includes/deprecated.php:3214 +msgid "The GD image library is not installed." +msgstr "La bibliothèque d’imagerie GD n’est pas installée." + +#: wp-includes/deprecated.php:3221 +msgid "File “%s” is not an image." +msgstr "Le fichier « %s » n’est pas une image." + +#: wp-includes/feed-atom-comments.php:19 +msgid "Comments on %s" +msgstr "Commentaires sur %s" + +#: wp-includes/feed-atom-comments.php:21 wp-includes/feed-rss2-comments.php:36 +msgid "Comments for %1$s searching on %2$s" +msgstr "Commentaires pour %1$s, recherche de %2$s" + +#: wp-includes/feed-atom-comments.php:23 wp-includes/feed-rss2-comments.php:38 +msgid "Comments for %s" +msgstr "Commentaires pour %s" + +#: wp-includes/feed-atom-comments.php:53 wp-includes/feed-rss2-comments.php:65 +msgid "Comment on %1$s by %2$s" +msgstr "Commentaires sur %1$s par %2$s" + +# Ne pas ajouter d'entités : utilisé par le flux RSS +#: wp-includes/feed-atom-comments.php:55 wp-includes/feed-rss2-comments.php:67 +msgid "By: %s" +msgstr "Par : %s" + +# Ne pas ajouter d'entités : utilisé par le flux RSS +#: wp-includes/feed-rss2-comments.php:34 +msgid "Comments on: %s" +msgstr "Commentaires sur : %s" + +# Ne pas ajouter d'entités : utilisé par le flux RSS +#: wp-includes/feed-rss2-comments.php:75 +msgid "Protected Comments: Please enter your password to view comments." +msgstr "" +"Commentaires protégés : saisissez votre mot de passe pour accéder aux " +"commentaires." + +#. translators: opening curly double quote +#: wp-includes/formatting.php:37 wp-includes/formatting.php:3335 +msgctxt "opening curly double quote" +msgid "“" +msgstr "« " + +#. translators: closing curly double quote +#: wp-includes/formatting.php:39 +msgctxt "closing curly double quote" +msgid "”" +msgstr " »" + +#. translators: apostrophe, for example in 'cause or can't +#: wp-includes/formatting.php:42 +msgctxt "apostrophe" +msgid "’" +msgstr "’" + +#. translators: prime, for example in 9' (nine feet) +#: wp-includes/formatting.php:45 +msgctxt "prime" +msgid "′" +msgstr "′" + +#. translators: double prime, for example in 9" (nine inches) +#: wp-includes/formatting.php:47 +msgctxt "double prime" +msgid "″" +msgstr "″" + +#. translators: opening curly single quote +#: wp-includes/formatting.php:50 +msgctxt "opening curly single quote" +msgid "‘" +msgstr "‘" + +#. translators: closing curly single quote +#: wp-includes/formatting.php:52 +msgctxt "closing curly single quote" +msgid "’" +msgstr "’" + +#. translators: en dash +#: wp-includes/formatting.php:55 +msgctxt "en dash" +msgid "–" +msgstr "–" + +#. translators: em dash +#: wp-includes/formatting.php:57 +msgctxt "em dash" +msgid "—" +msgstr "—" + +#. translators: min=minute +#: wp-includes/formatting.php:2145 +msgid "%s min" +msgid_plural "%s mins" +msgstr[0] "%s minute" +msgstr[1] "%s minutes" + +#: wp-includes/formatting.php:2150 +msgid "%s hour" +msgid_plural "%s hours" +msgstr[0] "%s heure" +msgstr[1] "%s heures" + +#: wp-includes/formatting.php:2155 +msgid "%s day" +msgid_plural "%s days" +msgstr[0] "%s jour" +msgstr[1] "%s jours" + +#: wp-includes/formatting.php:2160 +msgid "%s week" +msgid_plural "%s weeks" +msgstr[0] "%s semaine" +msgstr[1] "%s semaines" + +#: wp-includes/formatting.php:2165 +msgid "%s month" +msgid_plural "%s months" +msgstr[0] "%s mois" +msgstr[1] "%s mois" + +#: wp-includes/formatting.php:2170 +msgid "%s year" +msgid_plural "%s years" +msgstr[0] "%s année" +msgstr[1] "%s années" + +#: wp-includes/formatting.php:2223 wp-includes/general-template.php:2044 +msgid "…" +msgstr "…" + +#. translators: If your word count is based on single characters (East Asian +#. characters), +#. enter 'characters'. Otherwise, enter 'words'. Do not translate into your +#. own language. +#. translators: If your word count is based on single characters (East Asian +#. characters), +#. enter 'characters'. Otherwise, enter 'words'. Do not translate into +#. your own language. +#: wp-includes/formatting.php:2228 wp-includes/script-loader.php:356 +msgctxt "word count: words or characters?" +msgid "words" +msgstr "words" + +#: wp-includes/formatting.php:2812 +msgid "" +"The email address entered did not appear to be a valid email address. Please " +"enter a valid email address." +msgstr "" +"L’adresse de messagerie fournie ne semble pas être valide. Veuillez " +"saisir une adresse valide." + +#: wp-includes/formatting.php:2899 +msgid "" +"The WordPress address you entered did not appear to be a valid URL. Please " +"enter a valid URL." +msgstr "" +"L’adresse de WordPress que vous avez saisie ne semble pas être valide. " +"Veuillez entrer une adresse valide." + +#: wp-includes/formatting.php:2909 +msgid "" +"The Site address you entered did not appear to be a valid URL. Please enter " +"a valid URL." +msgstr "" +"L’adresse de site que vous avez saisie ne semble pas être valide. " +"Veuillez entrer une adresse valide." + +#: wp-includes/formatting.php:2950 +msgid "" +"The timezone you have entered is not valid. Please select a valid timezone." +msgstr "" +"Le fuseau horaire ne semble pas être valide. Veuillez en choisir une valide." + +#. translators: used between list items, there is a space after the and +#: wp-includes/formatting.php:3110 +msgid ", and " +msgstr " et " + +#. translators: used between only two list items, there is a space after the +#. and +#: wp-includes/formatting.php:3112 +msgid " and " +msgstr " et " + +#: wp-includes/functions.php:1038 +msgid "ERROR: This is not a valid feed template." +msgstr "ERREUR : ce n’est pas un flux valide." + +#: wp-includes/functions.php:1180 +msgid "" +"One or more database tables are unavailable. The database may need to be repaired." +msgstr "" +"Une ou plusieurs tables de votre base de données sont indisponibles. La base " +"de données a peut-être besoin d’être réparée." + +#: wp-includes/functions.php:1657 wp-includes/functions.php:1780 +msgid "" +"Unable to create directory %s. Is its parent directory writable by the " +"server?" +msgstr "" +"Impossible de créer le dossier %s. Son dossier parent est-il accessible en " +"écriture par le serveur ?" + +#: wp-includes/functions.php:1754 +msgid "Empty filename" +msgstr "Pas de nom de fichier" + +#: wp-includes/functions.php:1758 +msgid "Invalid file type" +msgstr "Type du fichier non valide" + +#: wp-includes/functions.php:1786 +msgid "Could not write file %s" +msgstr "Impossible d’écrire le fichier %s" + +#: wp-includes/functions.php:2076 +msgid "WordPress Failure Notice" +msgstr "Avertissement d’échec de WordPress" + +#: wp-includes/functions.php:2078 +msgid "You are attempting to log out of %s" +msgstr "Vous êtes en train de vous déconnecter de %s." + +#: wp-includes/functions.php:2079 +msgid "Do you really want to log out?" +msgstr "Voulez-vous réellement vous déconnecter ?" + +#: wp-includes/functions.php:2083 wp-includes/ms-functions.php:1611 +msgid "Please try again." +msgstr "Veuillez réessayer." + +#: wp-includes/functions.php:2157 +msgid "« Back" +msgstr "« Retour" + +#: wp-includes/functions.php:2169 wp-load.php:61 +msgid "WordPress › Error" +msgstr "WordPress » Erreur" + +#: wp-includes/functions.php:2828 +msgid "Database Error" +msgstr "Erreur de la base de données" + +#: wp-includes/functions.php:2832 wp-includes/ms-load.php:243 +msgid "Error establishing a database connection" +msgstr "Erreur lors de la connexion à la base de données" + +#: wp-includes/functions.php:2919 wp-includes/functions.php:2966 +msgid "" +"%1$s is deprecated since version %2$s! Use %3$s instead." +msgstr "" +"%1$s est déprécié depuis la version %2$s! Utilisez %3$s à " +"la place." + +#: wp-includes/functions.php:2921 wp-includes/functions.php:2968 +msgid "" +"%1$s is deprecated since version %2$s with no alternative " +"available." +msgstr "" +"%1$s est déprécié depuis la version %2$s, aucune " +"alternative n’est disponible." + +#: wp-includes/functions.php:3017 +msgid "" +"%1$s was called with an argument that is deprecated since " +"version %2$s! %3$s" +msgstr "" +"%1$s est appelé avec un argument qui est déprécié depuis la " +"version %2$s ! %3$s" + +#: wp-includes/functions.php:3019 +msgid "" +"%1$s was called with an argument that is deprecated since " +"version %2$s with no alternative available." +msgstr "" +"%1$s est appelé avec un argument qui est déprécié depuis la " +"version %2$s, aucune alternative n’est disponible." + +#: wp-includes/functions.php:3058 +msgid "(This message was added in version %s.)" +msgstr "(Ce message a été ajouté à la version %s.)" + +#: wp-includes/functions.php:3059 +msgid "" +"Please see Debugging in WordPress for more information." +msgstr "" +"Veuillez consulter la page Debugger dans WordPress (EN) pour plus d’" +"informations." + +#: wp-includes/functions.php:3060 +msgid "%1$s was called incorrectly. %2$s %3$s" +msgstr "%1$s est appelée de la mauvaise manière. %2$s %3$s" + +#: wp-includes/functions.php:3523 +msgid "Select a city" +msgstr "Sélectionnez une ville" + +#: wp-includes/functions.php:3568 wp-includes/functions.php:3572 +msgid "UTC" +msgstr "UTC" + +#: wp-includes/functions.php:3576 +msgid "Manual Offsets" +msgstr "Décalages manuels" + +#: wp-includes/functions.php:4083 wp-includes/js/tinymce/langs/wp-langs.php:23 +#: wp-includes/js/tinymce/wp-mce-help.php:245 +#: wp-includes/media-template.php:32 wp-includes/script-loader.php:204 +#: wp-includes/script-loader.php:294 wp-includes/script-loader.php:372 +msgid "Close" +msgstr "Fermer" + +#: wp-includes/functions.php:4094 +msgid "Session expired" +msgstr "La session a expiré" + +#: wp-includes/functions.php:4095 wp-includes/user.php:125 +msgid "Please log in again." +msgstr "Veuillez vous reconnecter." + +#: wp-includes/functions.php:4096 +msgid "" +"The login page will open in a new window. After logging in you can close it " +"and return to this page." +msgstr "" +"La page de connexion s’ouvrira dans une nouvelle fenêtre. Après vous " +"être connecté, vous pourrez la fermer et revenir à cette page." + +#: wp-includes/functions.wp-scripts.php:35 +#: wp-includes/functions.wp-scripts.php:72 +#: wp-includes/functions.wp-scripts.php:112 +#: wp-includes/functions.wp-scripts.php:138 +#: wp-includes/functions.wp-scripts.php:194 +#: wp-includes/functions.wp-scripts.php:222 +#: wp-includes/functions.wp-scripts.php:247 +#: wp-includes/functions.wp-styles.php:36 +#: wp-includes/functions.wp-styles.php:69 +#: wp-includes/functions.wp-styles.php:104 +#: wp-includes/functions.wp-styles.php:126 +#: wp-includes/functions.wp-styles.php:159 +#: wp-includes/functions.wp-styles.php:185 +#: wp-includes/functions.wp-styles.php:209 +msgid "" +"Scripts and styles should not be registered or enqueued until the %1$s, " +"%2$s, or %3$s hooks." +msgstr "" +"Les scripts et les styles ne peuvent pas être enregistrés ou ajoutés avant " +"le déclenchement des crochets %1$s, %2$s ou %3$s." + +#: wp-includes/functions.wp-scripts.php:161 +msgid "" +"Do not deregister the %1$s script in the administration area. To target the " +"frontend theme, use the %2$s hook." +msgstr "" +"Ne désenregistrez pas le script %1$s de la zone d’administration. Pour " +"cibler le thème public, utilisez le crochet %2$s." + +#: wp-includes/general-template.php:174 wp-includes/general-template.php:175 +#: wp-includes/general-template.php:182 +msgctxt "label" +msgid "Search for:" +msgstr "Recherche pour :" + +#: wp-includes/general-template.php:175 +msgctxt "placeholder" +msgid "Search …" +msgstr "Recherche…" + +#: wp-includes/general-template.php:177 wp-includes/general-template.php:184 +msgctxt "submit button" +msgid "Search" +msgstr "Rechercher" + +#: wp-includes/general-template.php:215 wp-login.php:538 wp-login.php:587 +#: wp-login.php:618 wp-login.php:700 +msgid "Log in" +msgstr "Connexion" + +#: wp-includes/general-template.php:217 +msgid "Log out" +msgstr "Déconnexion" + +#: wp-includes/general-template.php:303 wp-login.php:678 wp-login.php:837 +msgid "Username" +msgstr "Identifiant" + +#: wp-includes/general-template.php:304 wp-login.php:841 +msgid "Password" +msgstr "Mot de passe" + +#: wp-includes/general-template.php:305 wp-login.php:852 +msgid "Remember Me" +msgstr "Se souvenir de moi" + +#: wp-includes/general-template.php:306 wp-login.php:828 wp-login.php:854 +msgid "Log In" +msgstr "Se connecter" + +#: wp-includes/general-template.php:383 wp-login.php:541 wp-login.php:621 +#: wp-login.php:696 wp-login.php:871 +msgid "Register" +msgstr "Inscription" + +#: wp-includes/general-template.php:387 +msgid "Site Admin" +msgstr "Admin. du Site" + +#: wp-includes/general-template.php:452 +msgid "" +"The %s option is deprecated for the family of bloginfo() functions." +msgstr "" +"L’option %s est obsolète pour la famille des fonctions " +"basées sur bloginfo()." + +#: wp-includes/general-template.php:452 +msgid "Use the %s option instead." +msgstr "Utilisez plutôt l’option %s." + +#. translators: 1: separator, 2: search phrase +#: wp-includes/general-template.php:635 +msgid "Search Results %1$s %2$s" +msgstr "Résultats de recherche %1$s %2$s" + +#: wp-includes/general-template.php:640 +msgid "Page not found" +msgstr "Page non trouvée" + +# %1$s : le mois +# %2$d : l'année +#. translators: 1: month name, 2: 4-digit year +#: wp-includes/general-template.php:997 +msgid "%1$s %2$d" +msgstr "%1$s %2$d" + +#. translators: Calendar caption: 1: month name, 2: 4-digit year +#: wp-includes/general-template.php:1197 +msgctxt "calendar caption" +msgid "%1$s %2$s" +msgstr "%1$s %2$s" + +#: wp-includes/general-template.php:1223 wp-includes/general-template.php:1231 +msgid "View posts for %1$s %2$s" +msgstr "Voir les articles pour %1$s %2$s" + +#. translators: Separator between blog name and feed type in feed links +#: wp-includes/general-template.php:1652 wp-includes/general-template.php:1675 +msgctxt "feed link" +msgid "»" +msgstr "»" + +#. translators: 1: blog title, 2: separator (raquo) +#: wp-includes/general-template.php:1654 +msgid "%1$s %2$s Feed" +msgstr "%1$s %2$s Flux" + +#. translators: 1: blog title, 2: separator (raquo) +#: wp-includes/general-template.php:1656 +msgid "%1$s %2$s Comments Feed" +msgstr "%1$s %2$s Flux des commentaires" + +#. translators: 1: blog name, 2: separator(raquo), 3: post title +#: wp-includes/general-template.php:1677 +msgid "%1$s %2$s %3$s Comments Feed" +msgstr "%1$s %2$s %3$s Flux des commentaires" + +#. translators: 1: blog name, 2: separator(raquo), 3: category name +#: wp-includes/general-template.php:1679 +msgid "%1$s %2$s %3$s Category Feed" +msgstr "%1$s %2$s Flux de la catégorie %3$s" + +#. translators: 1: blog name, 2: separator(raquo), 3: tag name +#: wp-includes/general-template.php:1681 +msgid "%1$s %2$s %3$s Tag Feed" +msgstr "%1$s %2$s Flux du mot-clé %3$s" + +#. translators: 1: blog name, 2: separator(raquo), 3: author name +#: wp-includes/general-template.php:1683 +msgid "%1$s %2$s Posts by %3$s Feed" +msgstr "%1$s %2$s Flux des articles écrits par %3$s" + +#. translators: 1: blog name, 2: separator(raquo), 3: search phrase +#: wp-includes/general-template.php:1685 +msgid "%1$s %2$s Search Results for “%3$s” Feed" +msgstr "%1$s %2$s Flux de résultats de la recherche pour "%3$s"" + +#. translators: 1: blog name, 2: separator(raquo), 3: post type name +#: wp-includes/general-template.php:1687 +msgid "%1$s %2$s %3$s Feed" +msgstr "%1$s %2$s Flux pour %3$s" + +#: wp-includes/general-template.php:1996 +msgid "« Previous" +msgstr "« Précédent" + +#: wp-includes/general-template.php:1997 +msgid "Next »" +msgstr "Suivant »" + +#: wp-includes/general-template.php:2104 +msgctxt "admin color scheme" +msgid "Blue" +msgstr "Bleu" + +#: wp-includes/general-template.php:2106 +msgctxt "admin color scheme" +msgid "Gray" +msgstr "Gris" + +#: wp-includes/js/tinymce/langs/wp-langs.php:18 +msgid "Do you want to use the WYSIWYG mode for this textarea?" +msgstr "Voulez-vous utiliser le mode WYSIWYG pour ce champ textuel ?" + +#: wp-includes/js/tinymce/langs/wp-langs.php:19 +msgid "Apply" +msgstr "Appliquer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:20 +msgid "Insert" +msgstr "Insérer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:24 +msgid "Browse" +msgstr "Parcourir" + +#: wp-includes/js/tinymce/langs/wp-langs.php:25 +#: wp-includes/js/tinymce/langs/wp-langs.php:402 +msgid "Class" +msgstr "Classe" + +#: wp-includes/js/tinymce/langs/wp-langs.php:26 +msgid "-- Not set --" +msgstr "-- Pas réglé --" + +#: wp-includes/js/tinymce/langs/wp-langs.php:27 +#: wp-includes/js/tinymce/langs/wp-langs.php:324 +msgid "Copy/Cut/Paste is not available in Mozilla and Firefox." +msgstr "" +"Le Copier/Couper/Coller n’est pas disponible dans Mozilla ni Firefox." + +#: wp-includes/js/tinymce/langs/wp-langs.php:28 +msgid "" +"Currently not supported by your browser, use keyboard shortcuts instead." +msgstr "" +"Actuellement pas reconnu par votre navigateur ; utiliser les raccourcis-" +"clavier à la place." + +#: wp-includes/js/tinymce/langs/wp-langs.php:29 +msgid "" +"Sorry, but we have noticed that your popup-blocker has disabled a window " +"that provides application functionality. You will need to disable popup " +"blocking on this site in order to fully utilize this tool." +msgstr "" +"Désolé, mais nous avons remarqué que votre bloqueur de fenêtres pop-up a " +"annulé la fenêtre qui apporte certaines fonctionnalités. Vous devrez annuler " +"le blocage de popup pour ce site si vous souhaitez utiliser toutes les " +"fonctions de cet outil." + +#: wp-includes/js/tinymce/langs/wp-langs.php:30 +msgid "ERROR: Invalid values entered, these are marked in red." +msgstr "" +"ERREUR : certaines valeurs saisies ne sont pas valides, elles sont " +"indiquées en rouge." + +#: wp-includes/js/tinymce/langs/wp-langs.php:31 +msgid "{#field} must be a number" +msgstr "{#field} doit être un nombre" + +#: wp-includes/js/tinymce/langs/wp-langs.php:32 +msgid "{#field} must be a number greater than {#min}" +msgstr "{#field} doit être un nombre plus grand que {#min}" + +#: wp-includes/js/tinymce/langs/wp-langs.php:33 +msgid "{#field} must be a number or percentage" +msgstr "{#field} doit être un nombre ou un pourcentage" + +#: wp-includes/js/tinymce/langs/wp-langs.php:34 +#: wp-includes/js/tinymce/langs/wp-langs.php:328 +msgid "More colors" +msgstr "Plus de couleurs" + +#: wp-includes/js/tinymce/langs/wp-langs.php:38 +msgid "Black" +msgstr "Noir" + +#: wp-includes/js/tinymce/langs/wp-langs.php:39 +msgid "Burnt orange" +msgstr "Orange foncé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:40 +msgid "Dark olive" +msgstr "Olive foncé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:41 +msgid "Dark green" +msgstr "Vert foncé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:42 +msgid "Dark azure" +msgstr "Azur foncé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:43 +msgid "Navy Blue" +msgstr "Bleu marine" + +#: wp-includes/js/tinymce/langs/wp-langs.php:44 +msgid "Indigo" +msgstr "Bleu indigo" + +#: wp-includes/js/tinymce/langs/wp-langs.php:45 +msgid "Very dark gray" +msgstr "Gris foncé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:46 +msgid "Maroon" +msgstr "Rouge bordeaux" + +#: wp-includes/js/tinymce/langs/wp-langs.php:47 +msgid "Orange" +msgstr "Orange" + +#: wp-includes/js/tinymce/langs/wp-langs.php:48 +msgid "Olive" +msgstr "Vert olive" + +#: wp-includes/js/tinymce/langs/wp-langs.php:49 +msgid "Green" +msgstr "Vert" + +#: wp-includes/js/tinymce/langs/wp-langs.php:50 +msgid "Teal" +msgstr "Turquoise (bleu-vert)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:51 +msgid "Blue" +msgstr "Bleu" + +#: wp-includes/js/tinymce/langs/wp-langs.php:52 +msgid "Grayish blue" +msgstr "Bleu grisé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:53 +msgid "Gray" +msgstr "Gris" + +#: wp-includes/js/tinymce/langs/wp-langs.php:54 +msgid "Red" +msgstr "Rouge" + +#: wp-includes/js/tinymce/langs/wp-langs.php:55 +msgid "Amber" +msgstr "Ambre" + +#: wp-includes/js/tinymce/langs/wp-langs.php:56 +msgid "Yellow green" +msgstr "Jaune-vert" + +#: wp-includes/js/tinymce/langs/wp-langs.php:57 +msgid "Sea green" +msgstr "Vert de mer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:58 +msgid "Turquoise" +msgstr "Turquoise" + +#: wp-includes/js/tinymce/langs/wp-langs.php:59 +msgid "Royal blue" +msgstr "Bleu roi" + +#: wp-includes/js/tinymce/langs/wp-langs.php:60 +msgid "Purple" +msgstr "Violet" + +#: wp-includes/js/tinymce/langs/wp-langs.php:61 +msgid "Medium gray" +msgstr "Gris moyen" + +#: wp-includes/js/tinymce/langs/wp-langs.php:62 +msgid "Magenta" +msgstr "Bleur magenta" + +#: wp-includes/js/tinymce/langs/wp-langs.php:63 +msgid "Gold" +msgstr "Or" + +#: wp-includes/js/tinymce/langs/wp-langs.php:64 +msgid "Yellow" +msgstr "Jaune" + +#: wp-includes/js/tinymce/langs/wp-langs.php:65 +msgid "Lime" +msgstr "Lime (vert citron)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:66 +msgid "Aqua" +msgstr "Aqua" + +#: wp-includes/js/tinymce/langs/wp-langs.php:67 +msgid "Sky blue" +msgstr "Bleu ciel" + +#: wp-includes/js/tinymce/langs/wp-langs.php:68 +msgid "Brown" +msgstr "Marron" + +#: wp-includes/js/tinymce/langs/wp-langs.php:69 +msgid "Silver" +msgstr "Argent" + +#: wp-includes/js/tinymce/langs/wp-langs.php:70 +msgid "Pink" +msgstr "Rose" + +#: wp-includes/js/tinymce/langs/wp-langs.php:71 +msgid "Peach" +msgstr "Pèche" + +#: wp-includes/js/tinymce/langs/wp-langs.php:72 +msgid "Light yellow" +msgstr "Jaune clair" + +#: wp-includes/js/tinymce/langs/wp-langs.php:73 +msgid "Pale green" +msgstr "Vert clair" + +#: wp-includes/js/tinymce/langs/wp-langs.php:74 +msgid "Pale cyan" +msgstr "Cyan" + +#: wp-includes/js/tinymce/langs/wp-langs.php:75 +msgid "Light sky blue" +msgstr "Bleu ciel clair" + +#: wp-includes/js/tinymce/langs/wp-langs.php:76 +msgid "Plum" +msgstr "Prune" + +#: wp-includes/js/tinymce/langs/wp-langs.php:77 +msgid "White" +msgstr "Blanc" + +#: wp-includes/js/tinymce/langs/wp-langs.php:81 +#: wp-includes/js/tinymce/langs/wp-langs.php:368 +#: wp-includes/media-template.php:263 +msgid "Alignment" +msgstr "Alignement" + +#. translators: alignment +#: wp-includes/js/tinymce/langs/wp-langs.php:85 +msgid "Full" +msgstr "Complet" + +#. translators: alignment +#: wp-includes/js/tinymce/langs/wp-langs.php:89 +msgid "%Y-%m-%d" +msgstr "%Y-%m-%d" + +#. translators: year, month, date +#: wp-includes/js/tinymce/langs/wp-langs.php:90 +msgid "%H:%M:%S" +msgstr "%H h %M min %S s" + +#. translators: hours, minutes, seconds +#: wp-includes/js/tinymce/langs/wp-langs.php:91 +msgid "Insert date" +msgstr "Insérer la date" + +#: wp-includes/js/tinymce/langs/wp-langs.php:92 +msgid "Insert time" +msgstr "Insérer l’heure" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:131 +#: wp-includes/locale.php:146 +msgid "January" +msgstr "janvier" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:132 +#: wp-includes/locale.php:147 +msgid "February" +msgstr "février" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:133 +#: wp-includes/locale.php:148 +msgid "March" +msgstr "mars" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:134 +#: wp-includes/locale.php:149 +msgid "April" +msgstr "avril" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:135 +#: wp-includes/locale.php:150 +msgid "May" +msgstr "mai" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:136 +#: wp-includes/locale.php:151 +msgid "June" +msgstr "juin" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:137 +#: wp-includes/locale.php:152 +msgid "July" +msgstr "juillet" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:138 +#: wp-includes/locale.php:153 +msgid "August" +msgstr "août" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:139 +#: wp-includes/locale.php:154 +msgid "September" +msgstr "septembre" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:140 +#: wp-includes/locale.php:155 +msgid "October" +msgstr "octobre" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:141 +#: wp-includes/locale.php:156 +msgid "November" +msgstr "novembre" + +#. translators: month name +#: wp-includes/js/tinymce/langs/wp-langs.php:93 wp-includes/locale.php:142 +#: wp-includes/locale.php:157 +msgid "December" +msgstr "décembre" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:146 +msgid "Jan_January_abbreviation" +msgstr "jan" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:147 +msgid "Feb_February_abbreviation" +msgstr "fév" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:148 +msgid "Mar_March_abbreviation" +msgstr "mar" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:149 +msgid "Apr_April_abbreviation" +msgstr "avr" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:150 +msgid "May_May_abbreviation" +msgstr "mai" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:151 +msgid "Jun_June_abbreviation" +msgstr "juin" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:152 +msgid "Jul_July_abbreviation" +msgstr "juil" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:153 +msgid "Aug_August_abbreviation" +msgstr "août" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:154 +msgid "Sep_September_abbreviation" +msgstr "sept" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:155 +msgid "Oct_October_abbreviation" +msgstr "oct" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:156 +msgid "Nov_November_abbreviation" +msgstr "nov" + +#. translators: three-letter abbreviation of the month +#: wp-includes/js/tinymce/langs/wp-langs.php:94 wp-includes/locale.php:157 +msgid "Dec_December_abbreviation" +msgstr "déc" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:99 +#: wp-includes/locale.php:109 wp-includes/locale.php:122 +msgid "Sunday" +msgstr "Dimanche" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:100 +#: wp-includes/locale.php:110 wp-includes/locale.php:123 +msgid "Monday" +msgstr "Lundi" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:101 +#: wp-includes/locale.php:111 wp-includes/locale.php:124 +msgid "Tuesday" +msgstr "Mardi" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:102 +#: wp-includes/locale.php:112 wp-includes/locale.php:125 +msgid "Wednesday" +msgstr "Mercredi" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:103 +#: wp-includes/locale.php:113 wp-includes/locale.php:126 +msgid "Thursday" +msgstr "Jeudi" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:104 +#: wp-includes/locale.php:114 wp-includes/locale.php:127 +msgid "Friday" +msgstr "Vendredi" + +#. translators: weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:95 wp-includes/locale.php:105 +#: wp-includes/locale.php:115 wp-includes/locale.php:128 +msgid "Saturday" +msgstr "Samedi" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:122 +msgid "Sun" +msgstr "dim" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:123 +msgid "Mon" +msgstr "lun" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:124 +msgid "Tue" +msgstr "mar" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:125 +msgid "Wed" +msgstr "mer" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:126 +msgid "Thu" +msgstr "jeu" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:127 +msgid "Fri" +msgstr "ven" + +#. translators: three-letter abbreviation of the weekday +#: wp-includes/js/tinymce/langs/wp-langs.php:96 wp-includes/locale.php:128 +msgid "Sat" +msgstr "sam" + +#: wp-includes/js/tinymce/langs/wp-langs.php:100 +msgid "Print" +msgstr "Imprimer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:104 +#: wp-includes/js/tinymce/langs/wp-langs.php:397 +msgid "Preview" +msgstr "Aperçu" + +#: wp-includes/js/tinymce/langs/wp-langs.php:108 +msgid "Direction left to right" +msgstr "Direction de gauche à droite" + +#: wp-includes/js/tinymce/langs/wp-langs.php:109 +msgid "Direction right to left" +msgstr "Direction de droite à gauche" + +#: wp-includes/js/tinymce/langs/wp-langs.php:113 +msgid "Insert new layer" +msgstr "Insérer un nouveau calque" + +#: wp-includes/js/tinymce/langs/wp-langs.php:114 +msgid "Move forward" +msgstr "Avancer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:115 +msgid "Move backward" +msgstr "Reculer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:116 +msgid "Toggle absolute positioning" +msgstr "Modifier le positionnement absolu" + +#: wp-includes/js/tinymce/langs/wp-langs.php:117 +msgid "New layer..." +msgstr "Nouvelle couche…" + +#: wp-includes/js/tinymce/langs/wp-langs.php:122 +msgid "Cancel all changes" +msgstr "Annuler toutes les modifications" + +#: wp-includes/js/tinymce/langs/wp-langs.php:126 +msgid "Insert non-breaking space character" +msgstr "Insérer un espace insécable" + +#: wp-includes/js/tinymce/langs/wp-langs.php:130 +msgid "Run spell checking" +msgstr "Lancer le correcteur d’orthographe" + +#: wp-includes/js/tinymce/langs/wp-langs.php:131 +msgid "ieSpell not detected. Do you want to install it now?" +msgstr "" +"ieSpell n’a pas été détecté. Voulez-vous l’installer " +"maintenant ?" + +#: wp-includes/js/tinymce/langs/wp-langs.php:135 +msgid "Horizontal rule" +msgstr "Règle horizontale" + +#: wp-includes/js/tinymce/langs/wp-langs.php:139 +msgid "Emotions" +msgstr "Émotions" + +#: wp-includes/js/tinymce/langs/wp-langs.php:143 +msgid "Find" +msgstr "Chercher" + +#: wp-includes/js/tinymce/langs/wp-langs.php:144 +msgid "Find/Replace" +msgstr "Chercher/Remplacer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:148 +#: wp-includes/js/tinymce/langs/wp-langs.php:360 +msgid "Insert/edit image" +msgstr "Insérer/modifier une image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:152 +#: wp-includes/js/tinymce/langs/wp-langs.php:377 +#: wp-includes/script-loader.php:341 +msgid "Insert/edit link" +msgstr "Insérer/modifier un lien" + +#: wp-includes/js/tinymce/langs/wp-langs.php:156 +msgid "Citation" +msgstr "Citation" + +#: wp-includes/js/tinymce/langs/wp-langs.php:157 +msgid "Abbreviation" +msgstr "Abréviation" + +#: wp-includes/js/tinymce/langs/wp-langs.php:158 +msgid "Acronym" +msgstr "Acronyme" + +#: wp-includes/js/tinymce/langs/wp-langs.php:159 +msgid "Deletion" +msgstr "Coupure" + +#: wp-includes/js/tinymce/langs/wp-langs.php:160 +msgid "Insertion" +msgstr "Insertion" + +#: wp-includes/js/tinymce/langs/wp-langs.php:161 +msgid "Insert/Edit Attributes" +msgstr "Insérer/modider des attributs" + +#: wp-includes/js/tinymce/langs/wp-langs.php:165 +msgid "Edit CSS Style" +msgstr "Modifier le style CSS" + +#: wp-includes/js/tinymce/langs/wp-langs.php:169 +msgid "Paste as Plain Text" +msgstr "Coller du texte simple" + +#: wp-includes/js/tinymce/langs/wp-langs.php:170 +msgid "Paste from Word" +msgstr "Coller du texte Word" + +#: wp-includes/js/tinymce/langs/wp-langs.php:171 +msgid "Select All" +msgstr "Tout sélectionner" + +#: wp-includes/js/tinymce/langs/wp-langs.php:172 +msgid "" +"Paste is now in plain text mode. Click again to toggle back to regular paste " +"mode. After you paste something you will be returned to regular paste mode." +msgstr "" +"Le copier/coller est maintenant en mode « texte brut " +"». Cliquez de nouveau pour retourner au mode normal. Après avoir collé " +"votre contenu, le réglage reviendra au mode normal." + +#: wp-includes/js/tinymce/langs/wp-langs.php:173 +msgid "" +"Paste is now in plain text mode. Click again to toggle back to regular paste " +"mode." +msgstr "" +"Le copier/coller est maintenant en mode « texte brut " +"». Cliquez de nouveau pour retourner au mode normal." + +#: wp-includes/js/tinymce/langs/wp-langs.php:177 +#: wp-includes/js/tinymce/langs/wp-langs.php:179 +msgid "Use CTRL+V on your keyboard to paste the text into the window." +msgstr "" +"Utilisez Ctrl-V sur votre clavier pour coller le texte dans la fenêtre." + +#: wp-includes/js/tinymce/langs/wp-langs.php:178 +msgid "Keep linebreaks" +msgstr "Conserver les sauts de ligne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:183 +msgid "Inserts a new table" +msgstr "Insérer une nouvelle table" + +#: wp-includes/js/tinymce/langs/wp-langs.php:184 +msgid "Insert row before" +msgstr "Insérer une ligne avant" + +#: wp-includes/js/tinymce/langs/wp-langs.php:185 +msgid "Insert row after" +msgstr "Insérer une ligne après" + +#: wp-includes/js/tinymce/langs/wp-langs.php:186 +msgid "Delete row" +msgstr "Supprimer la ligne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:187 +msgid "Insert column before" +msgstr "Insérer une colonne avant" + +#: wp-includes/js/tinymce/langs/wp-langs.php:188 +msgid "Insert column after" +msgstr "Insérer une colonne après" + +#: wp-includes/js/tinymce/langs/wp-langs.php:189 +msgid "Remove column" +msgstr "Enlever la colonne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:190 +msgid "Split merged table cells" +msgstr "Scinder les cellules fusionnées du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:191 +msgid "Merge table cells" +msgstr "Fusionner les cellules du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:192 +msgid "Table row properties" +msgstr "Propriétés de la ligne du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:193 +msgid "Table cell properties" +msgstr "Propriétés de la cellule du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:194 +msgid "Table properties" +msgstr "Propriétés du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:195 +msgid "Paste table row before" +msgstr "Coller la ligne du tableau avant" + +#: wp-includes/js/tinymce/langs/wp-langs.php:196 +msgid "Paste table row after" +msgstr "Coller la ligne du tableau après" + +#: wp-includes/js/tinymce/langs/wp-langs.php:197 +msgid "Cut table row" +msgstr "Couper la ligne du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:198 +msgid "Copy table row" +msgstr "Copier la ligne du tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:199 +msgid "Delete table" +msgstr "Supprimer le tableau" + +#: wp-includes/js/tinymce/langs/wp-langs.php:200 +msgid "Row" +msgstr "Ligne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:201 +msgid "Column" +msgstr "Colonne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:202 +msgid "Cell" +msgstr "Cellule" + +#: wp-includes/js/tinymce/langs/wp-langs.php:206 +#: wp-includes/script-loader.php:511 wp-includes/script-loader.php:631 +msgid "The changes you made will be lost if you navigate away from this page." +msgstr "" +"Les modifications que vous avez faites seront perdues si vous changez de " +"page." + +#: wp-includes/js/tinymce/langs/wp-langs.php:210 +msgid "Toggle fullscreen mode (Alt + Shift + G)" +msgstr "Basculer en mode plein écran (Alt + Maj. + G)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:214 +#: wp-includes/js/tinymce/langs/wp-langs.php:391 +msgid "Insert / edit embedded media" +msgstr "Insérer / modifier un média" + +#: wp-includes/js/tinymce/langs/wp-langs.php:215 +msgid "Edit embedded media" +msgstr "Modifier le média inséré" + +#: wp-includes/js/tinymce/langs/wp-langs.php:219 +msgid "Document properties" +msgstr "Propriétés du document" + +#: wp-includes/js/tinymce/langs/wp-langs.php:223 +msgid "Insert predefined template content" +msgstr "Insérer le contenu d’un modèle prédéfini" + +#: wp-includes/js/tinymce/langs/wp-langs.php:227 +msgid "Visual control characters on/off." +msgstr "Activer les caractères de mise en page." + +# Pas d'entité HTML : utilisé dans un alt="". +#: wp-includes/js/tinymce/langs/wp-langs.php:231 +msgid "Toggle spellchecker (Alt + Shift + N)" +msgstr "Correcteur d’orthographe (Alt + Maj. + N)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:232 +msgid "Spellchecker settings" +msgstr "Réglages du correcteur d’orthographe" + +#: wp-includes/js/tinymce/langs/wp-langs.php:233 +msgid "Ignore word" +msgstr "Ignorer le mot" + +#: wp-includes/js/tinymce/langs/wp-langs.php:234 +msgid "Ignore all" +msgstr "Ignorer tout" + +#: wp-includes/js/tinymce/langs/wp-langs.php:235 +msgid "Languages" +msgstr "Langues" + +#: wp-includes/js/tinymce/langs/wp-langs.php:236 +msgid "Please wait..." +msgstr "Veuillez patienter…" + +#: wp-includes/js/tinymce/langs/wp-langs.php:237 +msgid "Suggestions" +msgstr "Suggestions" + +#: wp-includes/js/tinymce/langs/wp-langs.php:238 +msgid "No suggestions" +msgstr "Aucune suggestion" + +#: wp-includes/js/tinymce/langs/wp-langs.php:239 +msgid "No misspellings found." +msgstr "Aucune erreur trouvée." + +#: wp-includes/js/tinymce/langs/wp-langs.php:240 +msgid "Learn word" +msgstr "Retenir ce mot" + +#: wp-includes/js/tinymce/langs/wp-langs.php:244 +msgid "Insert Page Break" +msgstr "Insérer la balise Page break" + +#: wp-includes/js/tinymce/langs/wp-langs.php:248 +msgid "Types" +msgstr "Types" + +#: wp-includes/js/tinymce/langs/wp-langs.php:250 +msgid "Lower alpha" +msgstr "Lettres minuscules" + +#: wp-includes/js/tinymce/langs/wp-langs.php:251 +msgid "Lower greek" +msgstr "Lettres grecques minuscules" + +#: wp-includes/js/tinymce/langs/wp-langs.php:252 +msgid "Lower roman" +msgstr "Chiffres romains minuscules" + +#: wp-includes/js/tinymce/langs/wp-langs.php:253 +msgid "Upper alpha" +msgstr "Lettres majuscules" + +#: wp-includes/js/tinymce/langs/wp-langs.php:254 +msgid "Upper roman" +msgstr "Chiffres romains majuscules" + +#: wp-includes/js/tinymce/langs/wp-langs.php:255 +msgid "Circle" +msgstr "Cercle" + +#: wp-includes/js/tinymce/langs/wp-langs.php:256 +msgid "Disc" +msgstr "Disque" + +#: wp-includes/js/tinymce/langs/wp-langs.php:257 +msgid "Square" +msgstr "Carré" + +#: wp-includes/js/tinymce/langs/wp-langs.php:261 +#: wp-includes/js/tinymce/langs/wp-langs.php:331 +msgid "Rich Text Area" +msgstr "Zone de texte enrichi" + +#: wp-includes/js/tinymce/langs/wp-langs.php:265 +msgid "Words:" +msgstr "Mots :" + +#: wp-includes/js/tinymce/langs/wp-langs.php:270 +msgid "Styles" +msgstr "Styles" + +#. translators: TinyMCE inline styles +#: wp-includes/js/tinymce/langs/wp-langs.php:271 +msgid "Font size" +msgstr "Taille de police" + +#: wp-includes/js/tinymce/langs/wp-langs.php:272 +msgid "Font family" +msgstr "Famille des polices" + +#: wp-includes/js/tinymce/langs/wp-langs.php:273 +msgid "Format" +msgstr "Format" + +#: wp-includes/js/tinymce/langs/wp-langs.php:274 +msgid "Paragraph" +msgstr "Paragraphe" + +#: wp-includes/js/tinymce/langs/wp-langs.php:275 +msgid "Div" +msgstr "Div" + +#: wp-includes/js/tinymce/langs/wp-langs.php:276 +#: wp-includes/js/tinymce/wp-mce-help.php:204 +msgid "Address" +msgstr "Adresse" + +#: wp-includes/js/tinymce/langs/wp-langs.php:277 +msgid "Preformatted" +msgstr "Pré-formaté" + +#: wp-includes/js/tinymce/langs/wp-langs.php:278 +#: wp-includes/js/tinymce/wp-mce-help.php:201 +msgid "Heading 1" +msgstr "Titre 1" + +#: wp-includes/js/tinymce/langs/wp-langs.php:279 +#: wp-includes/js/tinymce/wp-mce-help.php:202 +msgid "Heading 2" +msgstr "Titre 2" + +#: wp-includes/js/tinymce/langs/wp-langs.php:280 +#: wp-includes/js/tinymce/wp-mce-help.php:202 +msgid "Heading 3" +msgstr "Titre 3" + +#: wp-includes/js/tinymce/langs/wp-langs.php:281 +#: wp-includes/js/tinymce/wp-mce-help.php:203 +msgid "Heading 4" +msgstr "Titre 4" + +#: wp-includes/js/tinymce/langs/wp-langs.php:282 +#: wp-includes/js/tinymce/wp-mce-help.php:203 +msgid "Heading 5" +msgstr "Titre 5" + +#: wp-includes/js/tinymce/langs/wp-langs.php:283 +#: wp-includes/js/tinymce/wp-mce-help.php:204 +msgid "Heading 6" +msgstr "Titre 6" + +#: wp-includes/js/tinymce/langs/wp-langs.php:284 +msgid "Blockquote" +msgstr "Bloc de citation" + +#: wp-includes/js/tinymce/langs/wp-langs.php:285 +msgid "Code" +msgstr "Code" + +#: wp-includes/js/tinymce/langs/wp-langs.php:286 +msgid "Code sample" +msgstr "Exemple de code" + +#: wp-includes/js/tinymce/langs/wp-langs.php:287 +msgid "Definition term " +msgstr "Terme de définition" + +#: wp-includes/js/tinymce/langs/wp-langs.php:288 +msgid "Definition description" +msgstr "Description de la définition" + +#: wp-includes/js/tinymce/langs/wp-langs.php:291 +#: wp-includes/js/tinymce/wp-mce-help.php:201 +msgid "Underline" +msgstr "Souligner" + +#: wp-includes/js/tinymce/langs/wp-langs.php:292 +msgid "Strikethrough (Alt + Shift + D)" +msgstr "Barrer (Alt + Maj. + D)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:293 +msgid "Align Left (Alt + Shift + L)" +msgstr "Aligner à gauche (Alt + Maj. + L)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:294 +msgid "Align Center (Alt + Shift + C)" +msgstr "Centrer (Alt + Maj. + C)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:295 +msgid "Align Right (Alt + Shift + R)" +msgstr "Aligner à droite (Alt + Maj. + R)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:296 +msgid "Align Full (Alt + Shift + J)" +msgstr "Justifier (Alt + Maj. + S)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:299 +msgid "Outdent" +msgstr "Désindenter" + +#: wp-includes/js/tinymce/langs/wp-langs.php:300 +msgid "Indent" +msgstr "Indenter" + +#: wp-includes/js/tinymce/langs/wp-langs.php:301 +msgid "Undo (Ctrl + Z)" +msgstr "Annuler (Ctrl + Z)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:302 +msgid "Redo (Ctrl + Y)" +msgstr "Rétablir (Ctrl + Y)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:306 +msgid "Cleanup messy code" +msgstr "Nettoyer le mauvais code" + +#: wp-includes/js/tinymce/langs/wp-langs.php:307 +msgid "Edit HTML Source" +msgstr "Modifier le code source HTML" + +#: wp-includes/js/tinymce/langs/wp-langs.php:308 +msgid "Subscript" +msgstr "Indice" + +#: wp-includes/js/tinymce/langs/wp-langs.php:309 +msgid "Superscript" +msgstr "Exposant" + +#: wp-includes/js/tinymce/langs/wp-langs.php:310 +msgid "Insert horizontal ruler" +msgstr "Insérer une règle horizontale" + +#: wp-includes/js/tinymce/langs/wp-langs.php:311 +msgid "Remove formatting" +msgstr "Enlever la mise en forme" + +#: wp-includes/js/tinymce/langs/wp-langs.php:312 +msgid "Select text color" +msgstr "Sélectionner la couleur du texte" + +#: wp-includes/js/tinymce/langs/wp-langs.php:313 +msgid "Select background color" +msgstr "Sélectionner la couleur du fond" + +#: wp-includes/js/tinymce/langs/wp-langs.php:314 +msgid "Insert custom character" +msgstr "Insérer un caractère particulier" + +#: wp-includes/js/tinymce/langs/wp-langs.php:315 +msgid "Toggle guidelines/invisible elements" +msgstr "Afficher les lignes/éléments invisibles" + +#: wp-includes/js/tinymce/langs/wp-langs.php:316 +#: wp-includes/js/tinymce/langs/wp-langs.php:345 +msgid "Insert/edit anchor" +msgstr "Insérer/modifier un lien interne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:317 +#: wp-includes/js/tinymce/wp-mce-help.php:197 +msgid "Cut" +msgstr "Couper" + +#: wp-includes/js/tinymce/langs/wp-langs.php:318 +#: wp-includes/js/tinymce/wp-mce-help.php:196 +msgid "Copy" +msgstr "Copier" + +#: wp-includes/js/tinymce/langs/wp-langs.php:319 +#: wp-includes/js/tinymce/wp-mce-help.php:196 +msgid "Paste" +msgstr "Coller" + +#: wp-includes/js/tinymce/langs/wp-langs.php:320 +msgid "Image properties" +msgstr "Propriétés de l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:321 +msgid "New document" +msgstr "Nouveau document" + +#: wp-includes/js/tinymce/langs/wp-langs.php:322 +#: wp-includes/js/tinymce/langs/wp-langs.php:338 +#: wp-includes/js/tinymce/wp-mce-help.php:217 +msgid "Help" +msgstr "Aide" + +#: wp-includes/js/tinymce/langs/wp-langs.php:325 +msgid "Path" +msgstr "Chemin " + +#: wp-includes/js/tinymce/langs/wp-langs.php:326 +msgid "Are you sure you want to clear all contents?" +msgstr " Voulez-vous vraiment supprimer tout le contenu ?" + +#: wp-includes/js/tinymce/langs/wp-langs.php:327 +msgid "" +"Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - " +"Alt-X" +msgstr "" +"Aller aux boutons d’outils - Alt+Q ; Aller à l’éditeur - " +"Alt-Z ; Aller au chemin de l’élément - Alt-X" + +#: wp-includes/js/tinymce/langs/wp-langs.php:329 +#: wp-includes/js/tinymce/langs/wp-langs.php:386 +msgid "Accessibility Help" +msgstr "Aide à propos de l’accessibilité" + +#: wp-includes/js/tinymce/langs/wp-langs.php:330 +msgid "Press ALT F10 for toolbar. Press ALT 0 for help." +msgstr "" +"Appuyez sur Alt + F10 pour la barre d’outils. Appuyez sur Alt + 0 pour " +"l’aide." + +#: wp-includes/js/tinymce/langs/wp-langs.php:332 +msgid "Toolbar" +msgstr "Barre d’outils" + +#: wp-includes/js/tinymce/langs/wp-langs.php:336 +#: wp-includes/js/tinymce/wp-mce-help.php:229 +msgid "About TinyMCE" +msgstr "À propos de TinyMCE" + +#: wp-includes/js/tinymce/langs/wp-langs.php:337 +#: wp-includes/js/tinymce/wp-mce-help.php:165 +msgid "About" +msgstr "À propos" + +#: wp-includes/js/tinymce/langs/wp-langs.php:339 +msgid "License" +msgstr "Licence" + +#: wp-includes/js/tinymce/langs/wp-langs.php:341 +msgid "Plugin" +msgstr "Extension" + +#: wp-includes/js/tinymce/langs/wp-langs.php:342 +#: wp-includes/theme-compat/sidebar.php:21 +msgid "Author" +msgstr "Auteur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:343 +msgid "Version" +msgstr "Version" + +#: wp-includes/js/tinymce/langs/wp-langs.php:344 +msgid "Loaded plugins" +msgstr "Extensions chargées" + +#: wp-includes/js/tinymce/langs/wp-langs.php:346 +msgid "Anchor name" +msgstr "Nom du lien interne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:347 +msgid "HTML Source Editor" +msgstr "Éditeur de source HTML" + +#: wp-includes/js/tinymce/langs/wp-langs.php:348 +msgid "Word wrap" +msgstr "Retour à la ligne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:349 +msgid "Select a color" +msgstr "Sélectionnez une couleur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:350 +msgid "Picker" +msgstr "Sélecteur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:351 +msgid "Color picker" +msgstr "Sélecteur de couleur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:352 +msgid "Palette" +msgstr "Palette" + +#: wp-includes/js/tinymce/langs/wp-langs.php:353 +msgid "Palette colors" +msgstr "Couleurs de la palette" + +#: wp-includes/js/tinymce/langs/wp-langs.php:354 +msgid "Named" +msgstr "Par nom" + +#: wp-includes/js/tinymce/langs/wp-langs.php:355 +msgid "Named colors" +msgstr "Couleurs nommées" + +#: wp-includes/js/tinymce/langs/wp-langs.php:356 +msgid "Color:" +msgstr "Couleur :" + +#: wp-includes/js/tinymce/langs/wp-langs.php:357 +msgctxt "html attribute" +msgid "Name:" +msgstr "Nom :" + +#: wp-includes/js/tinymce/langs/wp-langs.php:358 +msgid "Select custom character" +msgstr "Sélectionnez un caractère" + +#: wp-includes/js/tinymce/langs/wp-langs.php:359 +msgid "Use left and right arrows to navigate." +msgstr "Utilisez les flèches gauche et droite pour naviguer." + +#: wp-includes/js/tinymce/langs/wp-langs.php:361 +#: wp-includes/media-template.php:453 +msgid "Image URL" +msgstr "Adresse web de l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:362 +msgid "Image description" +msgstr "Description de l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:363 +msgid "Image list" +msgstr "Liste d’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:364 +msgid "Border" +msgstr "Bordure" + +#: wp-includes/js/tinymce/langs/wp-langs.php:365 +#: wp-includes/js/tinymce/langs/wp-langs.php:396 +msgid "Dimensions" +msgstr "Dimensions" + +#: wp-includes/js/tinymce/langs/wp-langs.php:366 +msgid "Vertical space" +msgstr "Espace vertical" + +#: wp-includes/js/tinymce/langs/wp-langs.php:367 +msgid "Horizontal space" +msgstr "Espace horizontal" + +#: wp-includes/js/tinymce/langs/wp-langs.php:369 +msgid "Baseline" +msgstr "Slogan" + +#: wp-includes/js/tinymce/langs/wp-langs.php:370 +#: wp-includes/js/tinymce/langs/wp-langs.php:471 +msgid "Top" +msgstr "Haut" + +#: wp-includes/js/tinymce/langs/wp-langs.php:371 +msgid "Middle" +msgstr "Milieu" + +#: wp-includes/js/tinymce/langs/wp-langs.php:372 +#: wp-includes/js/tinymce/langs/wp-langs.php:473 +msgid "Bottom" +msgstr "Bas" + +#: wp-includes/js/tinymce/langs/wp-langs.php:373 +msgid "Text top" +msgstr "Haut du texte" + +#: wp-includes/js/tinymce/langs/wp-langs.php:374 +msgid "Text bottom" +msgstr "Bas du texte" + +#: wp-includes/js/tinymce/langs/wp-langs.php:378 +msgid "Link URL" +msgstr "Cible du lien" + +#: wp-includes/js/tinymce/langs/wp-langs.php:379 +#: wp-includes/js/tinymce/langs/wp-langs.php:430 +msgid "Target" +msgstr "Cible" + +#: wp-includes/js/tinymce/langs/wp-langs.php:380 +msgid "Open link in the same window" +msgstr "Fenêtre courante" + +#: wp-includes/js/tinymce/langs/wp-langs.php:381 +msgid "Open link in a new window" +msgstr "Nouvelle fenêtre" + +#: wp-includes/js/tinymce/langs/wp-langs.php:383 +msgid "" +"The URL you entered seems to be an email address, do you want to add the " +"required mailto: prefix?" +msgstr "" +"L’adresse web que vous avez entrée semble être une adresse de " +"messagerie  ; voulez-vous y ajouter le préfixe « mailto: " +"» requis ?" + +#: wp-includes/js/tinymce/langs/wp-langs.php:384 +msgid "" +"The URL you entered seems to external link, do you want to add the required " +"http:// prefix?" +msgstr "" +"L’adresse web que vous avez entrée semble être un lien externe ; " +"voulez-vous ajouter le préfixe « http:// » requis ?" + +#: wp-includes/js/tinymce/langs/wp-langs.php:385 +msgid "Link list" +msgstr "Liste de liens" + +#: wp-includes/js/tinymce/langs/wp-langs.php:387 +msgid "General Usage" +msgstr "Utilisation générale" + +#: wp-includes/js/tinymce/langs/wp-langs.php:392 +msgid "General" +msgstr "Général" + +#: wp-includes/js/tinymce/langs/wp-langs.php:393 +#: wp-includes/js/tinymce/wp-mce-help.php:163 +msgid "Advanced" +msgstr "Avancé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:394 +msgid "File/URL" +msgstr "Fichier/Adresse web" + +#: wp-includes/js/tinymce/langs/wp-langs.php:395 +#: wp-includes/js/tinymce/wp-mce-help.php:213 +#: wp-includes/js/tinymce/wp-mce-help.php:214 +msgid "List" +msgstr "Liste" + +#: wp-includes/js/tinymce/langs/wp-langs.php:398 +msgid "Constrain proportions" +msgstr "Respecter les proportions" + +#: wp-includes/js/tinymce/langs/wp-langs.php:399 +msgid "Type" +msgstr "Type" + +#: wp-includes/js/tinymce/langs/wp-langs.php:400 +msgid "Id" +msgstr "Id" + +#: wp-includes/js/tinymce/langs/wp-langs.php:401 +msgctxt "html attribute" +msgid "Name" +msgstr "Nom" + +#: wp-includes/js/tinymce/langs/wp-langs.php:403 +msgid "V-Space" +msgstr "V-Space" + +#: wp-includes/js/tinymce/langs/wp-langs.php:404 +msgid "H-Space" +msgstr "H-Space" + +#: wp-includes/js/tinymce/langs/wp-langs.php:405 +msgid "Auto play" +msgstr "Lecture automatique" + +#: wp-includes/js/tinymce/langs/wp-langs.php:406 +#: wp-includes/js/tinymce/langs/wp-langs.php:488 +msgid "Loop" +msgstr "Répéter" + +#: wp-includes/js/tinymce/langs/wp-langs.php:407 +msgid "Show menu" +msgstr "Afficher le menu" + +#: wp-includes/js/tinymce/langs/wp-langs.php:408 +msgid "Quality" +msgstr "Qualité" + +#: wp-includes/js/tinymce/langs/wp-langs.php:409 +msgid "Scale" +msgstr "Appliquer" + +#: wp-includes/js/tinymce/langs/wp-langs.php:410 +#: wp-includes/media-template.php:432 +msgid "Align" +msgstr "Alignement" + +#: wp-includes/js/tinymce/langs/wp-langs.php:411 +msgid "SAlign" +msgstr "SAlignement" + +#: wp-includes/js/tinymce/langs/wp-langs.php:412 +msgid "WMode" +msgstr "WMode" + +#: wp-includes/js/tinymce/langs/wp-langs.php:414 +msgid "Base" +msgstr "Base" + +#: wp-includes/js/tinymce/langs/wp-langs.php:415 +msgid "Flashvars" +msgstr "Variables Flash" + +#: wp-includes/js/tinymce/langs/wp-langs.php:416 +msgid "SWLiveConnect" +msgstr "SWLiveConnect" + +#: wp-includes/js/tinymce/langs/wp-langs.php:417 +msgid "AutoHREF" +msgstr "AutoHREF" + +#: wp-includes/js/tinymce/langs/wp-langs.php:418 +msgid "Cache" +msgstr "Mémoire cache" + +#: wp-includes/js/tinymce/langs/wp-langs.php:419 +msgid "Hidden" +msgstr "Caché" + +#: wp-includes/js/tinymce/langs/wp-langs.php:420 +msgid "Controller" +msgstr "Contrôleur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:421 +msgid "Kiosk mode" +msgstr "Mode kiosque" + +#: wp-includes/js/tinymce/langs/wp-langs.php:422 +msgid "Play every frame" +msgstr "Jouer toutes les images" + +# traduction reprise de la trad tinymce... +# http://trac.midgard-project.org/browser/trunk/midcom/midcom.helper.datamanager2/static/tinymce/plugins/media/langs/fr_dlg.js +#: wp-includes/js/tinymce/langs/wp-langs.php:423 +msgid "Target cache" +msgstr "Cache cible" + +#: wp-includes/js/tinymce/langs/wp-langs.php:424 +msgid "No correction" +msgstr "Pas de correction" + +#: wp-includes/js/tinymce/langs/wp-langs.php:425 +msgid "Enable JavaScript" +msgstr "Activer JavaScript" + +#: wp-includes/js/tinymce/langs/wp-langs.php:426 +#: wp-includes/js/tinymce/langs/wp-langs.php:484 +msgid "Start time" +msgstr "Temps de début" + +#: wp-includes/js/tinymce/langs/wp-langs.php:427 +msgid "End time" +msgstr "Temps de fin" + +#: wp-includes/js/tinymce/langs/wp-langs.php:428 +msgid "href" +msgstr "href" + +#: wp-includes/js/tinymce/langs/wp-langs.php:429 +msgid "Choke speed" +msgstr "Vitesse de déroulement" + +#: wp-includes/js/tinymce/langs/wp-langs.php:431 +msgid "Volume" +msgstr "Volume" + +#: wp-includes/js/tinymce/langs/wp-langs.php:432 +#: wp-includes/js/tinymce/langs/wp-langs.php:487 +msgid "Auto start" +msgstr "Démarrage automatique" + +#: wp-includes/js/tinymce/langs/wp-langs.php:433 +msgid "Enabled" +msgstr "Activé" + +#: wp-includes/js/tinymce/langs/wp-langs.php:434 +#: wp-includes/script-loader.php:295 +msgid "Fullscreen" +msgstr "Plein écran" + +# à vérifier +#: wp-includes/js/tinymce/langs/wp-langs.php:435 +msgid "Invoke URLs" +msgstr "Lancer les adresses web" + +#: wp-includes/js/tinymce/langs/wp-langs.php:436 +#: wp-includes/script-loader.php:304 +msgid "Mute" +msgstr "Muet" + +#: wp-includes/js/tinymce/langs/wp-langs.php:437 +msgid "Stretch to fit" +msgstr "Redimensionner" + +#: wp-includes/js/tinymce/langs/wp-langs.php:438 +msgid "Windowless video" +msgstr "Vidéo sans fenêtre" + +#: wp-includes/js/tinymce/langs/wp-langs.php:439 +msgid "Balance" +msgstr "Balance" + +#: wp-includes/js/tinymce/langs/wp-langs.php:440 +msgid "Base URL" +msgstr "Adresse web de base" + +#: wp-includes/js/tinymce/langs/wp-langs.php:441 +msgid "Captioning id" +msgstr "Id du sous-titre" + +#: wp-includes/js/tinymce/langs/wp-langs.php:442 +msgid "Current marker" +msgstr "Marqueur actuel" + +#: wp-includes/js/tinymce/langs/wp-langs.php:443 +msgid "Current position" +msgstr "Position actuelle" + +#: wp-includes/js/tinymce/langs/wp-langs.php:444 +msgid "Default frame" +msgstr "Frame par défaut" + +#: wp-includes/js/tinymce/langs/wp-langs.php:445 +msgid "Play count" +msgstr "Nombre de lectures" + +#: wp-includes/js/tinymce/langs/wp-langs.php:446 +msgid "Rate" +msgstr "Notation" + +# ??? +#: wp-includes/js/tinymce/langs/wp-langs.php:447 +msgid "UI Mode" +msgstr "Mode UI" + +#: wp-includes/js/tinymce/langs/wp-langs.php:448 +msgid "Flash options" +msgstr "Options Flash" + +#: wp-includes/js/tinymce/langs/wp-langs.php:449 +msgid "QuickTime options" +msgstr "Options de QuickTime" + +#: wp-includes/js/tinymce/langs/wp-langs.php:450 +msgid "Windows media player options" +msgstr "Options Windows Media Player" + +#: wp-includes/js/tinymce/langs/wp-langs.php:451 +msgid "Real media player options" +msgstr "Option Real Media Player" + +#: wp-includes/js/tinymce/langs/wp-langs.php:452 +msgid "Shockwave options" +msgstr "Options de Shockwave" + +#: wp-includes/js/tinymce/langs/wp-langs.php:453 +msgid "Auto goto URL" +msgstr "Lancer automatiquement les adresses web" + +#: wp-includes/js/tinymce/langs/wp-langs.php:455 +msgid "Image status" +msgstr "Statut de l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:456 +msgid "Maintain aspect" +msgstr "Maintenir l’aspect" + +#: wp-includes/js/tinymce/langs/wp-langs.php:457 +msgid "No java" +msgstr "Pas de Java" + +#: wp-includes/js/tinymce/langs/wp-langs.php:458 +msgid "Prefetch" +msgstr "Préchargement" + +#: wp-includes/js/tinymce/langs/wp-langs.php:459 +msgid "Shuffle" +msgstr "Aléatoire" + +#: wp-includes/js/tinymce/langs/wp-langs.php:460 +msgid "Console" +msgstr "Console" + +#: wp-includes/js/tinymce/langs/wp-langs.php:461 +msgid "Num loops" +msgstr "Nombre de boucles" + +#: wp-includes/js/tinymce/langs/wp-langs.php:462 +msgid "Controls" +msgstr "Contrôles" + +# à vérifier +#: wp-includes/js/tinymce/langs/wp-langs.php:463 +msgid "Script callbacks" +msgstr "Rappels de script" + +#: wp-includes/js/tinymce/langs/wp-langs.php:464 +msgid "Stretch style" +msgstr "Style d’étirement" + +#: wp-includes/js/tinymce/langs/wp-langs.php:465 +msgid "Stretch H-Align" +msgstr "Étirement horizontal" + +#: wp-includes/js/tinymce/langs/wp-langs.php:466 +msgid "Stretch V-Align" +msgstr "Étirement vertical" + +#: wp-includes/js/tinymce/langs/wp-langs.php:467 +msgid "Sound" +msgstr "Son" + +#: wp-includes/js/tinymce/langs/wp-langs.php:468 +msgid "Progress" +msgstr "Progression" + +#: wp-includes/js/tinymce/langs/wp-langs.php:469 +msgid "QT Src" +msgstr "Source du QuickTime" + +#: wp-includes/js/tinymce/langs/wp-langs.php:470 +msgid "" +"Streamed rtsp resources should be added to the QT Src field under the " +"advanced tab." +msgstr "" +"Les flux RTSP (streaming) devraient être ajoutés au champ « Source du " +"QuickTime » dans l’onglet Avancé." + +#: wp-includes/js/tinymce/langs/wp-langs.php:476 +msgid "Top left" +msgstr "Haut gauche" + +#: wp-includes/js/tinymce/langs/wp-langs.php:477 +msgid "Top right" +msgstr "En haut à droite" + +#: wp-includes/js/tinymce/langs/wp-langs.php:478 +msgid "Bottom left" +msgstr "Bas gauche" + +#: wp-includes/js/tinymce/langs/wp-langs.php:479 +msgid "Bottom right" +msgstr "Bas droite" + +#: wp-includes/js/tinymce/langs/wp-langs.php:480 +msgid "Flash video options" +msgstr "Options de vidéo de Flash" + +#: wp-includes/js/tinymce/langs/wp-langs.php:481 +msgid "Scale mode" +msgstr "Mode d’étirement" + +#: wp-includes/js/tinymce/langs/wp-langs.php:482 +msgid "Buffer" +msgstr "Tampon" + +#: wp-includes/js/tinymce/langs/wp-langs.php:483 +msgid "Start image" +msgstr "Image de départ" + +#: wp-includes/js/tinymce/langs/wp-langs.php:485 +msgid "Default volume" +msgstr "Volume par défaut" + +#: wp-includes/js/tinymce/langs/wp-langs.php:486 +msgid "Hidden GUI" +msgstr "Interface cachée" + +# Basé sur la trad officielle TinyMCE +# http://trac.midgard-project.org/browser/trunk/midcom/midcom.helper.datamanager2/static/tinymce/plugins/media/langs/fr_dlg.js +#: wp-includes/js/tinymce/langs/wp-langs.php:489 +msgid "Show scale modes" +msgstr "Montrer les différentes échelles" + +#: wp-includes/js/tinymce/langs/wp-langs.php:490 +msgid "Smooth video" +msgstr "Vidéo continue" + +#: wp-includes/js/tinymce/langs/wp-langs.php:491 +msgid "JS Callback" +msgstr "Callback JavaScript" + +#: wp-includes/js/tinymce/langs/wp-langs.php:492 +msgid "HTML5 Video Options" +msgstr "Options de vidéo de HTML5" + +#: wp-includes/js/tinymce/langs/wp-langs.php:493 +msgid "Alternative source 1" +msgstr "Source alternative 1" + +#: wp-includes/js/tinymce/langs/wp-langs.php:494 +msgid "Alternative source 2" +msgstr "Source alternative 2" + +#: wp-includes/js/tinymce/langs/wp-langs.php:495 +msgid "Preload" +msgstr "Précharger" + +#: wp-includes/js/tinymce/langs/wp-langs.php:496 +msgid "Poster" +msgstr "Image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:497 +#: wp-includes/js/tinymce/langs/wp-langs.php:529 +msgid "Source" +msgstr "Adresse web source" + +#: wp-includes/js/tinymce/langs/wp-langs.php:501 +msgid "Show/Hide Kitchen Sink (Alt + Shift + Z)" +msgstr "Afficher/cacher les options avancées (Alt + Shift + Z)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:502 +msgid "Insert More Tag (Alt + Shift + T)" +msgstr "Insérer la balise « More » (Alt + Shift + T)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:503 +msgid "Insert Page break (Alt + Shift + P)" +msgstr "Insérer un saut de page (Alt + Shift + P)" + +#: wp-includes/js/tinymce/langs/wp-langs.php:505 +msgid "More..." +msgstr "Lire la suite…" + +#: wp-includes/js/tinymce/langs/wp-langs.php:506 +msgid "Next page..." +msgstr "Page suivante…" + +#: wp-includes/js/tinymce/langs/wp-langs.php:507 wp-includes/media.php:1887 +msgid "Add Media" +msgstr "Ajouter un média" + +#: wp-includes/js/tinymce/langs/wp-langs.php:508 +msgid "Add an Image" +msgstr "Ajouter une image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:509 +msgid "Add Video" +msgstr "Ajouter une vidéo" + +#: wp-includes/js/tinymce/langs/wp-langs.php:510 +msgid "Add Audio" +msgstr "Ajouter un son" + +#: wp-includes/js/tinymce/langs/wp-langs.php:511 wp-includes/media.php:1922 +msgid "Edit Gallery" +msgstr "Modifier la galerie" + +#: wp-includes/js/tinymce/langs/wp-langs.php:512 +msgid "Delete Gallery" +msgstr "Supprimer la galerie" + +#: wp-includes/js/tinymce/langs/wp-langs.php:513 +msgid "Distraction Free Writing mode (Alt + Shift + W)" +msgstr "Basculer en mode plein écran (Alt + Shift + W)" + +# Ne pas mettre d'entité HTML ( ...) : chaîne affichée dans l'éditeur visuel. +#: wp-includes/js/tinymce/langs/wp-langs.php:517 +#: wp-includes/media-template.php:203 +msgid "Edit Image" +msgstr "Modifier l’image" + +# Ne pas mettre d'entité HTML ( ...) : chaîne affichée dans l'éditeur visuel. +#: wp-includes/js/tinymce/langs/wp-langs.php:518 +msgid "Delete Image" +msgstr "Supprimer l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:519 +msgid "Advanced Settings" +msgstr "Options avancées" + +#: wp-includes/js/tinymce/langs/wp-langs.php:521 +#: wp-includes/media-template.php:336 +msgid "Size" +msgstr "Taille" + +#: wp-includes/js/tinymce/langs/wp-langs.php:522 +#: wp-includes/media-template.php:346 wp-includes/media.php:1749 +msgid "Thumbnail" +msgstr "Miniature" + +#: wp-includes/js/tinymce/langs/wp-langs.php:523 +#: wp-includes/media-template.php:347 wp-includes/media.php:1750 +msgid "Medium" +msgstr "Moyenne" + +#: wp-includes/js/tinymce/langs/wp-langs.php:524 +#: wp-includes/media-template.php:349 wp-includes/media.php:1752 +msgid "Full Size" +msgstr "Taille originale" + +#: wp-includes/js/tinymce/langs/wp-langs.php:525 +msgid "Current Link" +msgstr "Lien actuel" + +#: wp-includes/js/tinymce/langs/wp-langs.php:526 +msgid "Link to Image" +msgstr "Lier à l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:527 +msgid "Enter a link URL or click above for presets." +msgstr "" +"Saisissez une adresse web ou cliquez sur l’un des préréglages ci-dessus" + +#: wp-includes/js/tinymce/langs/wp-langs.php:528 +msgid "Advanced Image Settings" +msgstr "Options avancées de l’image" + +#: wp-includes/js/tinymce/langs/wp-langs.php:530 +msgid "Width" +msgstr "Largeur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:531 +#: wp-includes/js/tinymce/langs/wp-langs.php:536 +msgid "Height" +msgstr "Hauteur" + +#: wp-includes/js/tinymce/langs/wp-langs.php:532 +#: wp-includes/js/tinymce/langs/wp-langs.php:537 +msgid "Original Size" +msgstr "Taille originale" + +#: wp-includes/js/tinymce/langs/wp-langs.php:533 +#: wp-includes/js/tinymce/langs/wp-langs.php:538 +msgid "CSS Class" +msgstr "Classe CSS" + +#: wp-includes/js/tinymce/langs/wp-langs.php:534 +msgid "Advanced Link Settings" +msgstr "Options avancées du lien" + +#: wp-includes/js/tinymce/langs/wp-langs.php:535 +msgid "Link Rel" +msgstr "Attribut « Rel » du lien" + +#: wp-includes/js/tinymce/langs/wp-langs.php:539 +msgid "60%" +msgstr "60%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:540 +msgid "70%" +msgstr "70%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:541 +msgid "80%" +msgstr "80%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:542 +msgid "90%" +msgstr "90%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:543 +msgid "100%" +msgstr "100%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:544 +msgid "110%" +msgstr "120%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:545 +msgid "120%" +msgstr "120%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:546 +msgid "130%" +msgstr "130%" + +#: wp-includes/js/tinymce/langs/wp-langs.php:548 +#: wp-includes/media-template.php:230 wp-includes/media-template.php:421 +msgid "Caption" +msgstr "Légende" + +#: wp-includes/js/tinymce/langs/wp-langs.php:549 +msgid "Alternative Text" +msgstr "Texte alternatif" + +#: wp-includes/js/tinymce/wp-mce-help.php:16 +msgid "Rich Editor Help" +msgstr "Aide de l’éditeur visuel" + +#: wp-includes/js/tinymce/wp-mce-help.php:162 +msgid "Basics of Rich Editing" +msgstr "Bases de l’édition visuelle" + +#: wp-includes/js/tinymce/wp-mce-help.php:162 +msgid "Basics" +msgstr "Les bases" + +#: wp-includes/js/tinymce/wp-mce-help.php:163 +msgid "Advanced use of the Rich Editor" +msgstr "Utilisation avancée de l’éditeur visuel" + +#: wp-includes/js/tinymce/wp-mce-help.php:164 +msgid "Hotkeys" +msgstr "Raccourcis clavier" + +#: wp-includes/js/tinymce/wp-mce-help.php:165 +msgid "About the software" +msgstr "À propos de ce logiciel" + +#: wp-includes/js/tinymce/wp-mce-help.php:171 +msgid "Rich Editing Basics" +msgstr "Bases de l’édition visuelle" + +#: wp-includes/js/tinymce/wp-mce-help.php:172 +msgid "" +"Rich editing, also called WYSIWYG for What You See Is What You Get, " +"means your text is formatted as you type. The rich editor creates HTML code " +"behind the scenes while you concentrate on writing. Font styles, links and " +"images all appear approximately as they will on the internet." +msgstr "" +"L’édition visuelle, aussi appelée WYSIWYG pour What You " +"See Is What You Get (signifiant « ce que vous voyez est ce que " +"vous obtenez »), vous permet de mettre en forme votre texte tandis que " +"vous le saisissez. L’éditeur visuel crée le code HTML en coulisse, " +"tandis que vous vous concentrez sur l’écriture. Styles de la police, " +"liens et images apparaissent de la même manière que lors de leur publication " +"sur Internet." + +#: wp-includes/js/tinymce/wp-mce-help.php:173 +msgid "" +"WordPress includes a rich HTML editor that works well in all major web " +"browsers used today. However editing HTML is not the same as typing text. " +"Each web page has two major components: the structure, which is the actual " +"HTML code and is produced by the editor as you type, and the display, that " +"is applied to it by the currently selected WordPress theme and is defined in " +"style.css. WordPress is producing valid XHTML 1.0 which means that inserting " +"multiple line breaks (BR tags) after a paragraph would not produce white " +"space on the web page. The BR tags will be removed as invalid by the " +"internal HTML correcting functions." +msgstr "" +"WordPress comprend un éditeur HTML visuel qui fonctionne dans tous les " +"principaux navigateurs web actuels. Cependant, on ne modifie pas du code " +"HTML comme on saisit du texte. Chaque page web est faite de deux composants " +"principaux : sa structure, qui est maintenue par le code HTML lui-même " +"et est produite par l’éditeur tandis que vous écrivez, et sa mise en " +"forme, qui est appliquée par le thème WordPress actuellement sélectionné, et " +"est qui est définie par le fichier style.css. WordPress produit du code qui " +"est valide pour la norme XHTML 1.0, ce qui signifie qu’insérer " +"plusieurs retours à la ligne (balises BR) après un paragraphe ne produira " +"pas d’espace blanc supplémentaire sur la page web. Les balises BR " +"seront retirées, car elles seront considérées comme invalides par les " +"fonctions internes de correction HTML." + +#: wp-includes/js/tinymce/wp-mce-help.php:174 +msgid "" +"While using the editor, most basic keyboard shortcuts work like in any other " +"text editor. For example: Shift+Enter inserts line break, Ctrl+C = copy, Ctrl" +"+X = cut, Ctrl+Z = undo, Ctrl+Y = redo, Ctrl+A = select all, etc. (on Mac " +"use the Command key instead of Ctrl). See the Hotkeys tab for all available " +"keyboard shortcuts." +msgstr "" +"Lorsque vous utilisez l’éditeur, les raccourcis clavier les plus " +"basiques fonctionnent comme dans n’importe quel autre éditeur. Par " +"exemple : Shift+Retour insère un retour à la ligne, Ctrl+C = copier, " +"Ctrl+X = couper, Ctrl+Z = annuler, Ctrl+Y = rétablir, Ctrl+A = tout " +"sélectionner, etc. (sur Mac, utilisez la touche Commande au lieu de Ctrl). " +"Voir l’onglet Raccourcis Clavier pour connaître tous les raccourcis " +"disponibles." + +#: wp-includes/js/tinymce/wp-mce-help.php:175 +msgid "" +"If you do not like the way the rich editor works, you may turn it off from " +"Your Profile submenu, under Users in the admin menu." +msgstr "" +"Si vous n’aimez pas la manière de fonctionner de l’éditeur, vous " +"pouvez le désactiver depuis la page Votre Profil, dans le menu d’" +"administration Utilisateurs." + +#: wp-includes/js/tinymce/wp-mce-help.php:179 +msgid "Advanced Rich Editing" +msgstr "Édition visuelle avancée" + +#: wp-includes/js/tinymce/wp-mce-help.php:180 +msgid "Images and Attachments" +msgstr "Images et fichiers attachés" + +#: wp-includes/js/tinymce/wp-mce-help.php:181 +msgid "" +"There is a button in the editor toolbar for inserting images that are " +"already hosted somewhere on the internet. If you have a URL for an image, " +"click this button and enter the URL in the box which appears." +msgstr "" +"Un des boutons de la barre d’outils de l’éditeur sert à insérer " +"une image qui est déjà hébergée quelque part sur Internet. Si vous avez " +"l’adresse web de cette image, cliquez sur ce bouton et saisissez " +"l’adresse web dans le champ qui apparaît." + +#: wp-includes/js/tinymce/wp-mce-help.php:182 +msgid "" +"If you need to upload an image or another media file from your computer, you " +"can use the Media Library button above the editor. The media library will " +"attempt to create a thumbnail-sized copy from each uploaded image. To insert " +"your image into the post, first click on the thumbnail to reveal a menu of " +"options. When you have selected the options you like, click \"Insert into " +"Post\" and your image or file will appear in the post you are editing." +msgstr "" +"Si vous devez envoyer une image ou un autre média depuis votre ordinateur, " +"vous pouvez utiliser les boutons de la bibliothèque des médias, situés au-" +"dessus de l’éditeur. La bibliothèque de médias tentera de créer une " +"image miniature pour chaque image que vous mettrez en ligne. Pour insérer " +"ensuite l’image dans l’article, cliquez tout d’abord sur " +"la miniature pour faire apparaître un menu d’options. Une fois que " +"vous avez sélectionné les options qui vous conviennent, cliquez sur «" +" Envoyer dans l’éditeur », et votre image ou fichier " +"apparaîtra dans l’article que vous êtes en train de modifier. " + +#: wp-includes/js/tinymce/wp-mce-help.php:183 +msgid "HTML in the Rich Editor" +msgstr "HTML dans l’éditeur visuel" + +#: wp-includes/js/tinymce/wp-mce-help.php:184 +msgid "" +"Any HTML entered directly into the rich editor will show up as text when the " +"post is viewed. What you see is what you get. When you want to include HTML " +"elements that cannot be generated with the toolbar buttons, you must enter " +"it by hand in the Text editor. Examples are tables and <code>. To do " +"this, click the Text tab and edit the code, then switch back to Visual mode. " +"If the code is valid and understood by the editor, you should see it " +"rendered immediately." +msgstr "" +"Tout code HTML inséré via l’éditeur visuel apparaîtra comme du texte " +"quand l’article sera affiché. Si vous souhaitez inclure du code HTML " +"qui ne peut être généré avec les boutons de la barre d’outils, vous " +"devez le saisir à la main à l’aide de l’éditeur Texte. Par " +"exemple, c’est la seule façon de faire des tableaux ou d’" +"utiliser la balise <code>. Pour accéder à cet éditeur, cliquez sur " +"l’onglet « Texte » et saisissez votre code, puis " +"retournez dans l’éditeur visuel. Si le code HTML est valide et compris " +"par l’éditeur, le résultat devrait être immédiatement visible." + +#: wp-includes/js/tinymce/wp-mce-help.php:185 +msgid "Pasting in the Rich Editor" +msgstr "Collage dans l’éditeur visuel" + +#: wp-includes/js/tinymce/wp-mce-help.php:186 +msgid "" +"When pasting content from another web page the results can be inconsistent " +"and depend on your browser and on the web page you are pasting from. The " +"editor tries to correct any invalid HTML code that was pasted, but for best " +"results try using the Text tab or one of the paste buttons that are on the " +"second row. Alternatively try pasting paragraph by paragraph. In most " +"browsers to select one paragraph at a time, triple-click on it." +msgstr "" +"Coller du contenu en provenance d’une autre page Web peut amener à des " +"résultats inattendus voire incohérents, en fonction du navigateur que vous " +"utilisez et de la page d’origine du contenu copié/collé. L’" +"éditeur tentera de corriger le code HTML invalide qui a été collé, mais vous " +"obtiendrez de meilleurs résultats en passant par le mode Texte, ou par " +"l’un des boutons de collage situés dans la seconde rangée de boutons. " +"Vous pouvez également essayer de coller le contenu paragraphe par paragraphe " +"- dans la plupart des navigateurs, vous pouvez sélectionner un paragraphe " +"seul en cliquant trois fois sur celui-ci." + +#: wp-includes/js/tinymce/wp-mce-help.php:187 +msgid "" +"Pasting content from another application, like Word or Excel, is best done " +"with the Paste from Word button on the second row, or in Text mode." +msgstr "" +"Si vous souhaitez copier du contenu en provenance d’un autre " +"programme, comme Word ou Excel, il sera préférable d’utiliser le " +"bouton « Coller du texte Word », situé dans la seconde " +"rangée de boutons, ou de passer par le mode Texte." + +#: wp-includes/js/tinymce/wp-mce-help.php:191 +msgid "Writing at Full Speed" +msgstr "Écrire à vitesse maximale" + +#: wp-includes/js/tinymce/wp-mce-help.php:192 +msgid "" +"Rather than reaching for your mouse to click on the toolbar, use these " +"access keys. Windows and Linux use Ctrl + letter. Macintosh uses Command + " +"letter." +msgstr "" +"Plutôt que d’attraper votre souris pour cliquer sur la barre d’" +"outils, utilisez les raccourcis clavier. Sous Windows et Linux, utilisez Ctrl" +"+<lettre>  sous Macintosh, utilisez la touche Commande+<lettre>." + +#: wp-includes/js/tinymce/wp-mce-help.php:195 +#: wp-includes/js/tinymce/wp-mce-help.php:209 +msgid "Letter" +msgstr "Lettre" + +#: wp-includes/js/tinymce/wp-mce-help.php:195 +#: wp-includes/js/tinymce/wp-mce-help.php:209 +msgid "Action" +msgstr "Action" + +#: wp-includes/js/tinymce/wp-mce-help.php:197 +msgid "Select all" +msgstr "Sélectionner tout" + +#: wp-includes/js/tinymce/wp-mce-help.php:198 +msgid "Undo" +msgstr "Annuler" + +#: wp-includes/js/tinymce/wp-mce-help.php:198 +msgid "Redo" +msgstr "Rétablir" + +#: wp-includes/js/tinymce/wp-mce-help.php:200 +msgid "Bold" +msgstr "Gras" + +#: wp-includes/js/tinymce/wp-mce-help.php:200 +msgid "Italic" +msgstr "Italique" + +#: wp-includes/js/tinymce/wp-mce-help.php:207 +msgid "" +"The following shortcuts use different access keys: Alt + Shift + letter." +msgstr "" +"Vous pouvez accéder aux raccourcis suivants via les touches : Alt+Shift" +"+<lettre>." + +#: wp-includes/js/tinymce/wp-mce-help.php:210 +msgid "Check Spelling" +msgstr "Vérifier l’orthographe" + +#: wp-includes/js/tinymce/wp-mce-help.php:210 +msgid "Align Left" +msgstr "Aligner à gauche" + +#: wp-includes/js/tinymce/wp-mce-help.php:211 +msgid "Justify Text" +msgstr "Justifier le texte" + +#: wp-includes/js/tinymce/wp-mce-help.php:211 +msgid "Align Center" +msgstr "Centrer" + +#: wp-includes/js/tinymce/wp-mce-help.php:212 +msgid "Strikethrough" +msgstr "Barrer" + +#: wp-includes/js/tinymce/wp-mce-help.php:212 +msgid "Align Right" +msgstr "Aligner à droite" + +#: wp-includes/js/tinymce/wp-mce-help.php:213 +msgid "Insert link" +msgstr "Insérer un lien" + +#: wp-includes/js/tinymce/wp-mce-help.php:214 +msgid "Remove link" +msgstr "Enlever le lien" + +#: wp-includes/js/tinymce/wp-mce-help.php:215 +msgid "Quote" +msgstr "Citation" + +#: wp-includes/js/tinymce/wp-mce-help.php:215 +msgid "Insert Image" +msgstr "Insérer une image" + +#: wp-includes/js/tinymce/wp-mce-help.php:216 +msgid "Distraction Free Writing mode" +msgstr "Mode « aucune distraction »" + +#: wp-includes/js/tinymce/wp-mce-help.php:216 +msgid "Insert More Tag" +msgstr "Insérer la balise « More »" + +#: wp-includes/js/tinymce/wp-mce-help.php:217 +msgid "Insert Page Break tag" +msgstr "Insérer la balise « Page break »" + +#: wp-includes/js/tinymce/wp-mce-help.php:220 +msgid "Editor width in Distraction Free Writing mode:" +msgstr "" +"Largeur de l’éditeur en mode « aucune distraction " +"» :" + +#: wp-includes/js/tinymce/wp-mce-help.php:222 +msgid "Wider" +msgstr "Plus large" + +#: wp-includes/js/tinymce/wp-mce-help.php:223 +msgid "Narrower" +msgstr "Plus étroit" + +#: wp-includes/js/tinymce/wp-mce-help.php:224 +msgid "Default width" +msgstr "Largeur par défaut" + +#: wp-includes/js/tinymce/wp-mce-help.php:231 +msgid "Version:" +msgstr "Version :" + +#: wp-includes/js/tinymce/wp-mce-help.php:232 +msgid "" +"TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor " +"released as Open Source under %sLGPL\tby Moxiecode Systems AB. It has " +"the ability to convert HTML TEXTAREA fields or other HTML elements to editor " +"instances." +msgstr "" +"TinyMCE est un éditeur WYSIWYG compatible avec toutes les plateformes, basé " +"sur JavaScript, diffusé sous licence open-source %sLGPL\tpar Moxiecode " +"Systems AB. Il peut convertir les champs HTML TEXTAREA ou autres éléments " +"HTML en instance d’éditeur." + +#: wp-includes/js/tinymce/wp-mce-help.php:232 +msgid "GNU Library General Public License" +msgstr "Licence Publique Générale GNU" + +#: wp-includes/js/tinymce/wp-mce-help.php:233 +msgid "" +"Copyright © 2003-2011, Moxiecode Systems AB, All rights reserved." +msgstr "" +"Copyright © 2003-2011, Moxiecode Systems AB, Tous droits réservés. Traduction par " +"l’équipe de WordPress-Francophone." + +#: wp-includes/js/tinymce/wp-mce-help.php:234 +msgid "" +"For more information about this software visit the TinyMCE website." +msgstr "" +"Pour plus d’information sur ce logiciel, rendez-vous sur le site de TinyMCE." + +#: wp-includes/js/tinymce/wp-mce-help.php:237 +msgid "Got Moxie?" +msgstr "Êtes-vous Moxie ?" + +#: wp-includes/link-template.php:514 +msgid "Comments Feed" +msgstr "Flux des commentaires" + +#: wp-includes/link-template.php:727 wp-includes/link-template.php:937 +#: wp-includes/link-template.php:1012 wp-includes/link-template.php:1053 +msgid "Edit This" +msgstr "Modifier" + +#: wp-includes/link-template.php:1154 +msgid "Use commas instead of %s to separate excluded categories." +msgstr "" +"Utiliser les virgules à la place des %s pour séparer les catégories exclues." + +#: wp-includes/link-template.php:1228 wp-includes/link-template.php:1426 +msgid "Previous Post" +msgstr "Article précèdent" + +#: wp-includes/link-template.php:1228 wp-includes/link-template.php:1426 +msgid "Next Post" +msgstr "Article suivant" + +#: wp-includes/link-template.php:1801 +msgid "Newer Comments »" +msgstr "Commentaires plus récents »" + +#: wp-includes/link-template.php:1838 +msgid "« Older Comments" +msgstr "« Commentaires plus anciens" + +#: wp-includes/link-template.php:2494 +msgid "This is the short link." +msgstr "Ceci est un lien court." + +#: wp-includes/load.php:107 +msgid "" +"Your server is running PHP version %1$s but WordPress %2$s requires at least " +"%3$s." +msgstr "" +"Votre serveur utilise la version %1$s de PHP mais WordPress %2$s nécessite " +"au moins la version %3$s." + +#: wp-includes/load.php:112 +msgid "" +"Your PHP installation appears to be missing the MySQL extension which is " +"required by WordPress." +msgstr "" +"Votre installation PHP ne dispose pas de MySQL. Extension requise pour " +"WordPress." + +#: wp-includes/load.php:173 +msgid "Maintenance" +msgstr "Maintenance" + +#: wp-includes/load.php:177 +msgid "Briefly unavailable for scheduled maintenance. Check back in a minute." +msgstr "" +"Indisponibilité temporaire pour cause de maintenance. Veuillez revenir dans " +"un instant." + +#: wp-includes/load.php:368 +msgid "" +"ERROR: $table_prefix in wp-config.php can only contain numbers, letters, and underscores." +msgstr "" +"ERREUR: la ligne $table_prefix du fichier " +"wp-config.php ne doit contenir que des chiffres, lettres ou le " +"caractère souligné." + +#: wp-includes/load.php:446 +msgid "" +"The site you have requested is not installed properly. Please contact the " +"system administrator." +msgstr "" +"Le site que vous avez demandé n’est pas installé correctement. " +"Veuillez contacter l’administrateur de votre serveur." + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:109 +msgid "S_Sunday_initial" +msgstr "D" + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:110 +msgid "M_Monday_initial" +msgstr "L" + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:111 +msgid "T_Tuesday_initial" +msgstr "Ma" + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:112 +msgid "W_Wednesday_initial" +msgstr "Me" + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:113 +msgid "T_Thursday_initial" +msgstr "J" + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:114 +msgid "F_Friday_initial" +msgstr "V" + +#. translators: one-letter abbreviation of the weekday +#: wp-includes/locale.php:115 +msgid "S_Saturday_initial" +msgstr "S" + +#: wp-includes/locale.php:164 +msgid "am" +msgstr " " + +#: wp-includes/locale.php:165 +msgid "pm" +msgstr " " + +#: wp-includes/locale.php:166 +msgid "AM" +msgstr " " + +#: wp-includes/locale.php:167 +msgid "PM" +msgstr " " + +# juste un espace insécable +#. translators: $thousands_sep argument for http:php.net/number_format, default +#. is , +#: wp-includes/locale.php:173 +msgid "number_format_thousands_sep" +msgstr "  " + +# virgule et espace insécable +#. translators: $dec_point argument for http:php.net/number_format, default is +#. . +#: wp-includes/locale.php:177 +msgid "number_format_decimal_point" +msgstr ", " + +#. translators: 'rtl' or 'ltr'. This sets the text direction for WordPress. +#: wp-includes/locale.php:184 +msgctxt "text direction" +msgid "ltr" +msgstr "ltr" + +#. translators: localized date format, see http:php.net/date +#: wp-includes/locale.php:339 +msgid "F j, Y" +msgstr "j F Y" + +#. translators: localized time format, see http:php.net/date +#: wp-includes/locale.php:341 +msgid "g:i a" +msgstr "G \\h i \\m\\i\\n" + +#. translators: localized date and time format, see http:php.net/date +#: wp-includes/locale.php:343 +msgid "F j, Y g:i a" +msgstr "j F Y G \\h i \\m\\i\\n" + +#: wp-includes/media-template.php:40 +msgid "Drop files to upload" +msgstr "Déposez vos fichiers pour les mettre en ligne" + +#: wp-includes/media-template.php:53 +msgid "Upload Limit Exceeded" +msgstr "Limite de mise en ligne dépassée" + +#: wp-includes/media-template.php:58 +msgid "Drop files anywhere to upload" +msgstr "Déposez vos fichiers n’importe où pour les mettre en ligne" + +#: wp-includes/media-template.php:59 +msgid "Select Files" +msgstr "Sélectionner des fichiers" + +#: wp-includes/media-template.php:93 +msgid "Maximum upload file size: %d%s." +msgstr "Taille maximale d’un fichier mis en ligne : %d%s." + +#: wp-includes/media-template.php:99 +msgid "" +"Your browser has some limitations uploading large files with the multi-file " +"uploader. Please use the browser uploader for files over 100MB." +msgstr "" +"Votre navigateur présente certaines limitations qui l’empêchent " +"d’utiliser l’outil de mise en ligne multiple. Veuillez utiliser " +"l’outil du navigateur pour les " +"fichiers dépassant les 100 Mo." + +#: wp-includes/media-template.php:110 +msgid "Uploading" +msgstr "Mise en ligne" + +#: wp-includes/media-template.php:111 +msgid "Dismiss Errors" +msgstr "Ignorer les erreurs" + +#: wp-includes/media-template.php:125 +msgid "Error" +msgstr "Erreur " + +#: wp-includes/media-template.php:152 +msgid "Deselect" +msgstr "Désélectionner" + +#: wp-includes/media-template.php:160 +msgid "Caption this image…" +msgstr "Décrivez cette image…" + +#: wp-includes/media-template.php:164 +msgid "Describe this video…" +msgstr "Décrivez cette vidéo…" + +#: wp-includes/media-template.php:166 +msgid "Describe this audio file…" +msgstr "Décrivez ce fichier audio…" + +#: wp-includes/media-template.php:168 +msgid "Describe this media file…" +msgstr "Décrivez ce fichier média…" + +#: wp-includes/media-template.php:176 +msgid "Attachment Details" +msgstr "Détails du fichier attaché" + +#: wp-includes/media-template.php:204 +msgid "Refresh" +msgstr "Rafraîchir" + +#: wp-includes/media-template.php:209 +msgid "Length:" +msgstr "Durée :" + +#: wp-includes/media-template.php:213 +msgid "Delete Permanently" +msgstr "Supprimer définitivement" + +#: wp-includes/media-template.php:235 wp-includes/media-template.php:427 +msgid "Alt Text" +msgstr "Texte alternatif" + +#: wp-includes/media-template.php:240 +msgid "Description" +msgstr "Description" + +#: wp-includes/media-template.php:252 wp-includes/script-loader.php:481 +msgid "Clear" +msgstr "Effacer" + +#: wp-includes/media-template.php:259 +msgid "Attachment Display Settings" +msgstr "Réglages de l’affichage du fichier attaché" + +#: wp-includes/media-template.php:289 +msgid "Embed or Link" +msgstr "Intégrer ou lier" + +#: wp-includes/media-template.php:291 wp-includes/media-template.php:370 +#: wp-includes/media-template.php:450 +msgid "Link To" +msgstr "Lier à" + +#: wp-includes/media-template.php:302 +msgid "Embed Media Player" +msgstr "Intégrer le lecteur de média" + +#: wp-includes/media-template.php:309 +msgid "Link to Media File" +msgstr "Lien vers le fichier média" + +#: wp-includes/media-template.php:311 wp-includes/media-template.php:381 +msgid "Media File" +msgstr "Fichier média" + +#: wp-includes/media-template.php:316 +msgid "Link to Attachment Page" +msgstr "Lien vers la page du fichier attaché" + +#: wp-includes/media-template.php:318 wp-includes/media-template.php:378 +msgid "Attachment Page" +msgstr "Page du fichier attaché" + +# Indicateur de "custom link" -> "lien personnalisé" +#: wp-includes/media-template.php:323 wp-includes/media-template.php:456 +msgid "Custom URL" +msgstr "Lien personnalisé" + +#: wp-includes/media-template.php:348 wp-includes/media.php:1751 +msgid "Large" +msgstr "Grande" + +#: wp-includes/media-template.php:367 +msgid "Gallery Settings" +msgstr "Réglages de la galerie" + +#: wp-includes/media-template.php:390 +msgid "Columns" +msgstr "Colonnes" + +#: wp-includes/media-template.php:402 +msgid "Random Order" +msgstr "Ordre aléatoire" + +#: wp-includes/media.php:1570 +msgid "No editor could be selected." +msgstr "Aucun éditeur n’a pas pu être sélectionné." + +#: wp-includes/media.php:1647 wp-includes/script-loader.php:376 +msgid "Allowed Files" +msgstr "Fichiers autorisés" + +#: wp-includes/media.php:1889 +msgid "Select" +msgstr "Sélectionner" + +#. translators: This is a would-be plural string used in the media manager. +#. If there is not a word you can use in your language to avoid issues +#. with the +#. lack of plural support here, turn it into "selected: %d" then translate +#. it. +#: wp-includes/media.php:1895 +msgid "%d selected" +msgstr "%d sélection(s)" + +#: wp-includes/media.php:1896 +msgid "Drag and drop to reorder images." +msgstr "Glissez/déposez pour réorganiser les images." + +#: wp-includes/media.php:1899 +msgid "Upload Files" +msgstr "Envoyer des fichiers" + +#: wp-includes/media.php:1900 +msgid "Upload Images" +msgstr "Envoyer des images" + +#: wp-includes/media.php:1903 +msgid "Media Library" +msgstr "Bibliothèque de médias" + +#: wp-includes/media.php:1904 +msgid "Insert Media" +msgstr "Insérer un média" + +#: wp-includes/media.php:1905 +msgid "Create a new gallery" +msgstr "Créer une nouvelle galerie" + +#: wp-includes/media.php:1906 +msgid "← Return to library" +msgstr "← Revenir à la bibliothèque" + +#: wp-includes/media.php:1907 +msgid "All media items" +msgstr "Tous les éléments média" + +#: wp-includes/media.php:1908 +msgid "No items found." +msgstr "Aucun élément trouvé." + +#: wp-includes/media.php:1909 +msgid "Insert into page" +msgstr "Insérer dans la page" + +#: wp-includes/media.php:1909 +msgid "Insert into post" +msgstr "Insérer dans l’article" + +#: wp-includes/media.php:1910 +msgid "Uploaded to this page" +msgstr "Mis en ligne sur cette page" + +#: wp-includes/media.php:1910 +msgid "Uploaded to this post" +msgstr "Mis en ligne sur cet article" + +# Pas d'entité HTML : alert() JavaScript +#: wp-includes/media.php:1911 +msgid "" +"You are about to permanently delete this item.\n" +" 'Cancel' to stop, 'OK' to delete." +msgstr "" +"Vous êtes sur le point de supprimer définitivement cet élément.\n" +" « Annuler » pour abandonner, « OK » pour le supprimer." + +#: wp-includes/media.php:1914 +msgid "Insert from URL" +msgstr "Insérer à partir d’une adresse web" + +#: wp-includes/media.php:1917 +msgid "Set Featured Image" +msgstr "Mettre une image à la Une" + +#: wp-includes/media.php:1918 +msgid "Set featured image" +msgstr "Utiliser comme image à la Une" + +#: wp-includes/media.php:1921 +msgid "Create Gallery" +msgstr "Créer une galerie" + +#: wp-includes/media.php:1923 +msgid "← Cancel Gallery" +msgstr "← Annuler la galerie" + +#: wp-includes/media.php:1924 +msgid "Insert gallery" +msgstr "Insérer la galerie" + +#: wp-includes/media.php:1925 +msgid "Update gallery" +msgstr "Mettre à jour la galerie" + +#: wp-includes/media.php:1926 +msgid "Add to gallery" +msgstr "Ajouter à la galerie" + +#: wp-includes/media.php:1927 +msgid "Add to Gallery" +msgstr "Ajouter à la galerie" + +#: wp-includes/media.php:1928 +msgid "Reverse order" +msgstr "Inverser l’ordre" + +#: wp-includes/ms-default-constants.php:126 +msgid "" +"The constant VHOST is deprecated. Use the " +"boolean constant SUBDOMAIN_INSTALL in wp-config.php to enable a " +"subdomain configuration. Use is_subdomain_install() to check whether a " +"subdomain configuration is enabled." +msgstr "" +"La constante VHOST est obsolète. Utilisez la " +"constante booléenne SUBDOMAIN_INSTALL dans le fichier wp-config." +"php pour activer le mode sous-domaines. Utilisez is_subdomain_install() pour " +"vérifier si le mode sous-domaine est effectivement activé." + +#: wp-includes/ms-default-constants.php:128 +msgid "" +"Conflicting values for the constants VHOST and SUBDOMAIN_INSTALL. The value of SUBDOMAIN_INSTALL will be assumed to be your subdomain " +"configuration setting." +msgstr "" +"Les valeurs des constantes VHOST et SUBDOMAIN_INSTALL ne " +"correspondent pas. C’est la valeur de SUBDOMAIN_INSTALL qui " +"sera prise en compte pour votre réglage du mode sous-domaines." + +#: wp-includes/ms-functions.php:186 +msgid "The requested user does not exist." +msgstr "Cet utilisateur n’existe pas." + +#: wp-includes/ms-functions.php:248 +msgid "That user does not exist." +msgstr "Cet utilisateur n’existe pas." + +#: wp-includes/ms-functions.php:288 +msgid "ERROR: Site URL already taken." +msgstr "Erreur p;: cette adresse de site est déjà prise." + +#: wp-includes/ms-functions.php:295 +msgid "ERROR: problem creating site entry." +msgstr "Erreur : problème lors de la création de l’entrée du site." + +#: wp-includes/ms-functions.php:440 wp-includes/ms-functions.php:561 +msgid "Only lowercase letters (a-z) and numbers are allowed." +msgstr "Seuls les lettres minuscules (de a à z) et chiffres sont autorisés." + +#: wp-includes/ms-functions.php:447 +msgid "Please enter a username." +msgstr "Veuillez saisir un identifiant." + +#: wp-includes/ms-functions.php:455 +msgid "That username is not allowed." +msgstr "Cet identifiant n’est pas autorisé." + +#: wp-includes/ms-functions.php:458 +msgid "" +"You cannot use that email address to signup. We are having problems with " +"them blocking some of our email. Please use another email provider." +msgstr "" +"Vous ne pouvez pas vous inscrire avec cette adresse de messagerie. Nous " +"avons rencontré des problèmes de la part de ce service. Merci d’en " +"utiliser un autre." + +#: wp-includes/ms-functions.php:461 +msgid "Username must be at least 4 characters." +msgstr "L’identifiant doit utiliser au moins 4 caractères." + +#: wp-includes/ms-functions.php:464 +msgid "Sorry, usernames may not contain the character “_”!" +msgstr "" +"Désolé, les identifiants ne doivent pas contenir le caractère « " +"_ » !" + +#: wp-includes/ms-functions.php:468 +msgid "Sorry, usernames must have letters too!" +msgstr "Désolé, les identifiants doivent aussi avoir des lettres !" + +#: wp-includes/ms-functions.php:471 +msgid "Please enter a valid email address." +msgstr "Veuillez saisir une adresse de messagerie valide." + +#: wp-includes/ms-functions.php:477 +msgid "Sorry, that email address is not allowed!" +msgstr "Désolé, cette adresse de messagerie n’est pas autorisée !" + +#: wp-includes/ms-functions.php:482 wp-includes/user.php:1333 +msgid "Sorry, that username already exists!" +msgstr "Désolé, cet identifiant existe déjà !" + +#: wp-includes/ms-functions.php:486 wp-includes/user.php:1348 +msgid "Sorry, that email address is already used!" +msgstr "Désolé, cette adresse de messagerie est déjà utilisée !" + +#: wp-includes/ms-functions.php:498 +msgid "" +"That username is currently reserved but may be available in a couple of days." +msgstr "" +"Cet identifiant est pour le moment réservé, mais pourrait être disponible " +"dans quelques jours." + +#: wp-includes/ms-functions.php:508 +msgid "" +"That email address has already been used. Please check your inbox for an " +"activation email. It will become available in a couple of days if you do " +"nothing." +msgstr "" +"Cette adresse de messagerie a déjà été utilisée. Veuillez vérifier dans " +"votre messagerie si le message d’activation ne s’y trouve pas. " +"L’identifiant redeviendra disponible dans quelques jours si vous ne " +"faites rien." + +#: wp-includes/ms-functions.php:558 +msgid "Please enter a site name." +msgstr "Veuillez saisir un nom de site." + +#: wp-includes/ms-functions.php:564 +msgid "That name is not allowed." +msgstr "Ce nom n’est pas autorisé." + +#: wp-includes/ms-functions.php:567 +msgid "Site name must be at least 4 characters." +msgstr "L’identifiant du site doit utiliser au moins 4 caractères." + +#: wp-includes/ms-functions.php:570 +msgid "Sorry, site names may not contain the character “_”!" +msgstr "" +"Désolé, les identifiants de site ne doivent pas contenir le caractère “" +"_”!;!" + +#: wp-includes/ms-functions.php:574 +msgid "Sorry, you may not use that site name." +msgstr "Désolé, vous ne pouvez pas utiliser ce nom pour votre site." + +#: wp-includes/ms-functions.php:578 +msgid "Sorry, site names must have letters too!" +msgstr "" +"Désolé, les identifiants de site doivent également avoir des lettres !" + +#: wp-includes/ms-functions.php:585 +msgid "Please enter a site title." +msgstr "Veuillez saisir un titre de site." + +#: wp-includes/ms-functions.php:596 wp-includes/ms-functions.php:957 +msgid "Sorry, that site already exists!" +msgstr "Désolé, ce site existe déjà !" + +#: wp-includes/ms-functions.php:600 +msgid "Sorry, that site is reserved!" +msgstr "Désolé, ce site est réservé !" + +#: wp-includes/ms-functions.php:611 +msgid "That site is currently reserved but may be available in a couple days." +msgstr "" +"Ce site est réservé pour le moment, mais pourrait être disponible dans " +"quelques jours." + +# Pas d'entité HTML : texte envoyé par mail +#: wp-includes/ms-functions.php:731 +msgid "" +"To activate your blog, please click the following link:\n" +"\n" +"%s\n" +"\n" +"After you activate, you will receive *another email* with your login.\n" +"\n" +"After you activate, you can visit your site here:\n" +"\n" +"%s" +msgstr "" +"Pour activer votre site, veuillez cliquer sur le lien suivant :\n" +"\n" +"%s\n" +"\n" +"Après l'activation, vous recevrez *un autre courrier* contenant votre " +"identifiant.\n" +"\n" +"Vous pourrez alors vous rendre sur votre site ici :\n" +"\n" +"%s" + +#: wp-includes/ms-functions.php:741 wp-includes/ms-functions.php:792 +msgid "[%1$s] Activate %2$s" +msgstr "[%1s] Activation de %2s" + +# Pas d'entité HTML : texte envoyé par mail +#: wp-includes/ms-functions.php:784 +msgid "" +"To activate your user, please click the following link:\n" +"\n" +"%s\n" +"\n" +"After you activate, you will receive *another email* with your login." +msgstr "" +"Pour activer votre utilisateur, veuillez cliquer sur le lien suivant :\n" +"\n" +"%s\n" +"\n" +"Après l'activation, vous recevrez *un autre courrier* contenant votre " +"identifiant." + +#: wp-includes/ms-functions.php:827 +msgid "Invalid activation key." +msgstr "clé d’activation invalide." + +#: wp-includes/ms-functions.php:831 +msgid "The user is already active." +msgstr "Cet utilisateur est déjà activé." + +#: wp-includes/ms-functions.php:833 +msgid "The site is already active." +msgstr "Ce site est déjà activé." + +#: wp-includes/ms-functions.php:847 +msgid "Could not create user" +msgstr "Impossible de créer l’utilisateur." + +#: wp-includes/ms-functions.php:855 +msgid "That username is already activated." +msgstr "Cet identifiant est déjà activé." + +#: wp-includes/ms-functions.php:963 +msgid "Could not create site." +msgstr "Impossible de créer le site." + +# Pas d'entité HTML. +#: wp-includes/ms-functions.php:1016 +msgid "" +"New Site: %1$s\n" +"URL: %2$s\n" +"Remote IP: %3$s\n" +"\n" +"Disable these notifications: %4$s" +msgstr "" +"Nouveau site : %1$s\n" +"URL : %2$s\n" +"Adresse IP : %3$s\n" +"\n" +"Désactiver ces notifications : %4$s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/ms-functions.php:1023 +msgid "New Site Registration: %s" +msgstr "Inscription d'un nouveau site : %s" + +#: wp-includes/ms-functions.php:1051 +msgid "" +"New User: %1$s\n" +"Remote IP: %2$s\n" +"\n" +"Disable these notifications: %3$s" +msgstr "" +"Nouvel utilisateur : %1$s\n" +"Adresse IP : %2$s\n" +"\n" +"Désactiver ces notifications : %3$s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/ms-functions.php:1057 +msgid "New User Registration: %s" +msgstr "Inscription d'un nouvel utilisateur : %s" + +#: wp-includes/ms-functions.php:1135 +msgid "Already Installed" +msgstr "Déjà installé" + +#: wp-includes/ms-functions.php:1135 +msgid "" +"You appear to have already installed WordPress. To reinstall please clear " +"your old database tables first." +msgstr "" +"Il semblerait que WordPress soit déjà installé. Pour le réinstaller, " +"commencez par supprimer vos anciennes tables de la base de données." + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/ms-functions.php:1215 +msgid "" +"Dear User,\n" +"\n" +"Your new SITE_NAME site has been successfully set up at:\n" +"BLOG_URL\n" +"\n" +"You can log in to the administrator account with the following information:\n" +"Username: USERNAME\n" +"Password: PASSWORD\n" +"Log in here: BLOG_URLwp-login.php\n" +"\n" +"We hope you enjoy your new site. Thanks!\n" +"\n" +"--The Team @ SITE_NAME" +msgstr "" +"Cher utilisateur,\n" +"\n" +"Votre nouveau site SITE_NAME a été bien créé à l'adresse :\n" +"BLOG_URL\n" +"\n" +"Vous pouvez vous connecter au compte administrateur avec les informations " +"suivantes :\n" +"Identifiant : USERNAME\n" +"Mot de passe : PASSWORD\n" +"Connectez-vous ici : BLOG_URLwp-login.php\n" +"\n" +"Nous espérons que vous apprécierez votre nouveau site. Merci !\n" +"\n" +"--L'équipe @ SITE_NAME" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/ms-functions.php:1251 +msgid "New %1$s Site: %2$s" +msgstr "Nouveau site %1$s : %2$s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/ms-functions.php:1299 +msgid "New %1$s User: %2$s" +msgstr "Nouvel utilisateur %1$s : %2$s" + +#: wp-includes/ms-functions.php:1580 +msgid "This file is too big. Files must be less than %d KB in size." +msgstr "" +"Ce fichier est trop gros. La taille des fichiers doit être inférieure %d Ko." + +#: wp-includes/ms-functions.php:1655 +msgid "" +"An error occurred adding you to this site. Back to the homepage." +msgstr "" +"Une erreur est survenue lors de votre ajout à ce site. Retournez à l’" +"accueil." + +#: wp-includes/ms-functions.php:1657 +msgid "" +"You have been added to this site. Please visit the homepage or log in using your username and password." +msgstr "" +"Vous avez été ajouté à ce site. Vous pouvez vous rendre sur sa page d’accueil ou vous connecter à " +"l’aide de votre identifiant et mot de passe." + +#: wp-includes/ms-functions.php:1657 +msgid "WordPress › Success" +msgstr "WordPress » Réussite" + +# Pas d'entité HTML : texte envoyé par mail +#: wp-includes/ms-functions.php:1805 +msgid "" +"Dear User,\n" +"\n" +"Your new account is set up.\n" +"\n" +"You can log in with the following information:\n" +"Username: USERNAME\n" +"Password: PASSWORD\n" +"LOGINLINK\n" +"\n" +"Thanks!\n" +"\n" +"--The Team @ SITE_NAME" +msgstr "" +"Cher utilisateur,\n" +"\n" +"Votre nouveau compte a été créé.\n" +"\n" +"Vous pouvez vous connecter avec les informations suivantes :\n" +"Identifiant : USERNAME\n" +"Mot de passe : PASSWORD\n" +"LOGINLINK\n" +"\n" +"Merci !\n" +"\n" +"--L'équipe @ SITE_NAME" + +#: wp-includes/ms-load.php:95 +msgid "" +"This user has elected to delete their account and the content is no longer " +"available." +msgstr "" +"Cet utilisateur a choisi d’effacer son compte, et son contenu n’" +"est plus disponible." + +#: wp-includes/ms-load.php:102 +msgid "" +"This site has not been activated yet. If you are having problems activating " +"your site, please contact %1$s." +msgstr "" +"Ce site n’a pas encore été activé. Si vous rencontrez des problèmes " +"durant l’activation de votre site, veuillez contacter %1$s." + +#: wp-includes/ms-load.php:109 +msgid "This site has been archived or suspended." +msgstr "Ce site a été archivé ou suspendu." + +#: wp-includes/ms-load.php:225 +msgid "That site does not exist. Please try %s." +msgstr "" +"Cet importateur n’existe pas. Veuillez essayer %s." + +#: wp-includes/ms-load.php:227 +msgid "" +"No site defined on this host. If you are the owner of this site, please " +"check Debugging a WordPress Network for help." +msgstr "" +"Aucun site n’est défini sur cet hôte. Si vous êtes le propriétaire de " +"ce site, veuillez consulter la page Debugging a WordPress Network (en " +"anglais) pour obtenir de l’aide." + +#: wp-includes/ms-load.php:247 +msgid "" +"If your site does not display, please contact the owner of this network." +msgstr "" +"Si votre site ne s’affiche pas, veuillez contacter le gestionnaire de " +"ce réseau de sites." + +#: wp-includes/ms-load.php:248 +msgid "" +"If you are the owner of this network please check that MySQL is running " +"properly and all tables are error free." +msgstr "" +"Si vous êtes le gestionnaire de ce réseau de sites, veuillez vous assurer " +"que MySQL fonctionne correctement et qu’aucune table n’a d’" +"erreur." + +#: wp-includes/ms-load.php:250 +msgid "" +"Database tables are missing. This means that MySQL is not " +"running, WordPress was not installed properly, or someone deleted %s. You really should look at your database now." +msgstr "" +"Des tables de la base de données sont manquantes. Cela peut " +"signifier que MySQL ne fonctionne pas, ou que WordPress n’a pas été " +"installé correctement, ou que quelqu’un a effacé %s. Vous " +"devriez vraiment vraiment vérifier votre base de données au plus " +"vite." + +#: wp-includes/ms-load.php:252 +msgid "" +"Could not find site %1$s. Searched for table " +"%2$s in database %3$s. Is that right?" +msgstr "" +"Le site %1$s Nous avons " +"cherché la table %2$s dans la base de données %3$s. Est-ce " +"correct ?" + +#: wp-includes/ms-load.php:253 +msgid "What do I do now?" +msgstr "Que dois-je faire maintenant ?" + +#: wp-includes/ms-load.php:254 +msgid "" +"Read the bug report page. Some of the guidelines " +"there may help you figure out what went wrong." +msgstr "" +"Lisez la page de gestions des bugs (en anglais). " +"Certaines des bonnes pratiques qui y sont présentées pourraient vous aider à " +"comprendre ce qui a mal tourné." + +#: wp-includes/ms-load.php:255 +msgid "" +"If you’re still stuck with this message, then check that your database " +"contains the following tables:" +msgstr "" +"Si vous êtes toujours bloqué par ce message, vérifiez alors que votre base " +"de données contient bien les tables suivantes :" + +#: wp-includes/ms-settings.php:35 +msgid "Multisite only works without the port number in the URL." +msgstr "" +"La fonctionnalité multisites fonctionne uniquement sans le numéro de port " +"dans l’adresse." + +#: wp-includes/ms-settings.php:121 +msgid "Database tables are missing." +msgstr "Les tables de la base de données sont manquantes." + +#: wp-includes/ms-settings.php:122 +msgid "No site by that name on this system." +msgstr "Aucun site ne porte ce nom dans ce système." + +#: wp-includes/nav-menu.php:235 wp-includes/nav-menu.php:242 +msgid "" +"The menu name %s conflicts with another menu name. Please " +"try another." +msgstr "" +"Un menu nommé %s est en conflit avec un autre nom de menu. " +"Veuillez réessayer avec un notre nom." + +#: wp-includes/nav-menu.php:284 +msgid "The given object ID is not that of a menu item." +msgstr "" +"L’identifiant donné pour cet objet n’est pas une entrée de menu." + +# Indicateur de "custom link" -> "lien personnalisé" +#: wp-includes/nav-menu.php:618 +msgid "Custom" +msgstr "Lien" + +#: wp-includes/nav-menu.php:643 wp-includes/post-template.php:1072 +msgid "#%d (no title)" +msgstr "#%d (pas de titre)" + +#: wp-includes/option.php:108 +msgid "%s is a protected WP option and may not be modified" +msgstr "%s est une option protégée de WordPress, et ne peut être modifiée" + +#: wp-includes/pluggable.php:477 +msgid "ERROR: Invalid username or incorrect password." +msgstr "" +"ERREUR : l’identifiant ou le mot de passe " +"n’est pas valide." + +#: wp-includes/pluggable.php:809 +msgid "" +"You should specify a nonce action to be verified by using the first " +"parameter." +msgstr "" +"Vous devriez préciser une action de type « nonce », " +"qui sera vérifiée par le premier paramètre." + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1047 +msgid "New comment on your post \"%s\"" +msgstr "Nouveau commentaire sur votre article « %s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#. translators: 1: comment author, 2: author IP, 3: author domain +#: wp-includes/pluggable.php:1049 wp-includes/pluggable.php:1170 +msgid "Author : %1$s (IP: %2$s , %3$s)" +msgstr "Auteur : %1$s (IP : %2$s , %3$s)" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1050 wp-includes/pluggable.php:1171 +msgid "E-mail : %s" +msgstr "E-mail : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1051 wp-includes/pluggable.php:1061 +#: wp-includes/pluggable.php:1070 wp-includes/pluggable.php:1157 +#: wp-includes/pluggable.php:1164 wp-includes/pluggable.php:1172 +msgid "URL : %s" +msgstr "Adresse : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1052 wp-includes/pluggable.php:1173 +msgid "Whois : http://whois.arin.net/rest/ip/%s" +msgstr "Whois : http://whois.arin.net/rest/ip/%s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1053 wp-includes/pluggable.php:1174 +msgid "Comment: " +msgstr "Commentaire :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1054 +msgid "You can see all comments on this post here: " +msgstr "Vous pouvez lire tous les commentaires de cet article ici :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#. translators: 1: blog name, 2: post title +#: wp-includes/pluggable.php:1056 +msgid "[%1$s] Comment: \"%2$s\"" +msgstr "[%1$s] Commentaire : « %2$s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1058 +msgid "New trackback on your post \"%s\"" +msgstr "Nouveau rétrolien sur votre article « %s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#. translators: 1: website name, 2: author IP, 3: author domain +#. translators: 1: comment author, 2: author IP, 3: author domain +#: wp-includes/pluggable.php:1060 wp-includes/pluggable.php:1069 +msgid "Website: %1$s (IP: %2$s , %3$s)" +msgstr "Site Web : %1$s (IP : %2$s , %3$s)" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1062 wp-includes/pluggable.php:1071 +msgid "Excerpt: " +msgstr "Extrait :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1063 +msgid "You can see all trackbacks on this post here: " +msgstr "Vous pouvez lire tous les rétroliens de cet article ici :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#. translators: 1: blog name, 2: post title +#: wp-includes/pluggable.php:1065 +msgid "[%1$s] Trackback: \"%2$s\"" +msgstr "[%1$s] Rétrolien : « %2$s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1067 +msgid "New pingback on your post \"%s\"" +msgstr "Nouveau ping sur votre article « %s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1072 +msgid "You can see all pingbacks on this post here: " +msgstr "Vous pouvez lire tous les pings de cet article ici :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#. translators: 1: blog name, 2: post title +#: wp-includes/pluggable.php:1074 +msgid "[%1$s] Pingback: \"%2$s\"" +msgstr "[%1$s] Ping : « %2$s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1077 +msgid "Permalink: %s" +msgstr "Permalien : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1081 wp-includes/pluggable.php:1180 +msgid "Trash it: %s" +msgstr "Le mettre dans la Corbeille : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1083 wp-includes/pluggable.php:1182 +msgid "Delete it: %s" +msgstr "Le supprimer : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1084 wp-includes/pluggable.php:1183 +msgid "Spam it: %s" +msgstr "Le marquer comme indésirable : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1154 +msgid "A new trackback on the post \"%s\" is waiting for your approval" +msgstr "Un nouveau rétrolien sur l'article « %s » attend votre approbation" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1156 wp-includes/pluggable.php:1163 +msgid "Website : %1$s (IP: %2$s , %3$s)" +msgstr "Site Web : %1$s (IP: %2$s , %3$s)" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1158 +msgid "Trackback excerpt: " +msgstr "Extrait du rétrolien :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1161 +msgid "A new pingback on the post \"%s\" is waiting for your approval" +msgstr "Un nouveau ping sur l'article « %s » attend votre approbation" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1165 +msgid "Pingback excerpt: " +msgstr "Extrait du ping :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1168 +msgid "A new comment on the post \"%s\" is waiting for your approval" +msgstr "Un nouveau commentaire sur l'article « %s » attend votre approbation" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1178 +msgid "Approve it: %s" +msgstr "L'approuver : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1185 +msgid "" +"Currently %s comment is waiting for approval. Please visit the moderation " +"panel:" +msgid_plural "" +"Currently %s comments are waiting for approval. Please visit the moderation " +"panel:" +msgstr[0] "" +"En ce moment, %s commentaire attend votre approbation. Veuillez vous rendre " +"sur le panneau de modération :" +msgstr[1] "" +"En ce moment, %s commentaires attendent vos approbations. Veuillez vous " +"rendre sur le panneau de modération :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1189 +msgid "[%1$s] Please moderate: \"%2$s\"" +msgstr "[%1$s] Demande de modération pour « %2$s »" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1217 +msgid "Password Lost and Changed for user: %s" +msgstr "Mot de passe oublié et changé pour l'utilisateur : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1221 +msgid "[%s] Password Lost/Changed" +msgstr "[%s] Mot de passe oublié et changé" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1242 +msgid "New user registration on your site %s:" +msgstr "Inscription d'un nouvel utilisateur sur votre site %s :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1243 wp-includes/pluggable.php:1251 +#: wp-login.php:355 +msgid "Username: %s" +msgstr "Identifiant : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1244 +msgid "E-mail: %s" +msgstr "E-mail : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1246 +msgid "[%s] New User Registration" +msgstr "[%s] Inscription d'un nouvel utilisateur" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1252 +msgid "Password: %s" +msgstr "Mot de passe : %s" + +# Ne pas mettre d'entité HTML ( ...) : chaîne envoyée par e-mail. +#: wp-includes/pluggable.php:1255 +msgid "[%s] Your username and password" +msgstr "[%s] Votre identifiant et mot de passe" + +#: wp-includes/plugin.php:700 +msgid "" +"Only a static class method or function can be used in an uninstall hook." +msgstr "" +"Seule une méthode statique de classe ou une fonction peut être utilisée avec " +"un crochet de désinstallation." + +#: wp-includes/post-formats.php:70 +msgid "Invalid post" +msgstr "Article invalide" + +#: wp-includes/post-formats.php:92 +msgctxt "Post format" +msgid "Standard" +msgstr "Par défaut" + +#: wp-includes/post-formats.php:93 +msgctxt "Post format" +msgid "Aside" +msgstr "En passant" + +#: wp-includes/post-formats.php:94 +msgctxt "Post format" +msgid "Chat" +msgstr "Discussion" + +#: wp-includes/post-formats.php:95 +msgctxt "Post format" +msgid "Gallery" +msgstr "Galerie" + +#: wp-includes/post-formats.php:96 +msgctxt "Post format" +msgid "Link" +msgstr "Lien" + +#: wp-includes/post-formats.php:97 +msgctxt "Post format" +msgid "Image" +msgstr "Image" + +#: wp-includes/post-formats.php:98 +msgctxt "Post format" +msgid "Quote" +msgstr "Citation" + +#: wp-includes/post-formats.php:99 +msgctxt "Post format" +msgid "Status" +msgstr "État" + +#: wp-includes/post-formats.php:100 +msgctxt "Post format" +msgid "Video" +msgstr "Vidéo" + +#: wp-includes/post-formats.php:101 +msgctxt "Post format" +msgid "Audio" +msgstr "Son" + +#: wp-includes/post-template.php:110 +msgid "Protected: %s" +msgstr "Protégé : %s" + +#: wp-includes/post-template.php:113 +msgid "Private: %s" +msgstr "Privé : %s" + +#: wp-includes/post-template.php:186 +msgid "(more…)" +msgstr "(suite…)" + +#: wp-includes/post-template.php:272 +msgid "There is no excerpt because this is a protected post." +msgstr "Il n’y pas d’extrait, car cet article est protégé." + +#: wp-includes/post-template.php:640 +msgid "Pages:" +msgstr "Pages :" + +#: wp-includes/post-template.php:646 +msgid "Next page" +msgstr "Page suivante" + +#: wp-includes/post-template.php:647 +msgid "Previous page" +msgstr "Page précédente" + +#: wp-includes/post-template.php:910 +msgid "Home" +msgstr "Accueil" + +#: wp-includes/post-template.php:1250 +msgid "" +"This content is password protected. To view it please enter your password " +"below:" +msgstr "" +"Cet article est protégé par un mot de passe. Pour le lire, veuillez saisir " +"votre mot de passe ci-dessous :" + +#: wp-includes/post-template.php:1251 +msgid "Submit" +msgstr "Envoyer" + +#. translators: revision date format, see http:php.net/date +#: wp-includes/post-template.php:1328 +msgctxt "revision date format" +msgid "j F, Y @ G:i" +msgstr "j F Y \\à G \\h i \\m" + +#. translators: 1: date +#: wp-includes/post-template.php:1330 +msgctxt "post revision title extra" +msgid "%1$s [Autosave]" +msgstr "%1$s [Sauvegarde automatique]" + +#. translators: 1: date +#: wp-includes/post-template.php:1332 +msgctxt "post revision title extra" +msgid "%1$s [Current Revision]" +msgstr "%1$s [Version actuelle]" + +#. translators: revision date format, see http:php.net/date +#: wp-includes/post-template.php:1368 +msgctxt "revision date format" +msgid "j F, Y @ G:i:s" +msgstr "j F Y \\à G \\h i \\m" + +#. translators: post revision title: 1: author avatar, 2: author name, 3: time +#. ago, 4: date +#: wp-includes/post-template.php:1378 +msgctxt "post revision title" +msgid "%1$s %2$s, %3$s ago (%4$s)" +msgstr "%1$s %2$s, il y a %3$s (%4$s)" + +#: wp-includes/post-template.php:1385 +msgid "%1$s [Autosave]" +msgstr "%1$s [Sauvegarde automatique]" + +#: wp-includes/post-template.php:1386 +msgid "%1$s [Current Revision]" +msgstr "%1$s [Version actuelle]" + +#: wp-includes/post-template.php:1440 +msgid "JavaScript must be enabled to use this feature." +msgstr "JavaScript doit être activé pour utiliser cette fonctionnalité." + +#: wp-includes/post.php:22 +msgctxt "add new on admin bar" +msgid "Post" +msgstr "Article" + +#: wp-includes/post.php:38 +msgctxt "add new on admin bar" +msgid "Page" +msgstr "Page" + +#: wp-includes/post.php:55 +msgctxt "post type general name" +msgid "Media" +msgstr "Médias" + +#: wp-includes/post.php:56 +msgctxt "add new from admin bar" +msgid "Media" +msgstr "Fichier média" + +# contexte +#: wp-includes/post.php:57 +msgctxt "add new media" +msgid "Add New" +msgstr "Ajouter" + +#: wp-includes/post.php:58 +msgid "Edit Media" +msgstr "Modifier un média" + +#: wp-includes/post.php:59 +msgid "View Attachment Page" +msgstr "Afficher la page du fichier attaché" + +#: wp-includes/post.php:80 +msgid "Revisions" +msgstr "Révisions" + +#: wp-includes/post.php:81 +msgid "Revision" +msgstr "Révision" + +#: wp-includes/post.php:98 +msgid "Navigation Menu Items" +msgstr "Éléments de menu de navigation" + +#: wp-includes/post.php:99 +msgid "Navigation Menu Item" +msgstr "Élément de menu de navigation" + +#: wp-includes/post.php:110 +msgctxt "post" +msgid "Published" +msgstr "Publié" + +#: wp-includes/post.php:113 +msgid "Published (%s)" +msgid_plural "Published (%s)" +msgstr[0] "Publié (%s)" +msgstr[1] "Publiés (%s)" + +#: wp-includes/post.php:117 +msgctxt "post" +msgid "Scheduled" +msgstr "Planifié" + +#: wp-includes/post.php:120 +msgid "Scheduled (%s)" +msgid_plural "Scheduled (%s)" +msgstr[0] "Planifié (%s)" +msgstr[1] "Planifiés (%s)" + +#: wp-includes/post.php:124 +msgctxt "post" +msgid "Draft" +msgstr "Brouillon" + +#: wp-includes/post.php:127 +msgid "Draft (%s)" +msgid_plural "Drafts (%s)" +msgstr[0] "Brouillon (%s)" +msgstr[1] "Brouillons (%s)" + +#: wp-includes/post.php:131 +msgctxt "post" +msgid "Pending" +msgstr "En attente" + +#: wp-includes/post.php:134 +msgid "Pending (%s)" +msgid_plural "Pending (%s)" +msgstr[0] "En attente de relecture (%s)" +msgstr[1] "En attente de relecture (%s)" + +#: wp-includes/post.php:138 +msgctxt "post" +msgid "Private" +msgstr "Privé" + +#: wp-includes/post.php:141 +msgid "Private (%s)" +msgid_plural "Private (%s)" +msgstr[0] "Privé (%s)" +msgstr[1] "Privés (%s)" + +#: wp-includes/post.php:145 +msgctxt "post" +msgid "Trash" +msgstr "Corbeille" + +#: wp-includes/post.php:148 +msgid "Trash (%s)" +msgid_plural "Trash (%s)" +msgstr[0] "Corbeille (%s)" +msgstr[1] "Corbeille (%s)" + +#: wp-includes/post.php:831 wp-includes/post.php:852 +msgid "Draft" +msgstr "Brouillon" + +#: wp-includes/post.php:832 +msgid "Pending Review" +msgstr "En attente de relecture" + +#: wp-includes/post.php:833 wp-includes/post.php:853 +#: wp-includes/script-loader.php:431 +msgid "Private" +msgstr "Privé" + +#: wp-includes/post.php:834 wp-includes/post.php:854 +#: wp-includes/script-loader.php:436 +msgid "Published" +msgstr "Publié" + +#: wp-includes/post.php:1219 +msgid "Post types cannot exceed 20 characters in length" +msgstr "Les types de contenu ne peuvent dépasser les 20 caractères." + +#: wp-includes/post.php:1482 +msgctxt "post type general name" +msgid "Posts" +msgstr "Articles" + +#: wp-includes/post.php:1482 +msgctxt "post type general name" +msgid "Pages" +msgstr "Pages" + +#: wp-includes/post.php:1483 +msgctxt "post type singular name" +msgid "Post" +msgstr "Article" + +#: wp-includes/post.php:1483 +msgctxt "post type singular name" +msgid "Page" +msgstr "Page" + +#: wp-includes/post.php:1484 +msgctxt "post" +msgid "Add New" +msgstr "Ajouter" + +#: wp-includes/post.php:1484 +msgctxt "page" +msgid "Add New" +msgstr "Ajouter" + +#: wp-includes/post.php:1485 +msgid "Add New Post" +msgstr "Ajouter un nouvel article" + +#: wp-includes/post.php:1485 +msgid "Add New Page" +msgstr "Ajouter une nouvelle page" + +#: wp-includes/post.php:1486 +msgid "Edit Post" +msgstr "Modifier l’article" + +#: wp-includes/post.php:1486 +msgid "Edit Page" +msgstr "Modifier la page" + +#: wp-includes/post.php:1487 +msgid "New Page" +msgstr "Nouvelle page" + +#: wp-includes/post.php:1488 +msgid "View Page" +msgstr "Voir la page" + +#: wp-includes/post.php:1489 +msgid "Search Posts" +msgstr "Chercher dans les articles" + +#: wp-includes/post.php:1489 +msgid "Search Pages" +msgstr "Chercher dans les pages" + +#: wp-includes/post.php:1490 +msgid "No posts found." +msgstr "Aucun article trouvé." + +#: wp-includes/post.php:1490 +msgid "No pages found." +msgstr "Aucune page trouvée." + +#: wp-includes/post.php:1491 +msgid "No posts found in Trash." +msgstr "Aucun article trouvé dans la corbeille." + +#: wp-includes/post.php:1491 +msgid "No pages found in Trash." +msgstr "Aucune page trouvée dans la corbeille." + +#: wp-includes/post.php:1492 +msgid "Parent Page:" +msgstr "Page parente :" + +#: wp-includes/post.php:1493 +msgid "All Posts" +msgstr "Tous les articles" + +#: wp-includes/post.php:1493 +msgid "All Pages" +msgstr "Toutes les pages" + +#: wp-includes/post.php:2179 +msgid "Images" +msgstr "Images" + +#: wp-includes/post.php:2179 +msgid "Manage Images" +msgstr "Gérer les images" + +#: wp-includes/post.php:2179 +msgid "Image (%s)" +msgid_plural "Images (%s)" +msgstr[0] "Image (%s)" +msgstr[1] "Images (%s)" + +#: wp-includes/post.php:2180 +msgid "Audio" +msgstr "Sons" + +#: wp-includes/post.php:2180 +msgid "Manage Audio" +msgstr "Gérer l’audio" + +#: wp-includes/post.php:2180 +msgid "Audio (%s)" +msgid_plural "Audio (%s)" +msgstr[0] "Son (%s)" +msgstr[1] "Sons (%s)" + +#: wp-includes/post.php:2181 +msgid "Video" +msgstr "Vidéos" + +#: wp-includes/post.php:2181 +msgid "Manage Video" +msgstr "Gérer les vidéos" + +#: wp-includes/post.php:2181 +msgid "Video (%s)" +msgid_plural "Video (%s)" +msgstr[0] "Vidéo (%s)" +msgstr[1] "Vidéos (%s)" + +#: wp-includes/post.php:2632 +msgid "" +"Passing an integer number of posts is deprecated. Pass an array of arguments " +"instead." +msgstr "" +"Il n’est pas recommandé de passer un nombre entier d’" +"articles ; il est préférable de passer un tableau d’arguments." + +#: wp-includes/post.php:2743 +msgid "Content, title, and excerpt are empty." +msgstr "Le contenu de l’article, le titre et l’extrait sont vides." + +#: wp-includes/post.php:2800 +msgid "Whoops, the provided date is invalid." +msgstr "Oups, la date fournie n’est pas valable." + +#: wp-includes/post.php:2875 +msgid "Could not update post in the database" +msgstr "Impossible de mettre à jour l’article dans la base de données" + +#: wp-includes/post.php:2891 +msgid "Could not insert post into the database" +msgstr "Impossible d’insérer l’article dans la base de données" + +#: wp-includes/post.php:2938 +msgid "The page template is invalid." +msgstr "Le modèle de page est invalide." + +#: wp-includes/post.php:3237 wp-includes/script-loader.php:437 +#: wp-includes/script-loader.php:462 +msgctxt "tag delimiter" +msgid "," +msgstr ", " + +#: wp-includes/query.php:140 wp-includes/query.php:161 +#: wp-includes/query.php:181 wp-includes/query.php:205 +#: wp-includes/query.php:229 wp-includes/query.php:253 +#: wp-includes/query.php:282 wp-includes/query.php:302 +#: wp-includes/query.php:322 wp-includes/query.php:342 +#: wp-includes/query.php:363 wp-includes/query.php:383 +#: wp-includes/query.php:413 wp-includes/query.php:442 +#: wp-includes/query.php:462 wp-includes/query.php:489 +#: wp-includes/query.php:509 wp-includes/query.php:529 +#: wp-includes/query.php:549 wp-includes/query.php:569 +#: wp-includes/query.php:598 wp-includes/query.php:625 +#: wp-includes/query.php:645 wp-includes/query.php:665 +#: wp-includes/query.php:685 wp-includes/query.php:705 +msgid "" +"Conditional query tags do not work before the query is run. Before then, " +"they always return false." +msgstr "" +"Les balises de requête conditionnelle ne fonctionnent pas avant le lancement " +"de la requête. Avant cela, elles renvoient toujours le booléen false." + +#: wp-includes/query.php:721 +msgid "" +"In %1$s, use the %2$s method, not the %3$s function. See %4$s." +msgstr "" +"Dans %1$s, utilisez la méthode %2$s, pas la " +"fonction %3$s. Lisez %4$s." + +#: wp-includes/query.php:722 +msgid "http://codex.wordpress.org/Function_Reference/is_main_query" +msgstr "http://codex.wordpress.org/Function_Reference/is_main_query" + +#. translators: This is a comma-separated list of very common words that should +#. be excluded from a search, +#. * like a, an, and the. These are usually called "stopwords". You should +#. not simply translate these individual +#. * words into your language. Instead, look for and provide commonly +#. accepted stopwords in your language. +#: wp-includes/query.php:2017 +msgctxt "Comma-separated list of search stopwords in your language" +msgid "" +"about,an,are,as,at,be,by,com,for,from,how,in,is,it,of,on,or,that,the,this,to," +"was,what,when,where,who,will,with,www" +msgstr "" +"le,la,les,de,des,un,uns,une,unes,et,a,à,il,elle,on,ne,je,tu,nous,vous,ils," +"elles,son,sa,ses,que,quoi,se,qui,ce,cette,dans,en,du,au,aux,pour,pas,sur,y," +"ou,où,si,ton,ta,te,mon,ma,tout,toute,tous,toutes,ça,ni,www,com,fr,par,sur," +"par,dans,mais,vos,votre,vôtre,c,d,j,,l,m,n,s,t,sans,toi,moi,lui,leur,leurs" + +#: wp-includes/query.php:2173 +msgid "" +"\"caller_get_posts\" is deprecated. Use \"ignore_sticky_posts\" instead." +msgstr "" +"« caller_get_posts » n’est plus recommandé. " +"Utilisez « ignore_sticky_posts » à la place." + +#: wp-includes/registration-functions.php:7 wp-includes/registration.php:7 +msgid "This file no longer needs to be included." +msgstr "Ce fichier n’a plus besoin d’être inclus." + +#: wp-includes/revision.php:32 +msgid "Content" +msgstr "Contenu" + +#: wp-includes/revision.php:33 +msgid "Excerpt" +msgstr "Extrait" + +#: wp-includes/revision.php:230 +msgid "Cannot create a revision of a revision" +msgstr "Impossible de créer une version d’une version." + +#: wp-includes/revision.php:468 +msgid "You do not have permission to preview drafts." +msgstr "" +"Vous n’avez pas l’autorisation de prévisualiser les brouillons" + +# Pas d'entité : JavaScript. +#: wp-includes/script-loader.php:77 +msgid "" +"You are about to permanently delete the selected items.\n" +" 'Cancel' to stop, 'OK' to delete." +msgstr "" +"Vous êtes sur le point de supprimer définitivement les éléments " +"sélectionnés.\n" +" « Annuler » pour abandonner, « OK » pour les supprimer." + +#: wp-includes/script-loader.php:84 +msgid "Close all open tags" +msgstr "Fermer toutes les balises ouvertes" + +#: wp-includes/script-loader.php:85 +msgid "close tags" +msgstr "fermer les balises" + +# Pas d'entité HTML : utilisé dans un alert(). +#: wp-includes/script-loader.php:86 +msgid "Enter the URL" +msgstr "Saisissez l’adresse" + +#: wp-includes/script-loader.php:87 +msgid "Enter the URL of the image" +msgstr "Saisissez l’adresse de l’image" + +#: wp-includes/script-loader.php:88 +msgid "Enter a description of the image" +msgstr "Saisissez une description pour l’image" + +#: wp-includes/script-loader.php:89 +msgid "fullscreen" +msgstr "plein écran" + +#: wp-includes/script-loader.php:90 +msgid "Toggle fullscreen mode" +msgstr "Mode plein écran" + +#: wp-includes/script-loader.php:91 +msgid "text direction" +msgstr "direction du texte" + +#: wp-includes/script-loader.php:92 +msgid "Toggle Editor Text Direction" +msgstr "Inverser la direction de l’éditeur de texte" + +#: wp-includes/script-loader.php:103 wp-includes/script-loader.php:399 +msgid "You do not have permission to do that." +msgstr "Vous n’avez pas l’autorisation d’effectuer cela." + +#: wp-includes/script-loader.php:104 wp-includes/script-loader.php:400 +msgid "An unidentified error has occurred." +msgstr "Une erreur non identifiée est survenue." + +#: wp-includes/script-loader.php:109 wp-includes/script-loader.php:240 +msgid "Dismiss" +msgstr "Fermer" + +#: wp-includes/script-loader.php:121 +msgid "" +"Your session has expired. You can log in again from this page or go to the " +"login page." +msgstr "" +"Votre session a expiré. Vous pouvez vous reconnecter depuis cette page ou " +"aller à la page de connexion." + +#: wp-includes/script-loader.php:200 +msgid "Next >" +msgstr "Suiv. >" + +#: wp-includes/script-loader.php:201 +msgid "< Prev" +msgstr "< Préc." + +#: wp-includes/script-loader.php:202 +msgid "Image" +msgstr "Image" + +#: wp-includes/script-loader.php:203 +msgid "of" +msgstr "sur" + +#: wp-includes/script-loader.php:205 +msgid "" +"This feature requires inline frames. You have iframes disabled or your " +"browser does not support them." +msgstr "" +"Cette fonctionnalité requiert des iframes. Les iframes sont désactivées sur " +"votre navigateur, ou alors il ne les accepte pas." + +#: wp-includes/script-loader.php:218 +msgid "not configured" +msgstr "non configuré" + +#: wp-includes/script-loader.php:222 +msgid "You have attempted to queue too many files." +msgstr "Vous essayez d’envoyer trop de fichiers à la fois." + +#: wp-includes/script-loader.php:223 +msgid "%s exceeds the maximum upload size for this site." +msgstr "%s dépasse la limite d’envoi de ce site." + +#: wp-includes/script-loader.php:224 +msgid "This file is empty. Please try another." +msgstr "Le fichier est vide. Merci d’en essayer un autre." + +#: wp-includes/script-loader.php:225 +msgid "This file type is not allowed. Please try another." +msgstr "" +"Ce type de fichier n’est pas autorisé. Merci d’en essayer un " +"autre." + +#: wp-includes/script-loader.php:226 +msgid "This file is not an image. Please try another." +msgstr "" +"Ce fichier n’est pas une image. Merci d’en envoyer un autre." + +#: wp-includes/script-loader.php:227 +msgid "Memory exceeded. Please try another smaller file." +msgstr "Mémoire dépassée. Veuillez réessayer avec un fichier plus petit." + +#: wp-includes/script-loader.php:228 +msgid "This is larger than the maximum size. Please try another." +msgstr "" +"Ce fichier est plus grand que la taille maximale. Merci d’en envoyer " +"un autre." + +#: wp-includes/script-loader.php:229 +msgid "An error occurred in the upload. Please try again later." +msgstr "" +"Une erreur est survenue lors de l’envoi. Veuillez réessayer plus tard." + +#: wp-includes/script-loader.php:230 +msgid "" +"There was a configuration error. Please contact the server administrator." +msgstr "" +"Il y a une erreur de configuration. Veuillez contacter l’" +"administrateur de votre serveur." + +#: wp-includes/script-loader.php:231 +msgid "You may only upload 1 file." +msgstr "Vous pouvez seulement envoyer 1 fichier." + +#: wp-includes/script-loader.php:232 +msgid "HTTP error." +msgstr "Erreur HTTP." + +#: wp-includes/script-loader.php:233 +msgid "Upload failed." +msgstr "L’envoi a échoué." + +#: wp-includes/script-loader.php:234 +msgid "Please try uploading this file with the %1$sbrowser uploader%2$s." +msgstr "" +"Veuillez essayer de mettre ce fichier en ligne à l’aide de l’" +"%1$soutil du navigateur%2$s." + +#: wp-includes/script-loader.php:235 +msgid "" +"%s exceeds the maximum upload size for the multi-file uploader when used in " +"your browser." +msgstr "" +"%s dépasse la limite d’envoi pour l’outil de mise ne ligne " +"multiple utilisé avec votre navigateur." + +#: wp-includes/script-loader.php:236 +msgid "IO error." +msgstr "Erreur I/O (Entrées-Sorties)." + +#: wp-includes/script-loader.php:237 +msgid "Security error." +msgstr "Erreur de sécurité." + +#: wp-includes/script-loader.php:238 +msgid "File canceled." +msgstr "Fichier annulé." + +#: wp-includes/script-loader.php:239 +msgid "Upload stopped." +msgstr "L’envoi est stoppé." + +#: wp-includes/script-loader.php:241 +msgid "Crunching…" +msgstr "En cours de traitement…" + +#: wp-includes/script-loader.php:242 +msgid "moved to the trash." +msgstr "déplacé dans la corbeille." + +#: wp-includes/script-loader.php:243 +msgid "“%s” has failed to upload." +msgstr "« %s » n’a pas pu être mis en ligne." + +#: wp-includes/script-loader.php:296 +msgid "Download File" +msgstr "Télécharger le fichier" + +#: wp-includes/script-loader.php:297 +msgid "Download Video" +msgstr "Télécharger la vidéo" + +#: wp-includes/script-loader.php:298 +msgid "Play/Pause" +msgstr "Lecture/Pause" + +#: wp-includes/script-loader.php:299 +msgid "Mute Toggle" +msgstr "Inverser le son" + +#: wp-includes/script-loader.php:301 +msgid "Turn off Fullscreen" +msgstr "Quitter le plein écran" + +#: wp-includes/script-loader.php:302 +msgid "Go Fullscreen" +msgstr "Passer en plein écran" + +#: wp-includes/script-loader.php:303 +msgid "Unmute" +msgstr "Réactiver le son" + +#: wp-includes/script-loader.php:305 +msgid "Captions/Subtitles" +msgstr "Légendes/Sous-titres" + +#: wp-includes/script-loader.php:322 wp-login.php:610 +msgid "Strength indicator" +msgstr "Indicateur de sûreté" + +#: wp-includes/script-loader.php:323 +msgid "Very weak" +msgstr "Très faible" + +#: wp-includes/script-loader.php:324 +msgid "Weak" +msgstr "Faible" + +#. translators: password strength +#: wp-includes/script-loader.php:326 +msgctxt "password strength" +msgid "Medium" +msgstr "Moyenne" + +#: wp-includes/script-loader.php:327 +msgid "Strong" +msgstr "Forte" + +#: wp-includes/script-loader.php:328 +msgid "Mismatch" +msgstr "Incohérence" + +#: wp-includes/script-loader.php:344 wp-includes/script-loader.php:461 +msgid "(no title)" +msgstr "(pas de titre)" + +#: wp-includes/script-loader.php:345 +msgid "No matches found." +msgstr "Aucune correspondance trouvée." + +#: wp-includes/script-loader.php:368 +msgid "Save & Activate" +msgstr "Enregistrer & activer" + +#: wp-includes/script-loader.php:369 +msgid "Save & Publish" +msgstr "Enregistrer & publier" + +#: wp-includes/script-loader.php:370 +msgid "Saved" +msgstr "Enregistré" + +#: wp-includes/script-loader.php:407 +msgid "Approve and Reply" +msgstr "Approuver et répondre" + +#: wp-includes/script-loader.php:417 +msgid "OK" +msgstr "OK" + +#: wp-includes/script-loader.php:419 +msgid "Publish on:" +msgstr "Publié le :" + +# Ne pas mettre d'entité HTML ( ...) : chaîne utilisée par JavaScript. +#: wp-includes/script-loader.php:420 +msgid "Schedule for:" +msgstr "Planifier pour :" + +#: wp-includes/script-loader.php:421 +msgid "Published on:" +msgstr "Publié le :" + +#. translators: 1: month, 2: day, 3: year, 4: hour, 5: minute +#: wp-includes/script-loader.php:423 +msgid "%1$s %2$s, %3$s @ %4$s : %5$s" +msgstr "%2$s %1$s %3$s à %4$s h %5$s min" + +#: wp-includes/script-loader.php:424 +msgid "Show more comments" +msgstr "Afficher plus de commentaires" + +#: wp-includes/script-loader.php:425 +msgid "No more comments found." +msgstr "Il n’y a pas d’autres commentaires." + +#: wp-includes/script-loader.php:426 +msgid "Publish" +msgstr "Publier" + +#: wp-includes/script-loader.php:427 +msgid "Schedule" +msgstr "Planifier" + +#: wp-includes/script-loader.php:429 +msgid "Save as Pending" +msgstr "Mettre à relire" + +#: wp-includes/script-loader.php:430 +msgid "Save Draft" +msgstr "Enregistrer brouillon" + +#: wp-includes/script-loader.php:432 +msgid "Public" +msgstr "Public" + +#: wp-includes/script-loader.php:433 +msgid "Public, Sticky" +msgstr "Public, mis en avant" + +#: wp-includes/script-loader.php:434 +msgid "Password Protected" +msgstr "Protégé par un mot de passe" + +#: wp-includes/script-loader.php:435 +msgid "Privately Published" +msgstr "Publié en privé" + +#: wp-includes/script-loader.php:445 +msgid "Submitted on:" +msgstr "Envoyé le :" + +#: wp-includes/script-loader.php:459 wp-includes/script-loader.php:467 +msgid "Error while saving the changes." +msgstr "Erreur lors de la sauvegarde des modifications." + +#: wp-includes/script-loader.php:460 +msgid "Remove From Bulk Edit" +msgstr "Enlever des modifications groupées" + +#: wp-includes/script-loader.php:472 +msgid "Plugin Information:" +msgstr "Informations sur l’extension :" + +#: wp-includes/script-loader.php:473 +msgid "Are you sure you want to install this plugin?" +msgstr "Voulez-vous vraiment installer cette extension ?" + +#: wp-includes/script-loader.php:483 +msgid "Select Color" +msgstr "Sélectionner une couleur" + +#: wp-includes/script-loader.php:484 +msgid "Current Color" +msgstr "Couleur actuelle" + +#: wp-includes/script-loader.php:495 +msgid "Could not load the preview image. Please reload the page and try again." +msgstr "" +"Impossible de charger l’image de prévisualisation. Veuillez recharger " +"la page et réessayer." + +#: wp-includes/script-loader.php:500 +msgid "Use as featured image" +msgstr "Utiliser comme image à la Une" + +#: wp-includes/script-loader.php:501 +msgid "Saving..." +msgstr "Enregistrement..." + +#: wp-includes/script-loader.php:502 +msgid "Could not set that as the thumbnail image. Try a different attachment." +msgstr "" +"Impossible de s’en servir comme miniature. Essayez un autre fichier " +"attaché." + +#: wp-includes/script-loader.php:503 +msgid "Done" +msgstr "Terminé" + +#: wp-includes/script-loader.php:509 +msgctxt "search results" +msgid "No results found." +msgstr "Aucun résultat trouvé." + +# alert() +#: wp-includes/script-loader.php:510 +msgid "" +"You are about to permanently delete this menu. \n" +" 'Cancel' to stop, 'OK' to delete." +msgstr "" +"Vous êtes sur le point de supprimer définitivement ce menu.\n" +" « Annuler » pour abandonner, « OK » pour le supprimer." + +#: wp-includes/script-loader.php:630 +msgid "Saving Draft…" +msgstr "Enregistrement du brouillon…" + +#: wp-includes/taxonomy.php:68 +msgid "Navigation Menus" +msgstr "Menus de navigation" + +#: wp-includes/taxonomy.php:69 +msgid "Navigation Menu" +msgstr "Menu de navigation" + +#: wp-includes/taxonomy.php:81 +msgid "Link Categories" +msgstr "Catégories de liens" + +#: wp-includes/taxonomy.php:82 +msgid "Link Category" +msgstr "Catégorie de liens" + +#: wp-includes/taxonomy.php:83 +msgid "Search Link Categories" +msgstr "Chercher une catégorie de liens" + +#: wp-includes/taxonomy.php:85 +msgid "All Link Categories" +msgstr "Toutes les catégories de liens" + +#: wp-includes/taxonomy.php:86 +msgid "Edit Link Category" +msgstr "Modifier la catégorie de lien" + +#: wp-includes/taxonomy.php:87 +msgid "Update Link Category" +msgstr "Mettre à jour la catégorie de liens" + +#: wp-includes/taxonomy.php:88 +msgid "Add New Link Category" +msgstr "Ajouter une catégorie de liens" + +#: wp-includes/taxonomy.php:89 +msgid "New Link Category Name" +msgstr "Nom de la nouvelle catégorie de liens" + +#: wp-includes/taxonomy.php:111 wp-includes/taxonomy.php:112 +msgctxt "post format" +msgid "Format" +msgstr "Format" + +#: wp-includes/taxonomy.php:347 +msgid "Taxonomies cannot exceed 32 characters in length" +msgstr "Les taxinomies ne peuvent dépasser les 32 caractères." + +#: wp-includes/taxonomy.php:461 +msgctxt "taxonomy general name" +msgid "Tags" +msgstr "Mots-clés" + +#: wp-includes/taxonomy.php:461 +msgctxt "taxonomy general name" +msgid "Categories" +msgstr "Catégories" + +#: wp-includes/taxonomy.php:462 +msgctxt "taxonomy singular name" +msgid "Tag" +msgstr "Mot-clé" + +#: wp-includes/taxonomy.php:462 +msgctxt "taxonomy singular name" +msgid "Category" +msgstr "Catégorie" + +#: wp-includes/taxonomy.php:463 +msgid "Search Tags" +msgstr "Chercher dans les mots-clés" + +#: wp-includes/taxonomy.php:463 +msgid "Search Categories" +msgstr "Chercher une catégorie" + +#: wp-includes/taxonomy.php:464 +msgid "Popular Tags" +msgstr "Mots-clés populaires" + +#: wp-includes/taxonomy.php:465 +msgid "All Tags" +msgstr "Tous les mots-clés" + +#: wp-includes/taxonomy.php:465 +msgid "All Categories" +msgstr "Toutes" + +#: wp-includes/taxonomy.php:466 +msgid "Parent Category" +msgstr "Catégorie parente" + +#: wp-includes/taxonomy.php:467 +msgid "Parent Category:" +msgstr "Catégorie parente :" + +#: wp-includes/taxonomy.php:468 +msgid "Edit Tag" +msgstr "Modifier le mot-clé" + +#: wp-includes/taxonomy.php:468 +msgid "Edit Category" +msgstr "Modifier la catégorie" + +#: wp-includes/taxonomy.php:469 +msgid "View Tag" +msgstr "Voir le mot-clé" + +#: wp-includes/taxonomy.php:469 +msgid "View Category" +msgstr "Afficher la catégorie" + +#: wp-includes/taxonomy.php:470 +msgid "Update Tag" +msgstr "Mettre à jour le mot-clé" + +#: wp-includes/taxonomy.php:470 +msgid "Update Category" +msgstr "Mettre à jour la catégorie" + +#: wp-includes/taxonomy.php:471 +msgid "Add New Tag" +msgstr "Ajouter un nouveau mot-clé" + +#: wp-includes/taxonomy.php:471 +msgid "Add New Category" +msgstr "Ajouter une nouvelle catégorie" + +#: wp-includes/taxonomy.php:472 +msgid "New Tag Name" +msgstr "Nom du nouveau mot-clé" + +#: wp-includes/taxonomy.php:472 +msgid "New Category Name" +msgstr "Nom de la nouvelle catégorie" + +#: wp-includes/taxonomy.php:473 +msgid "Separate tags with commas" +msgstr "Séparez les mots-clés par des virgules" + +#: wp-includes/taxonomy.php:474 +msgid "Add or remove tags" +msgstr "Ajouter ou retirer des mots-clés" + +#: wp-includes/taxonomy.php:475 +msgid "Choose from the most used tags" +msgstr "Choisir parmi les mots-clés les plus utilisés" + +#: wp-includes/taxonomy.php:476 +msgid "No tags found." +msgstr "Aucun mot-clé trouvé." + +# contexte +#: wp-includes/taxonomy.php:936 wp-includes/taxonomy.php:3154 +msgid "Empty Term" +msgstr "Pas de terme" + +#: wp-includes/taxonomy.php:2123 wp-includes/taxonomy.php:2531 +msgid "A name is required for this term" +msgstr "Un nom est requis pour ce terme" + +#: wp-includes/taxonomy.php:2161 +msgid "A term with the name provided already exists with this parent." +msgstr "Un terme avec ce nom existe déjà pour ce parent." + +#: wp-includes/taxonomy.php:2165 wp-includes/taxonomy.php:2172 +#: wp-includes/taxonomy.php:2182 +msgid "Could not insert term into the database" +msgstr "Impossible d’insérer le terme dans la base de données" + +#: wp-includes/taxonomy.php:2176 +msgid "A term with the name provided already exists." +msgstr "Un terme existe déjà avec ce nom." + +#: wp-includes/taxonomy.php:2310 +msgid "Could not insert term relationship into the database" +msgstr "" +"Impossible d’insérer la relation du terme dans la base de données" + +#: wp-includes/taxonomy.php:2358 +msgid "Invalid Taxonomy" +msgstr "Taxinomie invalide" + +#: wp-includes/taxonomy.php:2564 +msgid "The slug “%s” is already in use by another term" +msgstr "L’identifiant « %s » est déjà utilisé par un autre terme" + +#: wp-includes/taxonomy.php:3315 +msgid "Invalid object ID" +msgstr "Identifiant d’objet non valide." + +#: wp-includes/theme-compat/comments-popup.php:10 +#: wp-includes/theme-compat/comments.php:10 +#: wp-includes/theme-compat/footer.php:10 +#: wp-includes/theme-compat/header.php:10 +#: wp-includes/theme-compat/sidebar.php:10 +msgid "Theme without %1$s" +msgstr "Thème sans %1$s." + +#: wp-includes/theme-compat/comments-popup.php:10 +#: wp-includes/theme-compat/comments.php:10 +#: wp-includes/theme-compat/footer.php:10 +#: wp-includes/theme-compat/header.php:10 +#: wp-includes/theme-compat/sidebar.php:10 +msgid "Please include a %1$s template in your theme." +msgstr "" +"Veuillez inclure un modèle de type « %1$s » à votre " +"thème." + +#: wp-includes/theme-compat/comments-popup.php:14 +msgid "%1$s - Comments on %2$s" +msgstr "%1$s - Commentaires sur %2$s" + +#: wp-includes/theme-compat/comments-popup.php:35 +msgid "" +"RSS feed for comments on " +"this post." +msgstr "" +"Flux RSS des commentaires " +"de cet article." + +#: wp-includes/theme-compat/comments-popup.php:38 +msgid "" +"The URL to TrackBack this " +"entry is: %s" +msgstr "" +"L’adresse web pour faire un rétrolien sur cet article est : " +"%s" + +#: wp-includes/theme-compat/comments-popup.php:56 +msgid "by %1$s — %2$s @ %4$s" +msgstr "par %1$s — %2$s à %4$s" + +#: wp-includes/theme-compat/comments-popup.php:62 +msgid "No comments yet." +msgstr "Pas encore de commentaire." + +#: wp-includes/theme-compat/comments-popup.php:66 +msgid "Leave a comment" +msgstr "Laisser un commentaire" + +#: wp-includes/theme-compat/comments-popup.php:67 +msgid "" +"Line and paragraph breaks automatic, e-mail address never displayed, " +"HTML allowed: " +"%s" +msgstr "" +"Les paragraphes et retours à la ligne sont automatiques. Les adresses de " +"messagerie ne sont pas affichées. HTML autorisé : %s" + +#: wp-includes/theme-compat/comments-popup.php:71 +msgid "" +"Logged in as %2$s. Log out »" +msgstr "" +"Connecté en tant que %2$s. Se déconnecter »" + +#: wp-includes/theme-compat/comments-popup.php:80 wp-login.php:682 +msgid "E-mail" +msgstr "E-mail" + +#: wp-includes/theme-compat/comments-popup.php:85 +msgid "URL" +msgstr "Adresse web" + +#: wp-includes/theme-compat/comments-popup.php:90 +msgid "Your Comment" +msgstr "Votre commentaire" + +#: wp-includes/theme-compat/comments-popup.php:98 +msgid "Say It!" +msgstr "Dites-le !" + +#: wp-includes/theme-compat/comments-popup.php:103 +msgid "Sorry, the comment form is closed at this time." +msgstr "Désolé, les commentaires sont fermés pour le moment." + +#: wp-includes/theme-compat/comments-popup.php:108 +msgid "Close this window." +msgstr "Fermer cette fenêtre." + +#: wp-includes/theme-compat/comments-popup.php:114 +msgid "Sorry, no posts matched your criteria." +msgstr "Désolé, aucun article ne correspond à vos critères." + +#: wp-includes/theme-compat/comments-popup.php:118 +msgid "" +"Powered by WordPress" +msgstr "" +"Propulsé par WordPress." + +#: wp-includes/theme-compat/comments.php:17 +msgid "This post is password protected. Enter the password to view comments." +msgstr "" +"Cet article est protégé par un mot de passe. Saisissez le mot de passe pour " +"voir les commentaires." + +#: wp-includes/theme-compat/comments.php:26 +msgid "One Response to %2$s" +msgid_plural "%1$s Responses to %2$s" +msgstr[0] "Une réponse à %2$s" +msgstr[1] "%1$s réponses à %2$s" + +#: wp-includes/theme-compat/comments.php:49 +msgid "Comments are closed." +msgstr "Les commentaires sont fermés." + +#: wp-includes/theme-compat/comments.php:72 +msgid "Logged in as %2$s." +msgstr "Connecté en tant que %2$s." + +#: wp-includes/theme-compat/comments.php:72 +msgid "Log out of this account" +msgstr "Se déconnecter" + +#: wp-includes/theme-compat/comments.php:72 +msgid "Log out »" +msgstr "Déconnexion »" + +#: wp-includes/theme-compat/comments.php:77 +#: wp-includes/theme-compat/comments.php:80 +msgid "(required)" +msgstr "(obligatoire)" + +#: wp-includes/theme-compat/comments.php:80 +msgid "Mail (will not be published)" +msgstr "Adresse de messagerie (ne sera pas publiée)" + +#: wp-includes/theme-compat/comments.php:87 +msgid "XHTML: You can use these tags: %s" +msgstr "" +"XHTML : Vous pouvez utiliser ces balises : " +"%s" + +#: wp-includes/theme-compat/comments.php:91 +msgid "Submit Comment" +msgstr "Soumettre le commentaire" + +#: wp-includes/theme-compat/footer.php:17 +msgid "%1$s is proudly powered by %2$s" +msgstr "%1$s est fièrement propulsé par %2$s" + +#: wp-includes/theme-compat/footer.php:19 +msgid "%1$s and %2$s." +msgstr "%1$s et %2$s." + +#: wp-includes/theme-compat/footer.php:19 +msgid "Entries (RSS)" +msgstr "Articles (RSS)" + +#: wp-includes/theme-compat/footer.php:19 +msgid "Comments (RSS)" +msgstr "Commentaires (RSS)" + +#: wp-includes/theme-compat/footer.php:20 +msgid "%d queries. %s seconds." +msgstr "%d requêtes. %s secondes." + +#: wp-includes/theme-compat/sidebar.php:32 +msgid "You are currently browsing the archives for the %s category." +msgstr "Vous parcourez actuellement les archives de la catégorie %s." + +#: wp-includes/theme-compat/sidebar.php:35 +msgid "" +"You are currently browsing the %2$s blog archives for " +"the day %3$s." +msgstr "" +"Vous parcourez actuellement les archives du site %2$s " +"pour la journée du %3$s." + +#: wp-includes/theme-compat/sidebar.php:35 +msgid "l, F jS, Y" +msgstr "l j F Y" + +#: wp-includes/theme-compat/sidebar.php:38 +msgid "" +"You are currently browsing the %2$s blog archives for " +"%3$s." +msgstr "" +"Vous parcourez actuellement les archives du site %2$s " +"pour %3$s." + +#: wp-includes/theme-compat/sidebar.php:38 +msgid "F, Y" +msgstr "F Y" + +#: wp-includes/theme-compat/sidebar.php:41 +msgid "" +"You are currently browsing the %2$s blog archives for " +"the year %3$s." +msgstr "" +"Vous parcourez actuellement les archives du site %2$s " +"pour l’année %3$s." + +#: wp-includes/theme-compat/sidebar.php:44 +msgid "" +"You have searched the %2$s blog archives for " +"‘%3$s’. If you are unable to find anything in " +"these search results, you can try one of these links." +msgstr "" +"Vous avez lancé une recherche dans les archives du site " +"%2$s avec la requête « %3$s ». Si " +"les résultats ne vous conviennent pas, vous pouvez essayer l’un de ces " +"liens." + +#: wp-includes/theme-compat/sidebar.php:47 +msgid "" +"You are currently browsing the %2$s blog archives." +msgstr "" +"Vous parcourez actuellement les archives du site %2$s." + +#: wp-includes/theme-compat/sidebar.php:73 +msgid "This page validates as XHTML 1.0 Transitional" +msgstr "Cette page est en XHTML 1.0 Transitional valide" + +#: wp-includes/theme-compat/sidebar.php:73 +msgid "Valid XHTML" +msgstr "" +"XHTML valide" + +#: wp-includes/theme-compat/sidebar.php:74 +msgid "XHTML Friends Network" +msgstr "XHTML Friends Network" + +#: wp-includes/theme-compat/sidebar.php:74 +msgid "XFN" +msgstr "XFN" + +#: wp-includes/update.php:477 +msgid "%d WordPress Update" +msgstr "%d mise à jour de WordPress" + +#: wp-includes/update.php:479 +msgid "%d Plugin Update" +msgid_plural "%d Plugin Updates" +msgstr[0] "%d mise à jour d’extension" +msgstr[1] "%d mises à jour d’extensions" + +#: wp-includes/update.php:481 +msgid "%d Theme Update" +msgid_plural "%d Theme Updates" +msgstr[0] "%d mise à jour de thème" +msgstr[1] "%d mises à jour de thèmes" + +#: wp-includes/update.php:483 +msgid "Translation Updates" +msgstr "Mises à jour des traductions" + +#: wp-includes/user.php:82 +msgid "ERROR: The username field is empty." +msgstr "" +"ERREUR : le champ de l’identifiant est vide." + +#: wp-includes/user.php:85 +msgid "ERROR: The password field is empty." +msgstr "ERREUR : le champ du mot de passe est vide." + +#: wp-includes/user.php:93 +msgid "" +"ERROR: Invalid username. Lost your password?" +msgstr "" +"ERREUR : l’identifiant n’est pas valide. " +"Avez-vous perdu votre mot de " +"passe ?" + +#: wp-includes/user.php:100 +msgid "" +"ERROR: The password you entered for the username " +"%1$s is incorrect. Lost your password?" +msgstr "" +"ERREUR : le mot de passe que vous avez saisi pour " +"l’identifiant %1$s n’est pas le bon. Avez-vous perdu votre mot de passe ?" + +#: wp-includes/user.php:144 +msgid "ERROR: Your account has been marked as a spammer." +msgstr "" +"ERREUR : votre compte a été marqué comme étant " +"indésirable." + +#: wp-includes/user.php:1330 +msgid "Cannot create a user with an empty login name." +msgstr "Impossible de créer un utilisateur avec un identifiant vide." + +#. translators: 1: first name, 2: last name +#: wp-includes/user.php:1367 +msgctxt "Display name based on first name and last name" +msgid "%1$s %2$s" +msgstr "%1$s %2$s" + +#: wp-includes/user.php:1473 +msgid "Invalid user ID." +msgstr "Indentifiant utilisateur non valide." + +#: wp-includes/user.php:1560 +msgid "AIM" +msgstr "AIM" + +#: wp-includes/user.php:1561 +msgid "Yahoo IM" +msgstr "Yahoo Messenger" + +#: wp-includes/user.php:1562 +msgid "Jabber / Google Talk" +msgstr "Jabber / Google Talk" + +#: wp-includes/user.php:1607 wp-includes/user.php:1610 +#: wp-includes/user.php:1614 wp-includes/user.php:1625 +#: wp-includes/user.php:1641 +msgid "Invalid key" +msgstr "Clé invalide" + +#: wp-includes/user.php:1674 +msgid "ERROR: Please enter a username." +msgstr "" +"ERREUR : veuillez renseigner l’identifiant." + +#: wp-includes/user.php:1676 +msgid "" +"ERROR: This username is invalid because it uses illegal " +"characters. Please enter a valid username." +msgstr "" +"ERREUR : cet identifiant n’est pas valide, car " +"il utiliser des caractères non autorisés. Merci d’utiliser un " +"identifiant valide." + +#: wp-includes/user.php:1679 +msgid "" +"ERROR: This username is already registered. Please choose " +"another one." +msgstr "" +"ERREUR : cet identifiant existe déjà. Merci d’en " +"choisir un autre." + +#: wp-includes/user.php:1684 +msgid "ERROR: Please type your e-mail address." +msgstr "" +"ERREUR : l’adresse de messagerie est obligatoire." + +#: wp-includes/user.php:1686 +msgid "ERROR: The email address isn’t correct." +msgstr "ERREUR : adresse de messagerie incorrecte." + +#: wp-includes/user.php:1689 +msgid "" +"ERROR: This email is already registered, please choose " +"another one." +msgstr "" +"ERREUR : cette adresse de messagerie est déjà " +"utilisée. Merci d’en choisir une autre." + +#: wp-includes/user.php:1702 +msgid "" +"ERROR: Couldn’t register you… please contact " +"the webmaster !" +msgstr "" +"ERREUR : inscription impossible… Veuillez " +"prendre contact avec le webmaster !" + +#: wp-includes/widgets.php:67 +msgid "There are no options for this widget." +msgstr "Il n’y a pas d’options pour ce widget." + +#: wp-includes/widgets.php:488 wp-includes/widgets.php:558 +msgid "Sidebar %d" +msgstr "Colonne latérale %d" + +#: wp-includes/widgets.php:490 +msgid "Sidebar" +msgstr "Colonne latérale" + +#: wp-includes/wp-db.php:836 +msgid "" +"

    Can’t select database

    \n" +"

    We were able to connect to the database server (which means your username " +"and password is okay) but not able to select the %1$s database." +"

    \n" +"
      \n" +"
    • Are you sure it exists?
    • \n" +"
    • Does the user %2$s have permission to use the %1$s database?
    • \n" +"
    • On some systems the name of your database is prefixed with your " +"username, so it would be like username_%1$s. Could that be the " +"problem?
    • \n" +"
    \n" +"

    If you don't know how to set up a database you should contact " +"your host. If all else fails you may find help at the WordPress Support Forums.

    " +msgstr "" +"

    Impossible de sélectionner la base de données

    \n" +"

    La connexion au serveur de base de données s’est bien faite (donc " +"votre identifiant et votre mot de passe sont les bons), mais la base de " +"données %1$s n’a pas pu être sélectionnée.

    \n" +"
      \n" +"
    • Êtes-vous certain(e) qu’elle existe ?
    • \n" +"
    • L’utilisateur %2$s a-t-il les droits pour utiliser la " +"base de données %1$s ?
    • \n" +"
    • Sur certains systèmes, le nom de votre base de données est préfixée de " +"votre identifiant, donc son nom complet peut être username_%1$s. Cela peut-il être la cause du problème&nbps;?
    • \n" +"
    \n" +"

    Si vous ne savez pas comment régler votre base de données, vous devriez " +"prendre contact avec votre hébergeur. Si toutes vos " +"tentatives échouent, peut-être trouverez-vous une réponse sur le forum d’entraide en " +"français.

    " + +#: wp-includes/wp-db.php:1031 +msgid "WordPress database error %1$s for query %2$s made by %3$s" +msgstr "" +"Erreur de la base de données WordPress %1$s pour la requête %2$s faite par " +"%3$s" + +#: wp-includes/wp-db.php:1033 +msgid "WordPress database error %1$s for query %2$s" +msgstr "Erreur de la base de données WordPress %1$s pour la requête %2$s" + +#: wp-includes/wp-db.php:1149 +msgid "" +"\n" +"

    Error establishing a database connection

    \n" +"

    This either means that the username and password information in your " +"wp-config.php file is incorrect or we can't contact the " +"database server at %s. This could mean your host's database " +"server is down.

    \n" +"
      \n" +"\t
    • Are you sure you have the correct username and password?
    • \n" +"\t
    • Are you sure that you have typed the correct hostname?
    • \n" +"\t
    • Are you sure that the database server is running?
    • \n" +"
    \n" +"

    If you're unsure what these terms mean you should probably contact your " +"host. If you still need help you can always visit the WordPress Support Forums.

    \n" +msgstr "" +"\n" +"

    Erreur lors de l’établissement de la connexion à la base de " +"données

    \n" +"

    Cela signifie soit que l’identifiant et/ou le mot de passe indiqué" +"(s) dans votre fichier wp-config.php sont incorrects, ou que le " +"serveur de base de données à l’adresse %s est " +"inaccessible - cela peut indiquer que le serveur de base de données de votre " +"hébergeur est défaillant.

    \n" +"
      \n" +"\t
    • Êtes-vous certain(e) d’avoir correctement indiqué votre " +"identifiant et votre mot de passe ?
    • \n" +"\t
    • Êtes-vous certain(e) d’avoir entré le bon serveur de base de " +"données ?
    • \n" +"\t
    • Êtes-vous certain(e) que le serveur de base de données fonctionne " +"correctement ?
    • \n" +"
    \n" +"

    Si vous n’êtes pas sûr(e) de bien comprendre les mots de cette " +"liste, vous devriez sans doute prendre contact avec votre hébergeur. Si " +"malgré cela cette erreur s’affiche toujours, indiquez votre problème " +"au forum d’entraide en " +"français.

    \n" + +#: wp-includes/wp-db.php:1667 +msgid "ERROR: WordPress %1$s requires MySQL %2$s or higher" +msgstr "" +"ERREUR : WordPress %1$s requiert MySQL %2$s ou une " +"version supérieure." + +#: wp-links-opml.php:29 +msgid "Links for %s" +msgstr "Liens pour %s" + +#: wp-load.php:56 +msgid "" +"There doesn't seem to be a wp-config.php file. I need this " +"before we can get started." +msgstr "" +"Il ne semble pas y avoir de fichier wp-config.php. J’en " +"ai besoin pour lancer le processus." + +#: wp-load.php:57 +msgid "" +"Need more help? We got it." +msgstr "" +"Besoin d’aide ? En voici." + +#: wp-load.php:58 +msgid "" +"You can create a wp-config.php file through a web interface, " +"but this doesn't work for all server setups. The safest way is to manually " +"create the file." +msgstr "" +"Vous pouvez créer un fichier wp-config.php par le biais de " +"cette interface, mais cela ne marche pour toutes les configurations de " +"serveur. La manière la plus sûre reste de créer le fichier à la main." + +#: wp-load.php:59 +msgid "Create a Configuration File" +msgstr "Créer un fichier de configuration" + +#: wp-login.php:96 +msgid "Powered by WordPress" +msgstr "Propulsé par WordPress" + +#: wp-login.php:212 +msgid "Are you lost?" +msgstr "Êtes-vous perdu(e) ?" + +#: wp-login.php:212 +msgid "← Back to %s" +msgstr "← Retour sur %s" + +#: wp-login.php:270 +msgid "ERROR: Enter a username or e-mail address." +msgstr "" +"ERREUR : veuillez saisir une adresse de messagerie ou " +"un identifiant." + +#: wp-login.php:274 +msgid "" +"ERROR: There is no user registered with that email address." +msgstr "" +"ERREUR : il n’y aucun utilisateur enregistré " +"avec cette adresse de messagerie." + +#: wp-login.php:291 +msgid "ERROR: Invalid username or e-mail." +msgstr "" +"ERREUR : l’identifiant ou l’adresse de " +"messagerie n’est pas valide." + +#: wp-login.php:328 +msgid "Password reset is not allowed for this user" +msgstr "" +"La réinitialisation du mot de passe n’est pas autorisée pour cet " +"utilisateur" + +# No HTML entities allowed +#: wp-login.php:353 +msgid "Someone requested that the password be reset for the following account:" +msgstr "" +"Quelqu'un a demandé le renouvellement de son mot de passe pour le compte " +"suivant :" + +# No HTML entities allowed. +#: wp-login.php:356 +msgid "If this was a mistake, just ignore this email and nothing will happen." +msgstr "" +"S'il s'agit d'une erreur, ignorez ce message et la demande ne sera pas prise " +"en compte." + +# No HTML entities allowed. +#: wp-login.php:357 +msgid "To reset your password, visit the following address:" +msgstr "Pour renouveler votre mot de passe, cliquez sur le lien suivant :" + +#: wp-login.php:367 +msgid "[%s] Password Reset" +msgstr "[%s] Renouvellement du mot de passe" + +#: wp-login.php:388 +msgid "The e-mail could not be sent." +msgstr "Le message n’a pas pu être envoyé." + +#: wp-login.php:388 +msgid "Possible reason: your host may have disabled the mail() function." +msgstr "" +"Raison possible : votre hébergeur peut avoir désactivé la fonction mail" +"()." + +#: wp-login.php:493 +msgid "Sorry, that key does not appear to be valid." +msgstr "Désolé, cette clé ne semble pas être valide." + +#: wp-login.php:495 +msgid "Sorry, that key has expired. Please try again." +msgstr "Désolé, cette clé a expiré. Veuillez réessayer." + +#: wp-login.php:515 +msgid "Lost Password" +msgstr "Mot de passe oublié" + +#: wp-login.php:515 +msgid "" +"Please enter your username or email address. You will receive a link to " +"create a new password via email." +msgstr "" +"Veuillez saisir votre identifiant ou votre adresse de messagerie. Un lien " +"permettant de créer un nouveau mot de passe vous sera envoyé par e-mail." + +#: wp-login.php:523 +msgid "Username or E-mail:" +msgstr "Identifiant ou adresse de messagerie :" + +#: wp-login.php:534 +msgid "Get New Password" +msgstr "Générer un mot de passe" + +#: wp-login.php:573 +msgid "The passwords do not match." +msgstr "Vos mots de passe ne correspondent pas." + +#: wp-login.php:587 +msgid "Password Reset" +msgstr "Renouvellement du mot de passe" + +#: wp-login.php:587 +msgid "Your password has been reset." +msgstr "Votre mot de passe a été réinitialisé." + +#: wp-login.php:595 wp-login.php:614 +msgid "Reset Password" +msgstr "Réinitialiser le mot de passe" + +#: wp-login.php:595 +msgid "Enter your new password below." +msgstr "" +"Veuillez saisir une deuxième fois votre nouveau mot de passe ci-dessous." + +#: wp-login.php:602 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: wp-login.php:606 +msgid "Confirm new password" +msgstr "Confirmer le nouveau mot de passe" + +#: wp-login.php:611 +msgid "" +"Hint: The password should be at least seven characters long. To make it " +"stronger, use upper and lower case letters, numbers and symbols like ! \" ? " +"$ % ^ & )." +msgstr "" +"Conseil : votre mot de passe devrait faire au moins 7 caractères de " +"long. Pour le rendre plus sûr, utilisez un mélange de majuscules, de " +"minuscules, de chiffres et de symboles comme ! \" ? $ % ^ &" +" )." + +#: wp-login.php:673 +msgid "Registration Form" +msgstr "Formulaire d’inscription" + +#: wp-login.php:673 +msgid "Register For This Site" +msgstr "S’inscrire sur ce site" + +#: wp-login.php:693 +msgid "A password will be e-mailed to you." +msgstr "Un mot de passe vous sera envoyé sur votre adresse de messagerie." + +#: wp-login.php:701 wp-login.php:876 +msgid "Password Lost and Found" +msgstr "Récupération de mot de passe" + +#: wp-login.php:701 wp-login.php:876 +msgid "Lost your password?" +msgstr "Mot de passe oublié ?" + +#: wp-login.php:745 +msgid "" +"ERROR: Cookies are blocked or not supported by your " +"browser. You must enable " +"cookies to use WordPress." +msgstr "" +"ERREUR : les cookies sont bloqués ou ne sont pas " +"reconnus pas votre navigateur. Vous devez activer les cookies pour utiliser WordPress." + +#: wp-login.php:763 +msgid "You have logged in successfully." +msgstr "Vous vous êtes bien connecté." + +#: wp-login.php:797 +msgid "" +"Session expired. Please log in again. You will not move away from this page." +msgstr "" +"La session a expiré. Veuillez vous reconnecter. Vous reviendrez sur cette " +"page." + +#: wp-login.php:801 +msgid "You are now logged out." +msgstr "Vous êtes désormais déconnecté(e)." + +#: wp-login.php:803 +msgid "User registration is currently not allowed." +msgstr "" +"Les nouvelles inscriptions ne sont pas autorisées pour l’instant." + +#: wp-login.php:805 +msgid "Check your e-mail for the confirmation link." +msgstr "Vérifiez votre messagerie pour y trouver le lien de confirmation." + +#: wp-login.php:807 +msgid "Check your e-mail for your new password." +msgstr "Vérifiez votre messagerie pour y trouver votre nouveau mot de passe." + +#: wp-login.php:809 +msgid "Registration complete. Please check your e-mail." +msgstr "Enregistrement terminé. Veuillez vérifier vos nouveaux e-mails." + +#: wp-login.php:811 +msgid "" +"You have successfully updated WordPress! Please log back in " +"to experience the awesomeness." +msgstr "" +"WordPress a bien été mis à jour ! Veuillez vos re-" +"connecter pour découvrir les formidables nouveautés." + +#: wp-mail.php:15 +msgid "This action has been disabled by the administrator." +msgstr "Cette action a été désactivée par l’administrateur." + +#: wp-mail.php:30 +msgid "Slow down cowboy, no need to check for new mails so often!" +msgstr "" +"Lève le pied, champion ! Inutile de vérifier tes e-mails aussi " +"souvent !" + +#: wp-mail.php:50 +msgid "There doesn’t seem to be any new mail." +msgstr "Il ne semble pas y avoir de nouvel e-mail." + +#: wp-mail.php:116 +msgid "Author is %s" +msgstr "L’auteur est %s" + +#: wp-mail.php:218 +msgid "Author: %s" +msgstr "Auteur : %s" + +#: wp-mail.php:219 +msgid "Posted title: %s" +msgstr "Titre publié : %s" + +#: wp-mail.php:222 +msgid "Oops: %s" +msgstr "Oups : %s" + +#: wp-mail.php:226 +msgid "Mission complete. Message %s deleted." +msgstr "Mission terminée. Message %s supprimé. " + +#: wp-signup.php:94 +msgid "Site Name:" +msgstr "Nom du site :" + +#: wp-signup.php:96 +msgid "Site Domain:" +msgstr "Domaine du site :" + +#: wp-signup.php:109 +msgid "sitename" +msgstr "nomdusite" + +#: wp-signup.php:111 +msgid "domain" +msgstr "domaine" + +#: wp-signup.php:112 +msgid "Your address will be %s." +msgstr "Votre adresse sera %s." + +#: wp-signup.php:112 +msgid "" +"Must be at least 4 characters, letters and numbers only. It cannot be " +"changed, so choose carefully!" +msgstr "" +"Doit contenir au moins 4 caractères, avec uniquement des lettres et des " +"chiffres. Vous ne pourrez pas en changer, donc choisissez bien !" + +#: wp-signup.php:117 +msgid "Site Title:" +msgstr "Titre du site :" + +#: wp-signup.php:126 +msgid "Privacy:" +msgstr "Vie privée :" + +#: wp-signup.php:127 +msgid "Allow search engines to index this site." +msgstr "Demander aux moteurs de recherche d’indexer ce site." + +#: wp-signup.php:131 +msgid "Yes" +msgstr "Oui" + +#: wp-signup.php:135 +msgid "No" +msgstr "Non" + +#: wp-signup.php:184 +msgid "(Must be at least 4 characters, letters and numbers only.)" +msgstr "" +"(Doit contenir au moins 4 caractères, uniquement des lettres ou des " +"chiffres.)" + +#: wp-signup.php:187 +msgid "Email Address:" +msgstr "Adresse e-mail :" + +#: wp-signup.php:191 +msgid "" +"We send your registration email to this address. (Double-check your email " +"address before continuing.)" +msgstr "" +"Nous enverrons votre confirmation d’inscription à cette adresse. " +"Vérifiez donc bien qu’elle est correcte avant de continuer." + +#: wp-signup.php:261 +msgid "Get another %s site in seconds" +msgstr "Ouvrir un autre site %s en quelques secondes" + +#: wp-signup.php:264 +msgid "There was a problem, please correct the form below and try again." +msgstr "" +"Il y a eu un problème, veuillez remplir le formulaire ci-dessous et " +"réessayer." + +#: wp-signup.php:267 +msgid "" +"Welcome back, %s. By filling out the form below, you can add another " +"site to your account. There is no limit to the number of sites you " +"can have, so create to your heart’s content, but write responsibly!" +msgstr "" +"Heureux de voir revoir, %s ! En remplissant le formulaire ci-dessous, " +"vous pouvez ajouter un autre site à votre compte. Il " +"n’y a pas de limite au nombre de sites dont vous pouvez disposer, donc " +"créez-en autant que vous le souhaitez, mais écrivez pondérément." + +#: wp-signup.php:273 +msgid "Sites you are already a member of:" +msgstr "Les sites que vous possédez déjà :" + +#: wp-signup.php:282 +msgid "" +"If you’re not going to use a great site domain, leave it for a new " +"user. Now have at it!" +msgstr "" +"Si vous ne comptez pas utiliser ce superbe nom de domaine, laissez-le à un " +"autre utilisateur. Et maintenant, lancez-vous !" + +#: wp-signup.php:297 +msgid "Create Site" +msgstr "Créer un site" + +#: wp-signup.php:374 +msgid "The site %s is yours." +msgstr "Le site %s est à vous." + +#: wp-signup.php:376 +msgid "" +"http://%2$s is your new site. Log in as “%4$s” using your existing password." +msgstr "" +"http://%2$s est votre nouveau site. Connectez-vous avec l’identifiant « %4$s " +"», à l’aide de votre mot de passe actuel." + +#: wp-signup.php:432 +msgid "Get your own %s account in seconds" +msgstr "Obtenez votre propre compte %s en quelques secondes" + +#: wp-signup.php:448 +msgid "Gimme a site!" +msgstr "Donnez-moi un site !" + +#: wp-signup.php:451 +msgid "Just a username, please." +msgstr "Juste l’identifiant, s’il vous plaît." + +#: wp-signup.php:455 +msgid "Next" +msgstr "Suivant" + +#: wp-signup.php:501 +msgid "%s is your new username" +msgstr "Votre nouvel identifiant est %s" + +#: wp-signup.php:502 +msgid "" +"But, before you can start using your new username, you must activate " +"it." +msgstr "" +"Mais, avant d’utiliser votre nouvel identifiant, vous devez " +"l’activer." + +#: wp-signup.php:503 wp-signup.php:633 +msgid "Check your inbox at %s and click the link given." +msgstr "" +"Consultez la boite de réception de l’adresse %s, et " +"cliquez sur le lien qui vous a été envoyé." + +#: wp-signup.php:504 +msgid "" +"If you do not activate your username within two days, you will have to sign " +"up again." +msgstr "" +"Si vous n’activez pas votre compte sous deux jours, vous devrez vous " +"réinscrire." + +#: wp-signup.php:570 +msgid "Signup" +msgstr "Inscription" + +#: wp-signup.php:630 +msgid "Congratulations! Your new site, %s, is almost ready." +msgstr "Félicitations! Votre nouveau site, %s, est presque prêt." + +#: wp-signup.php:632 +msgid "" +"But, before you can start using your site, you must activate it." +msgstr "" +"Mais, avant d’utiliser votre nouveau site, vous devez l’" +"activer." + +#: wp-signup.php:634 +msgid "" +"If you do not activate your site within two days, you will have to sign up " +"again." +msgstr "" +"Si vous n’activez pas votre site dans les deux jours, vous devrez à " +"nouveau l’enregistrer." + +#: wp-signup.php:635 +msgid "Still waiting for your email?" +msgstr "Toujours dans l’attente de votre e-mail ?" + +#: wp-signup.php:637 +msgid "" +"If you haven’t received your email yet, there are a number of things " +"you can do:" +msgstr "" +"Si vous n’avez encore pas reçu votre e-mail, il existe un certain " +"nombre de choses que vous pouvez faire :" + +#: wp-signup.php:639 +msgid "" +"Wait a little longer. Sometimes delivery of email can be delayed by " +"processes outside of our control." +msgstr "" +"Veuillez patienter encore quelques instants. Parfois, la livraison des " +"messages peut être retardée par des processus en dehors de notre contrôle." + +#: wp-signup.php:640 +msgid "" +"Check the junk or spam folder of your email client. Sometime emails wind up " +"there by mistake." +msgstr "" +"Vérifiez le courrier indésirable (ou dossier spam) de votre client de " +"messagerie. Parfois, certains messages arrivent là par erreur." + +#: wp-signup.php:641 +msgid "" +"Have you entered your email correctly? You have entered %s, if it’s " +"incorrect, you will not receive your email." +msgstr "" +"Avez-vous correctement saisi votre adresse de messagerie ? Vous aviez " +"saisi %s, mais si ce n’est pas correct, vous ne recevrez pas de " +"message." + +#: wp-signup.php:662 +msgctxt "Multisite active signup type" +msgid "all" +msgstr "tous" + +#: wp-signup.php:663 +msgctxt "Multisite active signup type" +msgid "none" +msgstr "aucune" + +#: wp-signup.php:664 +msgctxt "Multisite active signup type" +msgid "blog" +msgstr "site" + +#: wp-signup.php:665 +msgctxt "Multisite active signup type" +msgid "user" +msgstr "utilisateur" + +#: wp-signup.php:668 +msgid "" +"Greetings Site Administrator! You are currently allowing “%s” " +"registrations. To change or disable registration go to your Options page." +msgstr "" +"Salutations, cher administrateur du site ! Vous acceptez actuellement " +"les inscriptions de type « %s ». Pour modifier ou " +"désactiver les inscriptions, allez sur votre page d’" +"options." + +#: wp-signup.php:674 +msgid "Registration has been disabled." +msgstr "Les inscriptions ne sont pas autorisées pour le moment." + +#: wp-signup.php:677 +msgid "" +"You must first log in, and then you can create a new site." +msgstr "" +"Vous devez d’abord vous connecter avant de pouvoir " +"créer un nouveau site." + +#: wp-signup.php:685 +msgid "User registration has been disabled." +msgstr "Les inscriptions d’utilisateurs sont désactivées." + +#: wp-signup.php:691 +msgid "Site registration has been disabled." +msgstr "Les inscriptions de sites sont désactivées." + +#: wp-signup.php:710 +msgid "Sorry, new registrations are not allowed at this time." +msgstr "" +"Désolé, il n’est pas possible de s’enregistrer à l’heure " +"actuelle." + +#: wp-signup.php:712 +msgid "You are logged in already. No need to register again!" +msgstr "Vous êtes déjà connecté. Pas besoin de vous réinscrire !" + +#: wp-signup.php:718 +msgid "" +"The site you were looking for, %s, does not exist, but you " +"can create it now!" +msgstr "" +"Le site que vous cherchez (%s) n’existe pas, mais " +"vous pouvez le créer dès à présent !" + +#: wp-signup.php:720 +msgid "The site you were looking for, %s, does not exist." +msgstr "Le site que vous cherchez (%s) n’existe pas." + +#~ msgid "Visit Network" +#~ msgstr "Afficher le réseau" + +#~ msgid "Malformed URL: %s" +#~ msgstr "Adresse web malformée : %s" + +#~ msgid "Edit comment" +#~ msgstr "Modifier le commentaire" + +#~ msgid "Edit Link" +#~ msgstr "Modifier le lien" + +#~ msgid "Previously restored by %1$s %2$s, %3$s ago (%4$s)" +#~ msgstr "Auparavant rétabli par %1$s %2$s, il y a %3$s (%4$s)" + +#~ msgid "Add" +#~ msgstr "Ajouter" + +#~ msgid "Separate multiple categories with commas." +#~ msgstr "Séparez les catégories multiples par des virgules." + +#~ msgid "Site Suspended." +#~ msgstr "Site suspendu." + +#~ msgid "" +#~ "Please enter an API key. (Get your " +#~ "key.)" +#~ msgstr "" +#~ "Veuillez saisir une clé d’API. (Obtenir votre clé)" + +#~ msgid "This key is valid." +#~ msgstr "Cette clé est valide." + +#~ msgid "Akismet Configuration" +#~ msgstr "Configuration Akismet" + +#~ msgid "" +#~ "For many people, Akismet 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 Akismet.com." +#~ msgstr "" +#~ "Déjà utilisé par de nombreux sites, Akismet va vous " +#~ "permettre de réduire voire d’éliminer complètement les commentaires " +#~ "indésirables (spams) et les faux rétroliens qui affectent votre site. Si " +#~ "l’un d’eux passait au travers du filet, vous n’aurez " +#~ "qu’à simplement le marquer comme « indésirable " +#~ "» sur l’écran de modération, et Akismet apprendra de ses " +#~ "erreurs. Si vous n’avez pas encore de clé d’API, vous pouvez " +#~ "en obtenir une en allant sur Akismet.com." + +#~ msgid "What is this?" +#~ msgstr "" +#~ "De quoi s’agit-" +#~ "il ?" + +#~ msgid "Why might my key be invalid?" +#~ msgstr "Pourquoi ma clé ne serait-elle pas valide ?" + +#~ msgid "" +#~ "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." +#~ msgstr "" +#~ "Cela peut avoir deux causes : soit vous avez mal recopié la clé, " +#~ "soit l’extension n’a pas été capable de contacter les " +#~ "serveurs d’Akismet. Cette dernière erreur est souvent causée par un " +#~ "problème du côté du pare-feu (firewall) de l’hébergeur." + +#~ msgid "Update options »" +#~ msgstr "Mettre à jour les options »" + +#~ msgid "Check network status »" +#~ msgstr "Vérifier l’état du réseau »" + +#~ msgid "" +#~ "Click here to confirm that Akismet.com is up." +#~ msgstr "" +#~ "Cliquez ici pour confirmer que Akismet.com fonctionne." + +#~ msgid "— %s" +#~ msgstr "— %s" + +#~ msgid "Home URL" +#~ msgstr "Adresse web de l’accueil" + +#~ msgid "username and email used" +#~ msgstr "identifiant et e-mail utilisé" + +#~ msgid "(more...)" +#~ msgstr "(Lire la suite…)" + +#~ msgctxt "post revision" +#~ msgid "%1$s by %2$s" +#~ msgstr "%1$s par %2$s" + +#~ msgid "Restore" +#~ msgstr "Restaurer" + +#~ msgid "Compare Revisions" +#~ msgstr "Comparer les versions" + +#~ msgctxt "revisions column name" +#~ msgid "Old" +#~ msgstr "Ancien" + +#~ msgctxt "revisions column name" +#~ msgid "New" +#~ msgstr "Nouveau" + +#~ msgctxt "revisions column name" +#~ msgid "Date Created" +#~ msgstr "Date de création" + +#~ msgid "Actions" +#~ msgstr "Actions" diff --git a/sources/wp-content/languages/themes/twentythirteen-fr_FR.mo b/sources/wp-content/languages/themes/twentythirteen-fr_FR.mo new file mode 100644 index 0000000000000000000000000000000000000000..9c5fb1c5679843d5b65458891989d9b8a7f5d164 GIT binary patch literal 7430 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\n" +"Language-Team: WordPress-Francophone \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n>1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 1.5.4\n" + +#: 404.php:16 content-none.php:12 +msgid "Nothing Found" +msgstr "Rien n’a été trouvé" + +#: 404.php:21 +msgid "This is somewhat embarrassing, isn’t it?" +msgstr "C’est plutôt gênant, vous ne trouvez pas ?" + +#: 404.php:22 +msgid "It looks like nothing was found at this location. Maybe try a search?" +msgstr "" +"Apparemment, rien n’a été trouvé à cette adresse. Essayez avec " +"recherche ?" + +#: archive.php:29 +msgid "Daily Archives: %s" +msgstr "Archives quotidiennes :" + +#: archive.php:31 +msgid "Monthly Archives: %s" +msgstr "Archives mensuelles : %s" + +#: archive.php:31 +msgctxt "monthly archives date format" +msgid "F Y" +msgstr "F Y" + +#: archive.php:33 +msgid "Yearly Archives: %s" +msgstr "Archives annuelles : %s" + +#: archive.php:33 +msgctxt "yearly archives date format" +msgid "Y" +msgstr "Y" + +#: archive.php:35 +msgid "Archives" +msgstr "Archives" + +#: author-bio.php:16 +msgid "About %s" +msgstr "A propos %s" + +#: author-bio.php:20 +msgid "View all posts by %s " +msgstr "" +"Afficher tous les articles de %s " + +#: author.php:30 +msgid "All posts by %s" +msgstr "Tous les articles par %s" + +#: category.php:19 +msgid "Category Archives: %s" +msgstr "Archives pour la catégorie %s" + +#: comments.php:25 +msgctxt "comments title" +msgid "One thought on “%2$s”" +msgid_plural "%1$s thoughts on “%2$s”" +msgstr[0] "Une réflexion au sujet de « %2$s »" +msgstr[1] "%1$s réflexions au sujet de « %2$s »" + +#: comments.php:45 +msgid "Comment navigation" +msgstr "Navigation des commentaires" + +#: comments.php:46 +msgid "← Older Comments" +msgstr "← Commentaire plus ancien" + +#: comments.php:47 +msgid "Newer Comments →" +msgstr "Commentaires plus récents →" + +#: comments.php:52 +msgid "Comments are closed." +msgstr "Les commentaires sont fermés." + +#: content-aside.php:13 content-audio.php:24 content-gallery.php:24 +#: content-image.php:23 content-link.php:24 content-quote.php:13 +#: content-status.php:13 content-video.php:23 content.php:39 +msgid "Continue reading " +msgstr "Lire la suite " + +#: content-aside.php:14 content-audio.php:25 content-chat.php:24 +#: content-gallery.php:25 content-image.php:24 content-link.php:25 +#: content-quote.php:14 content-status.php:14 content-video.php:24 +#: content.php:40 image.php:70 page.php:35 +msgid "Pages:" +msgstr "Pages :" + +#: content-aside.php:20 content-aside.php:28 content-audio.php:31 +#: content-chat.php:29 content-gallery.php:39 content-image.php:35 +#: content-link.php:19 content-quote.php:25 content-status.php:19 +#: content-video.php:35 content.php:29 image.php:44 page.php:39 +msgid "Edit" +msgstr "Modifier" + +#: content-gallery.php:36 content-image.php:32 content-quote.php:22 +#: content-video.php:32 content.php:47 +msgid "Leave a comment" +msgstr "Laisser un commentaire" + +#: content-gallery.php:36 content-image.php:32 content-quote.php:22 +#: content-video.php:32 content.php:47 +msgid "One comment so far" +msgstr "Un commentaire pour le moment" + +#: content-gallery.php:36 content-image.php:32 content-quote.php:22 +#: content-video.php:32 content.php:47 +msgid "View all % comments" +msgstr "Afficher les % commentaires" + +#: content-none.php:18 +msgid "" +"Ready to publish your first post? Get started here." +msgstr "" +"Prêt à publier votre premier article ? Lancez-vous !" + +#: content-none.php:22 +msgid "" +"Sorry, but nothing matched your search terms. Please try again with " +"different keywords." +msgstr "" +"Désolé, mais rien ne correspond à votre critère de recherche. Veuillez " +"réessayer avec d’autres mots-clés." + +#: content-none.php:27 +msgid "" +"It seems we can’t find what you’re looking for. Perhaps " +"searching can help." +msgstr "" +"Il semblerait que nous ne soyons pas en mesure de trouver votre contenu. " +"Essayez en lançant une recherche." + +#. #-#-#-#-# twentythirteen.pot (Twenty Thirteen 1.0) #-#-#-#-# +#. Author URI of the plugin/theme +#: footer.php:20 +msgid "http://wordpress.org/" +msgstr "http://wordpress.org/" + +#: footer.php:20 +msgid "Semantic Personal Publishing Platform" +msgstr "Plate-forme de publication personnelle à la pointe de la sémantique" + +#: footer.php:20 +msgid "Proudly powered by %s" +msgstr "Fièrement propulsé par %s" + +#: functions.php:93 +msgid "Navigation Menu" +msgstr "Menu de navigation" + +#. Translators: If there are characters in your language that are not +#. * supported by Source Sans Pro, translate this to 'off'. Do not translate +#. * into your own language. +#: functions.php:124 +msgctxt "Source Sans Pro font: on or off" +msgid "on" +msgstr "on" + +#. Translators: If there are characters in your language that are not +#. * supported by Bitter, translate this to 'off'. Do not translate into your +#. * own language. +#: functions.php:130 +msgctxt "Bitter font: on or off" +msgid "on" +msgstr "on" + +#: functions.php:212 +msgid "Page %s" +msgstr "Page %s" + +#: functions.php:227 +msgid "Main Widget Area" +msgstr "Zone principale de widgets" + +#: functions.php:229 +msgid "Appears in the footer section of the site." +msgstr "Apparaît dans le pied de page du site." + +#: functions.php:237 +msgid "Secondary Widget Area" +msgstr "Zone secondaire de widgets" + +#: functions.php:239 +msgid "Appears on posts and pages in the sidebar." +msgstr "Apparaît dans la barre latérale des articles et pages." + +#: functions.php:264 +msgid "Posts navigation" +msgstr "Navigation des articles" + +#: functions.php:268 +msgid " Older posts" +msgstr " Articles plus anciens" + +#: functions.php:272 +msgid "Newer posts " +msgstr "Articles plus récents " + +#: functions.php:300 +msgid "Post navigation" +msgstr "Navigation des articles" + +#: functions.php:303 +msgctxt "Previous post link" +msgid " %title" +msgstr " %title" + +#: functions.php:304 +msgctxt "Next post link" +msgid "%title " +msgstr "%title " + +#: functions.php:324 +msgid "Sticky" +msgstr "Mis en avant" + +#. Translators: used between list items, there is a space after the comma. +#: functions.php:330 functions.php:336 +msgid ", " +msgstr ", " + +#: functions.php:345 +msgid "View all posts by %s" +msgstr "Afficher tous les articles par %s" + +#: functions.php:365 +msgctxt "1: post format name. 2: date" +msgid "%1$s on %2$s" +msgstr "%1$s le %2$s" + +#: functions.php:371 +msgid "Permalink to %s" +msgstr "Permalien vers %s" + +#: header.php:43 +msgid "Menu" +msgstr "Menu" + +#: header.php:44 +msgid "Skip to content" +msgstr "Aller au contenu principal" + +#: image.php:22 +msgid "" +"Published on in %5$s" +msgstr "" +"Publié le dans %5$s" + +#: image.php:38 +msgid "Link to full-size image" +msgstr "Lien vers l’image originale" + +#: image.php:39 +msgid "Full resolution" +msgstr "Pleine résolution" + +#: image.php:51 +msgid " Previous" +msgstr " Précédent" + +#: image.php:52 +msgid "Next " +msgstr "Suivant " + +#: inc/back-compat.php:38 inc/back-compat.php:50 inc/back-compat.php:65 +msgid "" +"Twenty Thirteen requires at least WordPress version 3.6. You are running " +"version %s. Please upgrade and try again." +msgstr "" +"Twenty Thirteen nécessite au moins WordPress 3.6. Vous utilisez la version " +"%s. Veuillez faire une mise à jour et réessayer." + +#: inc/custom-header.php:48 +msgctxt "header image description" +msgid "Circle" +msgstr "Cercle" + +#: inc/custom-header.php:53 +msgctxt "header image description" +msgid "Diamond" +msgstr "Losange" + +#: inc/custom-header.php:58 +msgctxt "header image description" +msgid "Star" +msgstr "Étoile" + +#: search.php:18 +msgid "Search Results for: %s" +msgstr "Résultats de recherche pour %s" + +#: tag.php:21 +msgid "Tag Archives: %s" +msgstr "Archives du mot-clé %s" + +#: taxonomy-post_format.php:23 +msgid "%s Archives" +msgstr "Archives des %s" + +#. Theme Name of the plugin/theme +msgid "Twenty Thirteen" +msgstr "Twenty Thirteen" + +#. Theme URI of the plugin/theme +msgid "http://wordpress.org/themes/twentythirteen" +msgstr "http://wordpress.org/themes/twentythirteen" + +#. Description of the plugin/theme +msgid "" +"The 2013 theme for WordPress takes us back to the blog, featuring a full " +"range of post formats, each displayed beautifully in their own unique way. " +"Design details abound, starting with a vibrant color scheme and matching " +"header images, beautiful typography and icons, and a flexible layout that " +"looks great on any device, big or small." +msgstr "" +"Le thème de WordPress pour 2013 nous ramène au blog, avec un grand nombre de " +"formats d'article, chacun s'affichant à sa propre manière, en toute beauté. " +"Vous y trouverez de nombreux détails de mise en page, à commencer par le jeu " +"de couleurs vives et les images d'en-tête assorties, une superbe typographie " +"et de belles icônes, et une mise en page flexible qui fonctionne sur toutes " +"les tailles d'écrans, grands ou petits." + +#. Author of the plugin/theme +msgid "the WordPress team" +msgstr "L’équipe WordPress" + +#~ msgid "Not found" +#~ msgstr "Introuvable" + +#~ msgid "Go back." +#~ msgstr "Revenir en arrière." + +#~ msgid "Author Archives: %s" +#~ msgstr "Archives de l’auteur : %s" + +#~ msgid "1 Reply" +#~ msgstr "1 réponse" + +#~ msgid "% Replies" +#~ msgstr "% réponses" + +#~ msgid "Link" +#~ msgstr "Lien" + +#~ msgid "" +#~ "Apologies, but no results were found. Perhaps searching will help find a " +#~ "related post." +#~ msgstr "" +#~ "Toutes nos excuses, mais votre requête n’a donné aucun résultat. " +#~ "Peut-être qu’une recherche peut vous indiquer un article lié." + +#~ msgid "Featured post" +#~ msgstr "Article mis en avant" + +#~ msgid "Primary Menu" +#~ msgstr "Menu principal" + +#~ msgctxt "Open Sans font: add new subset (greek, cyrillic, vietnamese)" +#~ msgid "no-subset" +#~ msgstr "no-subset " + +#~ msgid "" +#~ "Appears on posts and pages except the optional Front Page template, which " +#~ "has its own widgets" +#~ msgstr "" +#~ "Apparaît sur les articles et les pages, sauf le modèle facultatif Page " +#~ "d’Accueil, qui dispose de ses propres widgets." + +#~ msgid "First Front Page Widget Area" +#~ msgstr "Première zone de la Page d’Accueil" + +#~ msgid "" +#~ "Appears when using the optional Front Page template with a page set as " +#~ "Static Front Page" +#~ msgstr "" +#~ "Apparaît lorsque vous utilisez le modèle facultatif Page d’Accueil " +#~ "avec une page configurée en Page d’Accueil Statique." + +#~ msgid "Pingback:" +#~ msgstr "Ping :" + +#~ msgid "(Edit)" +#~ msgstr "(Modifier)" + +#~ msgid "Post author" +#~ msgstr "Auteur de l’article" + +#~ msgid "Your comment is awaiting moderation." +#~ msgstr "Votre commentaire est en attente de validation." + +#~ msgid "Reply" +#~ msgstr "Répondre" + +#~ msgid "" +#~ "This entry was posted in %1$s and tagged %2$s on %3$s by %4$s." +#~ msgstr "" +#~ "Cette entrée a été publiée dans %1$s, et marquée avec %2$s, le %3$s par %4$s." + +#~ msgid "" +#~ "This entry was posted in %1$s on %3$s by %4$s." +#~ msgstr "" +#~ "Cette entrée a été publiée dans %1$s le %3$s par %4$s." + +#~ msgid "" +#~ "This entry was posted on %3$s by %4$s." +#~ msgstr "" +#~ "Cette entrée a été publiée le %3$s par %4$s." + +#~ msgid "← Previous" +#~ msgstr "← Précédent" + +#~ msgid "Next →" +#~ msgstr "Suivant →" + +#~ msgid "No posts to display" +#~ msgstr "Aucun article à afficher" + +#~ msgctxt "Previous post link" +#~ msgid "←" +#~ msgstr "←" + +#~ msgctxt "Next post link" +#~ msgid "→" +#~ msgstr "→" + +#~ msgid "" +#~ "The 2012 theme for WordPress is a fully responsive theme that looks great " +#~ "on any device. Features include a front page template with its own " +#~ "widgets, an optional display font, styling for post formats on both index " +#~ "and single views, and an optional no-sidebar page template. Make it yours " +#~ "with a custom menu, header image, and background." +#~ msgstr "" +#~ "Le thème 2012 de WordPress est un thème conçu pour s’afficher de la " +#~ "meilleure manière sur n’importe quelle taille d’écran. Parmi " +#~ "ses fonctionnalités se trouvent un modèle de page d’accueil avec " +#~ "ses propres widgets, une police d’affichage optionnelle, un design " +#~ "pour les formats d’article à la fois sur l’index et en vue " +#~ "individuelle, et un modèle facultatif sans barre latérale. Vous pouvez le " +#~ "faire vôtre avec un menu personnalisé, une image d’en-tête, et un " +#~ "fond d’écran." + +#~ msgid "Front Page Template" +#~ msgstr "Modèle de Page d’Accueil" + +#~ msgid "Full-width Page Template, No Sidebar" +#~ msgstr "Modèle de page pleine largeur, sans barre latérale" + +#~ msgid "Reply " +#~ msgstr "Répondre " + +#~ msgid "Main menu" +#~ msgstr "Menu principal" + +#~ msgid "Skip to secondary content" +#~ msgstr "Aller au contenu secondaire" + +#~ msgid "Meta" +#~ msgstr "Méta" + +#~ msgid "The 2012 theme for WordPress." +#~ msgstr "Le thème de WordPress pour 2012" + +#~ msgid "" +#~ "Posted on by %7$s" +#~ msgstr "" +#~ "Publié le par " +#~ "%7$s" + +#~ msgid "Featured" +#~ msgstr "Mis en avant" + +#~ msgid "%1$s on %2$s said:" +#~ msgstr "Le %2$s, %1$s a dit :" + +#~ msgid "" +#~ "This entry was posted in %1$s and tagged %2$s by %5$s. Bookmark the permalink." +#~ msgstr "" +#~ "Ce contenu a été publié dans %1$s par %5$s, et " +#~ "marqué avec %2$s. Mettez-le en favori avec son permalien." + +#~ msgid "" +#~ "This post is password protected. Enter the password to view any comments." +#~ msgstr "" +#~ "Cet article est protégé par un mot de passe. Veuillez le saisir pour " +#~ "pouvoir lire ses commentaires." + +#~ msgid "" +#~ "This entry was posted in %1$s by %5$s. Bookmark the " +#~ "permalink." +#~ msgstr "" +#~ "Ce contenu a été publié dans %1$s par %5$s. Mettez-" +#~ "le en favori avec son permalien." + +#~ msgid "Posted in %2$s" +#~ msgstr "Publié dans %2$s" + +#~ msgid "Tagged %2$s" +#~ msgstr "Mots-clés : %2$s" + +#~ msgid "1 Reply" +#~ msgstr "Une réponse" + +#~ msgid "Blog Archives" +#~ msgstr "Archives du blog" + +#~ msgid "" +#~ "This entry was posted by %5$s. Bookmark the permalink." +#~ msgstr "" +#~ "Ce contenu a été publié par %5$s. Mettez-le en " +#~ "favori avec son permalien." + +#~ msgid "Quote" +#~ msgstr "Citation" + +#~ msgctxt "comments number" +#~ msgid "1" +#~ msgstr "1" + +#~ msgctxt "comments number" +#~ msgid "%" +#~ msgstr "%" + +#~ msgid "Featuring: %s" +#~ msgstr "Mise en avant : %s" + +#~ msgid "Recent Posts" +#~ msgstr "Articles récents" + +#~ msgid "Image" +#~ msgstr "Image" + +#~ msgid "" +#~ " by %6$s" +#~ msgstr "" +#~ " par %6$s" + +#~ msgid "Gallery" +#~ msgstr "Galerie" + +#~ msgid "This gallery contains %2$s photo." +#~ msgid_plural "This gallery contains %2$s photos." +#~ msgstr[0] "Cette galerie contient %2$s photo." +#~ msgstr[1] "Cette galerie contient %2$s photos." + +#~ msgid "Aside" +#~ msgstr "En passant" + +#~ msgid "Most Used Categories" +#~ msgstr "Catégories les plus utilisées" + +#~ msgid "Try looking in the monthly archives. %1$s" +#~ msgstr "Essayez de voir du côté des archives mensuelles. %1$s" + +#~ msgid "Image navigation" +#~ msgstr "Navigation des images" + +#~ msgid "Wheel" +#~ msgstr "Roue" + +#~ msgid "Shore" +#~ msgstr "Rivage" + +#~ msgid "Trolley" +#~ msgstr "Tramway" + +#~ msgid "Pine Cone" +#~ msgstr "Pomme de pin" + +#~ msgid "Chessboard" +#~ msgstr "Damier" + +#~ msgid "Lanterns" +#~ msgstr "Lanternes" + +#~ msgid "Willow" +#~ msgstr "Saule" + +#~ msgid "Hanoi Plant" +#~ msgstr "Plante de Hanoï" + +#~ msgid "Showcase Sidebar" +#~ msgstr "Colonne latérale de la vitrine" + +#~ msgid "The sidebar for the optional Showcase Template" +#~ msgstr "La colonne latérale pour le modèle factultatif de vitrine" + +#~ msgid "Footer Area One" +#~ msgstr "Zone 1 du pied de page" + +#~ msgid "An optional widget area for your site footer" +#~ msgstr "Une zone facultative de widgets pour le pied de page de votre site" + +#~ msgid "Footer Area Two" +#~ msgstr "Zone 2 du pied de page" + +#~ msgid "Footer Area Three" +#~ msgstr "Zone 3 du pied de page" + +#~ msgid "Status" +#~ msgstr "Humeur du moment" + +#~ msgid "Color Scheme" +#~ msgstr "Jeu de couleurs" + +#~ msgid "Link Color" +#~ msgstr "Couleur des liens" + +#~ msgid "Default Layout" +#~ msgstr "Mise en page par défaut" + +#~ msgid "Theme Options" +#~ msgstr "Options du thème" + +#~ msgid "" +#~ "Some themes provide customization options that are grouped together on a " +#~ "Theme Options screen. If you change themes, options may change or " +#~ "disappear, as they are theme-specific. Your current theme, Twenty Eleven, " +#~ "provides the following Theme Options:" +#~ msgstr "" +#~ "Certains thèmes proposent des options de personnalisation, regroupées sur " +#~ "l’écran « Options du thème" + +#~ msgid "" +#~ "Color Scheme: You can choose a color palette of \"Light" +#~ "\" (light background with dark text) or \"Dark\" (dark background with " +#~ "light text) for your site." +#~ msgstr "" +#~ "Jeu de couleurs : vous pouvez choisir comme palette " +#~ "de couleurs pour votre site « Clair » (fond clair " +#~ "et texte foncé), ou « Foncé » (fond foncé et texte " +#~ "clair)." + +#~ msgid "" +#~ "Link Color: You can choose the color used for text links " +#~ "on your site. You can enter the HTML color or hex code, or you can choose " +#~ "visually by clicking the \"Select a Color\" button to pick from a color " +#~ "wheel." +#~ msgstr "" +#~ "Couleur des liens : vous pouvez choisir la couleur " +#~ "des liens textuels de votre site. Saisissez le code couleur (code HTML ou " +#~ "hexadécimal), ou choisissez-la avec le sélecteur de couleur, en cliquant " +#~ "sur « Choisir une couleur »." + +#~ msgid "" +#~ "Default Layout: You can choose if you want your " +#~ "site’s default layout to have a sidebar on the left, the right, or " +#~ "not at all." +#~ msgstr "" +#~ "Mise en page par défaut : si vous le souhaitez, " +#~ "votre site peut afficher sa barre latérale sur le côté droit, le côté " +#~ "gauche, ou ne pas l’afficher du tout." + +#~ msgid "" +#~ "Remember to click \"Save Changes\" to save any changes you have made to " +#~ "the theme options." +#~ msgstr "" +#~ "N’oubliez pas de cliquer sur « Enregistrer les " +#~ "modifications » pour conserver toutes les modifications " +#~ "apportées aux options du thème" + +#~ msgid "For more information:" +#~ msgstr "Pour plus d’information :" + +#~ msgid "" +#~ "Documentation on Theme Options" +#~ msgstr "" +#~ "Documentation sur les options du thème (en)" + +#~ msgid "" +#~ "Support " +#~ "Forums" +#~ msgstr "" +#~ "Forums " +#~ "d’entraide en français" + +#~ msgid "Overview" +#~ msgstr "Vue d'ensemble" + +#~ msgid "Light" +#~ msgstr "Clair" + +#~ msgid "Dark" +#~ msgstr "Foncé" + +#~ msgid "Content on left" +#~ msgstr "Contenu à gauche" + +#~ msgid "Content on right" +#~ msgstr "Contenu à droite" + +#~ msgid "One-column, no sidebar" +#~ msgstr "Une colonne, pas de barre latérale" + +#~ msgid "Select a Color" +#~ msgstr "Choisir une couleur" + +#~ msgid "Default color: %s" +#~ msgstr "Couleur par défaut :" + +#~ msgid "%s Theme Options" +#~ msgstr "Options du thème %s" + +#~ msgid "" +#~ "Use this widget to list your recent Aside, Status, Quote, and Link posts" +#~ msgstr "" +#~ "Utiliser ce widget pour lister vos derniers contenus court : en " +#~ "passant, humeur du moment, citation, liens..." + +#~ msgid "Twenty Eleven Ephemera" +#~ msgstr "Contenu éphémère de Twenty Ten" + +#~ msgid "Ephemera" +#~ msgstr "Éphémère" + +#~ msgid "0 comments →" +#~ msgstr "Aucun commentaire →" + +#~ msgid "1 comment →" +#~ msgstr "Un commentaire →" + +#~ msgid "% comments →" +#~ msgstr "% commentaires →" + +#~ msgid "Link to %s" +#~ msgstr "Lien vers %s" + +#~ msgid "Title:" +#~ msgstr "Titre :" + +#~ msgid "" +#~ "This entry was posted in %1$s. Bookmark the permalink." +#~ msgstr "" +#~ "Ce contenu a été publié dans %1$s. Mettez-le en favori avec son permalien." + +#~ msgid "Search" +#~ msgstr "Recherche" + +#~ msgid "" +#~ "The 2011 theme for WordPress is sophisticated, lightweight, and " +#~ "adaptable. Make it yours with a custom menu, header image, and background " +#~ "-- then go further with available theme options for light or dark color " +#~ "scheme, custom link colors, and three layout choices. Twenty Eleven comes " +#~ "equipped with a Showcase page template that transforms your front page " +#~ "into a showcase to show off your best content, widget support galore " +#~ "(sidebar, three footer areas, and a Showcase page widget area), and a " +#~ "custom \"Ephemera\" widget to display your Aside, Link, Quote, or Status " +#~ "posts. Included are styles for print and for the admin editor, support " +#~ "for featured images (as custom header images on posts and pages and as " +#~ "large images on featured \"sticky\" posts), and special styles for six " +#~ "different post formats." +#~ msgstr "" +#~ "Le thème par défaut de WordPress pour 2011 est sophistiqué, léger et " +#~ "adaptable. Faites-le vôtre avec un menu personnalisé, une image d’" +#~ "en-tête et de fond - puis aller plus loin avec les options disponibles " +#~ "pour les couleurs du thèmes (claires ou foncées), celle des liens, et " +#~ "trois choix de mise en page. Twenty-Elevent est équipé d’un modèle " +#~ "de page Vitrine qui transforme votre page d’accueil en une vitrine " +#~ "pour montrer vos meilleurs contenus, reconnaît de nombreux widgets " +#~ "(colonne latérale, pied de page à trois zones, et une zone de widget pour " +#~ "la page page vitrine), et un widget personnalisable Ephémères, pour " +#~ "afficher vos contenus écrits en passant, vos liens, citations ou humeurs " +#~ "du moment. Sont inclus les styles pour l’impression et pour l’" +#~ "éditeur de l’administration, reconnaissance des images mises en " +#~ "avant (comme les images en-tête personnalisables par article et par page, " +#~ "ou la reprise en grand des images articles mis en avant), et des styles " +#~ "spéciaux pour six formats différents d’articles." + +#~ msgid "" +#~ "dark, light, white, black, gray, one-column, two-columns, left-sidebar, " +#~ "right-sidebar, fixed-width, flexible-width, custom-background, custom-" +#~ "colors, custom-header, custom-menu, editor-style, featured-image-header, " +#~ "featured-images, full-width-template, microformats, post-formats, rtl-" +#~ "language-support, sticky-post, theme-options, translation-ready" +#~ msgstr "" +#~ "dark, light, white, black, gray, one-column, two-columns, left-sidebar, " +#~ "right-sidebar, fixed-width, flexible-width, custom-background, custom-" +#~ "colors, custom-header, custom-menu, editor-style, featured-image-header, " +#~ "featured-images, full-width-template, microformats, post-formats, rtl-" +#~ "language-support, sticky-post, theme-options, translation-ready" + +#~ msgid "1 Reply" +#~ msgstr "Une réponse" + +#~ msgid "% Replies" +#~ msgstr "% réponses" + +#~ msgid "Leave a Reply" +#~ msgstr "Laisser une réponse" + +#~ msgid "Screen Info" +#~ msgstr "Information de l’écran" + +#~ msgid "[Edit]" +#~ msgstr "[Modifier]" + +#~ msgid "Reply" +#~ msgstr "Répondre" + +#~ msgid "Leave a reply" +#~ msgstr "Laisser une réponse" + +#~ msgid "Pages:" +#~ msgstr "Pages :" diff --git a/sources/wp-content/languages/themes/twentytwelve-fr_FR.mo b/sources/wp-content/languages/themes/twentytwelve-fr_FR.mo new file mode 100644 index 0000000000000000000000000000000000000000..3c53c3e6a0ea72281f7b2ccadaa141597319b9d2 GIT binary patch literal 8362 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 z\n" +"Language-Team: WordPress-Francophone \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n>1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 1.5.7\n" + +#: 404.php:17 +msgid "This is somewhat embarrassing, isn’t it?" +msgstr "C’est plutôt gênant, vous ne trouvez pas ?" + +#: 404.php:21 +msgid "" +"It seems we can’t find what you’re looking for. Perhaps " +"searching can help." +msgstr "" +"Il semblerait que nous ne soyons pas en mesure de trouver votre contenu. " +"Essayez en lançant une recherche." + +#: archive.php:29 +msgid "Daily Archives: %s" +msgstr "Archives quotidiennes :" + +#: archive.php:31 +msgid "Monthly Archives: %s" +msgstr "Archives mensuelles : %s" + +#: archive.php:31 +msgctxt "monthly archives date format" +msgid "F Y" +msgstr "F Y" + +#: archive.php:33 +msgid "Yearly Archives: %s" +msgstr "Archives annuelles : %s" + +#: archive.php:33 +msgctxt "yearly archives date format" +msgid "Y" +msgstr "Y" + +#: archive.php:35 +msgid "Archives" +msgstr "Archives" + +#: author.php:32 +msgid "Author Archives: %s" +msgstr "Archives de l’auteur : %s" + +#: author.php:53 content.php:53 +msgid "About %s" +msgstr "A propos %s" + +#: category.php:21 +msgid "Category Archives: %s" +msgstr "Archives pour la catégorie %s" + +#: comments.php:31 +msgid "One thought on “%2$s”" +msgid_plural "%1$s thoughts on “%2$s”" +msgstr[0] "Une réflexion au sujet de « %2$s »" +msgstr[1] "%1$s réflexions au sujet de « %2$s »" + +#: comments.php:42 +msgid "Comment navigation" +msgstr "Navigation des commentaires" + +#: comments.php:43 +msgid "← Older Comments" +msgstr "← Commentaire plus ancien" + +#: comments.php:44 +msgid "Newer Comments →" +msgstr "Commentaires plus récents →" + +#: comments.php:53 +msgid "Comments are closed." +msgstr "Les commentaires sont fermés." + +#: content-aside.php:15 content-image.php:13 content-link.php:14 +#: content-quote.php:13 content-status.php:21 content.php:39 +msgid "Continue reading " +msgstr "Lire la suite " + +#: content-aside.php:20 content-link.php:18 content-quote.php:17 +#: content-status.php:15 +msgid "Permalink to %s" +msgstr "Permalien vers %s" + +#: content-aside.php:23 content-image.php:23 content-link.php:21 +#: content-quote.php:20 content-status.php:27 content.php:28 +msgid "Leave a reply" +msgstr "Laisser une réponse" + +#: content-aside.php:23 content-image.php:23 content-link.php:21 +#: content-quote.php:20 content-status.php:27 content.php:28 +msgid "1 Reply" +msgstr "1 réponse" + +#: content-aside.php:23 content-image.php:23 content-link.php:21 +#: content-quote.php:20 content-status.php:27 content.php:28 +msgid "% Replies" +msgstr "% réponses" + +#: content-aside.php:26 content-image.php:26 content-link.php:24 +#: content-page.php:24 content-quote.php:23 content-status.php:30 +#: content.php:46 functions.php:341 image.php:37 +msgid "Edit" +msgstr "Modifier" + +#: content-link.php:12 +msgid "Link" +msgstr "Lien" + +#: content-none.php:13 index.php:49 search.php:34 +msgid "Nothing Found" +msgstr "Rien n’a été trouvé" + +#: content-none.php:17 index.php:53 +msgid "" +"Apologies, but no results were found. Perhaps searching will help find a " +"related post." +msgstr "" +"Toutes nos excuses, mais votre requête n’a donné aucun résultat. Peut-" +"être qu’une recherche peut vous indiquer un article lié." + +#: content-page.php:21 content.php:40 image.php:92 +msgid "Pages:" +msgstr "Pages :" + +#: content.php:14 +msgid "Featured post" +msgstr "Article mis en avant" + +#: content.php:57 +msgid "View all posts by %s " +msgstr "" +"Afficher tous les articles de %s " + +#. #-#-#-#-# twentytwelve.pot (Twenty Twelve 1.1.1) #-#-#-#-# +#. Author URI of the plugin/theme +#: footer.php:17 +msgid "http://wordpress.org/" +msgstr "http://wordpress.org/" + +#: footer.php:17 +msgid "Semantic Personal Publishing Platform" +msgstr "Plate-forme de publication personnelle à la pointe de la sémantique" + +#: footer.php:17 +msgid "Proudly powered by %s" +msgstr "Fièrement propulsé par %s" + +#: functions.php:64 +msgid "Primary Menu" +msgstr "Menu principal" + +#. 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. +#: functions.php:100 +msgctxt "Open Sans font: on or off" +msgid "on" +msgstr "on" + +#. 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. +#: functions.php:105 +msgctxt "Open Sans font: add new subset (greek, cyrillic, vietnamese)" +msgid "no-subset" +msgstr "no-subset " + +#: functions.php:213 +msgid "Page %s" +msgstr "Page %s" + +#: functions.php:238 +msgid "Main Sidebar" +msgstr "Colonne principale" + +#: functions.php:240 +msgid "" +"Appears on posts and pages except the optional Front Page template, which " +"has its own widgets" +msgstr "" +"Apparaît sur les articles et les pages, sauf le modèle facultatif Page " +"d’Accueil, qui dispose de ses propres widgets." + +#: functions.php:248 +msgid "First Front Page Widget Area" +msgstr "Première zone de la Page d’Accueil" + +#: functions.php:250 functions.php:260 +msgid "" +"Appears when using the optional Front Page template with a page set as " +"Static Front Page" +msgstr "" +"Apparaît lorsque vous utilisez le modèle facultatif Page d’Accueil " +"avec une page configurée en Page d’Accueil Statique." + +#: functions.php:258 +msgid "Second Front Page Widget Area" +msgstr "Seconde zone de la Page d’Accueil" + +#: functions.php:282 single.php:20 +msgid "Post navigation" +msgstr "Navigation des articles" + +#: functions.php:283 +msgid " Older posts" +msgstr " Articles plus anciens" + +#: functions.php:284 +msgid "Newer posts " +msgstr "Articles plus récents " + +#: functions.php:309 +msgid "Pingback:" +msgstr "Ping :" + +#: functions.php:309 +msgid "(Edit)" +msgstr "(Modifier)" + +#: functions.php:324 +msgid "Post author" +msgstr "Auteur de l’article" + +#. translators: 1: date, 2: time +#: functions.php:330 +msgid "%1$s at %2$s" +msgstr "%1$s le %2$s" + +#: functions.php:336 +msgid "Your comment is awaiting moderation." +msgstr "Votre commentaire est en attente de validation." + +#: functions.php:345 +msgid "Reply" +msgstr "Répondre" + +#. Translators: used between list items, there is a space after the comma. +#: functions.php:364 functions.php:367 +msgid ", " +msgstr ", " + +#: functions.php:378 +msgid "View all posts by %s" +msgstr "Afficher tous les articles par %s" + +#. Translators: 1 is category, 2 is tag, 3 is the date and 4 is the author's +#. name. +#: functions.php:384 +msgid "" +"This entry was posted in %1$s and tagged %2$s on %3$s by %4$s." +msgstr "" +"Cette entrée a été publiée dans %1$s, et marquée avec %2$s, le %3$s par %4$s." + +#: functions.php:386 +msgid "" +"This entry was posted in %1$s on %3$s by %4$s." +msgstr "" +"Cette entrée a été publiée dans %1$s le %3$s par " +"%4$s." + +#: functions.php:388 +msgid "This entry was posted on %3$s by %4$s." +msgstr "" +"Cette entrée a été publiée le %3$s par %4$s." + +#: header.php:43 +msgid "Menu" +msgstr "Menu" + +#: header.php:44 +msgid "Skip to content" +msgstr "Aller au contenu principal" + +#: image.php:26 +msgid "" +"Published at %4$s × " +"%5$s in %8$s." +msgstr "" +"Publié le en " +"%4$s × %5$s dans %8$s." + +#: image.php:41 +msgid "← Previous" +msgstr "← Précédent" + +#: image.php:42 +msgid "Next →" +msgstr "Suivant →" + +#: index.php:38 +msgid "No posts to display" +msgstr "Aucun article à afficher" + +#: index.php:42 +msgid "Ready to publish your first post? Get started here." +msgstr "" +"Prêt à publier votre premier article ? Lancez-vous !" + +#: search.php:18 +msgid "Search Results for: %s" +msgstr "Résultats de recherche pour %s" + +#: search.php:38 +msgid "" +"Sorry, but nothing matched your search criteria. Please try again with some " +"different keywords." +msgstr "" +"Désolé, mais rien ne correspond à votre critère de recherche. Veuillez " +"réessayer avec d’autres mots-clés." + +#: single.php:21 +msgctxt "Previous post link" +msgid "←" +msgstr "←" + +#: single.php:22 +msgctxt "Next post link" +msgid "→" +msgstr "→" + +#: tag.php:21 +msgid "Tag Archives: %s" +msgstr "Archives du mot-clé %s" + +#. Theme Name of the plugin/theme +msgid "Twenty Twelve" +msgstr "Twenty Twelve" + +#. Theme URI of the plugin/theme +msgid "http://wordpress.org/themes/twentytwelve" +msgstr "http://wordpress.org/themes/twentytwelve" + +#. Description of the plugin/theme +msgid "" +"The 2012 theme for WordPress is a fully responsive theme that looks great on " +"any device. Features include a front page template with its own widgets, an " +"optional display font, styling for post formats on both index and single " +"views, and an optional no-sidebar page template. Make it yours with a custom " +"menu, header image, and background." +msgstr "" +"Le thème 2012 de WordPress est un thème conçu pour s’afficher de la " +"meilleure manière sur n’importe quelle taille d’écran. Parmi ses " +"fonctionnalités se trouvent un modèle de page d’accueil avec ses " +"propres widgets, une police d’affichage optionnelle, un design pour " +"les formats d’article à la fois sur l’index et en vue " +"individuelle, et un modèle facultatif sans barre latérale. Vous pouvez le " +"faire vôtre avec un menu personnalisé, une image d’en-tête, et un fond " +"d’écran." + +#. Author of the plugin/theme +msgid "the WordPress team" +msgstr "L’équipe WordPress" + +#. Template Name of the plugin/theme +msgid "Front Page Template" +msgstr "Modèle de Page d’Accueil" + +#. Template Name of the plugin/theme +msgid "Full-width Page Template, No Sidebar" +msgstr "Modèle de page pleine largeur, sans barre latérale" + +#~ msgid "Reply " +#~ msgstr "Répondre " + +#~ msgid "Main menu" +#~ msgstr "Menu principal" + +#~ msgid "Skip to secondary content" +#~ msgstr "Aller au contenu secondaire" + +#~ msgid "Meta" +#~ msgstr "Méta" + +#~ msgid "The 2012 theme for WordPress." +#~ msgstr "Le thème de WordPress pour 2012" + +#~ msgid "" +#~ "Posted on by %7$s" +#~ msgstr "" +#~ "Publié le par " +#~ "%7$s" + +#~ msgid "Featured" +#~ msgstr "Mis en avant" + +#~ msgid "%1$s on %2$s said:" +#~ msgstr "Le %2$s, %1$s a dit :" + +#~ msgid "" +#~ "This entry was posted in %1$s and tagged %2$s by %5$s. Bookmark the permalink." +#~ msgstr "" +#~ "Ce contenu a été publié dans %1$s par %5$s, et " +#~ "marqué avec %2$s. Mettez-le en favori avec son permalien." + +#~ msgid "" +#~ "This post is password protected. Enter the password to view any comments." +#~ msgstr "" +#~ "Cet article est protégé par un mot de passe. Veuillez le saisir pour " +#~ "pouvoir lire ses commentaires." + +#~ msgid "" +#~ "This entry was posted in %1$s by %5$s. Bookmark the " +#~ "permalink." +#~ msgstr "" +#~ "Ce contenu a été publié dans %1$s par %5$s. Mettez-" +#~ "le en favori avec son permalien." + +#~ msgid "Posted in %2$s" +#~ msgstr "Publié dans %2$s" + +#~ msgid "Tagged %2$s" +#~ msgstr "Mots-clés : %2$s" + +#~ msgid "1 Reply" +#~ msgstr "Une réponse" + +#~ msgid "Blog Archives" +#~ msgstr "Archives du blog" + +#~ msgid "" +#~ "This entry was posted by %5$s. Bookmark the permalink." +#~ msgstr "" +#~ "Ce contenu a été publié par %5$s. Mettez-le en " +#~ "favori avec son permalien." + +#~ msgid "Quote" +#~ msgstr "Citation" + +#~ msgctxt "comments number" +#~ msgid "1" +#~ msgstr "1" + +#~ msgctxt "comments number" +#~ msgid "%" +#~ msgstr "%" + +#~ msgid "Featuring: %s" +#~ msgstr "Mise en avant : %s" + +#~ msgid "Recent Posts" +#~ msgstr "Articles récents" + +#~ msgid "Image" +#~ msgstr "Image" + +#~ msgid "" +#~ " by %6$s" +#~ msgstr "" +#~ " par %6$s" + +#~ msgid "Gallery" +#~ msgstr "Galerie" + +#~ msgid "This gallery contains %2$s photo." +#~ msgid_plural "This gallery contains %2$s photos." +#~ msgstr[0] "Cette galerie contient %2$s photo." +#~ msgstr[1] "Cette galerie contient %2$s photos." + +#~ msgid "Aside" +#~ msgstr "En passant" + +#~ msgid "Most Used Categories" +#~ msgstr "Catégories les plus utilisées" + +#~ msgid "Try looking in the monthly archives. %1$s" +#~ msgstr "Essayez de voir du côté des archives mensuelles. %1$s" + +#~ msgid "Image navigation" +#~ msgstr "Navigation des images" + +#~ msgid "Wheel" +#~ msgstr "Roue" + +#~ msgid "Shore" +#~ msgstr "Rivage" + +#~ msgid "Trolley" +#~ msgstr "Tramway" + +#~ msgid "Pine Cone" +#~ msgstr "Pomme de pin" + +#~ msgid "Chessboard" +#~ msgstr "Damier" + +#~ msgid "Lanterns" +#~ msgstr "Lanternes" + +#~ msgid "Willow" +#~ msgstr "Saule" + +#~ msgid "Hanoi Plant" +#~ msgstr "Plante de Hanoï" + +#~ msgid "Showcase Sidebar" +#~ msgstr "Colonne latérale de la vitrine" + +#~ msgid "The sidebar for the optional Showcase Template" +#~ msgstr "La colonne latérale pour le modèle factultatif de vitrine" + +#~ msgid "Footer Area One" +#~ msgstr "Zone 1 du pied de page" + +#~ msgid "An optional widget area for your site footer" +#~ msgstr "Une zone facultative de widgets pour le pied de page de votre site" + +#~ msgid "Footer Area Two" +#~ msgstr "Zone 2 du pied de page" + +#~ msgid "Footer Area Three" +#~ msgstr "Zone 3 du pied de page" + +#~ msgid "Status" +#~ msgstr "Humeur du moment" + +#~ msgid "Color Scheme" +#~ msgstr "Jeu de couleurs" + +#~ msgid "Link Color" +#~ msgstr "Couleur des liens" + +#~ msgid "Default Layout" +#~ msgstr "Mise en page par défaut" + +#~ msgid "Theme Options" +#~ msgstr "Options du thème" + +#~ msgid "" +#~ "Some themes provide customization options that are grouped together on a " +#~ "Theme Options screen. If you change themes, options may change or " +#~ "disappear, as they are theme-specific. Your current theme, Twenty Eleven, " +#~ "provides the following Theme Options:" +#~ msgstr "" +#~ "Certains thèmes proposent des options de personnalisation, regroupées sur " +#~ "l’écran « Options du thème" + +#~ msgid "" +#~ "Color Scheme: You can choose a color palette of \"Light" +#~ "\" (light background with dark text) or \"Dark\" (dark background with " +#~ "light text) for your site." +#~ msgstr "" +#~ "Jeu de couleurs : vous pouvez choisir comme palette " +#~ "de couleurs pour votre site « Clair » (fond clair " +#~ "et texte foncé), ou « Foncé » (fond foncé et texte " +#~ "clair)." + +#~ msgid "" +#~ "Link Color: You can choose the color used for text links " +#~ "on your site. You can enter the HTML color or hex code, or you can choose " +#~ "visually by clicking the \"Select a Color\" button to pick from a color " +#~ "wheel." +#~ msgstr "" +#~ "Couleur des liens : vous pouvez choisir la couleur " +#~ "des liens textuels de votre site. Saisissez le code couleur (code HTML ou " +#~ "hexadécimal), ou choisissez-la avec le sélecteur de couleur, en cliquant " +#~ "sur « Choisir une couleur »." + +#~ msgid "" +#~ "Default Layout: You can choose if you want your " +#~ "site’s default layout to have a sidebar on the left, the right, or " +#~ "not at all." +#~ msgstr "" +#~ "Mise en page par défaut : si vous le souhaitez, " +#~ "votre site peut afficher sa barre latérale sur le côté droit, le côté " +#~ "gauche, ou ne pas l’afficher du tout." + +#~ msgid "" +#~ "Remember to click \"Save Changes\" to save any changes you have made to " +#~ "the theme options." +#~ msgstr "" +#~ "N’oubliez pas de cliquer sur « Enregistrer les " +#~ "modifications » pour conserver toutes les modifications " +#~ "apportées aux options du thème" + +#~ msgid "For more information:" +#~ msgstr "Pour plus d’information :" + +#~ msgid "" +#~ "Documentation on Theme Options" +#~ msgstr "" +#~ "Documentation sur les options du thème (en)" + +#~ msgid "" +#~ "Support " +#~ "Forums" +#~ msgstr "" +#~ "Forums " +#~ "d’entraide en français" + +#~ msgid "Overview" +#~ msgstr "Vue d'ensemble" + +#~ msgid "Light" +#~ msgstr "Clair" + +#~ msgid "Dark" +#~ msgstr "Foncé" + +#~ msgid "Content on left" +#~ msgstr "Contenu à gauche" + +#~ msgid "Content on right" +#~ msgstr "Contenu à droite" + +#~ msgid "One-column, no sidebar" +#~ msgstr "Une colonne, pas de barre latérale" + +#~ msgid "Select a Color" +#~ msgstr "Choisir une couleur" + +#~ msgid "Default color: %s" +#~ msgstr "Couleur par défaut :" + +#~ msgid "%s Theme Options" +#~ msgstr "Options du thème %s" + +#~ msgid "" +#~ "Use this widget to list your recent Aside, Status, Quote, and Link posts" +#~ msgstr "" +#~ "Utiliser ce widget pour lister vos derniers contenus court : en " +#~ "passant, humeur du moment, citation, liens..." + +#~ msgid "Twenty Eleven Ephemera" +#~ msgstr "Contenu éphémère de Twenty Ten" + +#~ msgid "Ephemera" +#~ msgstr "Éphémère" + +#~ msgid "0 comments →" +#~ msgstr "Aucun commentaire →" + +#~ msgid "1 comment →" +#~ msgstr "Un commentaire →" + +#~ msgid "% comments →" +#~ msgstr "% commentaires →" + +#~ msgid "Link to %s" +#~ msgstr "Lien vers %s" + +#~ msgid "Title:" +#~ msgstr "Titre :" + +#~ msgid "" +#~ "This entry was posted in %1$s. Bookmark the permalink." +#~ msgstr "" +#~ "Ce contenu a été publié dans %1$s. Mettez-le en favori avec son permalien." + +#~ msgid " Previous" +#~ msgstr " Précédent" + +#~ msgid "Next " +#~ msgstr "Suivant " + +#~ msgid "Search" +#~ msgstr "Recherche" + +#~ msgid "" +#~ "The 2011 theme for WordPress is sophisticated, lightweight, and " +#~ "adaptable. Make it yours with a custom menu, header image, and background " +#~ "-- then go further with available theme options for light or dark color " +#~ "scheme, custom link colors, and three layout choices. Twenty Eleven comes " +#~ "equipped with a Showcase page template that transforms your front page " +#~ "into a showcase to show off your best content, widget support galore " +#~ "(sidebar, three footer areas, and a Showcase page widget area), and a " +#~ "custom \"Ephemera\" widget to display your Aside, Link, Quote, or Status " +#~ "posts. Included are styles for print and for the admin editor, support " +#~ "for featured images (as custom header images on posts and pages and as " +#~ "large images on featured \"sticky\" posts), and special styles for six " +#~ "different post formats." +#~ msgstr "" +#~ "Le thème par défaut de WordPress pour 2011 est sophistiqué, léger et " +#~ "adaptable. Faites-le vôtre avec un menu personnalisé, une image d’" +#~ "en-tête et de fond - puis aller plus loin avec les options disponibles " +#~ "pour les couleurs du thèmes (claires ou foncées), celle des liens, et " +#~ "trois choix de mise en page. Twenty-Elevent est équipé d’un modèle " +#~ "de page Vitrine qui transforme votre page d’accueil en une vitrine " +#~ "pour montrer vos meilleurs contenus, reconnaît de nombreux widgets " +#~ "(colonne latérale, pied de page à trois zones, et une zone de widget pour " +#~ "la page page vitrine), et un widget personnalisable Ephémères, pour " +#~ "afficher vos contenus écrits en passant, vos liens, citations ou humeurs " +#~ "du moment. Sont inclus les styles pour l’impression et pour l’" +#~ "éditeur de l’administration, reconnaissance des images mises en " +#~ "avant (comme les images en-tête personnalisables par article et par page, " +#~ "ou la reprise en grand des images articles mis en avant), et des styles " +#~ "spéciaux pour six formats différents d’articles." + +#~ msgid "" +#~ "dark, light, white, black, gray, one-column, two-columns, left-sidebar, " +#~ "right-sidebar, fixed-width, flexible-width, custom-background, custom-" +#~ "colors, custom-header, custom-menu, editor-style, featured-image-header, " +#~ "featured-images, full-width-template, microformats, post-formats, rtl-" +#~ "language-support, sticky-post, theme-options, translation-ready" +#~ msgstr "" +#~ "dark, light, white, black, gray, one-column, two-columns, left-sidebar, " +#~ "right-sidebar, fixed-width, flexible-width, custom-background, custom-" +#~ "colors, custom-header, custom-menu, editor-style, featured-image-header, " +#~ "featured-images, full-width-template, microformats, post-formats, rtl-" +#~ "language-support, sticky-post, theme-options, translation-ready" + +#~ msgid "1 Reply" +#~ msgstr "Une réponse" + +#~ msgid "% Replies" +#~ msgstr "% réponses" + +#~ msgid "Leave a Reply" +#~ msgstr "Laisser une réponse" + +#~ msgid "Screen Info" +#~ msgstr "Information de l’écran" + +#~ msgid "[Edit]" +#~ msgstr "[Modifier]" + +#~ msgid "Reply" +#~ msgstr "Répondre" + +#~ msgid "Leave a reply" +#~ msgstr "Laisser une réponse" + +#~ msgid "Pages:" +#~ msgstr "Pages :" diff --git a/sources/wp-content/plugins/akismet/admin.php b/sources/wp-content/plugins/akismet/admin.php new file mode 100644 index 0000000..f807191 --- /dev/null +++ b/sources/wp-content/plugins/akismet/admin.php @@ -0,0 +1,925 @@ +

    '.sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) .' '.sprintf(__('Please upgrade WordPress to a current version, or downgrade to version 2.4 of the Akismet plugin.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). '

    + '; + } + add_action('admin_notices', 'akismet_version_warning'); + + return; + } + + if ( function_exists( 'get_plugin_page_hook' ) ) + $hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' ); + else + $hook = 'dashboard_page_akismet-stats-display'; + add_meta_box('akismet-status', __('Comment History'), 'akismet_comment_status_meta_box', 'comment', 'normal'); +} +add_action('admin_init', 'akismet_admin_init'); + +add_action( 'admin_enqueue_scripts', 'akismet_load_js_and_css' ); +function akismet_load_js_and_css() { + global $hook_suffix; + + 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.9' ); + wp_enqueue_style( 'akismet.css'); + + wp_register_script( 'akismet.js', AKISMET_PLUGIN_URL . 'akismet.js', array('jquery'), '2.5.9' ); + wp_enqueue_script( 'akismet.js' ); + wp_localize_script( 'akismet.js', 'WPAkismet', array( + 'comment_author_url_nonce' => wp_create_nonce( 'comment_author_url_nonce' ) + ) ); + } +} + + +function akismet_nonce_field($action = -1) { return wp_nonce_field($action); } +$akismet_nonce = 'akismet-update-key'; + +function akismet_plugin_action_links( $links, $file ) { + if ( $file == plugin_basename( dirname(__FILE__).'/akismet.php' ) ) { + $links[] = ''.__( 'Settings' ).''; + } + + return $links; +} + +add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 ); + +function akismet_conf() { + global $akismet_nonce, $current_user; + + $new_key_link = 'https://akismet.com/get/'; + $config_link = esc_url( add_query_arg( array( 'page' => 'akismet-key-config', 'show' => 'enter-api-key' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'plugins.php' ) ) ); + $stats_link = esc_url( add_query_arg( array( 'page' => 'akismet-stats-display' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'index.php' ) ) ); + $api_key = akismet_get_key(); + $show_key_form = $api_key; + $key_status = 'empty'; + $saved_ok = false; + $key_status_text = ''; + + $ms = array(); + + if ( isset( $_POST['submit'] ) ) { + if ( function_exists('current_user_can') && !current_user_can('manage_options') ) + die(__('Cheatin’ uh?')); + + $show_key_form = true; + + check_admin_referer( $akismet_nonce ); + $key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] ); + $home_url = parse_url( get_bloginfo('url') ); + + if ( empty( $home_url['host'] ) ) + $ms[] = 'bad_home_url'; + + 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 != $api_key && $key_status == 'valid' ) { + $ms[] = 'new_key_valid'; + update_option('wordpress_api_key', $key); + } + elseif ( $key_status == 'invalid' ) + $ms[] = 'new_key_invalid'; + 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' ); + else + update_option( 'akismet_discard_month', 'false' ); + + if ( isset( $_POST['akismet_show_user_comments_approved'] ) ) + 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'] ) ) { + $show_key_form = true; + check_admin_referer( $akismet_nonce ); + akismet_get_server_connectivity(0); + } + elseif ( isset( $_GET['show'] ) && $_GET['show'] == 'enter-api-key' ) { + $show_key_form = true; + } + + 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 ( !isset( $_POST['submit'] ) ) { + if ( $key_status == 'invalid' ) + $ms[] = 'key_invalid'; + elseif ( !empty( $key ) && $key_status == 'failed' ) + $ms[] = 'key_failed'; + } + } + + $key_status_strings = array( + 'empty' => __( 'Empty' ), + 'valid' => __( 'Valid' ), + 'invalid' => __( 'Invalid' ), + 'failed' => __( 'Failed' ), + ); + + $messages = array( + '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 home option.'), esc_html( get_bloginfo('url') ), admin_url('options.php#home') ) ) + ); +?> + + +
    + +

    + +

    Stats' ), $stats_link ); ?>

    + +
    +

    +
    + + + + +
    +
    + +
    +
    + +

    + + +

    Sign up success! Please check your email for your Akismet API Key and enter it below.') ?>

    + + +

    + +
    + + + + + + + + + + + + + +
    +
    +

    create one here'), '#' );?>

    +
    +
    +
    + +
    +
    + +

    + +

    +
    + + +

    +
    + + + + + + + + + + + + + + + + +
    + +

    +

    fsockopen or gethostbynamel functions. Akismet cannot work correctly until this is fixed. Please contact your web host or firewall administrator and give them this information about Akismet\'s system requirements.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?>

    + 0 ) { + if ( $fail_count > 0 && $fail_count < count( $servers ) ) { // some connections work, some fail ?> +

    +

    this information about Akismet and firewalls.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?>

    + 0 ) { // all connections fail ?> +

    +

    Akismet cannot work correctly until this is fixed. Please contact your web host or firewall administrator and give them this information about Akismet and firewalls.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?>

    + +

    +

    + +

    +

    Akismet cannot work correctly until this is fixed. Please contact your web host or firewall administrator and give them this information about Akismet and firewalls.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?>

    + +
    + + + + + + $status ) : ?> + + + + + + +
    +
    + +
    +

    +

    clicking here.'), 'http://status.automattic.com/9931/136079/Akismet-API' ); ?>

    +
    + +
    + +
    +
    + 'akismet-key-config' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'plugins.php' ) ) );?> + +
    +

    enter your Akismet API key for it to work.' ), $config_link );?>

    + +
    ' . _x( 'Spam', 'comments' ) . ''; + global $submenu; + if ( isset( $submenu['edit-comments.php'] ) ) + $link = 'edit-comments.php'; + else + $link = 'edit.php'; + echo '

    '.sprintf( _n( 'Akismet has protected your site from %3$s spam comments.', 'Akismet has protected your site from %3$s spam comments.', $count ), 'http://akismet.com/?return=true', clean_url("$link?page=akismet-admin"), number_format_i18n($count) ).'

    '; +} +add_action('activity_box_end', 'akismet_stats'); + +function akismet_admin_warnings() { + global $wpcom_api_key, $pagenow; + + if ( + $pagenow == 'edit-comments.php' + || ( !empty( $_GET['page'] ) && $_GET['page'] == 'akismet-key-config' ) + || ( !empty( $_GET['page'] ) && $_GET['page'] == 'akismet-stats-display' ) + ) { + if ( get_option( 'akismet_alert_code' ) ) { + function akismet_alert() { + $alert = array( + 'code' => (int) get_option( 'akismet_alert_code' ), + 'msg' => get_option( 'akismet_alert_msg' ) + ); + ?> +
    +

    :

    +

    +

    %s' , 'https://akismet.com/errors/'.$alert['code'], 'https://akismet.com/errors/'.$alert['code'] );?> +

    +
    + + +
    + + + +
    +
    A
    +
    +
    +
    '.__('Activate your Akismet account').'
    +
    +
    +
    '.__('Almost done - activate your account and say goodbye to comment spam').'
    +
    +
    + + '; + } + } + + 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') ) { + function akismet_warning() { + global $wpdb; + akismet_fix_scheduled_recheck(); + $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 ' +

    '.__('Akismet has detected a problem.').' '.sprintf(__('Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation. Please check your Akismet configuration and contact your web host if problems persist.'), 'admin.php?page=akismet-key-config').'

    + '; + } + add_action('admin_notices', 'akismet_warning'); + return; + } +} + +// FIXME placeholder + +function akismet_comment_row_action( $a, $comment ) { + + // failsafe for old WP versions + if ( !function_exists('add_comment_meta') ) + 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); + $comment_status = wp_get_comment_status( $comment->comment_ID ); + $desc = null; + if ( $akismet_error ) { + $desc = __( 'Awaiting spam check' ); + } elseif ( !$user_result || $user_result == $akismet_result ) { + // Show the original Akismet result if the user hasn't overridden it, or if their decision was the same + if ( $akismet_result == 'true' && $comment_status != 'spam' && $comment_status != 'trash' ) + $desc = __( 'Flagged as spam by Akismet' ); + elseif ( $akismet_result == 'false' && $comment_status == 'spam' ) + $desc = __( 'Cleared by Akismet' ); + } else { + $who = get_comment_meta( $comment->comment_ID, 'akismet_user', true ); + if ( $user_result == 'true' ) + $desc = sprintf( __('Flagged as spam by %s'), $who ); + else + $desc = sprintf( __('Un-spammed by %s'), $who ); + } + + // add a History item to the hover links, just after Edit + if ( $akismet_result ) { + $b = array(); + foreach ( $a as $k => $item ) { + $b[ $k ] = $item; + if ( + $k == 'edit' + || ( $k == 'unspam' && $GLOBALS['wp_version'] >= 3.4 ) + ) { + $b['history'] = ' '. __('History') . ''; + } + } + + $a = $b; + } + + if ( $desc ) + echo ''.esc_html( $desc ).''; + + 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 ); + $comment_count = intval( $comment_count ); + echo ''; + } + + return $a; +} + +add_filter( 'comment_row_actions', 'akismet_comment_row_action', 10, 2 ); + +function akismet_comment_status_meta_box($comment) { + $history = akismet_get_comment_history( $comment->comment_ID ); + + if ( $history ) { + echo '
    '; + foreach ( $history as $row ) { + $time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT'; + echo '
    ' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . ' - '; + echo esc_html( $row['message'] ) . '
    '; + } + + echo '
    '; + + } +} + + +// add an extra column header to the comments screen +function akismet_comments_columns( $columns ) { + $columns[ 'akismet' ] = __( 'Akismet' ); + return $columns; +} + +#add_filter( 'manage_edit-comments_columns', 'akismet_comments_columns' ); + +// Show stuff in the extra column +function akismet_comment_column_row( $column, $comment_id ) { + if ( $column != 'akismet' ) + return; + + $history = akismet_get_comment_history( $comment_id ); + + if ( $history ) { + echo '
    '; + foreach ( $history as $row ) { + echo '
    ' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '
    '; + echo '
    ' . esc_html( $row['message'] ) . '
    '; + } + + echo '
    '; + } +} + +#add_action( 'manage_comments_custom_column', 'akismet_comment_column_row', 10, 2 ); + +// END FIXME + +// call out URLS in comments +function akismet_text_add_link_callback( $m ) { + // bare link? + if ( $m[4] == $m[2] ) + return ''.$m[4].''; + else + return ''.$m[4].''; +} + +function akismet_text_add_link_class( $comment_text ) { + return preg_replace_callback( '#]*)href="([^"]+)"([^>]*)>(.*?)#i', 'akismet_text_add_link_callback', $comment_text ); +} + +add_filter('comment_text', 'akismet_text_add_link_class'); + + +// WP 2.5+ +function akismet_rightnow() { + global $submenu, $wp_db_version; + + if ( 8645 < $wp_db_version ) // 2.7 + $link = 'edit-comments.php?comment_status=spam'; + elseif ( isset( $submenu['edit-comments.php'] ) ) + $link = 'edit-comments.php?page=akismet-admin'; + else + $link = 'edit.php?page=akismet-admin'; + + if ( $count = get_option('akismet_spam_count') ) { + $intro = sprintf( _n( + 'Akismet has protected your site from %2$s spam comment already. ', + 'Akismet has protected your site from %2$s spam comments already. ', + $count + ), 'http://akismet.com/?return=true', number_format_i18n( $count ) ); + } else { + $intro = sprintf( __('Akismet blocks spam from getting to your blog. '), 'http://akismet.com/?return=true' ); + } + + $link = function_exists( 'esc_url' ) ? esc_url( $link ) : clean_url( $link ); + if ( $queue_count = akismet_spam_count() ) { + $queue_text = sprintf( _n( + 'There\'s %1$s comment in your spam queue right now.', + 'There are %1$s comments in your spam queue right now.', + $queue_count + ), number_format_i18n( $queue_count ), $link ); + } else { + $queue_text = sprintf( __( "There's nothing in your spam queue at the moment." ), $link ); + } + + $text = $intro . '
    ' . $queue_text; + echo "

    $text

    \n"; +} + +add_action('rightnow_end', 'akismet_rightnow'); + + +// For WP >= 2.5 +function akismet_check_for_spam_button($comment_status) { + if ( 'approved' == $comment_status ) + return; + if ( function_exists('plugins_url') ) + $link = 'admin.php?action=akismet_recheck_queue'; + else + $link = 'edit-comments.php?page=akismet-admin&recheckqueue=true&noheader=true'; + echo "
    " . __('Check for Spam') . ""; +} +add_action('manage_comments_nav', 'akismet_check_for_spam_button'); + +function akismet_submit_nonspam_comment ( $comment_id ) { + global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site; + $comment_id = (int) $comment_id; + + $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'"); + if ( !$comment ) // it was deleted + return; + + // use the original version stored in comment_meta if available + $as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true); + if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) { + $comment = (object) array_merge( (array)$comment, $as_submitted ); + } + + $comment->blog = get_bloginfo('url'); + $comment->blog_lang = get_locale(); + $comment->blog_charset = get_option('blog_charset'); + $comment->permalink = get_permalink($comment->comment_post_ID); + if ( is_object($current_user) ) { + $comment->reporter = $current_user->user_login; + } + if ( is_object($current_site) ) { + $comment->site_domain = $current_site->domain; + } + + $comment->user_role = ''; + if ( isset( $comment->user_ID ) ) + $comment->user_role = akismet_get_user_roles($comment->user_ID); + + if ( akismet_test_mode() ) + $comment->is_test = 'true'; + + $post = get_post( $comment->comment_post_ID ); + $comment->comment_post_modified_gmt = $post->post_modified_gmt; + + $query_string = ''; + foreach ( $comment as $key => $data ) + $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&'; + + $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-ham", $akismet_api_port); + if ( $comment->reporter ) { + akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as not spam'), $comment->reporter ), 'report-ham' ); + update_comment_meta( $comment_id, 'akismet_user_result', 'false' ); + update_comment_meta( $comment_id, 'akismet_user', $comment->reporter ); + } + + do_action('akismet_submit_nonspam_comment', $comment_id, $response[1]); +} + +function akismet_submit_spam_comment ( $comment_id ) { + global $wpdb, $akismet_api_host, $akismet_api_port, $current_user, $current_site; + $comment_id = (int) $comment_id; + + $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = '$comment_id'"); + if ( !$comment ) // it was deleted + return; + if ( 'spam' != $comment->comment_approved ) + return; + + // use the original version stored in comment_meta if available + $as_submitted = get_comment_meta( $comment_id, 'akismet_as_submitted', true); + if ( $as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content']) ) { + $comment = (object) array_merge( (array)$comment, $as_submitted ); + } + + $comment->blog = get_bloginfo('url'); + $comment->blog_lang = get_locale(); + $comment->blog_charset = get_option('blog_charset'); + $comment->permalink = get_permalink($comment->comment_post_ID); + if ( is_object($current_user) ) { + $comment->reporter = $current_user->user_login; + } + if ( is_object($current_site) ) { + $comment->site_domain = $current_site->domain; + } + + $comment->user_role = ''; + if ( isset( $comment->user_ID ) ) + $comment->user_role = akismet_get_user_roles($comment->user_ID); + + if ( akismet_test_mode() ) + $comment->is_test = 'true'; + + $post = get_post( $comment->comment_post_ID ); + $comment->comment_post_modified_gmt = $post->post_modified_gmt; + + $query_string = ''; + foreach ( $comment as $key => $data ) + $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&'; + + $response = akismet_http_post($query_string, $akismet_api_host, "/1.1/submit-spam", $akismet_api_port); + if ( $comment->reporter ) { + akismet_update_comment_history( $comment_id, sprintf( __('%s reported this comment as spam'), $comment->reporter ), 'report-spam' ); + update_comment_meta( $comment_id, 'akismet_user_result', 'true' ); + update_comment_meta( $comment_id, 'akismet_user', $comment->reporter ); + } + do_action('akismet_submit_spam_comment', $comment_id, $response[1]); +} + +// For WP 2.7+ +function akismet_transition_comment_status( $new_status, $old_status, $comment ) { + if ( $new_status == $old_status ) + return; + + # we don't need to record a history item for deleted comments + if ( $new_status == 'delete' ) + return; + + if ( !is_admin() ) + return; + + if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) && !current_user_can( 'moderate_comments' ) ) + return; + + if ( defined('WP_IMPORTING') && WP_IMPORTING == true ) + return; + + // if this is present, it means the status has been changed by a re-check, not an explicit user action + if ( get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) ) + return; + + global $current_user; + $reporter = ''; + if ( is_object( $current_user ) ) + $reporter = $current_user->user_login; + + // Assumption alert: + // We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status + // is changed automatically by another plugin. Unfortunately WordPress doesn't provide an unambiguous way to + // determine why the transition_comment_status action was triggered. And there are several different ways by which + // to spam and unspam comments: bulk actions, ajax, links in moderation emails, the dashboard, and perhaps others. + // We'll assume that this is an explicit user action if POST or GET has an 'action' key. + if ( isset($_POST['action']) || isset($_GET['action']) ) { + if ( $new_status == 'spam' && ( $old_status == 'approved' || $old_status == 'unapproved' || !$old_status ) ) { + return akismet_submit_spam_comment( $comment->comment_ID ); + } elseif ( $old_status == 'spam' && ( $new_status == 'approved' || $new_status == 'unapproved' ) ) { + return akismet_submit_nonspam_comment( $comment->comment_ID ); + } + } + + akismet_update_comment_history( $comment->comment_ID, sprintf( __('%s changed the comment status to %s'), $reporter, $new_status ), 'status-' . $new_status ); +} + +add_action( 'transition_comment_status', 'akismet_transition_comment_status', 10, 3 ); + +// Total spam in queue +// get_option( 'akismet_spam_count' ) is the total caught ever +function akismet_spam_count( $type = false ) { + global $wpdb; + + if ( !$type ) { // total + $count = wp_cache_get( 'akismet_spam_count', 'widget' ); + if ( false === $count ) { + if ( function_exists('wp_count_comments') ) { + $count = wp_count_comments(); + $count = $count->spam; + } else { + $count = (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam'"); + } + wp_cache_set( 'akismet_spam_count', $count, 'widget', 3600 ); + } + return $count; + } elseif ( 'comments' == $type || 'comment' == $type ) { // comments + $type = ''; + } else { // pingback, trackback, ... + $type = $wpdb->escape( $type ); + } + + return (int) $wpdb->get_var("SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type'"); +} + + +function akismet_recheck_queue() { + global $wpdb, $akismet_api_host, $akismet_api_port; + + akismet_fix_scheduled_recheck(); + + if ( ! ( isset( $_GET['recheckqueue'] ) || ( isset( $_REQUEST['action'] ) && 'akismet_recheck_queue' == $_REQUEST['action'] ) ) ) + return; + + $moderation = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = '0'", ARRAY_A ); + foreach ( (array) $moderation as $c ) { + $c['user_ip'] = $c['comment_author_IP']; + $c['user_agent'] = $c['comment_agent']; + $c['referrer'] = ''; + $c['blog'] = get_bloginfo('url'); + $c['blog_lang'] = get_locale(); + $c['blog_charset'] = get_option('blog_charset'); + $c['permalink'] = get_permalink($c['comment_post_ID']); + + $c['user_role'] = ''; + if ( isset( $c['user_ID'] ) ) + $c['user_role'] = akismet_get_user_roles($c['user_ID']); + + if ( akismet_test_mode() ) + $c['is_test'] = 'true'; + + $id = (int) $c['comment_ID']; + + $query_string = ''; + foreach ( $c as $key => $data ) + $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&'; + + add_comment_meta( $c['comment_ID'], 'akismet_rechecking', true ); + $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port); + if ( 'true' == $response[1] ) { + wp_set_comment_status($c['comment_ID'], 'spam'); + update_comment_meta( $c['comment_ID'], 'akismet_result', 'true' ); + delete_comment_meta( $c['comment_ID'], 'akismet_error' ); + akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and caught this comment as spam'), 'check-spam' ); + + } elseif ( 'false' == $response[1] ) { + update_comment_meta( $c['comment_ID'], 'akismet_result', 'false' ); + delete_comment_meta( $c['comment_ID'], 'akismet_error' ); + akismet_update_comment_history( $c['comment_ID'], __('Akismet re-checked and cleared this comment'), 'check-ham' ); + // abnormal result: error + } else { + update_comment_meta( $c['comment_ID'], 'akismet_result', 'error' ); + akismet_update_comment_history( $c['comment_ID'], sprintf( __('Akismet was unable to re-check this comment (response: %s)'), substr($response[1], 0, 50)), 'check-error' ); + } + + delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' ); + } + $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' ); + wp_safe_redirect( $redirect_to ); + exit; +} + +add_action('admin_action_akismet_recheck_queue', 'akismet_recheck_queue'); + +// Adds an 'x' link next to author URLs, clicking will remove the author URL and show an undo link +function akismet_remove_comment_author_url() { + if ( !empty($_POST['id'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) { + global $wpdb; + $comment = get_comment( intval($_POST['id']), ARRAY_A ); + if (current_user_can('edit_comment', $comment['comment_ID'])) { + $comment['comment_author_url'] = ''; + do_action( 'comment_remove_author_url' ); + print(wp_update_comment( $comment )); + die(); + } + } +} + +add_action('wp_ajax_comment_author_deurl', 'akismet_remove_comment_author_url'); + +function akismet_add_comment_author_url() { + if ( !empty( $_POST['id'] ) && !empty( $_POST['url'] ) && check_admin_referer( 'comment_author_url_nonce' ) ) { + global $wpdb; + $comment = get_comment( intval($_POST['id']), ARRAY_A ); + if (current_user_can('edit_comment', $comment['comment_ID'])) { + $comment['comment_author_url'] = esc_url($_POST['url']); + do_action( 'comment_add_author_url' ); + print(wp_update_comment( $comment )); + die(); + } + } +} + +add_action('wp_ajax_comment_author_reurl', 'akismet_add_comment_author_url'); + +// Check connectivity between the WordPress blog and Akismet's servers. +// Returns an associative array of server IP addresses, where the key is the IP address, and value is true (available) or false (unable to connect). +function akismet_check_server_connectivity() { + global $akismet_api_host, $akismet_api_port, $wpcom_api_key; + + $test_host = 'rest.akismet.com'; + + // Some web hosts may disable one or both functions + if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) + return array(); + + $ips = gethostbynamel($test_host); + if ( !$ips || !is_array($ips) || !count($ips) ) + return array(); + + $servers = array(); + foreach ( $ips as $ip ) { + $response = akismet_verify_key( akismet_get_key(), $ip ); + // even if the key is invalid, at least we know we have connectivity + if ( $response == 'valid' || $response == 'invalid' ) + $servers[$ip] = true; + else + $servers[$ip] = false; + } + + return $servers; +} + +// Check the server connectivity and store the results in an option. +// Cached results will be used if not older than the specified timeout in seconds; use $cache_timeout = 0 to force an update. +// Returns the same associative array as akismet_check_server_connectivity() +function akismet_get_server_connectivity( $cache_timeout = 86400 ) { + $servers = get_option('akismet_available_servers'); + if ( (time() - get_option('akismet_connectivity_time') < $cache_timeout) && $servers !== false ) + return $servers; + + // There's a race condition here but the effect is harmless. + $servers = akismet_check_server_connectivity(); + update_option('akismet_available_servers', $servers); + update_option('akismet_connectivity_time', time()); + return $servers; +} + +// Returns true if server connectivity was OK at the last check, false if there was a problem that needs to be fixed. +function akismet_server_connectivity_ok() { + // skip the check on WPMU because the status page is hidden + global $wpcom_api_key; + if ( $wpcom_api_key ) + return true; + $servers = akismet_get_server_connectivity(); + return !( empty($servers) || !count($servers) || count( array_filter($servers) ) < count($servers) ); +} + +function akismet_admin_menu() { + if ( class_exists( 'Jetpack' ) ) { + add_action( 'jetpack_admin_menu', 'akismet_load_menu' ); + } else { + akismet_load_menu(); + } +} + +function akismet_load_menu() { + if ( class_exists( 'Jetpack' ) ) { + 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'), __('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/sources/wp-content/plugins/akismet/akismet.css b/sources/wp-content/plugins/akismet/akismet.css new file mode 100644 index 0000000..e96bc8a --- /dev/null +++ b/sources/wp-content/plugins/akismet/akismet.css @@ -0,0 +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}.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;-webkit-border-radius:0px} \ No newline at end of file diff --git a/sources/wp-content/plugins/akismet/akismet.gif b/sources/wp-content/plugins/akismet/akismet.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b93a89b9a0f089342cecaf4deaef48382523d03 GIT binary patch literal 2777 zcmd^;`9Bj31HdQ4Ts=<*DM!dFx6;8gL{i0M7_vVie=xFO=u_EPd?_QQgdSZy9ETZAt7NC(r&4gtWE?XQJ05`=NWhMV zK)3eBY?S1{8EtQ6c-DxQ^8KAHSqe_nrR zZeM!UbW-_5IC3B?kCIR}9**pf$1tLcXrD^QK9w?{1w*kVBa!(-X#_U3fErUwPbeFU z%pZ&`p~quJqY7z3S=}+k!_h^M0Am<3qgpk{r&xn>KRzo40)KFQ9b+n_wSvZ zoz2b7t*xyL;%wJ2HxS;%;c$37-pa~K3U-*w-pC5(IkT#Q_9)N^jmM;_!p=Bgr7!q) zb!>@TxYu`zq-Z^9RPR8Zkm2Sv&S;6}PUFMW9-YeyLG z3)$mLU3=!vvv7I&AKpMTtiOux=)3k_9PXG3a@k6shJ@%tazcKco(R4D;<^er>UB2 z^06_GrzuK{BzCGjyZ{Z?ct7$&00B~GL1wY>B~ZxKpCuVqcY@AkK3a}{0e6BkXAnZu z*iw|0u|QnbIRd@NMM6jYS+ox%NGa2{cjp;0V4`WRL}(q{j?Qv+Y{$Fa0^GFS==2CRF+hOxOF1OyL0uP>cNhmG5+^CAZl9O|;9DC~w7D3>P-o_CJ z9JzSyX$}05AzOpMvTJ!c?UyH!tY;WmQ*%oeUkkS9zLwy1Xm+-&-Rj^* zcf2&i6<0tYuk*X~5|?Wlh}`8bt3QlaTEs6eR(0yO06>+AM>Wqk?kn%<;;N70biOPp zJof1j)BVl+b*!|zldNgTe5cyt?0{=LQ0;pAlN07$MH+&6^MCzODtEC<`-^vN{{z#) z_JLSl&PCK!5iQ?d3bfm=Z&gQ2kYXZ!Z@u5eFl~L{xh}GO#KWB_QYoAJQHLtDqDAa8 z^7|S=(G8KmIsic&`UH%+4=Oe?4Np272qJl&%WYDe>)L(q2faRYI&;4^&_nkm1DR2S zF56QQ(K^8#gU^;Cm9^It^rl6d4Btaew7fQNqxemh|# zQrYB;H=dSYNPd}dJ^#dTq+#wLXr=hjxtZ5_YUReNar7TRi3_}TE+21k5Im#Rce8#n zTySD%&d^1-d2{T;VdyF=_5RHrIZy!rOo_V7^9;err<=%xo)qvK*Sj$lD;e8!b&KhD!k_g)Wx0O9oVlC;_L014x~c zW6U^xU%|@5qMyc+HgCeTzM;fjWjYUbR>H5SxQO_bbt)|X8E=#qDeayXp%eV}cnc9J zmJVu`w!9E{@pIv}hs<|b>tlkp(@N3}Ww&)l`xCE_o+PH)(?pT1Qc ztN%?&ip}W+53Htq7-B2zlnDau`7p$LU}bmX4KYlA+UX$|;=4 zM~e9lq4m8N}H@=Z>|>}N2-b2lA!{P>u5m=u<}6E)a{)O47krR@c~=IY%>aV46uJa3_b!U zoWz*|vD0)6fzGh2=O99>e7aT=$X{wjokHp{emJ6JLG`abg1YA*f zZa+h7)u_WoN@=-LJ?WjQn>EtB2#>p(jut!(xRTVo;W>-@Ewfk9nRSbRgB*vGhu-j- zSRo%b^Dc(+Hm%_fh~P_Y(oQ`rpT4kQv`t7ips3n!?(Q)r#q1j8NrZp~h5*aW z&rEZw{P|ai1DqUCpXI;oCrWV`R}N?{!t3}}dI6V58wCF*y$M6KJv~^6v{QRT2-4oO zYb)PsTJqNoxuH0zOlfG{q7uS37?TIP%nq4eo^te1K4#jrEmYh0<#5*o2Xd-a67wdy z!EkEdHc<3*%Eef;G5d@~yO=G{)Z4f=*5vZ6DB=n?{#c&VR;=`Q{-f1|8it!{i_8zb zl~{yUdTTNI zKJ)5q;w(7p!x4haMF~E84PRbU@MK&VaUKKPW=Q^j%tG>xNrv)!E3r4)N#A zZ@4}{gq!Rhon%>0MD#4aG~64Zgaw=iDgyLE1WbYR=4W_T!T_s12J>h`x'); + } + }); + jQuery('.remove_url').live('click', function () { + var thisId = jQuery(this).attr('commentid'); + var data = { + action: 'comment_author_deurl', + _wpnonce: WPAkismet.comment_author_url_nonce, + id: thisId + }; + jQuery.ajax({ + url: ajaxurl, + type: 'POST', + data: data, + beforeSend: function () { + // Removes "x" link + jQuery("a[commentid='"+ thisId +"']").hide(); + // Show temp status + jQuery("#author_comment_url_"+ thisId).html('Removing...'); + }, + success: function (response) { + if (response) { + // Show status/undo link + jQuery("#author_comment_url_"+ thisId).attr('cid', thisId).addClass('akismet_undo_link_removal').html('URL removed (undo)'); + } + } + }); + + return false; + }); + jQuery('.akismet_undo_link_removal').live('click', function () { + var thisId = jQuery(this).attr('cid'); + var thisUrl = jQuery(this).attr('href').replace("http://www.", "").replace("http://", ""); + var data = { + action: 'comment_author_reurl', + _wpnonce: WPAkismet.comment_author_url_nonce, + id: thisId, + url: thisUrl + }; + jQuery.ajax({ + url: ajaxurl, + type: 'POST', + data: data, + beforeSend: function () { + // Show temp status + jQuery("#author_comment_url_"+ thisId).html('Re-adding…'); + }, + success: function (response) { + if (response) { + // Add "x" link + jQuery("a[commentid='"+ thisId +"']").show(); + // Show link + jQuery("#author_comment_url_"+ thisId).removeClass('akismet_undo_link_removal').html(thisUrl); + } + } + }); + + 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 + thisParentWidth = (jQuery(this).parent().find('.grav-hijack').length) ? thisParentWidth - 42 + 'px' : thisParentWidth + 'px'; + if (jQuery(this).find('.mShot').length == 0 && !jQuery(this).hasClass('akismet_undo_link_removal')) { + var thisId = jQuery(this).attr('id').replace('author_comment_url_', ''); + jQuery('.widefat td').css('overflow', 'visible'); + jQuery(this).css('position', 'relative'); + var thisHref = jQuery.URLEncode(jQuery(this).attr('href')); + jQuery(this).append('
    '); + setTimeout(function () { + 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', wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=3'); + }, 12000); + } else { + jQuery(this).find('.mShot').css('left', thisParentWidth).show(); + } + }).mouseout(function () { + jQuery(this).find('.mShot').hide(); + }); +}); +// URL encode plugin +jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/; + while(x1 && m[1]!=''){o+=m[1];x+=m[1].length; + }else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16); + o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;} +}); +// 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(wpcomProtocol+'s0.wordpress.com/mshots/v1/'+jQuery.URLEncode(jQuery(this).attr('href'))+'?w=450'); + }); +}); diff --git a/sources/wp-content/plugins/akismet/akismet.php b/sources/wp-content/plugins/akismet/akismet.php new file mode 100644 index 0000000..919ea0e --- /dev/null +++ b/sources/wp-content/plugins/akismet/akismet.php @@ -0,0 +1,613 @@ +protect your blog from comment and trackback spam
    . 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) Sign up for an Akismet API key, and 3) Go to your Akismet configuration page, and save your API key. +Version: 2.5.9 +Author: Automattic +Author URI: http://automattic.com/wordpress-plugins/ +License: GPLv2 or later +*/ + +/* +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// 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.9'); +define('AKISMET_PLUGIN_URL', plugin_dir_url( __FILE__ )); + +/** If you hardcode a WP.com API key here, all key config screens will be hidden */ +if ( defined('WPCOM_API_KEY') ) + $wpcom_api_key = constant('WPCOM_API_KEY'); +else + $wpcom_api_key = ''; + +if ( isset($wp_db_version) && $wp_db_version <= 9872 ) + include_once dirname( __FILE__ ) . '/legacy.php'; + +include_once dirname( __FILE__ ) . '/widget.php'; + +if ( is_admin() ) + require_once dirname( __FILE__ ) . '/admin.php'; + +function akismet_init() { + global $wpcom_api_key, $akismet_api_host, $akismet_api_port; + + if ( $wpcom_api_key ) + $akismet_api_host = $wpcom_api_key . '.rest.akismet.com'; + else + $akismet_api_host = get_option('wordpress_api_key') . '.rest.akismet.com'; + + $akismet_api_port = 80; +} +add_action('init', 'akismet_init'); + +function akismet_get_key() { + global $wpcom_api_key; + if ( !empty($wpcom_api_key) ) + return $wpcom_api_key; + return get_option('wordpress_api_key'); +} + +function akismet_check_key_status( $key, $ip = null ) { + global $akismet_api_host, $akismet_api_port, $wpcom_api_key; + $blog = urlencode( get_option('home') ); + if ( $wpcom_api_key ) + $key = $wpcom_api_key; + $response = akismet_http_post("key=$key&blog=$blog", 'rest.akismet.com', '/1.1/verify-key', $akismet_api_port, $ip); + return $response; +} + +// given a response from an API call like akismet_check_key_status(), update the alert code options if an alert is present. +function akismet_update_alert( $response ) { + $code = $msg = null; + if ( isset($response[0]['x-akismet-alert-code']) ) { + $code = $response[0]['x-akismet-alert-code']; + $msg = $response[0]['x-akismet-alert-msg']; + } + + // only call update_option() if the value has changed + if ( $code != get_option( 'akismet_alert_code' ) ) { + update_option( 'akismet_alert_code', $code ); + update_option( 'akismet_alert_msg', $msg ); + } +} + +function akismet_verify_key( $key, $ip = null ) { + $response = akismet_check_key_status( $key, $ip ); + akismet_update_alert( $response ); + if ( !is_array($response) || !isset($response[1]) || $response[1] != 'valid' && $response[1] != 'invalid' ) + return 'failed'; + return $response[1]; +} + +// if we're in debug or test modes, use a reduced service level so as not to polute training or stats data +function akismet_test_mode() { + if ( defined('AKISMET_TEST_MODE') && AKISMET_TEST_MODE ) + return true; + return false; +} + +// return a comma-separated list of role names for the given user +function akismet_get_user_roles( $user_id ) { + $roles = false; + + if ( !class_exists('WP_User') ) + return false; + + if ( $user_id > 0 ) { + $comment_user = new WP_User($user_id); + if ( isset($comment_user->roles) ) + $roles = join(',', $comment_user->roles); + } + + if ( is_multisite() && is_super_admin( $user_id ) ) { + if ( empty( $roles ) ) { + $roles = 'super_admin'; + } else { + $comment_user->roles[] = 'super_admin'; + $roles = join( ',', $comment_user->roles ); + } + } + + return $roles; +} + +// Returns array with headers in $response[0] and body in $response[1] +function akismet_http_post($request, $host, $path, $port = 80, $ip=null) { + global $wp_version; + + $akismet_ua = "WordPress/{$wp_version} | "; + $akismet_ua .= 'Akismet/' . constant( 'AKISMET_VERSION' ); + + $akismet_ua = apply_filters( 'akismet_ua', $akismet_ua ); + + $content_length = strlen( $request ); + + $http_host = $host; + // use a specific IP if provided + // needed by akismet_check_server_connectivity() + if ( $ip && long2ip( ip2long( $ip ) ) ) { + $http_host = $ip; + } else { + $http_host = $host; + } + + // use the WP HTTP class if it is available + if ( function_exists( 'wp_remote_post' ) ) { + $http_args = array( + 'body' => $request, + 'headers' => array( + 'Content-Type' => 'application/x-www-form-urlencoded; ' . + 'charset=' . get_option( 'blog_charset' ), + 'Host' => $host, + 'User-Agent' => $akismet_ua + ), + 'httpversion' => '1.0', + 'timeout' => 15 + ); + $akismet_url = "http://{$http_host}{$path}"; + $response = wp_remote_post( $akismet_url, $http_args ); + if ( is_wp_error( $response ) ) + return ''; + + return array( $response['headers'], $response['body'] ); + } else { + $http_request = "POST $path HTTP/1.0\r\n"; + $http_request .= "Host: $host\r\n"; + $http_request .= 'Content-Type: application/x-www-form-urlencoded; charset=' . get_option('blog_charset') . "\r\n"; + $http_request .= "Content-Length: {$content_length}\r\n"; + $http_request .= "User-Agent: {$akismet_ua}\r\n"; + $http_request .= "\r\n"; + $http_request .= $request; + + $response = ''; + if( false != ( $fs = @fsockopen( $http_host, $port, $errno, $errstr, 10 ) ) ) { + fwrite( $fs, $http_request ); + + while ( !feof( $fs ) ) + $response .= fgets( $fs, 1160 ); // One TCP-IP packet + fclose( $fs ); + $response = explode( "\r\n\r\n", $response, 2 ); + } + return $response; + } +} + +// filter handler used to return a spam result to pre_comment_approved +function akismet_result_spam( $approved ) { + // bump the counter here instead of when the filter is added to reduce the possibility of overcounting + if ( $incr = apply_filters('akismet_spam_count_incr', 1) ) + update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr ); + // this is a one-shot deal + remove_filter( 'pre_comment_approved', 'akismet_result_spam' ); + return 'spam'; +} + +function akismet_result_hold( $approved ) { + // once only + remove_filter( 'pre_comment_approved', 'akismet_result_hold' ); + return '0'; +} + +// how many approved comments does this author have? +function akismet_get_user_comments_approved( $user_id, $comment_author_email, $comment_author, $comment_author_url ) { + global $wpdb; + + if ( !empty($user_id) ) + return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->comments WHERE user_id = %d AND comment_approved = 1", $user_id ) ); + + if ( !empty($comment_author_email) ) + return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_author_email = %s AND comment_author = %s AND comment_author_url = %s AND comment_approved = 1", $comment_author_email, $comment_author, $comment_author_url ) ); + + return 0; +} + +function akismet_microtime() { + $mtime = explode( ' ', microtime() ); + return $mtime[1] + $mtime[0]; +} + +// log an event for a given comment, storing it in comment_meta +function akismet_update_comment_history( $comment_id, $message, $event=null ) { + global $current_user; + + // failsafe for old WP versions + if ( !function_exists('add_comment_meta') ) + return false; + + $user = ''; + if ( is_object($current_user) && isset($current_user->user_login) ) + $user = $current_user->user_login; + + $event = array( + 'time' => akismet_microtime(), + 'message' => $message, + 'event' => $event, + 'user' => $user, + ); + + // $unique = false so as to allow multiple values per comment + $r = add_comment_meta( $comment_id, 'akismet_history', $event, false ); +} + +// get the full comment history for a given comment, as an array in reverse chronological order +function akismet_get_comment_history( $comment_id ) { + + // failsafe for old WP versions + if ( !function_exists('add_comment_meta') ) + return false; + + $history = get_comment_meta( $comment_id, 'akismet_history', false ); + usort( $history, 'akismet_cmp_time' ); + return $history; +} + +function akismet_cmp_time( $a, $b ) { + return $a['time'] > $b['time'] ? -1 : 1; +} + +// this fires on wp_insert_comment. we can't update comment_meta when akismet_auto_check_comment() runs +// because we don't know the comment ID at that point. +function akismet_auto_check_update_meta( $id, $comment ) { + global $akismet_last_comment; + + // failsafe for old WP versions + 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 ( 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 + if ( $akismet_last_comment['akismet_result'] == 'true' ) { + update_comment_meta( $comment->comment_ID, 'akismet_result', 'true' ); + akismet_update_comment_history( $comment->comment_ID, __('Akismet caught this comment as spam'), 'check-spam' ); + if ( $comment->comment_approved != 'spam' ) + akismet_update_comment_history( $comment->comment_ID, sprintf( __('Comment status was changed to %s'), $comment->comment_approved), 'status-changed'.$comment->comment_approved ); + } elseif ( $akismet_last_comment['akismet_result'] == 'false' ) { + update_comment_meta( $comment->comment_ID, 'akismet_result', 'false' ); + akismet_update_comment_history( $comment->comment_ID, __('Akismet cleared this comment'), 'check-ham' ); + if ( $comment->comment_approved == 'spam' ) { + if ( wp_blacklist_check($comment->comment_author, $comment->comment_author_email, $comment->comment_author_url, $comment->comment_content, $comment->comment_author_IP, $comment->comment_agent) ) + akismet_update_comment_history( $comment->comment_ID, __('Comment was caught by wp_blacklist_check'), 'wp-blacklisted' ); + else + akismet_update_comment_history( $comment->comment_ID, sprintf( __('Comment status was changed to %s'), $comment->comment_approved), 'status-changed-'.$comment->comment_approved ); + } + // abnormal result: error + } else { + update_comment_meta( $comment->comment_ID, 'akismet_error', time() ); + akismet_update_comment_history( $comment->comment_ID, sprintf( __('Akismet was unable to check this comment (response: %s), will automatically retry again later.'), substr($akismet_last_comment['akismet_result'], 0, 50)), 'check-error' ); + } + + // record the complete original data as submitted for checking + if ( isset($akismet_last_comment['comment_as_submitted']) ) + update_comment_meta( $comment->comment_ID, 'akismet_as_submitted', $akismet_last_comment['comment_as_submitted'] ); + } + } +} + +add_action( 'wp_insert_comment', 'akismet_auto_check_update_meta', 10, 2 ); + + +function akismet_auto_check_comment( $commentdata ) { + global $akismet_api_host, $akismet_api_port, $akismet_last_comment; + + $comment = $commentdata; + $comment['user_ip'] = $_SERVER['REMOTE_ADDR']; + $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'] ); + } + + $akismet_nonce_option = apply_filters( 'akismet_comment_nonce', get_option( 'akismet_comment_nonce' ) ); + $comment['akismet_comment_nonce'] = 'inactive'; + if ( $akismet_nonce_option == 'true' || $akismet_nonce_option == '' ) { + $comment['akismet_comment_nonce'] = 'failed'; + if ( isset( $_POST['akismet_comment_nonce'] ) && wp_verify_nonce( $_POST['akismet_comment_nonce'], 'akismet_comment_nonce_' . $comment['comment_post_ID'] ) ) + $comment['akismet_comment_nonce'] = 'passed'; + + // comment reply in wp-admin + if ( isset( $_POST['_ajax_nonce-replyto-comment'] ) && check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' ) ) + $comment['akismet_comment_nonce'] = 'passed'; + + } + + if ( akismet_test_mode() ) + $comment['is_test'] = 'true'; + + foreach ($_POST as $key => $value ) { + if ( is_string($value) ) + $comment["POST_{$key}"] = $value; + } + + $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' ); + + foreach ( $_SERVER as $key => $value ) { + if ( !in_array( $key, $ignore ) && is_string($value) ) + $comment["$key"] = $value; + else + $comment["$key"] = ''; + } + + $post = get_post( $comment['comment_post_ID'] ); + $comment[ 'comment_post_modified_gmt' ] = $post->post_modified_gmt; + + $query_string = ''; + foreach ( $comment as $key => $data ) + $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&'; + + $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] ) { + // akismet_spam_count will be incremented later by akismet_result_spam() + add_filter('pre_comment_approved', 'akismet_result_spam'); + + do_action( 'akismet_spam_caught' ); + + $last_updated = strtotime( $post->post_modified_gmt ); + $diff = time() - $last_updated; + $diff = $diff / 86400; + + if ( $post->post_type == 'post' && $diff > 30 && get_option( 'akismet_discard_month' ) == 'true' && empty($comment['user_ID']) ) { + // 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 ); + $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : get_permalink( $post ); + wp_safe_redirect( $redirect_to ); + die(); + } + } + + // if the response is neither true nor false, hold the comment for moderation and schedule a recheck + if ( 'true' != $response[1] && 'false' != $response[1] ) { + if ( !current_user_can('moderate_comments') ) { + add_filter('pre_comment_approved', 'akismet_result_hold'); + } + if ( !wp_next_scheduled( 'akismet_schedule_cron_recheck' ) ) { + wp_schedule_single_event( time() + 1200, 'akismet_schedule_cron_recheck' ); + } + } + + if ( function_exists('wp_next_scheduled') && function_exists('wp_schedule_event') ) { + // WP 2.1+: delete old comments daily + if ( !wp_next_scheduled('akismet_scheduled_delete') ) + wp_schedule_event(time(), 'daily', 'akismet_scheduled_delete'); + } elseif ( (mt_rand(1, 10) == 3) ) { + // WP 2.0: run this one time in ten + akismet_delete_old(); + } + $akismet_last_comment = $commentdata; + + akismet_fix_scheduled_recheck(); + return $commentdata; +} + +add_action('preprocess_comment', 'akismet_auto_check_comment', 1); + +function akismet_delete_old() { + global $wpdb; + $now_gmt = current_time('mysql', 1); + $comment_ids = $wpdb->get_col("SELECT comment_id FROM $wpdb->comments WHERE DATE_SUB('$now_gmt', INTERVAL 15 DAY) > comment_date_gmt AND comment_approved = 'spam'"); + if ( empty( $comment_ids ) ) + return; + + $comma_comment_ids = implode( ', ', array_map('intval', $comment_ids) ); + + do_action( 'delete_comment', $comment_ids ); + $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_id IN ( $comma_comment_ids )"); + $wpdb->query("DELETE FROM $wpdb->commentmeta WHERE comment_id IN ( $comma_comment_ids )"); + clean_comment_cache( $comment_ids ); + $n = mt_rand(1, 5000); + if ( apply_filters('akismet_optimize_table', ($n == 11)) ) // lucky number + $wpdb->query("OPTIMIZE TABLE $wpdb->comments"); + +} + +function akismet_delete_old_metadata() { + global $wpdb; + + $now_gmt = current_time( 'mysql', 1 ); + $interval = apply_filters( 'akismet_delete_commentmeta_interval', 15 ); + + # enfore a minimum of 1 day + $interval = absint( $interval ); + if ( $interval < 1 ) { + return; + } + + // akismet_as_submitted meta values are large, so expire them + // after $interval days regardless of the comment status + while ( TRUE ) { + $comment_ids = $wpdb->get_col( "SELECT $wpdb->comments.comment_id FROM $wpdb->commentmeta INNER JOIN $wpdb->comments USING(comment_id) WHERE meta_key = 'akismet_as_submitted' AND DATE_SUB('$now_gmt', INTERVAL {$interval} DAY) > comment_date_gmt LIMIT 10000" ); + + if ( empty( $comment_ids ) ) { + return; + } + + foreach ( $comment_ids as $comment_id ) { + delete_comment_meta( $comment_id, 'akismet_as_submitted' ); + } + } + + /* + $n = mt_rand( 1, 5000 ); + if ( apply_filters( 'akismet_optimize_table', ( $n == 11 ), 'commentmeta' ) ) { // lucky number + $wpdb->query( "OPTIMIZE TABLE $wpdb->commentmeta" ); + } + */ +} + +add_action('akismet_scheduled_delete', 'akismet_delete_old'); +add_action('akismet_scheduled_delete', 'akismet_delete_old_metadata'); + +function akismet_check_db_comment( $id, $recheck_reason = 'recheck_queue' ) { + global $wpdb, $akismet_api_host, $akismet_api_port; + + $id = (int) $id; + $c = $wpdb->get_row( "SELECT * FROM $wpdb->comments WHERE comment_ID = '$id'", ARRAY_A ); + if ( !$c ) + return; + + $c['user_ip'] = $c['comment_author_IP']; + $c['user_agent'] = $c['comment_agent']; + $c['referrer'] = ''; + $c['blog'] = get_option('home'); + $c['blog_lang'] = get_locale(); + $c['blog_charset'] = get_option('blog_charset'); + $c['permalink'] = get_permalink($c['comment_post_ID']); + $id = $c['comment_ID']; + if ( akismet_test_mode() ) + $c['is_test'] = 'true'; + $c['recheck_reason'] = $recheck_reason; + + $query_string = ''; + foreach ( $c as $key => $data ) + $query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&'; + + $response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port); + return ( is_array( $response ) && isset( $response[1] ) ) ? $response[1] : false; +} + +function akismet_cron_recheck() { + global $wpdb; + + $status = akismet_verify_key( akismet_get_key() ); + if ( get_option( 'akismet_alert_code' ) || $status == 'invalid' ) { + // since there is currently a problem with the key, reschedule a check for 6 hours hence + wp_schedule_single_event( time() + 21600, 'akismet_schedule_cron_recheck' ); + return false; + } + + delete_option('akismet_available_servers'); + + $comment_errors = $wpdb->get_col( " + SELECT comment_id + FROM {$wpdb->prefix}commentmeta + WHERE meta_key = 'akismet_error' + LIMIT 100 + " ); + + foreach ( (array) $comment_errors as $comment_id ) { + // if the comment no longer exists, or is too old, remove the meta entry from the queue to avoid getting stuck + $comment = get_comment( $comment_id ); + if ( !$comment || strtotime( $comment->comment_date_gmt ) < strtotime( "-15 days" ) ) { + delete_comment_meta( $comment_id, 'akismet_error' ); + continue; + } + + add_comment_meta( $comment_id, 'akismet_rechecking', true ); + $status = akismet_check_db_comment( $comment_id, 'retry' ); + + $msg = ''; + if ( $status == 'true' ) { + $msg = __( 'Akismet caught this comment as spam during an automatic retry.' ); + } elseif ( $status == 'false' ) { + $msg = __( 'Akismet cleared this comment during an automatic retry.' ); + } + + // If we got back a legit response then update the comment history + // other wise just bail now and try again later. No point in + // re-trying all the comments once we hit one failure. + if ( !empty( $msg ) ) { + delete_comment_meta( $comment_id, 'akismet_error' ); + akismet_update_comment_history( $comment_id, $msg, 'cron-retry' ); + update_comment_meta( $comment_id, 'akismet_result', $status ); + // make sure the comment status is still pending. if it isn't, that means the user has already moved it elsewhere. + $comment = get_comment( $comment_id ); + if ( $comment && 'unapproved' == wp_get_comment_status( $comment_id ) ) { + if ( $status == 'true' ) { + wp_spam_comment( $comment_id ); + } elseif ( $status == 'false' ) { + // comment is good, but it's still in the pending queue. depending on the moderation settings + // we may need to change it to approved. + if ( check_comment($comment->comment_author, $comment->comment_author_email, $comment->comment_author_url, $comment->comment_content, $comment->comment_author_IP, $comment->comment_agent, $comment->comment_type) ) + wp_set_comment_status( $comment_id, 1 ); + } + } + } else { + delete_comment_meta( $comment_id, 'akismet_rechecking' ); + wp_schedule_single_event( time() + 1200, 'akismet_schedule_cron_recheck' ); + return; + } + delete_comment_meta( $comment_id, 'akismet_rechecking' ); + } + + $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' ); + } +} +add_action( 'akismet_schedule_cron_recheck', 'akismet_cron_recheck' ); + +function akismet_add_comment_nonce( $post_id ) { + echo '

    '; + wp_nonce_field( 'akismet_comment_nonce_' . $post_id, 'akismet_comment_nonce', FALSE ); + echo '

    '; +} + +$akismet_comment_nonce_option = apply_filters( 'akismet_comment_nonce', get_option( 'akismet_comment_nonce' ) ); + +if ( $akismet_comment_nonce_option == 'true' || $akismet_comment_nonce_option == '' ) + add_action( 'comment_form', 'akismet_add_comment_nonce' ); + +global $wp_version; +if ( '3.0.5' == $wp_version ) { + remove_filter( 'comment_text', 'wp_kses_data' ); + if ( is_admin() ) + add_filter( 'comment_text', 'wp_kses_post' ); +} + +function akismet_fix_scheduled_recheck() { + $future_check = wp_next_scheduled( 'akismet_schedule_cron_recheck' ); + if ( !$future_check ) { + return; + } + + if ( get_option( 'akismet_alert_code' ) > 0 ) { + return; + } + + $check_range = time() + 1200; + if ( $future_check > $check_range ) { + wp_clear_scheduled_hook( 'akismet_schedule_cron_recheck' ); + wp_schedule_single_event( time() + 300, 'akismet_schedule_cron_recheck' ); + } +} diff --git a/sources/wp-content/plugins/akismet/img/logo.png b/sources/wp-content/plugins/akismet/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b5f5b9a1720277baf536fc765471f754decf7700 GIT binary patch literal 2710 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 literal 0 HcmV?d00001 diff --git a/sources/wp-content/plugins/akismet/index.php b/sources/wp-content/plugins/akismet/index.php new file mode 100644 index 0000000..a6ce9c8 --- /dev/null +++ b/sources/wp-content/plugins/akismet/index.php @@ -0,0 +1,2 @@ +escape( $type ); + return $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' AND comment_type='$type' ORDER BY comment_date DESC LIMIT $start, $end"); + } + + // All + return $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE comment_approved = 'spam' ORDER BY comment_date DESC LIMIT $start, $end"); +} + +// Totals for each comment type +// returns array( type => count, ... ) +function akismet_spam_totals() { + global $wpdb; + $totals = $wpdb->get_results( "SELECT comment_type, COUNT(*) AS cc FROM $wpdb->comments WHERE comment_approved = 'spam' GROUP BY comment_type" ); + $return = array(); + foreach ( $totals as $total ) + $return[$total->comment_type ? $total->comment_type : 'comment'] = $total->cc; + return $return; +} + +function akismet_manage_page() { + global $wpdb, $submenu, $wp_db_version; + + // WP 2.7 has its own spam management page + if ( 8645 <= $wp_db_version ) + return; + + $count = sprintf(__('Akismet Spam (%s)'), akismet_spam_count()); + if ( isset( $submenu['edit-comments.php'] ) ) + add_submenu_page('edit-comments.php', __('Akismet Spam'), $count, 'moderate_comments', 'akismet-admin', 'akismet_caught' ); + elseif ( function_exists('add_management_page') ) + add_management_page(__('Akismet Spam'), $count, 'moderate_comments', 'akismet-admin', 'akismet_caught'); +} + +function akismet_caught() { + global $wpdb, $comment, $akismet_caught, $akismet_nonce; + + akismet_recheck_queue(); + if (isset($_POST['submit']) && 'recover' == $_POST['action'] && ! empty($_POST['not_spam'])) { + check_admin_referer( $akismet_nonce ); + if ( function_exists('current_user_can') && !current_user_can('moderate_comments') ) + die(__('You do not have sufficient permission to moderate comments.')); + + $i = 0; + foreach ($_POST['not_spam'] as $comment): + $comment = (int) $comment; + if ( function_exists('wp_set_comment_status') ) + wp_set_comment_status($comment, 'approve'); + else + $wpdb->query("UPDATE $wpdb->comments SET comment_approved = '1' WHERE comment_ID = '$comment'"); + akismet_submit_nonspam_comment($comment); + ++$i; + endforeach; + $to = add_query_arg( 'recovered', $i, $_SERVER['HTTP_REFERER'] ); + wp_safe_redirect( $to ); + exit; + } + if ('delete' == $_POST['action']) { + check_admin_referer( $akismet_nonce ); + if ( function_exists('current_user_can') && !current_user_can('moderate_comments') ) + die(__('You do not have sufficient permission to moderate comments.')); + + $delete_time = $wpdb->escape( $_POST['display_time'] ); + $comment_ids = $wpdb->get_col( "SELECT comment_id FROM $wpdb->comments WHERE comment_approved = 'spam' AND '$delete_time' > comment_date_gmt" ); + if ( !empty( $comment_ids ) ) { + do_action( 'delete_comment', $comment_ids ); + $wpdb->query( "DELETE FROM $wpdb->comments WHERE comment_id IN ( " . implode( ', ', $comment_ids ) . " )"); + wp_cache_delete( 'akismet_spam_count', 'widget' ); + } + $to = add_query_arg( 'deleted', 'all', $_SERVER['HTTP_REFERER'] ); + wp_safe_redirect( $to ); + exit; + } + +if ( isset( $_GET['recovered'] ) ) { + $i = (int) $_GET['recovered']; + echo '

    ' . sprintf(__('%1$s comments recovered.'), $i) . "

    "; +} + +if (isset( $_GET['deleted'] ) ) + echo '

    ' . __('All spam deleted.') . '

    '; + +if ( isset( $GLOBALS['submenu']['edit-comments.php'] ) ) + $link = 'edit-comments.php'; +else + $link = 'edit.php'; +?> + +
    +

    + +

    %1$s spam for you since you first installed it.'), number_format_i18n($count) ); ?>

    +'.__('You have no spam currently in the queue. Must be your lucky day. :)').'

    '; + echo '
    '; +} else { + echo '

    '.__('You can delete all of the spam from your database with a single click. This operation cannot be undone, so you may wish to check to ensure that no legitimate comments got through first. Spam is automatically deleted after 15 days, so don’t sweat it.').'

    '; +?> + +
    + + +    + +
    + +
    +
    + +

    + +'.__('These are the latest comments identified as spam by Akismet. If you see any mistakes, simply mark the comment as "not spam" and Akismet will learn from the submission. If you wish to recover a comment from spam, simply select the comment, and click Not Spam. After 15 days we clean out the junk for you.').'

    '; ?> + +escape($_POST['s']); + $comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE + (comment_author LIKE '%$s%' OR + comment_author_email LIKE '%$s%' OR + comment_author_url LIKE ('%$s%') OR + comment_author_IP LIKE ('%$s%') OR + comment_content LIKE ('%$s%') ) AND + comment_approved = 'spam' + ORDER BY comment_date DESC"); +} else { + if ( isset( $_GET['apage'] ) ) + $page = (int) $_GET['apage']; + else + $page = 1; + + if ( $page < 2 ) + $page = 1; + + $current_type = false; + if ( isset( $_GET['ctype'] ) ) + $current_type = preg_replace( '|[^a-z]|', '', $_GET['ctype'] ); + + $comments = akismet_spam_comments( $current_type, $page ); + $total = akismet_spam_count( $current_type ); + $totals = akismet_spam_totals(); +?> +
      +
    • >
    • + $type_count ) { + if ( 'comment' == $type ) { + $type = 'comments'; + $show = __('Comments'); + } else { + $show = ucwords( $type ); + } + $type_count = number_format_i18n( $type_count ); + $extra = $current_type === $type ? ' class="active"' : ''; + echo "
    • $show ($type_count)
    • "; +} +do_action( 'akismet_tabs' ); // so plugins can add more tabs easily +?> +
    + +
    " id="akismetsearch"> +

    +

    +
    + 50 ) { +$total_pages = ceil( $total / 50 ); +$r = ''; +if ( 1 < $page ) { + $args['apage'] = ( 1 == $page - 1 ) ? '' : $page - 1; + $r .= '' . "\n"; +} +if ( ( $total_pages = ceil( $total / 50 ) ) > 1 ) { + for ( $page_num = 1; $page_num <= $total_pages; $page_num++ ) : + if ( $page == $page_num ) : + $r .= "$page_num\n"; + else : + $p = false; + if ( $page_num < 3 || ( $page_num >= $page - 3 && $page_num <= $page + 3 ) || $page_num > $total_pages - 3 ) : + $args['apage'] = ( 1 == $page_num ) ? '' : $page_num; + $r .= '' . ( $page_num ) . "\n"; + $in = true; + elseif ( $in == true ) : + $r .= "...\n"; + $in = false; + endif; + endif; + endfor; +} +if ( ( $page ) * 50 < $total || -1 == $total ) { + $args['apage'] = $page + 1; + $r .= '' . "\n"; +} +echo "

    $r

    "; +?> + + +
    + + +
      +comment_date); + $post = get_post($comment->comment_post_ID); + $post_title = $post->post_title; + if ($i % 2) $class = 'class="alternate"'; + else $class = ''; + echo "\n\t
    • "; + ?> + +

      comment_author_email) { ?>| comment_author_url && 'http://' != $comment->comment_author_url) { ?> | |

      + + + +

      — [ +comment_post_ID); +$post_title = wp_specialchars( $post->post_title, 'double' ); +$post_title = ('' == $post_title) ? "# $comment->comment_post_ID" : $post_title; +?> + ]

      + + + +
    + 50 ) { +$total_pages = ceil( $total / 50 ); +$r = ''; +if ( 1 < $page ) { + $args['apage'] = ( 1 == $page - 1 ) ? '' : $page - 1; + $r .= '' . "\n"; +} +if ( ( $total_pages = ceil( $total / 50 ) ) > 1 ) { + for ( $page_num = 1; $page_num <= $total_pages; $page_num++ ) : + if ( $page == $page_num ) : + $r .= "$page_num\n"; + else : + $p = false; + if ( $page_num < 3 || ( $page_num >= $page - 3 && $page_num <= $page + 3 ) || $page_num > $total_pages - 3 ) : + $args['apage'] = ( 1 == $page_num ) ? '' : $page_num; + $r .= '' . ( $page_num ) . "\n"; + $in = true; + elseif ( $in == true ) : + $r .= "...\n"; + $in = false; + endif; + endif; + endfor; +} +if ( ( $page ) * 50 < $total || -1 == $total ) { + $args['apage'] = $page + 1; + $r .= '' . "\n"; +} +echo "

    $r

    "; +} +?> +

    + +

    +

    +
    + +

    + + + +
    + +

    +    +

    +
    + +
    +" . __('Recheck Queue for Spam') . ""; + $page = str_replace( '
    ', '
    ' . $button, $page ); + return $page; + } + + if ( $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_approved = '0'" ) ) + ob_start( 'akismet_recheck_button' ); +} + +// This option causes tons of FPs, was removed in 2.1 +function akismet_kill_proxy_check( $option ) { return 0; } +add_filter('option_open_proxy_check', 'akismet_kill_proxy_check'); diff --git a/sources/wp-content/plugins/akismet/readme.txt b/sources/wp-content/plugins/akismet/readme.txt new file mode 100644 index 0000000..d0094d2 --- /dev/null +++ b/sources/wp-content/plugins/akismet/readme.txt @@ -0,0 +1,172 @@ +=== Akismet === +Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, automattic +Tags: akismet, comments, spam +Requires at least: 3.0 +Tested up to: 3.6 +Stable tag: 2.5.9 +License: GPLv2 or later + +Akismet checks your comments against the Akismet web service to see if they look like spam or not. + +== Description == + +Akismet checks your comments against the Akismet web service to see if they look like spam or not and lets you +review the spam it catches under your blog's "Comments" admin screen. + +Major new features in Akismet 2.5 include: + +* A comment status history, so you can easily see which comments were caught or cleared by Akismet, and which were spammed or unspammed by a moderator +* Links are highlighted in the comment body, to reveal hidden or misleading links +* If your web host is unable to reach Akismet's servers, the plugin will automatically retry when your connection is back up +* Moderators can see the number of approved comments for each user +* Spam and Unspam reports now include more information, to help improve accuracy + +PS: You'll need an [Akismet.com API key](http://akismet.com/get/) to use it. Keys are free for personal blogs, with paid subscriptions available for businesses and commercial sites. + +== Installation == + +Upload the Akismet plugin to your blog, Activate it, then enter your [Akismet.com API key](http://akismet.com/get/). + +1, 2, 3: You're done! + +== Changelog == + += 2.5.9 = +* Update 'Already have a key' link to redirect page rather than depend on javascript +* Fix some non-translatable strings to be translatable +* Update Activation banner in plugins page to redirect user to Akismet config page + += 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 +* 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 +* Modernize the widget code +* Fix a bug where comments were not held for moderation during an error condition +* Improve the UX and display when comments are temporarily held due to an error +* Make the Check For Spam button force a retry when comments are held due to an error +* Handle errors caused by an invalid key +* Don't retry comments that are too old +* Improve error messages when verifying an API key + += 2.5.5 = +* Add nonce check for comment author URL remove action +* Fix the settings link + += 2.5.4 = +* Limit Akismet CSS and Javascript loading in wp-admin to just the pages that need it +* Added author URL quick removal functionality +* Added mShot preview on Author URL hover +* Added empty index.php to prevent directory listing +* Move wp-admin menu items under Jetpack, if it is installed +* Purge old Akismet comment meta data, default of 15 days + += 2.5.3 = +* Specify the license is GPL v2 or later +* Fix a bug that could result in orphaned commentmeta entries +* Include hotfix for WordPress 3.0.5 filter issue + += 2.5.2 = + +* Properly format the comment count for author counts +* Look for super admins on multisite installs when looking up user roles +* Increase the HTTP request timeout +* Removed padding for author approved count +* Fix typo in function name +* Set Akismet stats iframe height to fixed 2500px. Better to have one tall scroll bar than two side by side. + += 2.5.1 = + +* Fix a bug that caused the "Auto delete" option to fail to discard comments correctly +* Remove the comment nonce form field from the 'Akismet Configuration' page in favor of using a filter, akismet_comment_nonce +* Fixed padding bug in "author" column of posts screen +* Added margin-top to "cleared by ..." badges on dashboard +* Fix possible error when calling akismet_cron_recheck() +* Fix more PHP warnings +* Clean up XHTML warnings for comment nonce +* Fix for possible condition where scheduled comment re-checks could get stuck +* Clean up the comment meta details after deleting a comment +* Only show the status badge if the comment status has been changed by someone/something other than Akismet +* Show a 'History' link in the row-actions +* Translation fixes +* Reduced font-size on author name +* Moved "flagged by..." notification to top right corner of comment container and removed heavy styling +* Hid "flagged by..." notification while on dashboard + += 2.5.0 = + +* Track comment actions under 'Akismet Status' on the edit comment screen +* Fix a few remaining deprecated function calls ( props Mike Glendinning ) +* Use HTTPS for the stats IFRAME when wp-admin is using HTTPS +* Use the WordPress HTTP class if available +* Move the admin UI code to a separate file, only loaded when needed +* Add cron retry feature, to replace the old connectivity check +* Display Akismet status badge beside each comment +* Record history for each comment, and display it on the edit page +* Record the complete comment as originally submitted in comment_meta, to use when reporting spam and ham +* Highlight links in comment content +* New option, "Show the number of comments you've approved beside each comment author." +* New option, "Use a nonce on the comment form." + += 2.4.0 = + +* Spell out that the license is GPLv2 +* Fix PHP warnings +* Fix WordPress deprecated function calls +* Fire the delete_comment action when deleting comments +* Move code specific for older WP versions to legacy.php +* General code clean up + += 2.3.0 = + +* Fix "Are you sure" nonce message on config screen in WPMU +* Fix XHTML compliance issue in sidebar widget +* Change author link; remove some old references to WordPress.com accounts +* Localize the widget title (core ticket #13879) + += 2.2.9 = + +* Eliminate a potential conflict with some plugins that may cause spurious reports + += 2.2.8 = + +* Fix bug in initial comment check for ipv6 addresses +* Report comments as ham when they are moved from spam to moderation +* Report comments as ham when clicking undo after spam +* Use transition_comment_status action when available instead of older actions for spam/ham submissions +* Better diagnostic messages when PHP network functions are unavailable +* Better handling of comments by logged-in users + += 2.2.7 = + +* Add a new AKISMET_VERSION constant +* Reduce the possibility of over-counting spam when another spam filter plugin is in use +* Disable the connectivity check when the API key is hard-coded for WPMU + += 2.2.6 = + +* Fix a global warning introduced in 2.2.5 +* Add changelog and additional readme.txt tags +* Fix an array conversion warning in some versions of PHP +* Support a new WPCOM_API_KEY constant for easier use with WordPress MU + += 2.2.5 = + +* Include a new Server Connectivity diagnostic check, to detect problems caused by firewalls + += 2.2.4 = + +* Fixed a key problem affecting the stats feature in WordPress MU +* Provide additional blog information in Akismet API calls diff --git a/sources/wp-content/plugins/akismet/widget.php b/sources/wp-content/plugins/akismet/widget.php new file mode 100644 index 0000000..8c5a120 --- /dev/null +++ b/sources/wp-content/plugins/akismet/widget.php @@ -0,0 +1,108 @@ + __( 'Display the number of spam comments Akismet has caught' ) ) + ); + + if ( is_active_widget( false, false, $this->id_base ) ) { + add_action( 'wp_head', array( $this, 'css' ) ); + } + } + + function css() { +?> + + + + + +

    + + +

    + + + + + +Hello, Dolly in the upper right of your admin screen on every page. +Author: Matt Mullenweg +Version: 1.6 +Author URI: http://ma.tt/ +*/ + +function hello_dolly_get_lyric() { + /** These are the lyrics to Hello Dolly */ + $lyrics = "Hello, Dolly +Well, hello, Dolly +It's so nice to have you back where you belong +You're lookin' swell, Dolly +I can tell, Dolly +You're still glowin', you're still crowin' +You're still goin' strong +We feel the room swayin' +While the band's playin' +One of your old favourite songs from way back when +So, take her wrap, fellas +Find her an empty lap, fellas +Dolly'll never go away again +Hello, Dolly +Well, hello, Dolly +It's so nice to have you back where you belong +You're lookin' swell, Dolly +I can tell, Dolly +You're still glowin', you're still crowin' +You're still goin' strong +We feel the room swayin' +While the band's playin' +One of your old favourite songs from way back when +Golly, gee, fellas +Find her a vacant knee, fellas +Dolly'll never go away +Dolly'll never go away +Dolly'll never go away again"; + + // Here we split it into lines + $lyrics = explode( "\n", $lyrics ); + + // And then randomly choose a line + return wptexturize( $lyrics[ mt_rand( 0, count( $lyrics ) - 1 ) ] ); +} + +// This just echoes the chosen line, we'll position it later +function hello_dolly() { + $chosen = hello_dolly_get_lyric(); + echo "

    $chosen

    "; +} + +// Now we set that function up to execute when the admin_notices action is called +add_action( 'admin_notices', 'hello_dolly' ); + +// We need some CSS to position the paragraph +function dolly_css() { + // This makes sure that the positioning is also good for right-to-left languages + $x = is_rtl() ? 'left' : 'right'; + + echo " + + "; +} + +add_action( 'admin_head', 'dolly_css' ); + +?> diff --git a/sources/wp-content/plugins/index.php b/sources/wp-content/plugins/index.php new file mode 100644 index 0000000..4e6c07c --- /dev/null +++ b/sources/wp-content/plugins/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/sources/wp-content/themes/index.php b/sources/wp-content/themes/index.php new file mode 100644 index 0000000..4e6c07c --- /dev/null +++ b/sources/wp-content/themes/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/404.php b/sources/wp-content/themes/twentythirteen/404.php new file mode 100644 index 0000000..131a134 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/404.php @@ -0,0 +1,31 @@ + + +
    +
    + + + +
    +
    +

    +

    + + +
    +
    + +
    +
    + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/archive.php b/sources/wp-content/themes/twentythirteen/archive.php new file mode 100644 index 0000000..9e0dd4d --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/archive.php @@ -0,0 +1,55 @@ + + +
    +
    + + +
    +

    +
    + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/author-bio.php b/sources/wp-content/themes/twentythirteen/author-bio.php new file mode 100644 index 0000000..ae2f522 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/author-bio.php @@ -0,0 +1,34 @@ + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/author.php b/sources/wp-content/themes/twentythirteen/author.php new file mode 100644 index 0000000..3d76ba3 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/author.php @@ -0,0 +1,62 @@ + + +
    +
    + + + + + +
    +

    ' . get_the_author() . '' ); ?>

    +
    + + + + + + + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/category.php b/sources/wp-content/themes/twentythirteen/category.php new file mode 100644 index 0000000..a221239 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/category.php @@ -0,0 +1,41 @@ + + +
    +
    + + +
    +

    + + +
    + +
    + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/comments.php b/sources/wp-content/themes/twentythirteen/comments.php new file mode 100644 index 0000000..3d1aff4 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/comments.php @@ -0,0 +1,59 @@ + + +
    + + +

    + ' . get_the_title() . '' ); + ?> +

    + +
      + 'ol', + 'short_ping' => true, + 'avatar_size' => 74, + ) ); + ?> +
    + + 1 && get_option( 'page_comments' ) ) : + ?> + + + + +

    + + + + + + +
    \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/content-aside.php b/sources/wp-content/themes/twentythirteen/content-aside.php new file mode 100644 index 0000000..8aa309b --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-aside.php @@ -0,0 +1,31 @@ + + +
    > +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + + + ', '' ); ?> + + + + + + + + ', '' ); ?> + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-audio.php b/sources/wp-content/themes/twentythirteen/content-audio.php new file mode 100644 index 0000000..5ba1862 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-audio.php @@ -0,0 +1,37 @@ + + +
    > +
    + +

    + +

    + +

    + +
    + +
    +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    +
    + +
    + + ', '' ); ?> + + + + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-chat.php b/sources/wp-content/themes/twentythirteen/content-chat.php new file mode 100644 index 0000000..b34ab46 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-chat.php @@ -0,0 +1,31 @@ + + +
    > +
    + +

    + +

    + +

    + +
    + +
    + + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-gallery.php b/sources/wp-content/themes/twentythirteen/content-gallery.php new file mode 100644 index 0000000..a4e2464 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-gallery.php @@ -0,0 +1,45 @@ + + +
    > +
    + +

    + +

    + +

    + +
    + +
    + + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> + + + +
    + +
    + + + + + ' . __( 'Leave a comment', 'twentythirteen' ) . '', __( 'One comment so far', 'twentythirteen' ), __( 'View all % comments', 'twentythirteen' ) ); ?> + + + ', '' ); ?> + + + + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-image.php b/sources/wp-content/themes/twentythirteen/content-image.php new file mode 100644 index 0000000..972423d --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-image.php @@ -0,0 +1,41 @@ + + +
    > +
    + +

    + +

    + +

    + +
    + +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + + + + + ' . __( 'Leave a comment', 'twentythirteen' ) . '', __( 'One comment so far', 'twentythirteen' ), __( 'View all % comments', 'twentythirteen' ) ); ?> + + + ', '' ); ?> + + + + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-link.php b/sources/wp-content/themes/twentythirteen/content-link.php new file mode 100644 index 0000000..2da7ffb --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-link.php @@ -0,0 +1,36 @@ + + +
    > +
    +

    + +

    + + +
    + +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + + +
    + + + + +
    + +
    diff --git a/sources/wp-content/themes/twentythirteen/content-none.php b/sources/wp-content/themes/twentythirteen/content-none.php new file mode 100644 index 0000000..d9549e1 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-none.php @@ -0,0 +1,31 @@ + + + + +
    + + +

    Get started here.', 'twentythirteen' ), admin_url( 'post-new.php' ) ); ?>

    + + + +

    + + + + +

    + + + +
    diff --git a/sources/wp-content/themes/twentythirteen/content-quote.php b/sources/wp-content/themes/twentythirteen/content-quote.php new file mode 100644 index 0000000..307537d --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-quote.php @@ -0,0 +1,27 @@ + + +
    > +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + + + + + ' . __( 'Leave a comment', 'twentythirteen' ) . '', __( 'One comment so far', 'twentythirteen' ), __( 'View all % comments', 'twentythirteen' ) ); ?> + + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-status.php b/sources/wp-content/themes/twentythirteen/content-status.php new file mode 100644 index 0000000..272f5de --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-status.php @@ -0,0 +1,25 @@ + + +
    > +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + + ', '' ); ?> + + + + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content-video.php b/sources/wp-content/themes/twentythirteen/content-video.php new file mode 100644 index 0000000..ac01758 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content-video.php @@ -0,0 +1,41 @@ + + +
    > +
    + +

    + +

    + +

    + +
    + +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + + + + + ' . __( 'Leave a comment', 'twentythirteen' ) . '', __( 'One comment so far', 'twentythirteen' ), __( 'View all % comments', 'twentythirteen' ) ); ?> + + + ', '' ); ?> + + + + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/content.php b/sources/wp-content/themes/twentythirteen/content.php new file mode 100644 index 0000000..d11e682 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/content.php @@ -0,0 +1,57 @@ + + +
    > +
    + +
    + +
    + + + +

    + +

    + +

    + + + +
    + + +
    + +
    + +
    + →', 'twentythirteen' ) ); ?> + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + + +
    + + + + + + + +
    +
    diff --git a/sources/wp-content/themes/twentythirteen/css/editor-style.css b/sources/wp-content/themes/twentythirteen/css/editor-style.css new file mode 100644 index 0000000..f7665a8 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/css/editor-style.css @@ -0,0 +1,578 @@ +/* +Theme Name: Twenty Thirteen +Description: Used to style the TinyMCE editor. +*/ + + +/** + * Table of Contents: + * + * 1.0 - Body + * 2.0 - Headings + * 3.0 - Text Elements + * 4.0 - Links + * 5.0 - Alignment + * 6.0 - Tables + * 7.0 - Images + * 8.0 - Post Formats + * 9.0 - RTL + * ---------------------------------------------------------------------------- + */ + + +/** + * 1.0 Body + * ---------------------------------------------------------------------------- + */ + +html .mceContentBody { + font-size: 100%; + max-width: 604px; +} + +body { + color: #141412; + font-family: "Source Sans Pro", Helvetica, sans-serif; + line-height: 1.5; + text-rendering: optimizeLegibility; + vertical-align: baseline; +} + + +/** + * 2.0 Headings + * ---------------------------------------------------------------------------- + */ + +h1, +h2, +h3, +h4, +h5, +h6 { + clear: both; + font-family: Bitter, Georgia, serif; + line-height: 1.3; +} + +h1 { + font-size: 48px; + margin: 33px 0; +} + +h2 { + font-size: 30px; + margin: 25px 0; +} + +h3 { + font-size: 22px; + margin: 22px 0; +} + +h4 { + font-size: 20px; + margin: 25px 0; +} + +h5 { + font-size: 18px; + margin: 30px 0; +} + +h6 { + font-size: 16px; + margin: 36px 0; +} + +hr { + background: url(../images/dotted-line.png) repeat center top; + background-size: 4px 4px; + border: 0; + height: 1px; + margin: 0 0 24px; +} + + +/** + * 3.0 Text Elements + * ---------------------------------------------------------------------------- + */ + +p { + margin: 0 0 24px; +} + +ol, +ul { + margin: 16px 0; + padding: 0 0 0 40px; +} + +ul { + list-style-type: square; +} + +ol { + list-style: decimal outside; +} + +li > ul, +li > ol { + margin: 0; +} + +dl { + margin: 0 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin: 0 0 20px; +} + +strong { + font-weight: bold; +} + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 14px; +} + +pre { + background: #f5f5f5; + color: #666; + font-family: monospace; + font-size: 14px; + margin: 20px 0; + overflow: auto; + padding: 20px; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +blockquote, +q { + quotes: none; +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ""; + content: none; +} + +blockquote { + font-size: 24px; + font-style: italic; + font-weight: 300; + margin: 24px 40px; +} + +blockquote blockquote { + margin-right: 0; +} + +blockquote cite, +blockquote small { + font-size: 14px; + font-weight: normal; + text-transform: uppercase; +} + +cite { + border-bottom: 0; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +address { + font-style: italic; + margin: 0 0 24px; +} + +del { + color: #333; +} + +ins { + background: #fff9c0; + border: none; + color: #333; + text-decoration: none; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + + +/** + * 4.0 Links + * ---------------------------------------------------------------------------- + */ + +a { + color: #ca3c08; + text-decoration: none; +} + +a:visited { + color: #ac0404; +} + +a:focus { + outline: thin dotted; +} + +a:active, +a:hover { + color: #ea9629; + outline: 0; +} + +a:hover { + text-decoration: underline; +} + + +/** + * 5.0 Alignment + * ---------------------------------------------------------------------------- + */ + +.alignleft { + float: left; + margin: 5px 20px 5px 0; +} + +.alignright { + float: right; + margin: 5px 0 5px 20px; +} + +.aligncenter { + display: block; + margin: 5px auto; +} + +img.alignnone { + margin: 5px 0; +} + + +/** + * 6.0 Tables + * ---------------------------------------------------------------------------- + */ + +table { + border-bottom: 1px solid #ededed; + border-collapse: collapse; + border-spacing: 0; + font-size: 14px; + line-height: 2; + margin: 0 0 20px; + width: 100%; +} + +caption, +th, +td { + font-weight: normal; + text-align: left; +} + +caption { + font-size: 16px; + margin: 20px 0; +} + +th { + font-weight: bold; + text-transform: uppercase; +} + +td { + border-top: 1px solid #ededed; + padding: 6px 10px 6px 0; +} + + +/** + * 7.0 Images + * ---------------------------------------------------------------------------- + */ + +img { + height: auto; + max-width: 100%; + vertical-align: middle; +} + +.wp-caption { + background: transparent; + border: none; + margin: 0; + padding: 0; + text-align: left; +} + +.wp-caption.alignleft { + margin: 5px 10px 5px 0; +} + +.wp-caption.alignright { + margin: 5px 0 5px 10px; +} + +.wp-caption-dt { + margin: 0; +} + +.wp-caption .wp-caption-text, +.wp-caption-dd { + color: #220e10; + font-size: 18px; + font-style: italic; + font-weight: 300; + line-height: 1.5; + margin-bottom: 24px; + padding: 0; +} + +.mceTemp + ul, +.mceTemp + ol { + list-style-position: inside; +} + + +/** + * 8.0 Post Formats + * ---------------------------------------------------------------------------- + */ + +/* Aside */ +.post-format-aside { + background-color: #f7f5e7; +} + +.post-format-aside blockquote { + font-size: 100%; + font-weight: normal; +} + +.post-format-aside cite { + font-size: 100%; + text-transform: none; +} + +.post-format-aside cite:before { + content: "\2014"; + margin-right: 5px; +} + +/* Audio */ +.post-format-audio { + background-color: #db572f; +} + +.post-format-audio a { + color: #fbfaf3; +} + +.post-format-audio:before { + background: url(../images/dotted-line.png) repeat-y 85px 0; + background-size: 4px 4px; + content: "\f109"; + display: block; + float: left; + font-family: Genericons; + font-size: 64px; + -webkit-font-smoothing: antialiased; + height: 100%; + line-height: 1; + width: 120px; +} + +/* Chat */ +.post-format-chat { + background-color: #eadaa6; +} + +.post-format-chat a { + color: #722d19; +} + +/* Gallery */ +.post-format-gallery { + background-color: #fbca3c; +} + +.post-format-gallery a { + color: #722d19; +} + +/* Image: same as Standard/Defaults */ + +/* Link */ +.post-format-link { + background-color: #f7f5e7; +} + +/* Quote */ +.post-format-quote { + background-color: #210d10; + color: #f7f5e7; +} + +.post-format-quote a { + color: #e63f2a; +} + +.post-format-quote blockquote { + font-size: 28px; + font-style: italic; + font-weight: 300; + margin: 0; + padding-left: 75px; + position: relative; +} + +.post-format-quote blockquote:before { + content: '\201C'; + font-size: 140px; + font-weight: 400; + line-height: .8; + padding-right: 25px; + position: absolute; + left: -15px; + top: -3px; +} + +.post-format-quote blockquote small, +.post-format-quote blockquote cite { + display: block; + font-size: 16px; +} + +.format-quote .entry-content cite a { + border-bottom: 1px dotted #fff; + color: #fff; +} + +.format-quote .entry-content cite a:hover { + text-decoration: none; +} + + +/* Status */ +.post-format-status { + background-color: #722d19; + color: #f7f5e7; + font-style: italic; + font-weight: 300; + padding: 0; + padding-left: 35px; +} + +.post-format-status.mceContentBody { + font-size: 24px; +} + +.post-format-status:before { + background: url(../images/dotted-line.png) repeat-y left bottom; + background-size: 4px 4px; + content: ""; + display: block; + float: left; + height: 100%; + position: relative; + left: -30px; + width: 1px; +} + +.post-format-status > p:first-child:before { + background-color: rgba(0, 0, 0, 0.65); + content: ""; + height: 3px; + width: 13px; + margin-top: 13px; + position: absolute; + left: 9px; +} + +.post-format-status a { + color: #eadaa6; +} + +/* Video */ +.post-format-video { + background-color: #db572f; +} + +.post-format-video a { + color: #fbfaf3; +} + + +/** + * 9.0 RTL + * ---------------------------------------------------------------------------- + */ + +html .mceContentBody.rtl { + direction: rtl; + unicode-bidi: embed; +} + +.rtl ol, +.rtl ul { + padding: 0 40px 0 0; +} + +.rtl .wp-caption, +.rtl tr th { + text-align: right; +} + +.rtl td { + padding: 6px 0 6px 10px; + text-align: right; +} + +.rtl blockquote blockquote { + margin-left: 0; + margin-right: 24px; +} + +.rtl.post-format-audio:before, +.rtl.post-format-status:before, +.rtl.post-format-status > p:first-child:before { + background: none; + content: none; +} diff --git a/sources/wp-content/themes/twentythirteen/css/ie.css b/sources/wp-content/themes/twentythirteen/css/ie.css new file mode 100644 index 0000000..c815a14 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/css/ie.css @@ -0,0 +1,284 @@ +/* +Styles for older IE versions (previous to IE9). +*/ + +.site { + min-width: 1040px; +} + +.genericon:before:hover, +.menu-toggle:after:hover, +.date a:before:hover, +.entry-meta .author a:before:hover, +.format-audio .entry-content:before:hover, +.comments-link a:before:hover, +.tags-links a:first-child:before:hover, +.categories-links a:first-child:before:hover, +.edit-link > a:before:hover, +.attachment-meta:before:hover, +.attachment-meta a:before:hover, +.comment-awaiting-moderation:before:hover, +.comment-reply-link:before:hover, +.comment-reply-title small a:before:hover, +.bypostauthor > .comment-body .fn:before:hover { + text-decoration: none; +} + +.nav-menu .sub-menu ul, +.nav-menu .children ul { + left: 100%; +} + +.site-header .home-link { + max-width: 1040px; +} + +.site-header .search-form [type="search"], +.site-header .search-form [type="text"] { + padding-top: 6px; +} + +img.alignright { + margin-right: 0; +} + +img.alignleft { + margin-left: 0; +} + +.site-main .sidebar-inner { + width: 1040px; +} + +.site-main .widget-area { + margin-right: 60px; +} + +.format-image .entry-content .size-full { + margin: 0; + max-width: 604px; +} + +.gallery-columns-1 .gallery-item, +.gallery-columns-2 .gallery-item, +.gallery-columns-3 .gallery-item { + max-width: none; +} + +.gallery img { + width: auto; +} + +.gallery-caption { + background: #000; + filter: alpha(opacity=0); +} + +.gallery-item:hover .gallery-caption { + filter: alpha(opacity=70); +} + +.comment { + clear: both; +} + +.comment-meta, +.comment-content, +.comment-list .reply { + width: 480px; +} + +.depth-2 .comment-meta, +.depth-2 .comment-content, +.comment-list .depth-2 .reply { + width: 460px; +} + +.depth-3 .comment-meta, +.depth-3 .comment-content, +.comment-list .depth-3 .reply { + width: 440px; +} + +.depth-4 .comment-meta, +.depth-4 .comment-content, +.comment-list .depth-4 .reply { + width: 420px; +} + +.depth-5 .comment-meta, +.depth-5 .comment-content, +.comment-list .depth-5 .reply { + width: 400px; +} + +.comment-meta { + margin-bottom: 0; +} + +.widget { + background: #f7f5e7; +} + +.site-footer .widget { + background: none; +} + +/* Internet Explorer 8 */ +.ie8 .site { + border: 0; +} + +.ie8 img.size-full, +.ie8 img.size-large { + height: auto; + width: auto; +} + +.ie8 .sidebar .entry-header, +.ie8 .sidebar .entry-content, +.ie8 .sidebar .entry-summary, +.ie8 .sidebar .entry-meta { + max-width: 724px; +} + +.ie8 .author-info { + margin-left: 0; +} + +.ie8 .paging-navigation .nav-previous .meta-nav { + padding: 5px 0 8px; + width: 40px; +} + +.ie8 .paging-navigation .nav-next { + line-height: 1; +} + +.ie8 .format-status .entry-content:before, +.ie8 .format-status .entry-meta:before { + content: none; +} + +.ie8 .site-main .widget-area { + margin-right: 0; +} + +/* Internet Explorer 7 */ +.ie7 audio, +.ie7 canvas, +.ie7 video { + display: inline; + zoom: 1; +} + +.ie7 legend { + margin-left: -7px; +} + +.ie7 button, +.ie7 input, +.ie7 select, +.ie7 textarea { + vertical-align: middle; +} + +.ie7 button, +.ie7 input[type="button"], +.ie7 input[type="reset"], +.ie7 input[type="submit"] { + overflow: visible; +} + +.ie7 input[type="checkbox"], +.ie7 input[type="radio"] { + height: 13px; + width: 13px; +} + +.ie7 .screen-reader-text { + clip: rect(1px 1px 1px 1px); /* IE7 */ +} + +.ie7 .site-header { + position: relative; + z-index: 1; +} + +.ie7 .main-navigation { + max-width: 930px; + padding-right: 150px; +} + +.ie7 .nav-menu li a, +.ie7 .nav-menu li { + display: block; + float: left; +} + +.ie7 .nav-menu ul { + top: 40px; +} + +.ie7 .nav-menu li ul ul { + left: 100%; + top: 0; +} + +.ie7 .site-header .search-form [type="search"], +.ie7 .site-header .search-form [type="text"] { + background-color: #fff; + border: 2px solid #c3c0ab; + cursor: text; + height: 28px; + outline: 0; + width: 150px; +} + +.ie7 .entry-header, +.ie7 .entry-content, +.ie7 .entry-summary, +.ie7 .entry-meta { + width: 604px; +} + +.ie7 .format-status .entry-content, +.ie7 .format-status .entry-meta { + padding-left: 60px; +} + +.ie7 .sidebar .format-status .entry-content, +.ie7 .sidebar .format-status .entry-meta { + padding-left: 60px; +} + +.ie7 .sidebar .post-navigation .nav-links, +.ie7 .sidebar .paging-navigation .nav-links { + width: 604px; +} + +.ie7 .paging-navigation .meta-nav { + padding: 0 0 10px; + vertical-align: middle; + width: 40px; +} + +.ie7 .comments-title, +.ie7 .comment-list, +.ie7 .comment-reply-title, +.ie7 .comment-respond .comment-form { + width: 604px; +} + +.ie7 .site-footer .widget-area { + max-width: none; + left: auto; +} + +/* RTL for Internet Explorer 7 & 8 */ +.rtl .format-audio .entry-content:before, +.rtl .comment-reply-link:before, +.rtl .comment-reply-login:before { + -ms-filter: "FlipH"; + filter: FlipH; +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/fonts/COPYING.txt b/sources/wp-content/themes/twentythirteen/fonts/COPYING.txt new file mode 100644 index 0000000..aece214 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/fonts/COPYING.txt @@ -0,0 +1,9 @@ +Genericons 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. + +The fonts are distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +As a special exception, if you create a document which uses this font, and embed this font or unaltered portions of this font into the document, this font does not by itself cause the resulting document to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the document might be covered by the GNU General Public License. If you modify this font, you may extend this exception to your version of the font, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. + +This license does not convey any intellectual property rights to third party trademarks that may be included in the icon font; such marks remain subject to all rights and guidelines of use of their owner. \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/fonts/LICENSE.txt b/sources/wp-content/themes/twentythirteen/fonts/LICENSE.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/fonts/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.eot b/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..defbbe51707ceb0134d83426c00ea4a688bff82a GIT binary patch literal 10388 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 XrRw#cHeM?tV`zongcS;2TIl})?e)3L literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.svg b/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.svg new file mode 100644 index 0000000..32ff53b --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.ttf b/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a21dcb6476ff897f0bdf5294873796f1ed1722b4 GIT binary patch literal 19864 zcmdsfd7Kp0z3(|yz0XWfSFf}6OfNG%1GDr@uQMz|3$hO22naLa!Xh995fBw)jFrVe zP%$qHF-ioziF!?*x4Ho_m*hI}n#HT_awS}EO!7iLFB(m}*BCTLnBskZr)pqO%+3A0 z_t)#8yQ)rAojT`te#`f_6pS;*6#Q72XV$DG3$CfnUBwu0Kx@P7i)YSacjFA>y*Q3s zvN)N#^r~wx`~<%DuDNl0gx$uSjLA!I-nMSb`fC>-Nbo09J@$YWJ@pFvz-*e5{RaeXIAHT-f#aH8e?iw_B zWcx31ybs6C*Ic`O$K1Z20**&;{QRct)~s6alYaC)^Gi7X@wKaVY~j0k3uCire38wo zu3bCVx%M6$@4y%wTduo)``4d!Jiypo7018YvTf}a?VWZ%V+&T|`mUSSu3lGh$)!KV zG4*G|m#D*@oBH4jv@O5&Z%-N9qh)c%jiVZBVG@oxTZJ#Eg(Gxt|4;rUW@Q#@+Jf1! zZx~zYIhGQ~ICbIAWdq9=vcj*~yRvPaz7Aw!tPNL+k(hTx#1ZI7v}6tDxv%1gu4=#- zFke>3JZN$Kn*GuFj`N-1pByKhCu>hmIN5h{?#U(Z%2)}8bL<`Vj^|J8Bs=Lj89mv3 zvT$iA1Hc(Dfpzrw4*vav2 z{~zu{25w_aV;vgv4QTTRhqQS&4r?qvtwyu84^15wZMP0bj%nQ2Rnw{Qj>ylo%Jxo8 z>KIrwG&4RN?bPIs4K)$1FgO&|3d5b6rGsvb#-pDc`el82xE|LHjn=<4Tpy2W*7hN7 z){VpB#PBfsvvyQnzPwYjbrfTK7oHy3b@}D>8bdesj$*TDDx7U{ba<6WU$Rqkc0_Ka zhdhn`BbwYYHy+U}iFq0u9NN8h_o@i(^wvkC!}Ytx(IVrB9_TVg=c)HZ@sNs+$iIr| zRCYv?n!Wwt&BfR*GslMU;j-$Ec;vYG@OWfsU~zp^Ef-SNooxx3@5Xe2Zp`la!BXc@d%28AX-JKhgX00WKBim%$Za{Nr_R$m7uv3n1ScqK%#!PCwtXYzpC#_k_nv&8SNzI?uoMkPL(khc$RherwNzHP+#2l5WR7$g# zOLmK^{b0c^JL$K=*{<0=ML%!XLgk{{n@W}ZAv*8(INOW0yq$IT@N6`2p|6DDjAF1D zvO20-*r+P0XK*YrRpsNpy1CCJQm%IVVGcevooTM5R$bP77$C;!$7GIU#9Ec7s9-$y zaxuW$i%ON^J!o;d+UXNsnG&6rNmCGbzoITH1@dx>; z=bzX2>sRXgd1~*my?c+z$?=WPKQHa0*1be&3sbpjS8b}GZh(c^t%9}~TR5rJmT72m z`JhYoJKD91vgW{O8^?_{gwfWQwR%s{i#=Pp*o1Lcam8D7xcd6EkfKR_T0LeV`>Qc- z&8uiu%%wK0cn?)#dYl^lN=dTX`uZ>}pVH!s`l1RE-RoiL6f8hICV6s^pvM+bL0|Fj zFQ9UP+rRgZ+@^o1)zQ88x; zHfbDB&7e6K9hK=cF_kk#dhw8|Jv3|DRVW3V$^!J!2=Siw+qj&@b>Ocl#8 zuDQifFfMEPpwr5*Ag(g;k+WQ^2Gw0m@q*e#s}ozfkGMAjvIYD$yJA(k(Ax>#f8y?~ zXV})et?K?0C-#5p>9*0|snR`dPlG?f!S*qlFz$Eck&ST<#Q>t`Kx(rK9@=IM68*G*3$>j}7cxzN=*;u1;WQ0M}NFYo+;gfa}qP zdD^i4BX(K?FN?DdrbUyQFRca2#2A%nA-&B>t>(BEF4II=(c%I5Yr)F3Ab&cV3I-Iv zEgt1cJeJ`3XeyUgjJ9?x_koobw(S)eYJx8;A9N1C6{T))hAy9az;O8tTmYqB~yL|Q~m&{%Km5bbk!?z=O$eD={7kIr5({N`tuJ#^P(h7alajDwKjdiDvXtxalImbHl_ zbzHkf@OiGRIqD___Ec4gRWc)h2vR`6BCs} zh07OaZ5^4y+@)91B(2^53|}5*-S2*Y3;YrkCbTb;%>>F zXtmk91x^ZaaO!?dAg5y=^j z<-(TATBlMcJHvIcDlS)fo0@Y|7j^Miv;M4pvxU9LKZVX8)c-@j{UyCP`up|vrdrF> zmwtA#vuV!8$F@DNwYqK2RXtp?czar+k`!&}QEZa*nDM)2HAF2s$#5N zOO(m5HkGwrW4$gFvhIOMc#4-`y{4x~B`v~|T>@DsR9P#lEWw7R=C;o4xeCNCBSp@w6@B3LgER3l8C?DvLpET3qtgaQaQ z=cQH~qyO+Leb;;I{>64+!5teW zd|E&9y@<*OgW*=&qkR4+>%K7i@jowdPg)V)_gszs2RZf8{=bFiN^>99U)WLRxdq+o z(p1ftf^)if-FuhmM^D{5GRQml=jZ7!SvNeSKO{|x^iOa8^p`!OTf*rjl~G$g4e0>vNGSY?RA^90`FnfWe;QR*Dkvupwm`-6c6)f7tvzdI*VkQ1gr-Gqe z-Ug1f*}<|dUdiK;REoF!_KW}4))DW^{*RHR8`K{L~Fg zJ}s^O7yWnoj$i8!@LO$%qz7-aSBGD}$J%Y3^u(sEtDpK^RZsG<_h$9i5A0oBoxW{( zv+oi8G5y*9*hAw}nF_tBvQ~C6)1V@uEMsNOogzCCNo&EfR%ftJ8?f4O0&swCP7kn{ z76LX(7bk#$LVyTb9oaIUGG3c1FiulRzlQROc+4$@d0c_fjV08*8?9{P-n|?3*SNb< zf31D`L$-w*uKe;)hpvxyY}`w>l}?|+uk;gc8L6C-=kK`kSKe^(AN13seFTbNDVb`0 z9b>O&3xz%n30x3Jl^7?0$Z7!{VT~PStr8HSA*t0J*Q6A|B_&m=t)pvdL(cY6T`ld_ zG2qFtfhRG_OuvLBY2q@tG;E2=QGf+W{Z(e&cdpHEtgEyCaDJN4b?ZOUN91RCl1mGB zZ!XwmS%0lCQ&j>qurBltaOex%024{UzSwgdT!(UXM2i=?y}9ZIIpsNiVngQt4D~ z8qWo7cAK61WT@R-2+T`ujX=26*e_)>q;#EvgF__K7ETPFXq9=+3w;e0i|ky`A~sIbEG~dpOjxDIN>>-2RRpp3rW+%wO&I-+oEr6Y;pm$E!W< zJv=^GtN24Te#vL`*eb0KSzg#DJ2vZY-1nmXO@7Ii?YloCOYifYNB(`ab*en?L(jnz zCFu|PEmvE@`?%XG$-F5hTcy)qmlQr^mtqm_qDEhBP(thdyz-L1%cEVx*_fr#RbNr# z4k~_E-%`Hzx~D(*MzqUjl^!15vyor_>I(kDjd%1||%$%fflwvTDcl3H6@ zn+r)IV6M#o+)8Wya%qO2mT*QRmarB)xz1Q;@_Gn@#jvDxDXkfrJ5`D`)1|RqaOHZe zu^njrpzNNtf>ti36kOJd#tH4y2bL^dCDwcHGT2?#J`3u&D7&$5@9HHRJVQCcJ<)jc z?96HG1dzj(pt^@iR<#Tqg*F}N5Z@Kvg!GL!uI zv7Xv+i^s9nl6&CaEtcQ@-GLE{}qn%4k5kXurKc7UE@l^dk5_d*p$Nd9WzJ9(;G60L&l+#j6GfhxN=^a(sC z0Cy#m@8{`M0OZaH^=QvVxq9hEe8ysFaQciz9&U$Q^bPKCcxI+==Z=TJn7Xt#=F#7` z?wNGSC6lHsSa|A)TzmR;ezeoq)_YJN;y?L^$7?zgwOh{P$p#i-dGZ&bae#iK?NBq_ zq-L~8w97|8J5z~#9wWz_F?PaaqQ|vI*P9J972=@?b zUyCZmnh;nm=GC%&TDwy0&JkLT;B>JqYxs-f%>oei-$sqIW`gVhXMY1}#v6{kmL2~U zojCgrfYcx`)J5#OtOQ&IS23wgC=-QjAjott z#X~Jq-JzS;-tfIO`kU|H@zyto7JKb>kJBCx-u5}mAFlny^Y>qM^E3LXJKxi9JaI)q z|5e{DU&%dui==?UKR_;K!D^YE)XzH)V-u4ZamjmMehA{tG& z$iS{k+3l=^@OC>vjk!s!x2!c8HV`Tlyx0P1^Ayvd^!&0m-&350y~$;5vZq*wJ@_0$ zV8r=p(55}PcnN5u%~FoIt-hw-i#&sLIN4haP9p*au>wWU63}!mybq^~`RZCGq$f|K ztGav6c^rgb$pL>b6wE)EEs{sJTHP1VR!6ozb7FAsm5bK+ zDta1c&scQ5$Kl-StFZwEKX#sffw0l-`hPq)ar=5+mmN65r~P!>vA$9Nzu% zM2FkwEI55ZW#K1Rm3ChG>SJI1^Ve<|?7IKPiPM+ev$g$FpHFXDylVFjej3Xlu>;ad z`%3Epcofyh00_O8CWYrV0xO7lQ8dF-bb{hlV}TT}Cm6|j5)q5JJ#dl_ojj>OBHd~3 zSiY-2a?;!vTRaPR6Y;g%;JP%kEYm6|3ZVs(ngUU40Td$7ydH4|&EBU4loGS~NCvRD zo~B6LVEj-no$|qJ@TOCo`MfR7G8(|vWXcjUNr6pWai2mbKcX7E5bMSOp4?Y8DTKmupi5VGK7j0){aJ7)H_zKvF0&EnH6k+hR)uGm7B*tvBy>{dwry(jf6O<6q}(1KkQ#X@cco57X)jfz#}kp@Ta29CP%gy zMg|T@qMbuD&$A}#K-S8#1Nz$@{g^(aAM@yMW4#c0JE1=%H4S7{#7yYtJcF{48f7-U z|CoM^cO2`V-lRWuf^HhSdLRq6hOi5_Gn)=h3BfmM!iu(neqHd*xt0{+AY&c;oA%r})>tEeH9_O*Q=GiVD56rb+LN1oe)J3VtlOZ}VpT5&aRK zd6M_u`y@|~KDlq-zR?&Ty6;J;;mLdX(CCw!e*r?k{{<~5E*D_qf^ohiMf8m+d?fq^ zsAv)HpNO|@+$%#wgtLfWim>fPzbf(#D*CM;c|n!|Ua3t$Z3#SBnM80K^5O(6gDN3H zMMHqLG9WB&8@vJUt`)oxQNRmT7JnFvUaXBP-oupvYeRDj@jx*QMmbDgUX+eS!r?qu&g*ZK zQvFhXK()Oz7@uXe_Q1fm&?Tu zU4+Xe=eetJvA&Q0TwkFdUjaKJV&qsA2C}n8u_{mth$B#r$BVG@aSFpD$a&tfvrH}( z^xI+*JF%ZbGmbKm48bZ1HHj>~INm!JLj@fxAXOdgTJZ#AK%jn_%BA)ua+lg$;aLH` zOJxMu0d(Pe*n$WIXTCoOA5!V{^_XwM?3Vdmo)^{(^J;$h3MfI|8q@ zZ-0)!tCs0rMiGnq7uQtNP0fgi~V%D zn43gfPjL#`Yz6F3D;FKpY3mu|!_Ps2z)`MES5f^l6FUbGWH4_+Emp? zboE?c4D0Gc76nm1q<0XBL}-sRsgdzCY%6&O(4Um&tRq`$wYWXtSYi z9Cnbi3a6nu0qIkX@RRJ&k+7v*{9J02GgCia$Ny8+m2W(8!_V$(IhWbA447K+h9|zE zBd7SE*R8lulFy|zY3!5(!pP0BN7=fu(PP*UWOEKNVGYikL)@IhVVXmuKm;F}MWb?% z1u7^dq&0apCrzuw>-@mZFbIETRx;(y|N6{!O6q?#Ia>IS%x?laIBtF|LRZC8rADEp z8`}_dZE7Ti-4un|HRq1R5_}C~?rm7V2#JdpOO;yN=+f2}+||}fyKNLeg9w?c+ztx0 zVU;yYpVq3BLJb~r8|u78D?&0KUh@A7Vo_)e0kSxZ|6gT?osa<$pZXg}cQ%eiJYs>1 z)Zt*ZW5^{_PN$u?1YQziPH+Z53}Nd?|4=;wvbW(e51DLP)Xd%@?sB+7k!ux^=5#kbs6KV)KImLewx@|G}Ky{jU3ez3E2-786bH7qG~}_y_B+zkZ!= z)vfEdUB8}xpx?D{@!|!1JHP&cMGHsYGNAVfX$&?o1PV-AP&G+CXpv?GM%hP53p^yE zKqgttLM;}XCL(s?X;5g{orsMxdv&NT+>+>|bfRYQmTX?~B#n8dQz5&U7!Oq=RozMn z3Sj7jFAsMrmq)^i$PkbD0IQJ`j&Yjr-XDJZ?)6(RE&a~7ceO0HvgM~cPwel==^gGm zIzbcv<1W5K5M=KUuj0qtIBm@Os=K=uEu{NirTaz~??2(zJ948(?(U-b|8b|ji)g}E z^JBS={U?YIklTRiBOF=*jVTd&cXGRvN(~C69}Ccx`iS^J{(+r;tkN~;gW}R6KZrhj zPJXr%RW6(!!H--}PmhS7(<7Xnf2`6qW3f@fbQLVhI@#wLMP~@bg;0l6Erhw+4Y5=L zwPYwoxlhs6f?Y5t>Ete?lnD1})t;gUJPPm8H&)G~g*@oBsId8+^WgNDA?}QfTx|+)MQvpeE>PWp2b;I7J(6$2B*CEuLZp zXn}|p$W*ML2)@O^K?|T|r-ZflDNeXC_(LD~gMEbJC1>UgjHZQAYyq94RW#}7pdg*GqEUnYa zyqr$!XiATYyazqoHewsW!yO`aj>;IPCC~FDQ}k8gxQ(19Mx`V`=SpeuN__$S;?5D& z+!Riu2S5mJoExp8bEeOTp3!SWpfnkL1c8TbfCuIxd6&ttvk@;SL=zAO{{0lv$^Z9~%gefQlrN&559wuk@ndug{&*W|k5pZeS$%g?TuG2@C;?R%c%heey= zu8=@cv_sI=jEx1MA+l_Mkv(sN<3)ChYq_MBJWd!l557((fyKNHZFcBoR%~m)GS>8I zc2e1{sz9hI+TNWZmF*>ThHww0SR_e8K?J%o@Enj|v|}O&ex*~*d58lH6op`06EXXk zfl~RGI%m3~FMR&q?THPEmX@J6KKqpZ)PVjhzo%vRcb|QV_Yd%_zQwp^-`2#OF5 zvatNbTOZt(NT5Jz`08Wd9evK&a?yT$OM>q(EAm7=n5g+`rOXOkc$-L+d&?!S$SZpT z04N9^L_h!|fdoE7VH)KS3}t8(G?EIWVzs!DN2&%vO4hmr*)hLTtZc$I1nX7XLM;xZ zSOIIzij_z*!H*Tn5bDp5NUXV>*r%mMn~hviQCX%ChX7DhY2B6sTcE{MZ0Jb;3qe%5 zKnCOXqepL-)WI!V22J<#X?+SENsP{ns^6m$Jz8(*F#cs51PQt%h^UqpG&DWR0U)79 z;EyH;^bO@+^aE*^td>eclbL7~rAh!7VaY0-RHJH%s3Q_vNi}dd3sr*g8nvlLWWuOQ zg@g;?KN~WldN62M(z5tE*!#GXzECgFvM|4Ae<=nfJ-95K|VRRO*4W9YXFRS`t-S!0Q~Hon};$NI@%D zGf5@PxL7KnPV#@DN5V;Qiqj(80>22oHwX>agh+^ocr=>Q>S2-bFw}a$@E9r%PcdOP zg(MCBq+B!rC5q*YU}UA@t$<_}V`QZp8o`-hL^%X;c2oyyNM`GmgHE^KC`|KVH3%r@ zGW|S-(lj@ZCC0>)JU}|PnBTBPf0utn9a;L7$G)(M4NPr#W_RoNq-rjCyuC>36Dggn0$xK%|<&f>2AKFF4eZq9Q2N?xHXR zB%rE~qK8trk{#H?3QwXaqtKNVtC5Q+S{WK^eb}>@BFCxf?tK zD${7kY%ZipkuQKf#Ue7QJvPw)ShV6E!6}Ge^`eL+t@Tk#fFkXPzfVOtKBX0s+QhVW zQCUlf%AKUBS$3x}ZK{)n3MMQzK1hMdAC#1a=H?I;#FQcwoWP!^h`3O33Pm6$qkOd* zMNYT?**3&eDHw(zL~(L2NRdhlWC9j9v6$e{I3i^6G0P~8MfS`s*8eOj^Np|A#_FC! zXebS)=mNCV`Tv%W!)nWkkj9td6J&`_LF9qpPCq2>t>7DIHmZ0MtYR4d$=t}ahA4+m#Sr)v=o4uMyZz|x zU$`=Pbld(Dp^#a}B*DalH1-V&N)QXTkYG)BE z1Nf(i^-uV`d2b9Ho5vfmo%hm!-p3Dcc7SSrd4$d$8+c>hJpDHVFAuyiSDK^u$uFK^ zxPsl z#;7b6_2PugqvU3^;&Q;dzhB1R(tXSLGOG4owp91&zNLH_^tO+`Y*R&Fz|VOe#a*pv zd~2Eh_oUnSvSsp!xR!3CXG;a>d8(v>o+s@AP|8Q3=SN2@K&J(xLg3283LNOR#AjBwUskZ~uiL6uE=IWkJ8$ATgvhA75ogDfZ5=LFV9Q3?>Kt6Xv= zC^+VF0DHpp1L7cWg>|d)QFB!_>9SVTL&6_V;c~ngMqqeS z+3@#hs?d_>CU2(BEFeD4;|hBBLWss$GVC|AX;>rZA|_({lxM1CbHrOZ-ZVLB0dO-E zIdXMIKFwA^xt@~MMg*{O1S)J++Jz^K6P}_M=TUKw@^wO4Q9rW-^(CN($z+MbEU_gc zqyO@kXV@?GUka-(ek|(i`U9Q%pLkU#zlyInJR-77WRJ{vHT+H{Y)lhYYY8hQsL}-i z-&z67$l8b~=y+>`6^b6mLWospj>6Vfz#m}6MpR>$BGG2@1Z1UDF9IdP5B)e(gtbrJ41-E_3`Y4vV+4~40Zn22MII#g1z6$ZM^9 zj-An;<83vo>{$$qd_jx~m{kFan#BljBYqE54Jou4@7);M621riLF4%FnwpK?iXw$WT1%)* z7pf(T!CDhj5~M^L)kXyz0mSoigd7tn?T8T{TUdc4tU&4!WgIeW%<1Q|hSEGmNqBWH zv_<~Qd5n)8U&r{5RN_Ay{e!FE#saqYD z6FN!vWt4-S<|`n8YNupVQp<`MQ%}&RRXYL5}ru7%3got5CzaMLylDyEx)QSFr z(FyNCCz8vIX`IVX8U6=W6MO|{5KBoo2I~m8XynkThzD;!lHU}9V|bX}epLK|Ds}J= z57YaPUV3-w{5K$de!MD}M`bxjK{1LFKk_DI3RN{bKQ%gY&Zu;Bj(+Ueu8+JEnL_E! z9O>w%5rmw1%Pv&mjPw1Bac^cM$MBLcba+Xa14`L!0`&@`C}si+0Vc%>DOGaWNw8gH z5?mfK9CpJugh6+t#2oFgdqp=g2%4f4t0D5jC8k#-VKpGpQI50_te?m9behdAd4m>+ z3ZzIqZFqyyVc`_oD0fPJj)i^jtT1h&d4Ocz`?l9hui6YFi?##Q=nFiTEx|ao|7;E@t&pV zoZhnpf07F$-ghGZ_#*Q?r~h~8jLglL^ijR~ITS`?J&lowMIwYqxa0!^o>|!kWAF^r z!a&6s4SaShD>abC|8F8R`#6O5G4QMzEO`j8<64@8)LjsnfyxFlBOakY(^VJM{pXOG zY5+5`rZmel=gnL)=6nvCAv*$l06e4`MOlIhW9SUFOZZD8V5N`xRcVAc~ujMflpR2^IABE$iD@R^nD+XCKi#T1q&Yi z<~>(cPkEO$p?7@BZykMp{8sc#14R$wgZmup%q#TE@PAU^mwFoi!73Yv(xW(e(zqEH zsf38gAo9+r>0i1X9(NGs7h z&auUGhOVM$5}amgV;1}pq%h8j5#cO5Ku<8+#aS8!L$9FVxsQWwVo&fC-@(7Yzt4|J zbEJEulk!uRuUh`Mb-H!0?F;sG_7@#jJ0s55Tn(-ru18$&RP3qrR~9NaRqm~FRZXfo zbhS4k&8}Zxxs$UOG4=fFQHn1=7|Kt!5kW?go8`2omDb)ck~Kp?KPENG7)+U&nrh zud&aOIr){jFCmuwj=3+hNx0Xz#=@HUBy-=&cJM3BeH+@3oBK}WdpN)!{|xJv7K*ns=d%cK$Xd3IU5_ze$2Q|Qh3|D}iLg~Tz8Tw1*xN3y`smd+;lAy7 zhb)5H0J?uW_SWM6VOfLUEjSwMwGG#7$KMt<3GuBYyGi_Y;Z5Gn>;~W=dg6MtZ^9jP z?`Di>Ext*#Zb54&`d`Ji;!5i0TC~K0@Qf$U{K)erV0P38&5Zh^>#k>uaJ(K*qxo#Z zJiAyo{`ydZbs6$R%TU2H`GWU#e(25%^&R=pHA}^_$5Zv((+1gMP>G&Behk-Ol-td* z-iY%(Vtif5VdXHcYcb|epijDH9nKJ)R-5;CVcUaxgcPp5(AYja{(0zys1t$Jx*k2> zfM25a<_q5a;h8PNm8-|CwlU5Hg2oXx54{;&lo4~xV!gXDwn-RaH(FBorLmg2?#%OO zxzJ}d8X-Fzm3Q2N`cNCHpd5Ia--Tk2N?wIvWHtA|CVTOEuAc{Z5P`TF)Qi{gdfvdp zC>d$u5k$sgJkFbuQ%)cb*v2RDiM$=fBAs|QJIT9w4>V1hXAm#QA@tYF`}ib2nNPv% zu>Htx7WhScI-kKW<}>*$KAX=$1^zrffR_gs@P+&mKFBZSi}+%`gkQ!HOXNd*m@nrm z_~rZxekGjnmG&DpZa zFV$`Im+Ch9OLZIlrMiv&Qr$*>scxgcRJYMzs@v?Z#~5d-$Lz1i?61e{ugC1K$Lz1i z=r3)KBW;c&ZH^;tjw5Z3BW;c&ZH^;tjw5Z3BV+cHG5g7w{bbC3GG;#+v!9IFPsZ#g zbG9F2J{fa98FM}vb3Pe!J{fa98FM}vb3U0KgFcxagFcxav%i!J@we_6A?tl3}I>@REdmo?WbYpz$;T(4|* z8pe*Fxn1LTu>s97I8@|(&v0=T{Xb5c2mc9_e-U=n;V}NwrOStgHGezF`lUauSjgD_ E0Y(B4qyPW_ literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.woff b/sources/wp-content/themes/twentythirteen/fonts/genericons-regular-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..b57e62c0f67219a9c0635f0f88c4255842bc80d0 GIT binary patch literal 12156 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 literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/fonts/genericons.css b/sources/wp-content/themes/twentythirteen/fonts/genericons.css new file mode 100644 index 0000000..2fde399 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/fonts/genericons.css @@ -0,0 +1,157 @@ +/** + + Genericons Helper CSS + +*/ + + +/** + * The font was graciously generated by Font Squirrel (http://www.fontsquirrel.com). We love those guys. + */ +@font-face { + font-family: 'Genericons'; + src: url('genericons-regular-webfont.eot'); +} + +@font-face { + font-family: 'Genericons'; + src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), + url('genericons-regular-webfont.ttf') format('truetype'), + url('genericons-regular-webfont.svg#genericonsregular') format('svg'); + font-weight: normal; + font-style: normal; +} + + +/** + * All Genericons. + */ +[class*="genericon"] { + display: inline-block; + width: 16px; + height: 16px; + -webkit-font-smoothing: antialiased; + font-size: 16px; + line-height: 1; + font-family: 'Genericons'; + text-decoration: inherit; + font-weight: normal; + font-style: normal; + vertical-align: top; +} + +/* IE7 */ +[class*="genericon"] { + *overflow: auto; + *zoom: 1; + *display: inline; +} + +/** + * Individual icons. + */ + +/* Post formats */ +.genericon-standard:before { content: '\f100'; } +.genericon-aside:before { content: '\f101'; } +.genericon-image:before { content: '\f102'; } +.genericon-gallery:before { content: '\f103'; } +.genericon-video:before { content: '\f104'; } +.genericon-status:before { content: '\f105'; } +.genericon-quote:before { content: '\f106'; } +.genericon-link:before { content: '\f107'; } +.genericon-chat:before { content: '\f108'; } +.genericon-audio:before { content: '\f109'; } + +/* Social icons */ +.genericon-github:before { content: '\f200'; } +.genericon-dribbble:before { content: '\f201'; } +.genericon-twitter:before { content: '\f202'; } +.genericon-facebook:before { content: '\f203'; } +.genericon-facebook-alt:before { content: '\f204'; } +.genericon-wordpress:before { content: '\f205'; } +.genericon-googleplus:before { content: '\f206'; } +.genericon-linkedin:before { content: '\f207'; } +.genericon-linkedin-alt:before { content: '\f208'; } +.genericon-pinterest:before { content: '\f209'; } +.genericon-pinterest-alt:before { content: '\f210'; } +.genericon-flickr:before { content: '\f211'; } +.genericon-vimeo:before { content: '\f212'; } +.genericon-youtube:before { content: '\f213'; } +.genericon-tumblr:before { content: '\f214'; } +.genericon-instagram:before { content: '\f215'; } +.genericon-codepen:before { content: '\f216'; } + +/* Meta icons */ +.genericon-comment:before { content: '\f300'; } +.genericon-category:before { content: '\f301'; } +.genericon-tag:before { content: '\f302'; } +.genericon-time:before { content: '\f303'; } +.genericon-user:before { content: '\f304'; } +.genericon-day:before { content: '\f305'; } +.genericon-week:before { content: '\f306'; } +.genericon-month:before { content: '\f307'; } +.genericon-pinned:before { content: '\f308'; } + +/* Other icons */ +.genericon-search:before { content: '\f400'; } +.genericon-unzoom:before { content: '\f401'; } +.genericon-zoom:before { content: '\f402'; } +.genericon-show:before { content: '\f403'; } +.genericon-hide:before { content: '\f404'; } +.genericon-close:before { content: '\f405'; } +.genericon-close-alt:before { content: '\f406'; } +.genericon-trash:before { content: '\f407'; } +.genericon-star:before { content: '\f408'; } +.genericon-home:before { content: '\f409'; } +.genericon-mail:before { content: '\f410'; } +.genericon-edit:before { content: '\f411'; } +.genericon-reply:before { content: '\f412'; } +.genericon-feed:before { content: '\f413'; } +.genericon-warning:before { content: '\f414'; } +.genericon-share:before { content: '\f415'; } +.genericon-attachment:before { content: '\f416'; } +.genericon-location:before { content: '\f417'; } +.genericon-checkmark:before { content: '\f418'; } +.genericon-menu:before { content: '\f419'; } +.genericon-top:before { content: '\f420'; } +.genericon-minimize:before { content: '\f421'; } +.genericon-maximize:before { content: '\f422'; } +.genericon-404:before { content: '\f423'; } +.genericon-spam:before { content: '\f424'; } +.genericon-summary:before { content: '\f425'; } +.genericon-cloud:before { content: '\f426'; } +.genericon-key:before { content: '\f427'; } +.genericon-dot:before { content: '\f428'; } +.genericon-next:before { content: '\f429'; } +.genericon-previous:before { content: '\f430'; } +.genericon-expand:before { content: '\f431'; } +.genericon-collapse:before { content: '\f432'; } +.genericon-dropdown:before { content: '\f433'; } +.genericon-dropdown-left:before { content: '\f434'; } +.genericon-top:before { content: '\f435'; } +.genericon-draggable:before { content: '\f436'; } +.genericon-phone:before { content: '\f437'; } +.genericon-send-to-phone:before { content: '\f438'; } +.genericon-plugin:before { content: '\f439'; } +.genericon-cloud-download:before { content: '\f440'; } +.genericon-cloud-upload:before { content: '\f441'; } +.genericon-external:before { content: '\f442'; } +.genericon-document:before { content: '\f443'; } +.genericon-book:before { content: '\f444'; } +.genericon-cog:before { content: '\f445'; } +.genericon-unapprove:before { content: '\f446'; } +.genericon-cart:before { content: '\f447'; } +.genericon-pause:before { content: '\f448'; } +.genericon-stop:before { content: '\f449'; } +.genericon-skip-back:before { content: '\f450'; } +.genericon-skip-ahead:before { content: '\f451'; } +.genericon-play:before { content: '\f452'; } +.genericon-tablet:before { content: '\f453'; } +.genericon-send-to-tablet:before { content: '\f454'; } + +/* Generic shapes */ +.genericon-uparrow:before { content: '\f500'; } +.genericon-rightarrow:before { content: '\f501'; } +.genericon-downarrow:before { content: '\f502'; } +.genericon-leftarrow:before { content: '\f503'; } diff --git a/sources/wp-content/themes/twentythirteen/footer.php b/sources/wp-content/themes/twentythirteen/footer.php new file mode 100644 index 0000000..725251c --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/footer.php @@ -0,0 +1,26 @@ + + +
    +
    + + +
    + + +
    +
    +
    + + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/functions.php b/sources/wp-content/themes/twentythirteen/functions.php new file mode 100644 index 0000000..047675f --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/functions.php @@ -0,0 +1,548 @@ + for posts and comments. + add_theme_support( 'automatic-feed-links' ); + + /* + * Switches default core markup for search form, comment form, + * and comments to output valid HTML5. + */ + add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list' ) ); + + /* + * This theme supports all available post formats by default. + * See http://codex.wordpress.org/Post_Formats + */ + add_theme_support( 'post-formats', array( + 'aside', 'audio', 'chat', 'gallery', 'image', 'link', 'quote', 'status', 'video' + ) ); + + // This theme uses wp_nav_menu() in one location. + register_nav_menu( 'primary', __( 'Navigation Menu', 'twentythirteen' ) ); + + /* + * This theme uses a custom image size for featured images, displayed on + * "standard" posts and pages. + */ + add_theme_support( 'post-thumbnails' ); + set_post_thumbnail_size( 604, 270, true ); + + // This theme uses its own gallery styles. + add_filter( 'use_default_gallery_style', '__return_false' ); +} +add_action( 'after_setup_theme', 'twentythirteen_setup' ); + +/** + * Return the Google font stylesheet URL, if available. + * + * The use of Source Sans Pro and Bitter by default is localized. For languages + * that use characters not supported by the font, the font can be disabled. + * + * @since Twenty Thirteen 1.0 + * + * @return string Font stylesheet or empty string if disabled. + */ +function twentythirteen_fonts_url() { + $fonts_url = ''; + + /* Translators: If there are characters in your language that are not + * supported by Source Sans Pro, translate this to 'off'. Do not translate + * into your own language. + */ + $source_sans_pro = _x( 'on', 'Source Sans Pro font: on or off', 'twentythirteen' ); + + /* Translators: If there are characters in your language that are not + * supported by Bitter, translate this to 'off'. Do not translate into your + * own language. + */ + $bitter = _x( 'on', 'Bitter font: on or off', 'twentythirteen' ); + + if ( 'off' !== $source_sans_pro || 'off' !== $bitter ) { + $font_families = array(); + + if ( 'off' !== $source_sans_pro ) + $font_families[] = 'Source Sans Pro:300,400,700,300italic,400italic,700italic'; + + if ( 'off' !== $bitter ) + $font_families[] = 'Bitter:400,700'; + + $query_args = array( + 'family' => urlencode( implode( '|', $font_families ) ), + 'subset' => urlencode( 'latin,latin-ext' ), + ); + $fonts_url = add_query_arg( $query_args, "//fonts.googleapis.com/css" ); + } + + return $fonts_url; +} + +/** + * Enqueue scripts and styles for the front end. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_scripts_styles() { + /* + * Adds JavaScript to pages with the comment form to support + * sites with threaded comments (when in use). + */ + if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) + wp_enqueue_script( 'comment-reply' ); + + // Adds Masonry to handle vertical alignment of footer widgets. + if ( is_active_sidebar( 'sidebar-1' ) ) + wp_enqueue_script( 'jquery-masonry' ); + + // Loads JavaScript file with functionality specific to Twenty Thirteen. + wp_enqueue_script( 'twentythirteen-script', get_template_directory_uri() . '/js/functions.js', array( 'jquery' ), '2013-07-18', true ); + + // Add Source Sans Pro and Bitter fonts, used in the main stylesheet. + wp_enqueue_style( 'twentythirteen-fonts', twentythirteen_fonts_url(), array(), null ); + + // Add Genericons font, used in the main stylesheet. + wp_enqueue_style( 'genericons', get_template_directory_uri() . '/fonts/genericons.css', array(), '2.09' ); + + // Loads our main stylesheet. + wp_enqueue_style( 'twentythirteen-style', get_stylesheet_uri(), array(), '2013-07-18' ); + + // Loads the Internet Explorer specific stylesheet. + wp_enqueue_style( 'twentythirteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentythirteen-style' ), '2013-07-18' ); + wp_style_add_data( 'twentythirteen-ie', 'conditional', 'lt IE 9' ); +} +add_action( 'wp_enqueue_scripts', 'twentythirteen_scripts_styles' ); + +/** + * Filter the page title. + * + * Creates a nicely formatted and more specific title element text for output + * in head of document, based on current view. + * + * @since Twenty Thirteen 1.0 + * + * @param string $title Default title text for current view. + * @param string $sep Optional separator. + * @return string The filtered title. + */ +function twentythirteen_wp_title( $title, $sep ) { + global $paged, $page; + + if ( is_feed() ) + return $title; + + // Add the site name. + $title .= get_bloginfo( 'name' ); + + // Add the site description for the home/front page. + $site_description = get_bloginfo( 'description', 'display' ); + if ( $site_description && ( is_home() || is_front_page() ) ) + $title = "$title $sep $site_description"; + + // Add a page number if necessary. + if ( $paged >= 2 || $page >= 2 ) + $title = "$title $sep " . sprintf( __( 'Page %s', 'twentythirteen' ), max( $paged, $page ) ); + + return $title; +} +add_filter( 'wp_title', 'twentythirteen_wp_title', 10, 2 ); + +/** + * Register two widget areas. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_widgets_init() { + register_sidebar( array( + 'name' => __( 'Main Widget Area', 'twentythirteen' ), + 'id' => 'sidebar-1', + 'description' => __( 'Appears in the footer section of the site.', 'twentythirteen' ), + 'before_widget' => '', + 'before_title' => '

    ', + 'after_title' => '

    ', + ) ); + + register_sidebar( array( + 'name' => __( 'Secondary Widget Area', 'twentythirteen' ), + 'id' => 'sidebar-2', + 'description' => __( 'Appears on posts and pages in the sidebar.', 'twentythirteen' ), + 'before_widget' => '', + 'before_title' => '

    ', + 'after_title' => '

    ', + ) ); +} +add_action( 'widgets_init', 'twentythirteen_widgets_init' ); + +if ( ! function_exists( 'twentythirteen_paging_nav' ) ) : +/** + * Display navigation to next/previous set of posts when applicable. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_paging_nav() { + global $wp_query; + + // Don't print empty markup if there's only one page. + if ( $wp_query->max_num_pages < 2 ) + return; + ?> + + post_parent ) : get_adjacent_post( false, '', true ); + $next = get_adjacent_post( false, '', false ); + + if ( ! $next && ! $previous ) + return; + ?> + + ' . __( 'Sticky', 'twentythirteen' ) . '
    '; + + if ( ! has_post_format( 'link' ) && 'post' == get_post_type() ) + twentythirteen_entry_date(); + + // Translators: used between list items, there is a space after the comma. + $categories_list = get_the_category_list( __( ', ', 'twentythirteen' ) ); + if ( $categories_list ) { + echo '' . $categories_list . ''; + } + + // Translators: used between list items, there is a space after the comma. + $tag_list = get_the_tag_list( '', __( ', ', 'twentythirteen' ) ); + if ( $tag_list ) { + echo '' . $tag_list . ''; + } + + // Post author + if ( 'post' == get_post_type() ) { + printf( '', + esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ), + esc_attr( sprintf( __( 'View all posts by %s', 'twentythirteen' ), get_the_author() ) ), + get_the_author() + ); + } +} +endif; + +if ( ! function_exists( 'twentythirteen_entry_date' ) ) : +/** + * Print HTML with date information for current post. + * + * Create your own twentythirteen_entry_date() to override in a child theme. + * + * @since Twenty Thirteen 1.0 + * + * @param boolean $echo (optional) Whether to echo the date. Default true. + * @return string The HTML-formatted post date. + */ +function twentythirteen_entry_date( $echo = true ) { + if ( has_post_format( array( 'chat', 'status' ) ) ) + $format_prefix = _x( '%1$s on %2$s', '1: post format name. 2: date', 'twentythirteen' ); + else + $format_prefix = '%2$s'; + + $date = sprintf( '', + esc_url( get_permalink() ), + esc_attr( sprintf( __( 'Permalink to %s', 'twentythirteen' ), the_title_attribute( 'echo=0' ) ) ), + esc_attr( get_the_date( 'c' ) ), + esc_html( sprintf( $format_prefix, get_post_format_string( get_post_format() ), get_the_date() ) ) + ); + + if ( $echo ) + echo $date; + + return $date; +} +endif; + +if ( ! function_exists( 'twentythirteen_the_attached_image' ) ) : +/** + * Print the attached image with a link to the next attached image. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_the_attached_image() { + /** + * Filter the image attachment size to use. + * + * @since Twenty thirteen 1.0 + * + * @param array $size { + * @type int The attachment height in pixels. + * @type int The attachment width in pixels. + * } + */ + $attachment_size = apply_filters( 'twentythirteen_attachment_size', array( 724, 724 ) ); + $next_attachment_url = wp_get_attachment_url(); + $post = get_post(); + + /* + * 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. + */ + $attachment_ids = get_posts( array( + 'post_parent' => $post->post_parent, + 'fields' => 'ids', + 'numberposts' => -1, + 'post_status' => 'inherit', + 'post_type' => 'attachment', + 'post_mime_type' => 'image', + 'order' => 'ASC', + 'orderby' => 'menu_order ID' + ) ); + + // If there is more than 1 attachment in a gallery... + if ( count( $attachment_ids ) > 1 ) { + foreach ( $attachment_ids as $attachment_id ) { + if ( $attachment_id == $post->ID ) { + $next_id = current( $attachment_ids ); + break; + } + } + + // get the URL of the next image attachment... + if ( $next_id ) + $next_attachment_url = get_attachment_link( $next_id ); + + // or get the URL of the first image attachment. + else + $next_attachment_url = get_attachment_link( array_shift( $attachment_ids ) ); + } + + printf( '%3$s', + esc_url( $next_attachment_url ), + the_title_attribute( array( 'echo' => false ) ), + wp_get_attachment_image( $post->ID, $attachment_size ) + ); +} +endif; + +/** + * Return the post URL. + * + * @uses get_url_in_content() to get the URL in the post meta (if it exists) or + * the first link found in the post content. + * + * Falls back to the post permalink if no URL is found in the post. + * + * @since Twenty Thirteen 1.0 + * + * @return string The Link format URL. + */ +function twentythirteen_get_link_url() { + $content = get_the_content(); + $has_url = get_url_in_content( $content ); + + return ( $has_url ) ? $has_url : apply_filters( 'the_permalink', get_permalink() ); +} + +/** + * Extend the default WordPress body classes. + * + * Adds body classes to denote: + * 1. Single or multiple authors. + * 2. Active widgets in the sidebar to change the layout and spacing. + * 3. When avatars are disabled in discussion settings. + * + * @since Twenty Thirteen 1.0 + * + * @param array $classes A list of existing body class values. + * @return array The filtered body class list. + */ +function twentythirteen_body_class( $classes ) { + if ( ! is_multi_author() ) + $classes[] = 'single-author'; + + if ( is_active_sidebar( 'sidebar-2' ) && ! is_attachment() && ! is_404() ) + $classes[] = 'sidebar'; + + if ( ! get_option( 'show_avatars' ) ) + $classes[] = 'no-avatars'; + + return $classes; +} +add_filter( 'body_class', 'twentythirteen_body_class' ); + +/** + * Adjust content_width value for video post formats and attachment templates. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_content_width() { + global $content_width; + + if ( is_attachment() ) + $content_width = 724; + elseif ( has_post_format( 'audio' ) ) + $content_width = 484; +} +add_action( 'template_redirect', 'twentythirteen_content_width' ); + +/** + * Add postMessage support for site title and description for the Customizer. + * + * @since Twenty Thirteen 1.0 + * + * @param WP_Customize_Manager $wp_customize Customizer object. + * @return void + */ +function twentythirteen_customize_register( $wp_customize ) { + $wp_customize->get_setting( 'blogname' )->transport = 'postMessage'; + $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage'; + $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage'; +} +add_action( 'customize_register', 'twentythirteen_customize_register' ); + +/** + * Enqueue Javascript postMessage handlers for the Customizer. + * + * Binds JavaScript handlers to make the Customizer preview + * reload changes asynchronously. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_customize_preview_js() { + wp_enqueue_script( 'twentythirteen-customizer', get_template_directory_uri() . '/js/theme-customizer.js', array( 'customize-preview' ), '20130226', true ); +} +add_action( 'customize_preview_init', 'twentythirteen_customize_preview_js' ); diff --git a/sources/wp-content/themes/twentythirteen/header.php b/sources/wp-content/themes/twentythirteen/header.php new file mode 100644 index 0000000..e19703c --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/header.php @@ -0,0 +1,51 @@ + section and everything up till
    + * + * @package WordPress + * @subpackage Twenty_Thirteen + * @since Twenty Thirteen 1.0 + */ +?> + + + +> + + + + + <?php wp_title( '|', true, 'right' ); ?> + + + + + + +> +
    + + +
    diff --git a/sources/wp-content/themes/twentythirteen/image.php b/sources/wp-content/themes/twentythirteen/image.php new file mode 100644 index 0000000..b2d86bf --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/image.php @@ -0,0 +1,82 @@ + + +
    +
    +
    > +
    +

    + + +
    + +
    + + +
    +
    + + + +
    + +
    + +
    +
    + + post_content ) ) : ?> +
    + + '' ) ); ?> +
    + + +
    +
    + + + +
    +
    + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/images/dotted-line-2x.png b/sources/wp-content/themes/twentythirteen/images/dotted-line-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..07f6c93f29ab47b71b6d203a3e5a37ab49642256 GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqvYsxEArj%q2?+@iY={2;|DS%K iO_D?FfU4mV5e5daJzJl?Z~Y2V$l&Sf=d#Wzp$Py_6&QX1 literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/dotted-line-light-2x.png b/sources/wp-content/themes/twentythirteen/images/dotted-line-light-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..059d4ec05171be7a9bab5140ee59814561aea8fc GIT binary patch literal 85 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqGM+AuArj%q2?+@s*dG4>|KB*_ iFb|99gGmxWTntTjwpdDa?wtly$KdJe=d#Wzp$Pyq8W(T? literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/dotted-line-light.png b/sources/wp-content/themes/twentythirteen/images/dotted-line-light.png new file mode 100644 index 0000000000000000000000000000000000000000..b7f82cdbfd223a587bdc7bc5e724dd798a7aa911 GIT binary patch literal 80 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 literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/headers/diamond-thumbnail.png b/sources/wp-content/themes/twentythirteen/images/headers/diamond-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..82777a04cb88ca0439a5ade06381c163fcaa9dad GIT binary patch literal 1847 zcmYLKdsq`!7DtL*p6ddFQm9LXWThs40vWrCpYl)y!T<$?gzz?r84`;PaaF8hA{3)Y zQE)6%utG_+DTI(fKo%5{f;fx~2_~Y5#Rrp>iN!0W>f;91M2& z0m0(O4@TdXt_BBJfO1B|SDS%4e!9B^ARmGKE3G##ft~^|xEGYH1Ya!!=o;|m6_C=v z*&NW34O-%729AL7@4(qqux$xw2nXjS;2Q?$5rFbQ@boq)rGbi7peqF!{sA&wXD*ck zJRh7{54QV(hhspW1-eqf4l3x(?P-t!-r^Sn<$$OFZ3!JG_qW&V1Gp62QNDfoE7(Wd z6J2e!v6&B|H-shc%Iv$wj_V6`{xB!&a_vz6xv81;F0B>zYga0w+wOMu{_XX|H*Zd# zm^vA6op>s^kwv865JzX+^qE@H+41P{zBO65M!yi{XZ?IDQBa5%!um%o3d=NlG}6Q| z3$?rj^loK)Su!@R&8(#F;aZ_?-d$hffQDw~;!9YCaK2Xnnd+u;Ui3r@3-Kt0mEJwM zU_8fbzf&Yc7ci|#pbmW>*DC5;qIiy0m?K?F)+!od(V?WXJ zKhw>rzmGp76}qV`6j_0$tB1S%a0UEJ-nys0_+FoZnjUe(q!pbCWEIrjTMTQaF%v_| zyRfZZVOd)vvO?ah>+vDad$ghMwBwVGcn+3rWvrJspEz!xyUhOL6(q=T^9DLZrFL1o@Sl`nN?iZEhCqYFYGP7WPt3jkmPY#ZBCtiiH3iF=5Xc-pi z$7pq4KgcJ`vXSN=TSwMcRYu}!PH1qX6LH|xPL0G|tSC`l5ziwe3w6EcQruDdTs5X? z9ZqKd1|?mFBCe@dCqp^%e~)jjq&G1<&_be0OgtI(#OvzW8p%~IGlUpG5?Lw+3BH)h z!w>N<7)huL#9KxSL1iFm+Pt1yw39M9L-QiDiath^G`G!s=x zPlbpi?SJ7$k)~MLD<;TGVOr}`9*no_{6ptmp=E!TiL9Lg%%b}*BvI!1dOQ^bSc~%A}Qr5DT+bP?V#5@zBl87IH(TtV_+uh?B&FI ztG6xD`%IE9h@o#f<$y-i@QWi0Iz@rx`1WqujyU08)&;crGzse|Obhz$4m8JkKj&gU@S=jR8X+bt$wNTC zCIOzNv96(uSOA*-|AccyDYZS;Kw9>=2@fT}IuUZE9ZAIPh%_lx(}yi3dy`W2cd;)V z7*dM4Dl#7!8O&1-^s`EiEi71F;=mEZx<|uZR^WH+6nnYR4oyg+DPNuQso-P0bY03B z2ij4ky-9*oMq;&PLh~U=N-->yl6uhh>-JMD)2jL8+Z6iyf?c1urB}rNc9;AKZK5~E KZBU12%l-rXtfLVC literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/headers/diamond.png b/sources/wp-content/themes/twentythirteen/images/headers/diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..a14de6146938dd619f0dbdd8657ab2427f134b55 GIT binary patch literal 14266 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 literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/headers/star-thumbnail.png b/sources/wp-content/themes/twentythirteen/images/headers/star-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..693bb7618bbe65c106536ab376168a09f6efdd39 GIT binary patch literal 4039 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 literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/headers/star.png b/sources/wp-content/themes/twentythirteen/images/headers/star.png new file mode 100644 index 0000000000000000000000000000000000000000..24ca62686d5ebdbfd7bae2c0cc8e3afe4f7e2074 GIT binary patch literal 22620 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 literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/search-icon-2x.png b/sources/wp-content/themes/twentythirteen/images/search-icon-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..02b63b8027efb48e1edd1344fa8b81690df30950 GIT binary patch literal 829 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sZv%WnTt!5L{{R0EBu4^z=RETk z(Bpn3L4Lsu42;aIZ0y`T0)j%qBBJsNipnYmM#iRQR@OGQc0Rs-(J_e?l~ofa&Rei> z(c&drw(i)uYwy1O2M!)Oa`e=t%U7;mzj5>K>o@N{fBo_6&tI?n6H-7EH+s4_hE&9z zy_O%o$U%bjgP|7Bnb^Z7!H4Zg=rf-+%e=oXy>bjhT;^-<{rPFL7*U zw@PtJAA5UXRNK=X>yjmXTNfxSm>u`Q{$BSyro6WbV!J0XEXh0I87{wC1u|*f}AJY@@p31IL^*3~;!Onlq?-dIf=I)=XzVV6L!WW4F z3-8-2Yb*~55!k@E=2Oe$)B72g6)rg3{@du`vMuZvI~auzbZ{6kBy4(csQIgYhXZ3B zzki~G@H#`~LuV3qoNRDskTrb4U?7pexT4chwBaZNdxILA6hk}Xe1;Um35+{<3K&x+ zA8ccke;FLLxP6_v{TC+P*Uq0deUrSvWFX!w*iC5zFXS%ybVomurZrE2`Sm^hJl!3m|t zRhRyRPc8L5=N2l-8FFkdL;CDamgVo37k&s+ndrc9$)aZAoB8h({z@LKPxX~4-yHYl zcFBJOCPtYsg$Y^$9>N?QtV}DJ{54}`{$78`-khI5eZmjvisZk*WWnI+>gTe~DWM4f D1|tld literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/images/search-icon.png b/sources/wp-content/themes/twentythirteen/images/search-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..11d8dc8e508ef47cca63ace49a5a4c377d5f3b6b GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaARRs8ixQd7f{r~?TNYWV{ny_XA z&<*M(L4Lsu42=8&5|Z)?28LGFHeTL!^$m?PX3kx)a>MRD2kzdx|KQ2XSFiv4JrQK) z2h_67)5S5Q;#TR!NTDVJ0oRLs3JcCG%9x?VR{Q(@LRAyPh=O|m)K?R3bS|3|qow+J zh6UStrtnHL7uk}TKkKUM7IoJ>_?F=`iz};ST_abo^PJ$tQ3}T-CTU*rkl>n<61pg1 zf=8~0qNE6)*^dAo{vX*AXToOkN=CK)`TwDN=elj{t@rs^^Y6LH6xXh1pxn5j?S}L8 zm*pK&Gg=z&q`rB-dq(QlK<8>(A>Ts@#}94L+@koIYvWzJ8iv<(f|ImAGuHuqz~JfX K=d#Wzp$P!)KZd3N literal 0 HcmV?d00001 diff --git a/sources/wp-content/themes/twentythirteen/inc/back-compat.php b/sources/wp-content/themes/twentythirteen/inc/back-compat.php new file mode 100644 index 0000000..b08813c --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/inc/back-compat.php @@ -0,0 +1,71 @@ +

    %s

    ', $message ); +} + +/** + * Prevent the Theme Customizer from being loaded on WordPress versions prior to 3.6. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_customize() { + wp_die( sprintf( __( 'Twenty Thirteen requires at least WordPress version 3.6. You are running version %s. Please upgrade and try again.', 'twentythirteen' ), $GLOBALS['wp_version'] ), '', array( + 'back_link' => true, + ) ); +} +add_action( 'load-customize.php', 'twentythirteen_customize' ); + +/** + * Prevent the Theme Preview from being loaded on WordPress versions prior to 3.4. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_preview() { + if ( isset( $_GET['preview'] ) ) { + wp_die( sprintf( __( 'Twenty Thirteen requires at least WordPress version 3.6. You are running version %s. Please upgrade and try again.', 'twentythirteen' ), $GLOBALS['wp_version'] ) ); + } +} +add_action( 'template_redirect', 'twentythirteen_preview' ); diff --git a/sources/wp-content/themes/twentythirteen/inc/custom-header.php b/sources/wp-content/themes/twentythirteen/inc/custom-header.php new file mode 100644 index 0000000..3214f63 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/inc/custom-header.php @@ -0,0 +1,227 @@ + '220e10', + 'default-image' => '%s/images/headers/circle.png', + + // Set height and width, with a maximum value for the width. + 'height' => 230, + 'width' => 1600, + + // Callbacks for styling the header and the admin preview. + 'wp-head-callback' => 'twentythirteen_header_style', + 'admin-head-callback' => 'twentythirteen_admin_header_style', + 'admin-preview-callback' => 'twentythirteen_admin_header_image', + ); + + add_theme_support( 'custom-header', $args ); + + /* + * Default custom headers packaged with the theme. + * %s is a placeholder for the theme template directory URI. + */ + register_default_headers( array( + 'circle' => array( + 'url' => '%s/images/headers/circle.png', + 'thumbnail_url' => '%s/images/headers/circle-thumbnail.png', + 'description' => _x( 'Circle', 'header image description', 'twentythirteen' ) + ), + 'diamond' => array( + 'url' => '%s/images/headers/diamond.png', + 'thumbnail_url' => '%s/images/headers/diamond-thumbnail.png', + 'description' => _x( 'Diamond', 'header image description', 'twentythirteen' ) + ), + 'star' => array( + 'url' => '%s/images/headers/star.png', + 'thumbnail_url' => '%s/images/headers/star-thumbnail.png', + 'description' => _x( 'Star', 'header image description', 'twentythirteen' ) + ), + ) ); +} +add_action( 'after_setup_theme', 'twentythirteen_custom_header_setup', 11 ); + +/** + * Load our special font CSS files. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_custom_header_fonts() { + // Add Source Sans Pro and Bitter fonts. + wp_enqueue_style( 'twentythirteen-fonts', twentythirteen_fonts_url(), array(), null ); + + // Add Genericons font. + wp_enqueue_style( 'genericons', get_template_directory_uri() . '/fonts/genericons.css', array(), '2.09' ); +} +add_action( 'admin_print_styles-appearance_page_custom-header', 'twentythirteen_custom_header_fonts' ); + +/** + * Style the header text displayed on the blog. + * + * get_header_textcolor() options: Hide text (returns 'blank'), or any hex value. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_header_style() { + $header_image = get_header_image(); + $text_color = get_header_textcolor(); + + // If no custom options for text are set, let's bail. + if ( empty( $header_image ) && $text_color == get_theme_support( 'custom-header', 'default-text-color' ) ) + return; + + // If we get this far, we have custom styles. + ?> + + Header admin panel. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_admin_header_style() { + $header_image = get_header_image(); +?> + + Header admin panel. + * + * This callback overrides the default markup displayed there. + * + * @since Twenty Thirteen 1.0 + * + * @return void + */ +function twentythirteen_admin_header_image() { + ?> + + + +
    +
    + + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/js/functions.js b/sources/wp-content/themes/twentythirteen/js/functions.js new file mode 100644 index 0000000..777a5cf --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/js/functions.js @@ -0,0 +1,81 @@ +/** + * Functionality specific to Twenty Thirteen. + * + * Provides helper functions to enhance the theme experience. + */ + +( function( $ ) { + var body = $( 'body' ), + _window = $( window ); + + /** + * Adds a top margin to the footer if the sidebar widget area is higher + * than the rest of the page, to help the footer always visually clear + * the sidebar. + */ + $( function() { + if ( body.is( '.sidebar' ) ) { + var sidebar = $( '#secondary .widget-area' ), + secondary = ( 0 == sidebar.length ) ? -40 : sidebar.height(), + margin = $( '#tertiary .widget-area' ).height() - $( '#content' ).height() - secondary; + + if ( margin > 0 && _window.innerWidth() > 999 ) + $( '#colophon' ).css( 'margin-top', margin + 'px' ); + } + } ); + + /** + * Enables menu toggle for small screens. + */ + ( function() { + var nav = $( '#site-navigation' ), button, menu; + if ( ! nav ) + return; + + button = nav.find( '.menu-toggle' ); + if ( ! button ) + return; + + // Hide button if menu is missing or empty. + menu = nav.find( '.nav-menu' ); + if ( ! menu || ! menu.children().length ) { + button.hide(); + return; + } + + $( '.menu-toggle' ).on( 'click.twentythirteen', function() { + nav.toggleClass( 'toggled-on' ); + } ); + } )(); + + /** + * Makes "skip to content" link work correctly in IE9 and Chrome for better + * accessibility. + * + * @link http://www.nczonline.net/blog/2013/01/15/fixing-skip-to-content-links/ + */ + _window.on( 'hashchange.twentythirteen', function() { + var element = document.getElementById( location.hash.substring( 1 ) ); + + if ( element ) { + if ( ! /^(?:a|select|input|button|textarea)$/i.test( element.tagName ) ) + element.tabIndex = -1; + + element.focus(); + } + } ); + + /** + * Arranges footer widgets vertically. + */ + if ( $.isFunction( $.fn.masonry ) ) { + var columnWidth = body.is( '.sidebar' ) ? 228 : 245; + + $( '#secondary .widget-area' ).masonry( { + itemSelector: '.widget', + columnWidth: columnWidth, + gutterWidth: 20, + isRTL: body.is( '.rtl' ) + } ); + } +} )( jQuery ); \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/js/html5.js b/sources/wp-content/themes/twentythirteen/js/html5.js new file mode 100644 index 0000000..a788916 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/js/html5.js @@ -0,0 +1,7 @@ +/*! HTML5 Shiv v3.6 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ +/* Source: https://github.com/aFarkas/html5shiv */ +(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); +a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; +c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^<|^(?:a|b|button|code|div|fieldset|form|h1|h2|h3|h4|h5|h6|i|iframe|img|input|label|li|link|ol|option|p|param|q|script|select|span|strong|style|table|tbody|td|textarea|tfoot|th|thead|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a"); +var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a, +b){a||(a=f);if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d\n" +"Language-Team: LANGUAGE \n" + +#: 404.php:16 +msgid "Not found" +msgstr "" + +#: 404.php:21 +msgid "This is somewhat embarrassing, isn’t it?" +msgstr "" + +#: 404.php:22 +msgid "It looks like nothing was found at this location. Maybe try a search?" +msgstr "" + +#: archive.php:29 +msgid "Daily Archives: %s" +msgstr "" + +#: archive.php:31 +msgid "Monthly Archives: %s" +msgstr "" + +#: archive.php:31 +msgctxt "monthly archives date format" +msgid "F Y" +msgstr "" + +#: archive.php:33 +msgid "Yearly Archives: %s" +msgstr "" + +#: archive.php:33 +msgctxt "yearly archives date format" +msgid "Y" +msgstr "" + +#: archive.php:35 +msgid "Archives" +msgstr "" + +#: author-bio.php:26 +msgid "About %s" +msgstr "" + +#: author-bio.php:30 +msgid "View all posts by %s " +msgstr "" + +#: author.php:31 +msgid "All posts by %s" +msgstr "" + +#: category.php:19 +msgid "Category Archives: %s" +msgstr "" + +#: comments.php:25 +msgctxt "comments title" +msgid "One thought on “%2$s”" +msgid_plural "%1$s thoughts on “%2$s”" +msgstr[0] "" +msgstr[1] "" + +#: comments.php:45 +msgid "Comment navigation" +msgstr "" + +#: comments.php:46 +msgid "← Older Comments" +msgstr "" + +#: comments.php:47 +msgid "Newer Comments →" +msgstr "" + +#: comments.php:52 +msgid "Comments are closed." +msgstr "" + +#: content-aside.php:13 content-audio.php:24 content-gallery.php:24 +#: content-image.php:23 content-link.php:24 content-quote.php:13 +#: content-status.php:13 content-video.php:23 content.php:41 +msgid "Continue reading " +msgstr "" + +#: content-aside.php:14 content-audio.php:25 content-chat.php:24 +#: content-gallery.php:25 content-image.php:24 content-link.php:25 +#: content-quote.php:14 content-status.php:14 content-video.php:24 +#: content.php:42 image.php:70 page.php:35 +msgid "Pages:" +msgstr "" + +#: content-aside.php:20 content-aside.php:28 content-audio.php:31 +#: content-chat.php:29 content-gallery.php:39 content-image.php:35 +#: content-link.php:19 content-quote.php:25 content-status.php:19 +#: content-video.php:35 content.php:31 image.php:44 page.php:39 +msgid "Edit" +msgstr "" + +#: content-gallery.php:36 content-image.php:32 content-quote.php:22 +#: content-video.php:32 content.php:49 +msgid "Leave a comment" +msgstr "" + +#: content-gallery.php:36 content-image.php:32 content-quote.php:22 +#: content-video.php:32 content.php:49 +msgid "One comment so far" +msgstr "" + +#: content-gallery.php:36 content-image.php:32 content-quote.php:22 +#: content-video.php:32 content.php:49 +msgid "View all % comments" +msgstr "" + +#: content-none.php:12 +msgid "Nothing Found" +msgstr "" + +#: content-none.php:18 +msgid "" +"Ready to publish your first post? Get started here." +msgstr "" + +#: content-none.php:22 +msgid "" +"Sorry, but nothing matched your search terms. Please try again with " +"different keywords." +msgstr "" + +#: content-none.php:27 +msgid "" +"It seems we can’t find what you’re looking for. Perhaps " +"searching can help." +msgstr "" + +#. #-#-#-#-# twentythirteen.pot (Twenty Thirteen 1.1) #-#-#-#-# +#. Author URI of the plugin/theme +#: footer.php:19 +msgid "http://wordpress.org/" +msgstr "" + +#: footer.php:19 +msgid "Semantic Personal Publishing Platform" +msgstr "" + +#: footer.php:19 +msgid "Proudly powered by %s" +msgstr "" + +#: functions.php:97 +msgid "Navigation Menu" +msgstr "" + +#. Translators: If there are characters in your language that are not +#. * supported by Source Sans Pro, translate this to 'off'. Do not translate +#. * into your own language. +#: functions.php:128 +msgctxt "Source Sans Pro font: on or off" +msgid "on" +msgstr "" + +#. Translators: If there are characters in your language that are not +#. * supported by Bitter, translate this to 'off'. Do not translate into your +#. * own language. +#: functions.php:134 +msgctxt "Bitter font: on or off" +msgid "on" +msgstr "" + +#: functions.php:220 +msgid "Page %s" +msgstr "" + +#: functions.php:235 +msgid "Main Widget Area" +msgstr "" + +#: functions.php:237 +msgid "Appears in the footer section of the site." +msgstr "" + +#: functions.php:245 +msgid "Secondary Widget Area" +msgstr "" + +#: functions.php:247 +msgid "Appears on posts and pages in the sidebar." +msgstr "" + +#: functions.php:272 +msgid "Posts navigation" +msgstr "" + +#: functions.php:276 +msgid " Older posts" +msgstr "" + +#: functions.php:280 +msgid "Newer posts " +msgstr "" + +#: functions.php:308 +msgid "Post navigation" +msgstr "" + +#: functions.php:311 +msgctxt "Previous post link" +msgid " %title" +msgstr "" + +#: functions.php:312 +msgctxt "Next post link" +msgid "%title " +msgstr "" + +#: functions.php:332 +msgid "Sticky" +msgstr "" + +#. Translators: used between list items, there is a space after the comma. +#: functions.php:338 functions.php:344 +msgid ", " +msgstr "" + +#: functions.php:353 +msgid "View all posts by %s" +msgstr "" + +#: functions.php:373 +msgctxt "1: post format name. 2: date" +msgid "%1$s on %2$s" +msgstr "" + +#: functions.php:379 +msgid "Permalink to %s" +msgstr "" + +#: header.php:43 +msgid "Menu" +msgstr "" + +#: header.php:44 +msgid "Skip to content" +msgstr "" + +#: image.php:22 +msgid "" +"Published on in %5$s" +msgstr "" + +#: image.php:38 +msgid "Link to full-size image" +msgstr "" + +#: image.php:39 +msgid "Full resolution" +msgstr "" + +#: image.php:51 +msgid " Previous" +msgstr "" + +#: image.php:52 +msgid "Next " +msgstr "" + +#: inc/back-compat.php:41 inc/back-compat.php:53 inc/back-compat.php:68 +msgid "" +"Twenty Thirteen requires at least WordPress version 3.6. You are running " +"version %s. Please upgrade and try again." +msgstr "" + +#: inc/custom-header.php:51 +msgctxt "header image description" +msgid "Circle" +msgstr "" + +#: inc/custom-header.php:56 +msgctxt "header image description" +msgid "Diamond" +msgstr "" + +#: inc/custom-header.php:61 +msgctxt "header image description" +msgid "Star" +msgstr "" + +#: search.php:18 +msgid "Search Results for: %s" +msgstr "" + +#: tag.php:21 +msgid "Tag Archives: %s" +msgstr "" + +#: taxonomy-post_format.php:23 +msgid "%s Archives" +msgstr "" + +#. Theme Name of the plugin/theme +msgid "Twenty Thirteen" +msgstr "" + +#. Theme URI of the plugin/theme +msgid "http://wordpress.org/themes/twentythirteen" +msgstr "" + +#. Description of the plugin/theme +msgid "" +"The 2013 theme for WordPress takes us back to the blog, featuring a full " +"range of post formats, each displayed beautifully in their own unique way. " +"Design details abound, starting with a vibrant color scheme and matching " +"header images, beautiful typography and icons, and a flexible layout that " +"looks great on any device, big or small." +msgstr "" + +#. Author of the plugin/theme +msgid "the WordPress team" +msgstr "" diff --git a/sources/wp-content/themes/twentythirteen/page.php b/sources/wp-content/themes/twentythirteen/page.php new file mode 100644 index 0000000..5545367 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/page.php @@ -0,0 +1,50 @@ + + +
    +
    + + + + +
    > +
    + +
    + +
    + + +

    +
    + +
    + + '', 'link_before' => '', 'link_after' => '' ) ); ?> +
    + +
    + ', '' ); ?> +
    +
    + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/rtl.css b/sources/wp-content/themes/twentythirteen/rtl.css new file mode 100644 index 0000000..5428630 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/rtl.css @@ -0,0 +1,766 @@ +/* +Theme Name: Twenty Thirteen +Description: Adds support for languages written in a Right To Left (RTL) direction. +It's easy, just a matter of overwriting all the horizontal positioning attributes +of your CSS stylesheet in a separate stylesheet file named rtl.css. + +See http://codex.wordpress.org/Right_to_Left_Language_Support +*/ + +/** + * Table of Contents: + * + * 1.0 - Reset + * 4.0 - Header + * 4.1 - Site Header + * 4.2 - Navigation + * 5.0 - Content + * 5.2 - Entry Meta + * 5.4 - Galleries + * 5.5 - Post Formats + * 5.6 - Attachments + * 5.7 - Post/Paging Navigation + * 5.8 - Author Bio + * 5.9 - Archives + * 5.10 - Search Results/No posts + * 5.12 - Comments + * 6.0 - Sidebar + * 6.1 - Widgets + * 7.0 - Footer + * 8.0 - Media Queries + * 9.0 - Print + * ---------------------------------------------------------------------------- + */ + + +/** + * 1.0 Reset + * ---------------------------------------------------------------------------- + */ + +body { + direction: rtl; + unicode-bidi: embed; +} + +a { + display: inline-block; +} + +blockquote blockquote { + margin-left: 0; + margin-right: 24px; +} + +menu, +ol, +ul { + padding: 0 40px 0 0; +} + +caption, +th, +td { + text-align: right; +} + +td { + padding-left: 10px; + padding-right: 0; +} + +.assistive-text:focus { + left: auto; + right: 5px; +} + + +/** + * 4.0 Header + * ---------------------------------------------------------------------------- + */ + +/** + * 4.1 Site Header + * ---------------------------------------------------------------------------- + */ + +.site-header > a:first-child { + display: inherit; +} + +.site-description { + font-style: normal; +} + + +/** + * 4.2 Navigation + * ---------------------------------------------------------------------------- + */ + +/* Navbar */ +ul.nav-menu, +div.nav-menu > ul { + margin: 0 -20px 0 0; + padding: 0 0 0 40px; +} + +.nav-menu .sub-menu, +.nav-menu .children { + float: right; + left: auto; + right: -2px; +} + +.nav-menu .sub-menu ul, +.nav-menu .children ul { + border-left: 2px solid #f7f5e7; + border-right: 0; + left: auto; + right: 100%; +} + +.main-navigation .search-form { + left: 0; + right: auto; +} + +.site-header .search-field { + background-position: 98% center; + padding: 0 34px 0 0; +} + +.nav-menu .current_page_item > a, +.nav-menu .current_page_ancestor > a, +.nav-menu .current-menu-item > a, +.nav-menu .current-menu-ancestor > a { + font-style: normal; +} + +.menu-toggle { + padding-left: 0; + padding-right: 20px; +} + + +/** + * 5.0 Content + * ---------------------------------------------------------------------------- + */ + +.sidebar .entry-header, +.sidebar .entry-content, +.sidebar .entry-summary, +.sidebar .entry-meta { + padding-left: 376px; + padding-right: 60px; +} + + +/** + * 5.2 Entry Meta + * ---------------------------------------------------------------------------- + */ + +.entry-meta > span { + margin-left: 20px; + margin-right: auto; +} + +.entry-meta > span:last-child { + margin-left: 0; + margin-right: auto; +} + +.featured-post:before { + margin-left: 2px; + margin-right: auto; +} + +.entry-meta .date a:before { + margin-left: 2px; +} + +.comments-link a:before { + margin-left: 2px; + margin-right: auto; +} + +.tags-links a:first-child:before { + margin-left: 2px; +} + +.edit-link a:before { + margin-left: 2px; +} + +.page-links .page-links-title { + margin-left: 20px; + margin-right: auto; +} + +/** + * 5.4 Galleries + * ---------------------------------------------------------------------------- + */ + +.gallery { + margin-left: auto; + margin-right: -4px; +} + +.gallery-item { + float: right; + margin: 0 0 4px 4px; +} + +.gallery-item a { + display: inline; +} + + +/** + * 5.5 Post Formats + * ---------------------------------------------------------------------------- + */ + +.entry-content a { + display: inline; +} + +.format-aside cite:before { + content: normal; + margin-right: auto; +} + +.format-aside cite:after { + content: "\2014"; + margin-left: 5px; +} + +.format-audio .entry-content:before { + float: right; + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1); +} + +.format-audio .audio-content { + background-position: right top; + float: left; + padding-left: 0; + padding-right: 35px; +} + +.format-chat .entry-meta .date a:before { + margin-left: 4px; + margin-right: auto; +} + +.format-image .wp-caption-text { + text-align: right; +} + +.format-link .entry-title { + margin-left: 20px; + margin-right: auto; +} + +.format-status .entry-content, +.format-status .entry-meta { + padding-left: 0; + padding-right: 35px; +} + +.sidebar .format-status .entry-content, +.sidebar .format-status .entry-meta { + padding-left: 376px; + padding-right: 95px; +} + +.format-status .entry-content:before, +.format-status .entry-meta:before { + left: auto; + right: 10px; +} + +.sidebar .format-status .entry-content:before, +.sidebar .format-status .entry-meta:before { + left: auto; + right: 70px; +} + +.format-status .entry-content p:first-child:before { + left: auto; + right: 4px; +} + +.sidebar .format-status .entry-content p:first-child:before { + left: auto; + right: 64px; +} + +.format-quote blockquote { + padding-left: 0; + padding-right: 75px; +} + +.format-quote blockquote:before { + content: '\201D'; + padding-left: 25px; + padding-right: 0; + left: auto; + right: -15px; +} + + +/** + * 5.6 Attachments + * ---------------------------------------------------------------------------- + */ + +.attachment .entry-title { + float: right; +} + +.attachment .entry-title:before { + margin-left: 10px; + margin-right: auto; +} + +.attachment .entry-meta { + float: left; +} + +.image-navigation .nav-previous { + left: auto; + right: 0; +} + +.image-navigation .nav-next { + left: 0; + right: auto; +} + +.attachment .entry-caption { + text-align: right; +} + + +/** + * 5.7 Post/Paging Navigation + * ---------------------------------------------------------------------------- + */ + +.navigation .nav-previous { + float: right; +} + +.navigation .nav-next { + float: left; +} + +.sidebar .paging-navigation .nav-links, +.sidebar .post-navigation .nav-links { + padding-left: 376px; + padding-right: 60px; +} + +.paging-navigation .nav-previous .meta-nav { + margin-left: 10px; + margin-right: auto; +} + +.paging-navigation .nav-next .meta-nav { + margin-left: auto; + margin-right: 10px; +} + +.post-navigation a[rel="next"] { + float: left; + text-align: left; +} + + +/** + * 5.8 Author Bio + * ---------------------------------------------------------------------------- + */ + +.author-info { + text-align: right; /* gallery & video post formats */ +} + +.author.sidebar .author-info { + padding-left: 376px; + padding-right: 60px; +} + +.author-avatar .avatar { + float: right; + margin: 0 0 30px 30px; +} + +.author-link { + margin-left: auto; + margin-right: 2px; +} + + +/** + * 5.9 Archives + * ---------------------------------------------------------------------------- + */ + +.sidebar .archive-meta { + padding-left: 316px; + padding-right: 0; +} + + +/** + * 5.10 Search Results/No posts + * ---------------------------------------------------------------------------- + */ + +.sidebar .page-content { + padding-left: 376px; + padding-right: 60px; +} + +/** + * 5.12 Comments + * ---------------------------------------------------------------------------- + */ + +.sidebar .comments-title, +.sidebar .comment-list, +.sidebar .comment-reply-title, +.sidebar .comment-navigation, +.sidebar .comment-respond .comment-form { + padding-left: 376px; + padding-right: 60px; +} + +.comment-list .children { + margin-left: auto; + margin-right: 20px; +} + +.comment-author { + float: right; + margin-left: 50px; + margin-right: auto; +} + +.comment-list .edit-link { + margin-left: auto; + margin-right: 20px; +} + +.comment-metadata, +.comment-content, +.comment-list .reply, +.comment-awaiting-moderation { + float: left; +} + +.comment-awaiting-moderation:before { + margin-left: 5px; + margin-right: auto; +} + +.comment-reply-link:before, +.comment-reply-login:before { + margin-left: 3px; + margin-right: auto; + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1); +} + +.comment-reply-title small a { + float: left; +} + +.comment-form [for="author"], +.comment-form [for="email"], +.comment-form [for="url"], +.comment-form [for="comment"] { + float: right; +} + +.form-allowed-tags code { + margin-left: auto; + margin-right: 3px; +} + +.sidebar .no-comments { + padding-left: 376px; + padding-right: 60px; +} + + +/** + * 6.0 Sidebar + * ---------------------------------------------------------------------------- + */ + +.site-main .widget-area { + float: left; +} + +.widget-area a { + max-width: 100%; +} + + +/** + * 6.1 Widgets + * ---------------------------------------------------------------------------- + */ + +.widget .widget-title { + font-style: normal; +} + +.widget li > ul, +.widget li > ol { + margin-left: auto; + margin-right: 20px; +} + +/** + * 7.0 Footer + * ---------------------------------------------------------------------------- + */ + +.site-footer .widget-area, +.sidebar .site-footer { + text-align: right; +} +.sidebar .site-footer .widget-area { + left: auto; + right: -158px; +} + +.site-footer .widget { + float: right; + margin-left: 20px; + margin-right: auto; +} + +.sidebar .site-footer .widget:nth-of-type(4), +.sidebar .site-footer .widget:nth-of-type(3) { + margin-left: 0; + margin-right: auto; +} + + +/** + * 8.0 Media Queries + * ---------------------------------------------------------------------------- + */ + +@media (max-width: 1069px) { + ul.nav-menu, + div.nav-menu > ul { + margin-left: auto; + margin-right: 0; + } + + .error404 .page-header, + .sidebar .format-image .entry-content img.size-full, + .sidebar .format-image .wp-caption:first-child .wp-caption-text { + margin-right: auto; + } + + .main-navigation .search-form { + left: 20px; + right: auto; + } + + .site-main .widget-area { + margin-left: 60px; + margin-right: auto; + } +} + +@media (max-width: 999px) { + .sidebar .entry-header, + .sidebar .entry-content, + .sidebar .entry-summary, + .sidebar .entry-meta, + .sidebar .comment-list, + .sidebar .comment-reply-title, + .sidebar .comment-navigation, + .sidebar .comment-respond .comment-form, + .sidebar .featured-gallery, + .sidebar .post-navigation .nav-links, + .author.sidebar .author-info, + .sidebar .format-image .entry-content { + max-width: 604px; + padding-left: 0; + padding-right: 0; + } + + .site-main .widget-area { + float: none; + margin-left: auto; + } + + .attachment .entry-meta { + float: right; + text-align: right; + } + + .sidebar .format-status .entry-content, + .sidebar .format-status .entry-meta { + padding-left: 0; + padding-right: 35px; + } + + .sidebar .format-status .entry-content:before, + .sidebar .format-status .entry-meta:before { + left: auto; + right: 10px; + } + + .sidebar .format-status .entry-content p:first-child:before { + left: auto; + right: 4px; + } + + .sidebar .site-footer .widget-area { + left: auto; + right: 0; + } + + .sidebar .paging-navigation .nav-links { + padding: 0 60px; + } +} + +@media (max-width: 767px) { + .format-image .entry-content img:first-of-type, + .format-image .wp-caption:first-child .wp-caption-text { + margin-right: auto; + } +} + +@media (max-width: 643px) { + .sidebar .entry-header, + .sidebar .entry-content, + .sidebar .entry-summary, + .sidebar .entry-meta, + .sidebar .comment-list, + .sidebar .comment-navigation, + .sidebar .featured-gallery, + .sidebar .post-navigation .nav-links, + .sidebar .format-image .entry-content { + padding-left: 20px; + padding-right: 20px; + } + + #content .format-status .entry-content, + #content .format-status .entry-met { + padding-left: 0; + padding-right: 35px; + } + + .menu-toggle:after { + padding-left: 0; + padding-right: 8px; + } + + .toggled-on .nav-menu, + .toggled-on .nav-menu > ul { + margin-left: auto; + margin-right: 0; + } + + .toggled-on .nav-menu li > ul { + margin-left: auto; + margin-right: 20px; + right: auto; + } + + #content .featured-gallery { + padding-left: 0; + padding-right: 24px; + } + + .gallery-columns-1 .gallery-item { + margin-left: 0; + margin-right: auto; + } + + .comment-author { + margin-left: 30px; + margin-right: auto; + } + + .format-audio .audio-content { + background: none; + float: none; + padding-left: 0; + padding-right: 0; + } + + .gallery-columns-3 .gallery-item:nth-of-type(3n) { + margin-left: 4px; + margin-right: auto; + } +} + +@media (max-width: 359px) { + .gallery { + margin-left: auto; + margin-right: 0; + } + + .gallery .gallery-item:nth-of-type(even) { + margin-left: 0; + margin-right: auto; + } + + .gallery .gallery-item, + .gallery.gallery-columns-3 .gallery-item:nth-of-type(even), + .gallery-columns-3 .gallery-item:nth-of-type(3n), + .gallery-columns-5 .gallery-item:nth-of-type(5n), + .gallery-columns-7 .gallery-item:nth-of-type(7n), + .gallery-columns-9 .gallery-item:nth-of-type(9n) { + margin-left: 4px; + margin-right: auto; + } + + .comment-author .avatar { + margin-left: 5px; + margin-right: auto; + } +} + + +/** + * 9.0 Print + * ---------------------------------------------------------------------------- + */ + +@media print { + .entry-content img.alignleft, + .entry-content .wp-caption.alignleft { + margin-left: auto; + margin-right: 0; + } + + .entry-content img.alignright, + .entry-content .wp-caption.alignright { + margin-left: 0; + margin-right: auto; + } +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/screenshot.png b/sources/wp-content/themes/twentythirteen/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..199c8d53687fd1127b72528090c0006be2ba43bf GIT binary patch literal 54593 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 + +
    +
    + + + + + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/sidebar-main.php b/sources/wp-content/themes/twentythirteen/sidebar-main.php new file mode 100644 index 0000000..3c700ad --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/sidebar-main.php @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/sidebar.php b/sources/wp-content/themes/twentythirteen/sidebar.php new file mode 100644 index 0000000..cb5cf98 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/sidebar.php @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/single.php b/sources/wp-content/themes/twentythirteen/single.php new file mode 100644 index 0000000..1694a0d --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/single.php @@ -0,0 +1,28 @@ + + +
    +
    + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/style.css b/sources/wp-content/themes/twentythirteen/style.css new file mode 100644 index 0000000..71646fc --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/style.css @@ -0,0 +1,3125 @@ +/* +Theme Name: Twenty Thirteen +Theme URI: http://wordpress.org/themes/twentythirteen +Author: the WordPress team +Author URI: http://wordpress.org/ +Description: The 2013 theme for WordPress takes us back to the blog, featuring a full range of post formats, each displayed beautifully in their own unique way. Design details abound, starting with a vibrant color scheme and matching header images, beautiful typography and icons, and a flexible layout that looks great on any device, big or small. +Version: 1.1 +License: GNU General Public License v2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html +Tags: black, brown, orange, tan, white, yellow, light, one-column, two-columns, right-sidebar, flexible-width, custom-header, custom-menu, editor-style, featured-images, microformats, post-formats, rtl-language-support, sticky-post, translation-ready +Text Domain: twentythirteen + +This theme, like WordPress, is licensed under the GPL. +Use it to make something cool, have fun, and share what you've learned with others. +*/ + + +/** + * Table of Contents: + * + * 1.0 - Reset + * 2.0 - Repeatable Patterns + * 3.0 - Basic Structure + * 4.0 - Header + * 4.1 - Site Header + * 4.2 - Navigation + * 5.0 - Content + * 5.1 - Entry Header + * 5.2 - Entry Meta + * 5.3 - Entry Content + * 5.4 - Galleries + * 5.5 - Post Formats + * 5.6 - Attachments + * 5.7 - Post/Paging Navigation + * 5.8 - Author Bio + * 5.9 - Archives + * 5.10 - Search Results/No posts + * 5.11 - 404 + * 5.12 - Comments + * 5.13 - Multisite + * 6.0 - Sidebar + * 6.1 - Widgets + * 7.0 - Footer + * 8.0 - Media Queries + * 9.0 - Print + * ---------------------------------------------------------------------------- + */ + + +/** + * 1.0 Reset + * + * Modified from Normalize.css to provide cross-browser consistency and a smart + * default styling of HTML elements. + * + * @see http://git.io/normalize + * ---------------------------------------------------------------------------- + */ + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +nav, +section, +summary { + display: block; +} + +audio, +canvas, +video { + display: inline-block; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +[hidden] { + display: none; +} + +html { + font-size: 100%; + overflow-y: scroll; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +html, +button, +input, +select, +textarea { + font-family: "Source Sans Pro", Helvetica, sans-serif; +} + +body { + color: #141412; + line-height: 1.5; + margin: 0; +} + +a { + color: #ca3c08; + text-decoration: none; +} + +a:visited { + color: #ac0404; +} + +a:focus { + outline: thin dotted; +} + +a:active, +a:hover { + color: #ea9629; + outline: 0; +} + +a:hover { + text-decoration: underline; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + clear: both; + font-family: Bitter, Georgia, serif; + line-height: 1.3; +} + +h1 { + font-size: 48px; + margin: 33px 0; +} + +h2 { + font-size: 30px; + margin: 25px 0; +} + +h3 { + font-size: 22px; + margin: 22px 0; +} + +h4 { + font-size: 20px; + margin: 25px 0; +} + +h5 { + font-size: 18px; + margin: 30px 0; +} + +h6 { + font-size: 16px; + margin: 36px 0; +} + +address { + font-style: italic; + margin: 0 0 24px; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, +strong { + font-weight: bold; +} + +dfn { + font-style: italic; +} + +mark { + background: #ff0; + color: #000; +} + +p { + margin: 0 0 24px; +} + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 14px; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre { + background: #f5f5f5; + color: #666; + font-family: monospace; + font-size: 14px; + margin: 20px 0; + overflow: auto; + padding: 20px; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +blockquote, +q { + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + quotes: none; +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ""; + content: none; +} + +blockquote { + font-size: 18px; + font-style: italic; + font-weight: 300; + margin: 24px 40px; +} + +blockquote blockquote { + margin-right: 0; +} + +blockquote cite, +blockquote small { + font-size: 14px; + font-weight: normal; + text-transform: uppercase; +} + +blockquote em, +blockquote i { + font-style: normal; + font-weight: 300; +} + +blockquote strong, +blockquote b { + font-weight: 400; +} + +small { + font-size: smaller; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +dl { + margin: 0 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin: 0 0 20px; +} + +menu, +ol, +ul { + margin: 16px 0; + padding: 0 0 0 40px; +} + +ul { + list-style-type: square; +} + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +li > ul, +li > ol { + margin: 0; +} + +img { + -ms-interpolation-mode: bicubic; + border: 0; + vertical-align: middle; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 0; +} + +form { + margin: 0; +} + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +legend { + border: 0; + padding: 0; + white-space: normal; +} + +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + max-width: 100%; + vertical-align: baseline; +} + +button, +input { + line-height: normal; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} + +button[disabled], +input[disabled] { + cursor: default; +} + +input[type="checkbox"], +input[type="radio"] { + padding: 0; +} + +input[type="search"] { + -webkit-appearance: textfield; + padding-right: 2px; /* Don't cut off the webkit search cancel button */ + width: 270px; +} + +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +table { + border-bottom: 1px solid #ededed; + border-collapse: collapse; + border-spacing: 0; + font-size: 14px; + line-height: 2; + margin: 0 0 20px; + width: 100%; +} + +caption, +th, +td { + font-weight: normal; + text-align: left; +} + +caption { + font-size: 16px; + margin: 20px 0; +} + +th { + font-weight: bold; + text-transform: uppercase; +} + +td { + border-top: 1px solid #ededed; + padding: 6px 10px 6px 0; +} + +del { + color: #333; +} + +ins { + background: #fff9c0; + text-decoration: none; +} + +hr { + background: url(images/dotted-line.png) repeat center top; + background-size: 4px 4px; + border: 0; + height: 1px; + margin: 0 0 24px; +} + + +/** + * 2.0 Repeatable Patterns + * ---------------------------------------------------------------------------- + */ + +.genericon:before, +.menu-toggle:after, +.featured-post:before, +.date a:before, +.entry-meta .author a:before, +.format-audio .entry-content:before, +.comments-link a:before, +.tags-links a:first-child:before, +.categories-links a:first-child:before, +.edit-link a:before, +.attachment .entry-title:before, +.attachment-meta:before, +.attachment-meta a:before, +.comment-awaiting-moderation:before, +.comment-reply-link:before, +.comment-reply-login:before, +.comment-reply-title small a:before, +.bypostauthor > .comment-body .fn:before, +.error404 .page-title:before { + -webkit-font-smoothing: antialiased; + display: inline-block; + font: normal 16px/1 Genericons; + vertical-align: text-bottom; +} + +/* Clearing floats */ +.clear:after, +.attachment .entry-header:after, +.site-footer .widget-area:after, +.entry-content:after, +.page-content:after, +.navigation:after, +.nav-links:after, +.gallery:after, +.comment-form-author:after, +.comment-form-email:after, +.comment-form-url:after, +.comment-body:after { + clear: both; +} + +.clear:before, +.clear:after, +.attachment .entry-header:before, +.attachment .entry-header:after, +.site-footer .widget-area:before, +.site-footer .widget-area:after, +.entry-content:before, +.entry-content:after, +.page-content:before, +.page-content:after, +.navigation:before, +.navigation:after, +.nav-links:before, +.nav-links:after, +.gallery:before, +.gallery:after, +.comment-form-author:before, +.comment-form-author:after, +.comment-form-email:before, +.comment-form-email:after, +.comment-form-url:before, +.comment-form-url:after, +.comment-body:before, +.comment-body:after { + content: ""; + display: table; +} + +/* Assistive text */ +.screen-reader-text { + clip: rect(1px, 1px, 1px, 1px); + position: absolute !important; +} + +.screen-reader-text:focus { + background-color: #f1f1f1; + border-radius: 3px; + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + color: #21759b; + display: block; + font-size: 14px; + font-weight: bold; + height: auto; + line-height: normal; + padding: 15px 23px 14px; + position: absolute; + left: 5px; + top: 5px; + text-decoration: none; + width: auto; + z-index: 100000; /* Above WP toolbar */ +} + +/* Form fields, general styles first. */ +button, +input, +textarea { + border: 2px solid #d4d0ba; + font-family: inherit; + padding: 5px; +} + +input, +textarea { + color: #141412; +} + +input:focus, +textarea:focus { + border: 2px solid #c3c0ab; + outline: 0; +} + +/* Buttons */ +button, +input[type="submit"], +input[type="button"], +input[type="reset"] { + background: #e05d22; /* Old browsers */ + background: -webkit-linear-gradient(top, #e05d22 0%, #d94412 100%); /* Chrome 10+, Safari 5.1+ */ + background: linear-gradient(to bottom, #e05d22 0%, #d94412 100%); /* W3C */ + border: none; + border-bottom: 3px solid #b93207; + border-radius: 2px; + color: #fff; + display: inline-block; + padding: 11px 24px 10px; + text-decoration: none; +} + +button:hover, +button:focus, +input[type="submit"]:hover, +input[type="button"]:hover, +input[type="reset"]:hover, +input[type="submit"]:focus, +input[type="button"]:focus, +input[type="reset"]:focus { + background: #ed6a31; /* Old browsers */ + background: -webkit-linear-gradient(top, #ed6a31 0%, #e55627 100%); /* Chrome 10+, Safari 5.1+ */ + background: linear-gradient(to bottom, #ed6a31 0%, #e55627 100%); /* W3C */ + outline: none; +} + +button:active, +input[type="submit"]:active, +input[type="button"]:active, +input[type="reset"]:active { + background: #d94412; /* Old browsers */ + background: -webkit-linear-gradient(top, #d94412 0%, #e05d22 100%); /* Chrome 10+, Safari 5.1+ */ + background: linear-gradient(to bottom, #d94412 0%, #e05d22 100%); /* W3C */ + border: none; + border-top: 3px solid #b93207; + padding: 10px 24px 11px; +} + +.post-password-required input[type="submit"] { + padding: 7px 24px 4px; + vertical-align: bottom; +} + +.post-password-required input[type="submit"]:active { + padding: 5px 24px 6px; +} + +/* Placeholder text color -- selectors need to be separate to work. */ +::-webkit-input-placeholder { + color: #7d7b6d; +} + +:-moz-placeholder { + color: #7d7b6d; +} + +::-moz-placeholder { + color: #7d7b6d; +} + +:-ms-input-placeholder { + color: #7d7b6d; +} + +/* + * Responsive images + * + * Fluid images for posts, comments, and widgets + */ +.entry-content img, +.entry-summary img, +.comment-content img, +.widget img, +.wp-caption { + max-width: 100%; +} + +/* Make sure images with WordPress-added height and width attributes are scaled correctly. */ +.entry-content img, +.entry-summary img, +.comment-content img[height], +img[class*="align"], +img[class*="wp-image-"], +img[class*="attachment-"] { + height: auto; +} + +img.size-full, +img.size-large, +img.wp-post-image { + height: auto; + max-width: 100%; +} + +/* Make sure videos and embeds fit their containers. */ +embed, +iframe, +object, +video { + max-width: 100%; +} + +/* Override the Twitter embed fixed width. */ +.entry-content .twitter-tweet-rendered { + max-width: 100% !important; +} + +/* Images */ +.alignleft { + float: left; +} + +.alignright { + float: right; +} + +.aligncenter { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.alignleft { + margin: 5px 20px 5px 0; +} + +.wp-caption.alignleft { + margin: 5px 10px 5px 0; +} + +img.alignright { + margin: 5px 0 5px 20px; +} + +.wp-caption.alignright { + margin: 5px 0 5px 10px; +} + +img.aligncenter { + margin: 5px auto; +} + +img.alignnone { + margin: 5px 0; +} + +.wp-caption .wp-caption-text, +.entry-caption, +.gallery-caption { + color: #220e10; + font-size: 18px; + font-style: italic; + font-weight: 300; +} + +img.wp-smiley, +.rsswidget img { + border: 0; + border-radius: 0; + box-shadow: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} + +.wp-caption.alignleft + ul, +.wp-caption.alignleft + ol { + list-style-position: inside; +} + + +/** + * 3.0 Basic Structure + * ---------------------------------------------------------------------------- + */ + +.site { + background-color: #fff; + border-left: 1px solid #f2f2f2; + border-right: 1px solid #f2f2f2; + margin: 0 auto; + max-width: 1600px; + width: 100%; +} + +.site-main { + position: relative; +} + +.site-main .sidebar-container { + height: 0; + position: absolute; + top: 40px; + width: 100%; + z-index: 1; +} + +.site-main .sidebar-inner { + margin: 0 auto; + max-width: 1040px; +} + + +/** + * 4.0 Header + * ---------------------------------------------------------------------------- + */ + +/** + * 4.1 Site Header + * ---------------------------------------------------------------------------- + */ + +.site-header { + position: relative; +} + +.site-header .home-link { + color: #141412; + display: block; + margin: 0 auto; + max-width: 1080px; + min-height: 230px; + padding: 0 20px; + text-decoration: none; + width: 100%; +} + +.site-header .site-title:hover { + text-decoration: underline; +} + +.site-title { + font-size: 60px; + font-weight: bold; + line-height: 1; + margin: 0; + padding: 58px 0 10px; +} + +.site-description { + font: 300 italic 24px "Source Sans Pro", Helvetica, sans-serif; + margin: 0; +} + + +/** + * 4.2 Navigation + * ---------------------------------------------------------------------------- + */ + +.main-navigation { + clear: both; + margin: 0 auto; + max-width: 1080px; + min-height: 45px; + position: relative; +} + +ul.nav-menu, +div.nav-menu > ul { + margin: 0; + padding: 0 40px 0 0; +} + +.nav-menu li { + display: inline-block; + position: relative; +} + +.nav-menu li a { + color: #141412; + display: block; + font-size: 15px; + line-height: 1; + padding: 15px 20px; + text-decoration: none; +} + +.nav-menu li:hover > a, +.nav-menu li a:hover { + background-color: #220e10; + color: #fff; +} + +.nav-menu .sub-menu, +.nav-menu .children { + background-color: #220e10; + border: 2px solid #f7f5e7; + border-top: 0; + display: none; + padding: 0; + position: absolute; + left: -2px; + z-index: 99999; +} + +.nav-menu .sub-menu ul, +.nav-menu .children ul { + border-left: 0; + left: 100%; + top: 0; +} + +ul.nav-menu ul a, +.nav-menu ul ul a { + color: #fff; + margin: 0; + width: 200px; +} + +ul.nav-menu ul a:hover, +.nav-menu ul ul a:hover { + background-color: #db572f; +} + +ul.nav-menu li:hover > ul, +.nav-menu ul li:hover > ul { + display: block; +} + +.nav-menu .current_page_item > a, +.nav-menu .current_page_ancestor > a, +.nav-menu .current-menu-item > a, +.nav-menu .current-menu-ancestor > a { + color: #bc360a; + font-style: italic; +} + +.menu-toggle { + display: none; +} + +/* Navbar */ +.navbar { + background-color: #f7f5e7; + margin: 0 auto; + max-width: 1600px; + width: 100%; +} + +.site-header .search-form { + position: absolute; + right: 20px; + top: 1px; +} + +.site-header .search-field { + background-color: transparent; + background-image: url(images/search-icon.png); + background-position: 5px center; + background-repeat: no-repeat; + background-size: 24px 24px; + border: none; + cursor: pointer; + height: 37px; + margin: 3px 0; + padding: 0 0 0 34px; + position: relative; + -webkit-transition: width 400ms ease, background 400ms ease; + transition: width 400ms ease, background 400ms ease; + width: 0; +} + +.site-header .search-field:focus { + background-color: #fff; + border: 2px solid #c3c0ab; + cursor: text; + outline: 0; + width: 230px; +} + + +/** + * 5.0 Content + * ---------------------------------------------------------------------------- + */ + +.hentry { + padding: 40px 0; +} + +.entry-header, +.entry-content, +.entry-summary, +.entry-meta { + margin: 0 auto; + max-width: 604px; + width: 100%; +} + +.sidebar .entry-header, +.sidebar .entry-content, +.sidebar .entry-summary, +.sidebar .entry-meta { + max-width: 1040px; + padding: 0 376px 0 60px; +} + + +/** + * 5.1 Entry Header + * ---------------------------------------------------------------------------- + */ + +.sidebar .entry-header .entry-meta { + padding: 0; +} + +.entry-thumbnail img { + display: block; + margin: 0 auto 10px; +} + +.entry-header { + margin-bottom: 30px; +} + +.entry-title { + font-weight: normal; + margin: 0 0 5px; +} + +.entry-title a { + color: #141412; +} + +.entry-title a:hover { + color: #ea9629; +} + + +/** + * 5.2 Entry Meta + * ---------------------------------------------------------------------------- + */ + +.entry-meta { + clear: both; + font-size: 14px; +} + +.entry-meta a { + color: #bc360a; +} + +.entry-meta a:hover { + color: #bc360a; +} + +.entry-meta > span { + margin-right: 20px; +} + +.entry-meta > span:last-child { + margin-right: 0; +} + +.featured-post:before { + content: "\f308"; + margin-right: 2px; +} + +.entry-meta .date a:before { + content: "\f303"; +} + +.comments-link a:before { + content: "\f300"; + margin-right: 2px; + position: relative; + top: -1px; +} + +.entry-meta .author a:before { + content: "\f304"; + position: relative; + top: -1px; +} + +.categories-links a:first-child:before { + content: "\f301"; +} + +.tags-links a:first-child:before { + content: "\f302"; + position: relative; + top: -1px; +} + +.edit-link a:before { + content: "\f411"; + position: relative; + top: -1px; +} + +.single-author .entry-meta .author, +.sticky.format-standard .entry-meta .date, +.sticky.format-audio .entry-meta .date, +.sticky.format-chat .entry-meta .date, +.sticky.format-image .entry-meta .date, +.sticky.format-gallery .entry-meta .date { + display: none; +} + + +/** + * 5.3 Entry Content + * ---------------------------------------------------------------------------- + */ + +.entry-content { + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; + word-wrap: break-word; +} + +.entry-content a, +.comment-content a { + color: #bc360a; +} + +.entry-content a:hover, +.comment-content a:hover { + color: #ea9629; +} + +.entry-content blockquote { + font-size: 24px; +} + +.entry-content blockquote cite, +.entry-content blockquote small { + font-size: 16px; +} + +.entry-content img.alignleft, +.entry-content .wp-caption.alignleft { + margin-left: -60px; +} + +.entry-content img.alignright, +.entry-content .wp-caption.alignright { + margin-right: -60px; +} + +footer.entry-meta { + margin-top: 24px; +} + +.format-standard footer.entry-meta { + margin-top: 0; +} + +/* Page links */ +.page-links { + clear: both; + font-size: 16px; + font-style: italic; + font-weight: normal; + line-height: 2.2; + margin: 20px 0; + text-transform: uppercase; +} + +.page-links a, +.page-links > span { + background: #fff; + border: 1px solid #fff; + padding: 5px 10px; + text-decoration: none; +} + +.format-status .entry-content .page-links a, +.format-gallery .entry-content .page-links a, +.format-chat .entry-content .page-links a, +.format-quote .entry-content .page-links a, +.page-links a { + background: #e63f2a; + border: 1px solid #e63f2a; + color: #fff; +} + +.format-gallery .entry-content .page-links a:hover, +.format-audio .entry-content .page-links a:hover, +.format-status .entry-content .page-links a:hover, +.format-video .entry-content .page-links a:hover, +.format-chat .entry-content .page-links a:hover, +.format-quote .entry-content .page-links a:hover, +.page-links a:hover { + background: #fff; + color: #e63f2a; +} + +.format-status .entry-content .page-links > span, +.format-quote .entry-content .page-links > span { + background: none; +} + +.page-links .page-links-title { + background: transparent; + border: none; + margin-right: 20px; + padding: 0; +} + +/* Mediaelements */ +.hentry .mejs-mediaelement, +.hentry .mejs-container .mejs-controls { + background: #220e10; +} + +.hentry .mejs-controls .mejs-time-rail .mejs-time-loaded, +.hentry .mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current { + background: #fff; +} + +.hentry .mejs-controls .mejs-time-rail .mejs-time-current { + background: #ea9629; +} + +.hentry .mejs-controls .mejs-time-rail .mejs-time-total, +.hentry .mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total { + background: #595959; +} + +.hentry .mejs-controls .mejs-time-rail span, +.hentry .mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total, +.hentry .mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current { + border-radius: 0; +} + + +/** + * 5.4 Galleries + * ---------------------------------------------------------------------------- + */ + +.gallery { + margin-bottom: 20px; + margin-left: -4px; +} + +.gallery-item { + float: left; + margin: 0 4px 4px 0; + overflow: hidden; + position: relative; +} + +.gallery-columns-1.gallery-size-medium, +.gallery-columns-1.gallery-size-thumbnail, +.gallery-columns-2.gallery-size-thumbnail, +.gallery-columns-3.gallery-size-thumbnail { + display: table; + margin: 0 auto 20px; +} + +.gallery-columns-1 .gallery-item, +.gallery-columns-2 .gallery-item, +.gallery-columns-3 .gallery-item { + text-align: center; +} + +.gallery-columns-4 .gallery-item { + max-width: 23%; + max-width: -webkit-calc(25% - 4px); + max-width: calc(25% - 4px); +} + +.gallery-columns-5 .gallery-item { + max-width: 19%; + max-width: -webkit-calc(20% - 4px); + max-width: calc(20% - 4px); +} + +.gallery-columns-6 .gallery-item { + max-width: 15%; + max-width: -webkit-calc(16.7% - 4px); + max-width: calc(16.7% - 4px); +} + +.gallery-columns-7 .gallery-item { + max-width: 13%; + max-width: -webkit-calc(14.28% - 4px); + max-width: calc(14.28% - 4px); +} + +.gallery-columns-8 .gallery-item { + max-width: 11%; + max-width: -webkit-calc(12.5% - 4px); + max-width: calc(12.5% - 4px); +} + +.gallery-columns-9 .gallery-item { + max-width: 9%; + max-width: -webkit-calc(11.1% - 4px); + max-width: calc(11.1% - 4px); +} + +.gallery-columns-1 .gallery-item:nth-of-type(1n), +.gallery-columns-2 .gallery-item:nth-of-type(2n), +.gallery-columns-3 .gallery-item:nth-of-type(3n), +.gallery-columns-4 .gallery-item:nth-of-type(4n), +.gallery-columns-5 .gallery-item:nth-of-type(5n), +.gallery-columns-6 .gallery-item:nth-of-type(6n), +.gallery-columns-7 .gallery-item:nth-of-type(7n), +.gallery-columns-8 .gallery-item:nth-of-type(8n), +.gallery-columns-9 .gallery-item:nth-of-type(9n) { + margin-right: 0; +} + +.gallery-caption { + background-color: rgba(0, 0, 0, 0.7); + box-sizing: border-box; + color: #fff; + font-size: 14px; + line-height: 1.3; + margin: 0; + max-height: 50%; + opacity: 0; + padding: 2px 8px; + position: absolute; + bottom: 0; + left: 0; + text-align: left; + -webkit-transition: opacity 400ms ease; + transition: opacity 400ms ease; + width: 100%; +} + +.gallery-caption:before { + box-shadow: 0 -10px 15px #000 inset; + content: ""; + height: 100%; + min-height: 49px; + position: absolute; + left: 0; + top: 0; + width: 100%; +} + +.gallery-item:hover .gallery-caption { + opacity: 1; +} + +.gallery-columns-7 .gallery-caption, +.gallery-columns-8 .gallery-caption, +.gallery-columns-9 .gallery-caption { + display: none; +} + + +/** + * 5.5 Post Formats + * ---------------------------------------------------------------------------- + */ + +/* Aside */ +.format-aside { + background-color: #f7f5e7; +} + +.blog .format-aside:first-of-type, +.single .format-aside:first-of-type, +.format-aside + .format-aside, +.format-aside + .format-link, +.format-link + .format-aside { + box-shadow: inset 0 2px 2px rgba(173, 165, 105, 0.2); +} + +.format-aside .entry-meta { + margin-top: 0; +} + +.format-aside blockquote { + font-size: 100%; + font-weight: normal; +} + +.format-aside cite { + font-size: 100%; + text-transform: none; +} + +.format-aside cite:before { + content: "\2014"; + margin-right: 5px; +} + +/* Audio */ +.format-audio { + background-color: #db572f; +} + +.format-audio .entry-title { + font-size: 28px; + font-weight: bold; +} + +.format-audio .entry-content:before { + content: "\f109"; + float: left; + font-size: 64px; + position: relative; + top: 4px; +} + +.format-audio .entry-content a, +.format-audio .entry-meta a, +.format-audio .entry-content a:hover, +.format-audio .entry-meta a:hover { + color: #fbfaf3; +} + +.format-audio .audio-content { + background: url(images/dotted-line.png) repeat-y left top; + background-size: 4px 4px; + float: right; + padding-left: 35px; + width: 80%; + width: -webkit-calc(100% - 85px); + width: calc(100% - 85px); +} + +.format-audio .wp-audio-shortcode { + height: 30px !important; /* Override mediaelement.js style */ + margin: 20px 0; + max-width: 400px !important; /* Override mediaelement.js style */ +} + +.format-audio audio { + max-width: 100% !important; /* Avoid player width overflow. */ +} + +/* Chat */ +.format-chat { + background-color: #eadaa6; +} + +.format-chat .entry-title { + font-size: 28px; + font-weight: bold; +} + +.format-chat .entry-meta a, +.format-chat .entry-content a { + color: #722d19; +} + +.format-chat .entry-meta .date a:before { + content: "\f108"; + margin-right: 2px; +} + +.format-chat .entry-meta .author { + display: none; +} + +.format-chat .chat { + margin: 0; +} + +.format-chat .chat .chat-timestamp { + color: #722d19; + float: right; + font-size: 12px; + font-weight: normal; + margin: 5px 10px 0; +} + +.format-chat .chat .fn { + font-style: normal; +} + +/* Gallery */ +.format-gallery { + background-color: #fbca3c; +} + +.format-gallery .entry-header { + margin-bottom: 15px; +} + +.format-gallery .entry-title { + font-size: 50px; + font-weight: 400; + margin: 0; +} + +.format-gallery .entry-meta a, +.format-gallery .entry-content a { + color: #722d19; +} + +/* Image */ +.format-image .entry-title { + font-size: 28px; + font-weight: bold; +} + +.format-image .categories-links, +.format-image .tags-links { + display: none; +} + +/* Link */ +.format-link { + background-color: #f7f5e7; +} + +.blog .format-link:first-of-type, +.single .format-link:first-of-type { + box-shadow: inset 0 2px 2px rgba(173, 165, 105, 0.2); +} + +.format-link .entry-header, +.format-link .entry-content p:last-child { + margin-bottom: 0; +} + +.format-link .entry-title { + color: #ca3c08; + display: inline; + font: 300 italic 20px "Source Sans Pro", Helvetica, sans-serif; + margin-right: 20px; +} + +.format-link .entry-title a { + color: #bc360a; +} + +.format-link div.entry-meta { + display: inline; +} + +/* Quote */ +.format-quote { + background-color: #210d10; +} + +.format-quote .entry-content, +.format-quote .entry-meta { + color: #f7f5e7; +} + +.format-quote .entry-content blockquote { + font-size: 28px; + margin: 0; +} + +.format-quote .entry-content a, +.format-quote .entry-meta a, +.format-quote .linked { + color: #e63f2a; +} + +.format-quote .entry-content cite a { + border-bottom: 1px dotted #fff; + color: #fff; +} + +.format-quote .entry-content cite a:hover { + text-decoration: none; +} + +.format-quote blockquote small, +.format-quote blockquote cite { + display: block; + font-size: 16px; +} + +.format-quote blockquote { + font-style: italic; + font-weight: 300; + padding-left: 75px; + position: relative; +} + +.format-quote blockquote:before { + content: '\201C'; + font-size: 140px; + font-weight: 400; + line-height: .8; + padding-right: 25px; + position: absolute; + left: -15px; + top: -3px; +} + +.format-quote .entry-meta .author { + display: none; +} + +/* Status */ +.format-status { + background-color: #722d19; + padding: 0; +} + +.format-status .entry-content, +.format-status .entry-meta { + padding-left: 35px; + position: relative; +} + +.format-status .entry-content a { + color: #eadaa6; +} + +.format-status .entry-meta a { + color: #f7f5e7; +} + +.sidebar .format-status .entry-content, +.sidebar .format-status .entry-meta { + padding-left: 95px; +} + +.format-status .entry-content:before, +.format-status .entry-meta:before { + background: url(images/dotted-line.png) repeat-y left bottom; + background-size: 4px 4px; + content: ""; + display: block; + height: 100%; + position: absolute; + left: 10px; + top: 0; + width: 1px; +} + +.sidebar .format-status .entry-content:before, +.sidebar .format-status .entry-meta:before { + left: 70px; +} + +.format-status .categories-links, +.format-status .tags-links { + display: none; +} + +/* Ensures the dots in the dot background are in lockstep. */ +.format-status .entry-meta:before { + background-position: left top; +} + +.format-status .entry-content { + color: #f7f5e7; + font-size: 24px; + font-style: italic; + font-weight: 300; + padding-bottom: 30px; + padding-top: 40px; + position: relative; +} + +.format-status .entry-content p:first-child:before { + background-color: rgba(0, 0, 0, 0.65); + content: ""; + height: 3px; + margin-top: 13px; + position: absolute; + left: 4px; + width: 13px; +} + +.sidebar .format-status .entry-content > p:first-child:before { + left: 64px; +} + +.format-status .entry-content p:last-child { + margin-bottom: 0; +} + +.format-status .entry-meta { + margin-top: 0; + padding-bottom: 40px; +} + +.format-status .entry-meta .date a:before { + content: "\f105"; +} + +/* Video */ +.format-video { + background-color: #db572f; +} + +.format-video .entry-content a, +.format-video .entry-meta a, +.format-video .entry-content a:hover, +.format-video .entry-meta a:hover { + color: #fbfaf3; +} + +.format-video .entry-title { + font-size: 50px; + font-weight: 400; +} + +.format-video .entry-meta { + color: #220e10; +} + + +/** + * 5.6 Attachments + * ---------------------------------------------------------------------------- + */ + +.attachment .hentry { + background-color: #e8e5ce; + margin: 0; + padding: 0; +} + +.attachment .entry-header { + margin-bottom: 0; + max-width: 1040px; + padding: 30px 0; +} + +.attachment .entry-title { + display: inline-block; + float: left; + font: 300 italic 30px "Source Sans Pro", Helvetica, sans-serif; + margin: 0; +} + +.attachment .entry-title:before { + content: "\f416"; + font-size: 32px; + margin-right: 10px; +} + +.attachment .entry-meta { + clear: none; + color: inherit; + float: right; + max-width: 604px; + padding: 9px 0 0; + text-align: right; +} + +.hentry.attachment:not(.image-attachment) .entry-meta { + max-width: 104px; +} + +.attachment footer.entry-meta { + display: none; +} + +.attachment-meta:before { + content: "\f307"; +} + +.full-size-link a:before { + content: "\f402"; +} + +.full-size-link:before { + content: none; +} + +.attachment .entry-meta a, +.attachment .entry-meta .edit-link:before, +.attachment .full-size-link:before { + color: #ca3c08; +} + +.attachment .entry-content { + background-color: #fff; + max-width: 100%; + padding: 40px 0; +} + +.image-navigation { + margin: 0 auto; + max-width: 1040px; + position: relative; +} + +.image-navigation a:hover { + text-decoration: none; +} + +.image-navigation .nav-previous, +.image-navigation .nav-next { + position: absolute; + top: 50px; +} + +.image-navigation .nav-previous { + left: 0; +} + +.image-navigation .nav-next { + right: 0; +} + +.image-navigation .meta-nav { + font-size: 32px; + font-weight: 300; + vertical-align: -4px; +} + +.attachment .entry-attachment, +.attachment .type-attachment p { + margin: 0 auto; + max-width: 724px; + text-align: center; +} + +.attachment .entry-attachment .attachment { + display: inline-block; +} + +.attachment .entry-caption { + text-align: left; +} + +.attachment .entry-description { + margin: 20px auto 0; + max-width: 604px; +} + +.attachment .entry-caption p:last-child, +.attachment .entry-description p:last-child { + margin: 0; +} + +.attachment .site-main .sidebar-container { + display: none; +} + + +/** + * 5.7 Post/Paging Navigation + * ---------------------------------------------------------------------------- + */ + +.navigation .nav-previous { + float: left; +} + +.navigation .nav-next { + float: right; +} + +.navigation a { + color: #bc360a; +} + +.navigation a:hover { + color: #ea9629; + text-decoration: none; +} + +.paging-navigation { + background-color: #e8e5ce; + padding: 40px 0; +} + +.paging-navigation .nav-links { + margin: 0 auto; + max-width: 604px; + width: 100%; +} + +.sidebar .paging-navigation .nav-links { + max-width: 1040px; + padding: 0 376px 0 60px; +} + +.paging-navigation .nav-next { + padding: 13px 0; +} + +.paging-navigation a { + font-size: 22px; + font-style: italic; + font-weight: 300; +} + +.paging-navigation .meta-nav { + background-color: #e63f2a; + border-radius: 50%; + color: #fff; + display: inline-block; + font-size: 26px; + padding: 3px 0 8px; + text-align: center; + width: 50px; +} + +.paging-navigation .nav-previous .meta-nav { + margin-right: 10px; + padding: 17px 0 23px; + width: 80px; +} + +.paging-navigation .nav-next .meta-nav { + margin-left: 10px; +} + +.paging-navigation a:hover .meta-nav { + background-color: #ea9629; + text-decoration: none; +} + +.post-navigation { + background-color: #fff; + color: #ca3c08; + font-size: 20px; + font-style: italic; + font-weight: 300; + padding: 20px 0; +} + +.post-navigation .nav-links { + margin: 0 auto; + max-width: 1040px; +} + +.sidebar .post-navigation .nav-links { + padding: 0 376px 0 60px; +} + +.post-navigation a[rel="next"] { + float: right; + text-align: right; +} + + +/** + * 5.8 Author Bio + * ---------------------------------------------------------------------------- + */ + +.author-info { + margin: 0 auto; + max-width: 604px; + padding: 30px 0 10px; + text-align: left; /* gallery & video post formats */ + width: 100%; +} + +.author.sidebar .author-info { + max-width: 1040px; + padding: 30px 376px 10px 60px; +} + +.single .author-info { + padding: 50px 0 0; +} + +.author-avatar .avatar { + float: left; + margin: 0 30px 30px 0; +} + +.single-format-status .author-description { + color: #f7f5e7; +} + +.author-description .author-title { + clear: none; + font: 300 italic 20px "Source Sans Pro", Helvetica, sans-serif; + margin: 0 0 8px; +} + +.author-link { + color: #ca3c08; + margin-left: 2px; +} + +.author.archive .author-link { + display: none; +} + + +/** + * 5.9 Archives + * ---------------------------------------------------------------------------- + */ + +.archive-header { + background-color: #e8e5ce; +} + +.archive-title, +.archive-meta { + font: 300 italic 30px "Source Sans Pro", Helvetica, sans-serif; + margin: 0 auto; + max-width: 1040px; + padding: 30px 0; + width: 100%; +} + +.archive-meta { + font-size: 16px; + font-style: normal; + font-weight: normal; + margin-top: -15px; + padding: 0 0 11px; +} + +.sidebar .archive-meta { + padding-right: 316px; +} + + +/** + * 5.10 Search Results/No posts + * ---------------------------------------------------------------------------- + */ + +.page-header { + background-color: #e8e5ce; +} + +.page-title { + font: 300 italic 30px "Source Sans Pro", Helvetica, sans-serif; + margin: 0 auto; + max-width: 1040px; + padding: 30px 0; + width: 100%; +} + +.page-content { + margin: 0 auto; + max-width: 604px; + padding: 40px 0; + width: 100%; +} + +.sidebar .page-content { + margin: 0 auto; + max-width: 1040px; + padding: 40px 376px 40px 60px; +} + + +/** + * 5.11 404 + * ---------------------------------------------------------------------------- + */ + +.error404 .page-header { + background-color: #fff; +} + +.error404 .page-title { + line-height: 0.6; + margin: 0; + padding: 300px; + position: relative; + text-align: center; + width: auto; +} + +.error404 .page-title:before { + color: #e8e5ce; + content: "\f423"; + font-size: 964px; + line-height: 0.6; + overflow: hidden; + position: absolute; + left: 7px; + top: 28px; +} + +.error404 .page-wrapper { + background-color: #e8e5ce; +} + +.error404 .page-header, +.error404 .page-content { + margin: 0 auto; + max-width: 1040px; + padding-bottom: 40px; + width: 100%; +} + + +/** + * 5.12 Comments + * ---------------------------------------------------------------------------- + */ + +.comments-title, +.comment-list, +.comment-reply-title, +.must-log-in, +.comment-respond .comment-form, +.comment-respond iframe { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 604px; + width: 100%; +} + +.sidebar .comments-title, +.sidebar .comment-list, +.sidebar .must-log-in, +.sidebar .comment-reply-title, +.sidebar .comment-navigation, +.sidebar .comment-respond .comment-form { + max-width: 1040px; + padding-left: 60px; + padding-right: 376px; +} + +.comments-title { + font: 300 italic 28px "Source Sans Pro", Helvetica, sans-serif; +} + +.comment-list, +.comment-list .children { + list-style-type: none; + padding: 0; +} + +.comment-list .children { + margin-left: 20px; +} + +.comment-list > li:after, +.comment-list .children > li:before { + background: url(images/dotted-line.png) repeat left top; + background-size: 4px 4px; + content: ""; + display: block; + height: 1px; + width: 100%; +} + +.comment-list > li:last-child:after { + display: none; +} + +.comment-body { + padding: 24px 0; + position: relative; +} + +.comment-author { + float: left; + max-width: 74px; +} + +.comment-author .avatar { + display: block; + margin-bottom: 10px; +} + +.comment-author .fn { + word-wrap: break-word; +} + +.comment-author .fn, +.comment-author .url, +.comment-reply-link, +.comment-reply-login { + color: #bc360a; + font-size: 14px; + font-style: normal; + font-weight: normal; +} + +.says { + display: none; +} + +.no-avatars .comment-author { + margin: 0 0 5px; + max-width: 100%; + position: relative; +} + +.no-avatars .comment-metadata, +.no-avatars .comment-content, +.no-avatars .comment-list .reply { + width: 100%; +} + +.bypostauthor > .comment-body .fn:before { + content: "\f408"; + vertical-align: text-top; +} + +.comment-list .edit-link { + margin-left: 20px; +} + +.comment-metadata, +.comment-awaiting-moderation, +.comment-content, +.comment-list .reply { + float: right; + width: 79%; + width: -webkit-calc(100% - 124px); + width: calc(100% - 124px); + word-wrap: break-word; +} + +.comment-meta, +.comment-meta a { + color: #a2a2a2; + font-size: 13px; +} + +.comment-meta a:hover { + color: #ea9629; +} + +.comment-metadata { + margin-bottom: 20px; +} + +.ping-meta { + color: #a2a2a2; + font-size: 13px; + line-height: 2; +} + +.comment-awaiting-moderation { + color: #a2a2a2; +} + +.comment-awaiting-moderation:before { + content: "\f414"; + margin-right: 5px; + position: relative; + top: -2px; +} + +.comment-reply-link:before, +.comment-reply-login:before { + content: "\f412"; + margin-right: 3px; +} + +/* Comment form */ +.comment-respond { + background-color: #f7f5e7; + padding: 30px 0; +} + +.comment .comment-respond { + margin-bottom: 20px; + padding: 20px; +} + +.comment-reply-title { + font: 300 italic 28px "Source Sans Pro", Helvetica, sans-serif; +} + +.comment-reply-title small a { + color: #131310; + display: inline-block; + float: right; + height: 16px; + overflow: hidden; + width: 16px; +} + +.comment-reply-title small a:hover { + color: #ed331c; + text-decoration: none; +} + +.comment-reply-title small a:before { + content: "\f406"; + vertical-align: top; +} + +.sidebar .comment-list .comment-reply-title, +.sidebar .comment-list .comment-respond .comment-form { + padding: 0; +} + +.comment-form .comment-notes { + margin-bottom: 15px; +} + +.comment-form .comment-form-author, +.comment-form .comment-form-email, +.comment-form .comment-form-url { + margin-bottom: 8px; +} + +.comment-form [for="author"], +.comment-form [for="email"], +.comment-form [for="url"], +.comment-form [for="comment"] { + float: left; + padding: 5px 0; + width: 120px; +} + +.comment-form .required { + color: #ed331c; +} + +.comment-form input[type="text"], +.comment-form input[type="email"], +.comment-form input[type="url"] { + max-width: 270px; + width: 60%; +} + +.comment-form textarea { + width: 100%; +} + +.form-allowed-tags, +.form-allowed-tags code { + color: #686758; + font-size: 12px; +} + +.form-allowed-tags code { + font-size: 10px; + margin-left: 3px; +} + +.comment-list .pingback, +.comment-list .trackback { + padding-top: 24px; +} + +.comment-navigation { + font-size: 20px; + font-style: italic; + font-weight: 300; + margin: 0 auto; + max-width: 604px; + padding: 20px 0 30px; + width: 100%; +} + +.no-comments { + background-color: #f7f5e7; + font-size: 20px; + font-style: italic; + font-weight: 300; + margin: 0; + padding: 40px 0; + text-align: center; +} + +.sidebar .no-comments { + padding-left: 60px; + padding-right: 376px; +} + + +/** + * 5.13 Multisite + * ---------------------------------------------------------------------------- + */ + +.site-main .mu_register { + margin: 0 auto; + max-width: 604px; + width: 100%; +} + +.mu_alert { + margin-top: 25px; +} + +.site-main .mu_register input[type="submit"], +.site-main .mu_register #blog_title, +.site-main .mu_register #user_email, +.site-main .mu_register #blogname, +.site-main .mu_register #user_name { + font-size: inherit; + width: 270px; +} + +.site-main .mu_register input[type="submit"] { + width: auto; +} + + +/** + * 6.0 Sidebar + * ---------------------------------------------------------------------------- + */ + +.site-main .widget-area { + float: right; + width: 300px; +} + + +/** + * 6.1 Widgets + * ---------------------------------------------------------------------------- + */ + +.widget { + background-color: rgba(247, 245, 231, 0.7); + font-size: 14px; + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; + margin: 0 0 24px; + padding: 20px; + word-wrap: break-word; +} + +.widget .widget-title { + font: 300 italic 20px "Source Sans Pro", Helvetica, sans-serif; + margin: 0 0 10px; +} + +.widget ul, +.widget ol { + list-style-type: none; + margin: 0; + padding: 0; +} + +.widget li { + padding: 5px 0; +} + +.widget .children li:last-child { + padding-bottom: 0; +} + +.widget li > ul, +.widget li > ol { + margin-left: 20px; +} + +.widget a { + color: #bc360a; +} + +.widget a:hover { + color: #ea9629; +} + +/* Search widget */ +.search-form .search-submit { + display: none; +} + +/* RSS Widget */ +.widget_rss .rss-date { + display: block; +} + +.widget_rss .rss-date, +.widget_rss li > cite { + color: #a2a2a2; +} + +/* Calendar Widget */ +.widget_calendar table, +.widget_calendar td { + border: 0; + border-collapse: separate; + border-spacing: 1px; +} + +.widget_calendar caption { + font-size: 14px; + margin: 0; +} + +.widget_calendar th, +.widget_calendar td { + padding: 0; + text-align: center; +} + +.widget_calendar a { + display: block; +} + +.widget_calendar a:hover { + background-color: rgba(0, 0, 0, 0.15); +} + +.widget_calendar tbody td { + background-color: rgba(255, 255, 255, 0.5); +} + +.site-footer .widget_calendar tbody td { + background-color: rgba(255, 255, 255, 0.05); +} + +.widget_calendar tbody .pad, .site-footer .widget_calendar tbody .pad { + background-color: transparent; +} + + +/** + * 7.0 Footer + * ---------------------------------------------------------------------------- + */ + +.site-footer { + background-color: #e8e5ce; + color: #686758; + font-size: 14px; + text-align: center; +} + +.site-footer .widget-area, +.sidebar .site-footer { + text-align: left; +} + +.site-footer a { + color: #686758; +} + +.site-footer .sidebar-container { + background-color: #220e10; + padding: 20px 0; +} + +.site-footer .widget-area { + margin: 0 auto; + max-width: 1040px; + width: 100%; +} + +.sidebar .site-footer .widget-area { + max-width: 724px; + position: relative; + left: -158px; +} + +.site-footer .widget { + background: transparent; + color: #fff; + float: left; + margin-right: 20px; + width: 245px; +} + +.sidebar .site-footer .widget { + width: 228px; +} + +.sidebar .site-footer .widget:nth-of-type(4), +.sidebar .site-footer .widget:nth-of-type(3) { + margin-right: 0; +} + +.site-footer .widget a { + color: #e6402a; +} + +.site-footer .widget-title, +.site-footer .widget-title a, +.site-footer .wp-caption-text { + color: #fff; +} + +.site-info { + margin: 0 auto; + max-width: 1040px; + padding: 30px 0; + width: 100%; +} + +#wpstats { + display: block; + margin: -10px auto 0; +} + + +/** + * 8.0 Media Queries + * ---------------------------------------------------------------------------- + */ + +@media (max-width: 1599px) { + .site { + border: 0; + } +} + +@media (max-width: 1069px) { + .sidebar img.alignleft, + .sidebar .wp-caption.alignleft { + margin-left: 0; + } + + .sidebar img.alignright, + .sidebar .wp-caption.alignright { + margin-right: 0; + } + + .error404 .page-header { + margin-left: auto; + max-width: 604px; + width: 100%; + } + + .archive-header, + .search .page-header, + .archive .page-header, + .blog .page-header, + .error404 .page-content, + .search .page-content, + .archive .page-content, + .attachment .entry-header, + .attachment .entry-content, + .post-navigation .nav-links, + .sidebar .site-info, + .site-footer .widget-area { + padding-left: 20px; + padding-right: 20px; + } + + .error404 .page-title { + font-size: 24px; + padding: 180px; + } + + .error404 .page-title:before { + font-size: 554px; + } + + .attachment .image-navigation { + max-width: 724px; + } + + .image-navigation .nav-previous, + .image-navigation .nav-next { + position: static; + } + + .site-main .widget-area { + margin-right: 60px; + } +} + +@media (max-width: 999px) { + .sidebar .entry-header, + .sidebar .entry-content, + .sidebar .entry-summary, + .sidebar .entry-meta, + .sidebar .comment-list, + .sidebar .comment-reply-title, + .sidebar .comment-navigation, + .sidebar .comment-respond .comment-form, + .sidebar .featured-gallery, + .sidebar .post-navigation .nav-links, + .author.sidebar .author-info { + max-width: 604px; + padding-left: 0; + padding-right: 0; + } + + .sidebar .site-info, + .search.sidebar .page-content, + .blog.sidebar .page-content, + .attachment .entry-header, + .sidebar .comments-title { + max-width: 604px; + } + + .sidebar .archive-meta, + .attachment .entry-header, + .search.sidebar .page-content, + .blog.sidebar .page-content, + .sidebar .site-info, + .sidebar .comments-title, + .sidebar .no-comments { + padding-left: 0; + padding-right: 0; + } + + .attachment .entry-meta { + float: left; + text-align: left; + width: 100%; + } + + .attachment .entry-content { + max-width: 100%; + padding: 40px 0; + } + + .format-status .entry-content { + padding-top: 40px; + } + + .format-status .entry-meta { + padding-bottom: 40px; + } + + .sidebar .format-status .entry-content, + .sidebar .format-status .entry-meta { + padding-left: 35px; + } + + .sidebar .format-status .entry-content:before, + .sidebar .format-status .entry-meta:before { + left: 10px; + } + + .sidebar .format-status .entry-content p:first-child:before { + left: 4px; + } + + .sidebar .paging-navigation .nav-links { + padding: 0 60px; + } + + .site-main .sidebar-container { + height: auto; + margin: 0 auto; + max-width: 604px; + position: relative; + top: 20px; + } + + .site-main .widget-area { + float: none; + margin: 0; + width: 100%; + } + + .sidebar .site-footer .widget-area { + max-width: 100%; + left: 0; + } +} + +/* Collapse oversized image and pulled images after iPad breakpoint. */ +@media (max-width: 767px) { + .entry-content img.alignleft, + .entry-content .wp-caption.alignleft { + margin-left: 0; + } + + .entry-content img.alignright, + .entry-content .wp-caption.alignright { + margin-right: 0; + } + + .attachment .image-navigation, + .attachment .entry-attachment .attachment { + max-width: 604px; + padding: 0; + width: 100%; + } + + .gallery-caption { + display: none; + } +} + +@media (max-width: 643px) { + .site-title { + font-size: 30px; + } + + #content .entry-header, + #content .entry-content, + #content .entry-summary, + #content footer.entry-meta, + #content .featured-gallery, + .search.sidebar .page-content, + .blog.sidebar .page-content, + .sidebar .post-navigation .nav-links, + .paging-navigation .nav-links, + #content .author-info, + .comments-area .comments-title, + .comments-area .comment-list, + .comments-area .comment-navigation, + .comment-respond, + .sidebar .site-info, + .sidebar .paging-navigation .nav-links { + padding-left: 20px; + padding-right: 20px; + } + + #content .format-status .entry-content, + #content .format-status .entry-met { + padding-left: 35px; + } + + /* Small menu */ + .menu-toggle { + cursor: pointer; + display: inline-block; + font: bold 16px/1.3 "Source Sans Pro", Helvetica, sans-serif; + margin: 0; + padding: 12px 0 12px 20px; + } + + .menu-toggle:after { + content: "\f502"; + font-size: 12px; + padding-left: 8px; + vertical-align: -4px; + } + + .toggled-on .menu-toggle:after { + content: "\f500"; + vertical-align: 2px; + } + + .toggled-on .nav-menu, + .toggled-on .nav-menu > ul { + display: block; + margin-left: 0; + padding: 0; + width: 100%; + } + + .toggled-on li, + .toggled-on .children { + display: block; + } + + .toggled-on .nav-menu li > ul { + background-color: transparent; + display: block; + float: none; + margin-left: 20px; + position: relative; + left: auto; + top: auto; + } + + .toggled-on .nav-menu li > ul a { + color: #141412; + width: auto; + } + + .toggled-on .nav-menu li:hover > a, + .toggled-on .nav-menu .children a { + background-color: transparent; + color: #141412; + } + + .toggled-on .nav-menu li a:hover, + .toggled-on .nav-menu ul a:hover { + background-color: #db572f; + color: #fff; + } + + ul.nav-menu, + div.nav-menu > ul { + display: none; + } + + #content .featured-gallery { + padding-left: 24px; + } + + .gallery-columns-1 .gallery-item { + margin-right: 0; + width: 100%; + } + + .entry-title, + .format-chat .entry-title, + .format-image .entry-title, + .format-gallery .entry-title, + .format-video .entry-title { + font-size: 22px; + font-weight: bold; + } + + .format-quote blockquote, + .format-status .entry-content { + font-size: 18px; + } + + .format-quote blockquote small, + .format-quote blockquote cite { + font-size: 13px; + } + + .error404 .page-title { + padding: 40px 0 0; + } + + .error404 .page-title:before { + content: normal; + } + + .comment-author { + margin-right: 30px; + } + + .comment-author .avatar { + height: auto; + max-width: 100%; + } + + .comment-metadata, + .comment-content, + .comment-list .reply { + width: 70%; + width: -webkit-calc(100% - 104px); + width: calc(100% - 104px); + } + + .comment-form input[type="text"], + .comment-form input[type="email"], + .comment-form input[type="url"] { + width: -webkit-calc(100% - 120px); + width: calc(100% - 120px); + } + + .comment-form textarea { + height: 80px; /* Smaller field for mobile. */ + } + + /* Audio */ + .format-audio .entry-content:before { + display: none; + } + + .format-audio .audio-content { + background-image: none; + float: none; + padding-left: 0; + width: auto; + } +} + +/* Mobile devices */ +@media (max-width: 359px) { + .gallery { + margin-left: 0; + } + + .gallery .gallery-item, + .gallery-columns-2.gallery-size-thumbnail .gallery-item { + max-width: none; + width: 49%; + width: -webkit-calc(50% - 4px); + width: calc(50% - 4px); + } + + .gallery-columns-1.gallery-size-medium, + .gallery-columns-1.gallery-size-thumbnail, + .gallery-columns-2.gallery-size-thumbnail, + .gallery-columns-3.gallery-size-thumbnail { + display: block; + } + + .gallery-columns-1 .gallery-item, + .gallery-columns-1.gallery-size-medium .gallery-item, + .gallery-columns-1.gallery-size-thumbnail .gallery-item { + text-align: center; + width: 98%; + width: -webkit-calc(100% - 4px); + width: calc(100% - 4px); + } + + .gallery-columns-3 .gallery-item:nth-of-type(3n), + .gallery-columns-5 .gallery-item:nth-of-type(5n), + .gallery-columns-7 .gallery-item:nth-of-type(7n), + .gallery-columns-9 .gallery-item:nth-of-type(9n) { + margin-right: 4px; + } + + .gallery br { + display: none; + } + + .gallery .gallery-item:nth-of-type(even) { + margin-right: 0; + } + + /* Comments */ + .comment-author { + margin: 0 0 5px; + max-width: 100%; + } + + .comment-author .avatar { + display: inline; + margin: 0 5px 0 0; + max-width: 20px; + } + + .comment-metadata, + .comment-content, + .comment-list .reply { + width: 100%; + } +} + + +/** + * 9.0 Print + * ---------------------------------------------------------------------------- + */ + +/* Retina-specific styles. */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + + .site-header .search-field { + background-image: url(images/search-icon-2x.png); + } + + .format-audio .audio-content, + .format-status .entry-content:before, + .format-status .entry-meta:before, + .comment-list > li:after, + .comment-list .children > li:before { + background-image: url(images/dotted-line-2x.png); + } +} + +@media print { + body { + background: none !important; + color: #000; + font-size: 10pt; + } + + footer a[rel="bookmark"]:link:after, + footer a[rel="bookmark"]:visited:after { + content: " [" attr(href) "] "; /* Show URLs */ + } + + .site { + max-width: 98%; + } + + .site-header { + background-image: none !important; + } + + .site-header .home-link { + max-width: none; + min-height: 0; + } + + .site-title { + color: #000; + font-size: 21pt; + } + + .site-description { + font-size: 10pt; + } + + .author-avatar, + .site-footer, + .comment-respond, + .comments-area .comment-edit-link, + .comments-area .reply, + .comments-link, + .entry-meta .edit-link, + .page-links, + .site-content nav, + .widget-area, + .main-navigation, + .navbar, + .more-link { + display: none; + } + + .entry-header, + .entry-content, + .entry-summary, + .entry-meta { + margin: 0; + width: 100%; + } + + .page-title, + .entry-title { + font-size: 21pt; + } + + .entry-meta, + .entry-meta a { + color: #444; + font-size: 10pt; + } + + .entry-content img.alignleft, + .entry-content .wp-caption.alignleft { + margin-left: 0; + } + + .entry-content img.alignright, + .entry-content .wp-caption.alignright { + margin-right: 0; + } + + .format-image .entry-content .size-full { + margin: 0; + } + + /* Remove colors from post formats */ + .hentry { + background-color: #fff; + } + + /* Comments */ + .comments-area > li.comment { + background: none; + position: relative; + width: auto; + } + + .comment-metadata { + float: none; + } + + .comment-author .fn, + .comment-reply-link, + .comment-reply-login { + color: #333; + } +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/tag.php b/sources/wp-content/themes/twentythirteen/tag.php new file mode 100644 index 0000000..2929321 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/tag.php @@ -0,0 +1,43 @@ + + +
    +
    + + +
    +

    + + +
    + +
    + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentythirteen/taxonomy-post_format.php b/sources/wp-content/themes/twentythirteen/taxonomy-post_format.php new file mode 100644 index 0000000..bbec046 --- /dev/null +++ b/sources/wp-content/themes/twentythirteen/taxonomy-post_format.php @@ -0,0 +1,41 @@ + + +
    +
    + + +
    +

    ' . get_post_format_string( get_post_format() ) . '' ); ?>

    +
    + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/404.php b/sources/wp-content/themes/twentytwelve/404.php new file mode 100644 index 0000000..db3ef81 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/404.php @@ -0,0 +1,29 @@ + + +
    +
    + +
    +
    +

    +
    + +
    +

    + +
    +
    + +
    +
    + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/archive.php b/sources/wp-content/themes/twentytwelve/archive.php new file mode 100644 index 0000000..2d442bd --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/archive.php @@ -0,0 +1,63 @@ + + +
    +
    + + +
    +

    ' . get_the_date() . '' ); + elseif ( is_month() ) : + printf( __( 'Monthly Archives: %s', 'twentytwelve' ), '' . get_the_date( _x( 'F Y', 'monthly archives date format', 'twentytwelve' ) ) . '' ); + elseif ( is_year() ) : + printf( __( 'Yearly Archives: %s', 'twentytwelve' ), '' . get_the_date( _x( 'Y', 'yearly archives date format', 'twentytwelve' ) ) . '' ); + else : + _e( 'Archives', 'twentytwelve' ); + endif; + ?>

    +
    + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/author.php b/sources/wp-content/themes/twentytwelve/author.php new file mode 100644 index 0000000..6570108 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/author.php @@ -0,0 +1,84 @@ + + +
    +
    + + + + + +
    +

    ' . get_the_author() . '' ); ?>

    +
    + + + + + + +
    +
    + +
    +
    +

    +

    +
    +
    + + + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/category.php b/sources/wp-content/themes/twentytwelve/category.php new file mode 100644 index 0000000..0376977 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/category.php @@ -0,0 +1,51 @@ + + +
    +
    + + +
    +

    ' . single_cat_title( '', false ) . '' ); ?>

    + + +
    + +
    + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/comments.php b/sources/wp-content/themes/twentytwelve/comments.php new file mode 100644 index 0000000..d6a733e --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/comments.php @@ -0,0 +1,60 @@ + + +
    + + + + +

    + ' . get_the_title() . '' ); + ?> +

    + +
      + 'twentytwelve_comment', 'style' => 'ol' ) ); ?> +
    + + 1 && get_option( 'page_comments' ) ) : // are there comments to navigate through ?> + + + + +

    + + + + + + +
    \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/content-aside.php b/sources/wp-content/themes/twentytwelve/content-aside.php new file mode 100644 index 0000000..4a84ae7 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-aside.php @@ -0,0 +1,28 @@ + + +
    > +
    +

    +
    + →', 'twentytwelve' ) ); ?> +
    +
    + +
    + + + + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content-image.php b/sources/wp-content/themes/twentytwelve/content-image.php new file mode 100644 index 0000000..a683b83 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-image.php @@ -0,0 +1,28 @@ + + +
    > +
    + →', 'twentytwelve' ) ); ?> +
    + +
    + +

    +

    +
    + + + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content-link.php b/sources/wp-content/themes/twentytwelve/content-link.php new file mode 100644 index 0000000..31e4ec9 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-link.php @@ -0,0 +1,26 @@ + + +
    > +
    +
    + →', 'twentytwelve' ) ); ?> +
    + +
    + + + + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content-none.php b/sources/wp-content/themes/twentytwelve/content-none.php new file mode 100644 index 0000000..b775782 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-none.php @@ -0,0 +1,20 @@ + + +
    +
    +

    +
    + +
    +

    + +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content-page.php b/sources/wp-content/themes/twentytwelve/content-page.php new file mode 100644 index 0000000..0abcbf7 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-page.php @@ -0,0 +1,26 @@ + + +
    > +
    + + + +

    +
    + +
    + + '' ) ); ?> +
    +
    + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content-quote.php b/sources/wp-content/themes/twentytwelve/content-quote.php new file mode 100644 index 0000000..0a98a96 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-quote.php @@ -0,0 +1,25 @@ + + +
    > +
    + →', 'twentytwelve' ) ); ?> +
    + +
    + + + + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content-status.php b/sources/wp-content/themes/twentytwelve/content-status.php new file mode 100644 index 0000000..55b72db --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content-status.php @@ -0,0 +1,42 @@ + + +
    > +
    +
    +

    +

    +
    + +
    + +
    + →', 'twentytwelve' ) ); ?> +
    + +
    + + + + ', '' ); ?> +
    +
    diff --git a/sources/wp-content/themes/twentytwelve/content.php b/sources/wp-content/themes/twentytwelve/content.php new file mode 100644 index 0000000..daaad34 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/content.php @@ -0,0 +1,70 @@ + + +
    > + +
    + +
    + +
    + + +

    + +

    + +

    + + + + +
    + + +
    + +
    + +
    + →', 'twentytwelve' ) ); ?> + '' ) ); ?> +
    + + + +
    diff --git a/sources/wp-content/themes/twentytwelve/css/ie.css b/sources/wp-content/themes/twentytwelve/css/ie.css new file mode 100644 index 0000000..ddb1e41 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/css/ie.css @@ -0,0 +1,243 @@ +/* +Styles for older IE versions (previous to IE9). +*/ + +body { + background-color: #e6e6e6; +} +body.custom-background-empty { + background-color: #fff; +} +body.custom-background-empty .site, +body.custom-background-white .site { + box-shadow: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} +.assistive-text, +.site .screen-reader-text { + clip: rect(1px 1px 1px 1px); /* IE7 */ +} +.full-width .site-content { + float: none; + width: 100%; +} +img.size-full, +img.size-large, +img.header-image, +img.wp-post-image, +img[class*="align"], +img[class*="wp-image-"], +img[class*="attachment-"] { + width: auto; /* Prevent stretching of full-size and large-size images with height and width attributes in IE8 */ +} +.author-avatar { + float: left; + margin-top: 8px; + margin-top: 0.571428571rem; +} +.author-description { + float: right; + width: 80%; +} +.site { + box-shadow: 0 2px 6px rgba(100, 100, 100, 0.3); + margin: 48px auto; + max-width: 960px; + overflow: hidden; + padding: 0 40px; +} +.site-content { + float: left; + width: 65.104166667%; +} +body.template-front-page .site-content, +body.attachment .site-content, +body.full-width .site-content { + width: 100%; +} +.widget-area { + float: right; + width: 26.041666667%; +} +.site-header h1, +.site-header h2 { + text-align: left; +} +.site-header h1 { + font-size: 26px; + line-height: 1.846153846; +} +.main-navigation ul.nav-menu, +.main-navigation div.nav-menu > ul { + border-bottom: 1px solid #ededed; + border-top: 1px solid #ededed; + display: inline-block !important; + text-align: left; + width: 100%; +} +.main-navigation ul { + margin: 0; + text-indent: 0; +} +.main-navigation li a, +.main-navigation li { + display: inline-block; + text-decoration: none; +} +.ie7 .main-navigation li a, +.ie7 .main-navigation li { + display: inline; +} +.main-navigation li a { + border-bottom: 0; + color: #6a6a6a; + line-height: 3.692307692; + text-transform: uppercase; +} +.main-navigation li a:hover { + color: #000; +} +.main-navigation li { + margin: 0 40px 0 0; + position: relative; +} +.main-navigation li ul { + display: none; + margin: 0; + padding: 0; + position: absolute; + top: 100%; + z-index: 1; +} +.ie7 .main-navigation li ul { + left: 0; +} +.main-navigation li ul ul, +.ie7 .main-navigation li ul ul { + top: 0; + left: 100%; +} +.main-navigation ul li:hover > ul { + border-left: 0; + display: block; +} +.main-navigation li ul li a { + background: #efefef; + border-bottom: 1px solid #ededed; + display: block; + font-size: 11px; + line-height: 2.181818182; + padding: 8px 10px; + width: 180px; +} +.main-navigation li ul li a:hover { + background: #e3e3e3; + color: #444; +} +.main-navigation .current-menu-item > a, +.main-navigation .current-menu-ancestor > a, +.main-navigation .current_page_item > a, +.main-navigation .current_page_ancestor > a { + color: #636363; + font-weight: bold; +} +.menu-toggle { + display: none; +} +.entry-header .entry-title { + font-size: 22px; +} +#respond form input[type="text"] { + width: 46.333333333%; +} +#respond form textarea.blog-textarea { + width: 79.666666667%; +} +.template-front-page .site-content, +.template-front-page article { + overflow: hidden; +} +.template-front-page.has-post-thumbnail article { + float: left; + width: 47.916666667%; +} +.entry-page-image { + float: right; + margin-bottom: 0; + width: 47.916666667%; +} +.template-front-page .widget-area .widget, +.template-front-page.two-sidebars .widget-area .front-widgets { + float: left; + margin-bottom: 24px; + width: 51.875%; +} +.template-front-page .widget-area .widget:nth-child(odd) { + clear: right; +} +.template-front-page .widget-area .widget:nth-child(even), +.template-front-page.two-sidebars .widget-area .front-widgets + .front-widgets { + float: right; + margin: 0 0 24px; + width: 39.0625%; +} +.template-front-page.two-sidebars .widget, +.template-front-page.two-sidebars .widget:nth-child(even) { + float: none; + width: auto; +} + +/* =RTL overrides for IE7 and IE8 +-------------------------------------------------------------- */ +.rtl .site-header h1, +.rtl .site-header h2 { + text-align: right; +} +.rtl .widget-area, +.rtl .author-description { + float: left; +} +.rtl .author-avatar, +.rtl .site-content { + float: right; +} +.rtl .main-navigation ul.nav-menu, +.rtl .main-navigation div.nav-menu > ul { + text-align: right; +} +.rtl .main-navigation ul li ul li, +.rtl .main-navigation ul li ul li ul li { + margin-left: 40px; + margin-right: auto; +} +.rtl .main-navigation li ul ul { + position: absolute; + bottom: 0; + right: 100%; + z-index: 1; +} +.ie7 .rtl .main-navigation li ul ul { + position: absolute; + bottom: 0; + right: 100%; + z-index: 1; +} +.ie7 .rtl .main-navigation ul li { + z-index: 99; +} +.ie7 .rtl .main-navigation li ul { + position: absolute; + bottom: 100%; + right: 0; + z-index: 1; +} +.ie7 .rtl .main-navigation li { + margin-right: auto; + margin-left: 40px; +} +.ie7 .rtl .main-navigation li ul ul ul { + position: relative; + z-index: 1; +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/editor-style-rtl.css b/sources/wp-content/themes/twentytwelve/editor-style-rtl.css new file mode 100644 index 0000000..5fd832c --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/editor-style-rtl.css @@ -0,0 +1,28 @@ +/* +Theme Name: Twenty Twelve +Description: Used to style the TinyMCE editor for RTL languages. +See also rtl.css file. +*/ + +html .mceContentBody { + direction: rtl; + unicode-bidi: embed; +} +li { + margin: 0 24px 0 0; + margin: 0 1.714285714rem 0 0; +} +dl { + margin: 0 24px; + margin: 0 1.714285714rem; +} +tr th { + text-align: right; +} +td { + padding: 6px 0 6px 10px; + text-align: right; +} +.wp-caption { + text-align: right; +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/editor-style.css b/sources/wp-content/themes/twentytwelve/editor-style.css new file mode 100644 index 0000000..24e9b24 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/editor-style.css @@ -0,0 +1,342 @@ +/* +Theme Name: Twenty Twelve +Description: Used to style the TinyMCE editor. +*/ + +html { + font-size: 87.5%; +} +html .mceContentBody { + max-width: 625px; +} +body { + color: #444; + font-family: "Open Sans", Helvetica, Arial, sans-serif; + font-size: 14px; + font-size: 1rem; + line-height: 1; + text-rendering: optimizeLegibility; + vertical-align: baseline; +} + + +/* =Headings +-------------------------------------------------------------- */ + +h1, +h2, +h3, +h4, +h5, +h6 { + clear: both; + line-height: 1.846153846; + margin: 24px 0; + margin: 1.714285714rem 0; +} +h1 { + font-size: 21px; + font-size: 1.5rem; + line-height: 1.5; +} +h2 { + font-size: 18px; + font-size: 1.285714286rem; + line-height: 1.6; +} +h3 { + font-size: 16px; + font-size: 1.142857143rem; +} +h4 { + font-size: 14px; + font-size: 1rem; +} +h5 { + font-size: 13px; + font-size: 0.928571429rem; +} +h6 { + font-size: 12px; + font-size: 0.857142857rem; +} +hr { + background-color: #ccc; + border: 0; + height: 1px; + margin: 24px; + margin-bottom: 1.714285714rem; +} + + +/* =Text elements +-------------------------------------------------------------- */ + +p { + line-height: 1.714285714; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; +} +ul, +ol { + margin: 0 0 24px; + margin: 0 0 1.714285714rem; + line-height: 1.714285714; + padding: 0; +} +ul { + list-style: disc outside; +} +ol { + list-style: decimal outside; +} +ul ul, +ol ol, +ul ol, +ol ul { + margin-bottom: 0; +} +li { + margin: 0 0 0 24px; + margin: 0 0 0 1.714285714rem; +} +dl { + margin: 0 24px; + margin: 0 1.714285714rem; +} +dt { + font-weight: bold; + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +dd { + line-height: 1.714285714; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; +} +strong { + font-weight: bold; +} +cite, +em, +i { + font-style: italic; +} +cite { + border: none; +} +big { + font-size: 128.571429%; +} +.mceContentBody blockquote { + font-style: italic !important; + font-weight: normal; + margin: 0; + padding: 24px; + padding: 1.714285714rem; +} +pre { + border: 1px solid #ededed; + color: #666; + font-family: Consolas, Monaco, Lucida Console, monospace; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 1.714285714; + margin: 24px 0; + margin: 1.714285714rem 0; + overflow: auto; + padding: 24px; + padding: 1.714285714rem; +} +code, +kbd, +samp, +var { + font-family: Consolas, Monaco, Lucida Console, monospace; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; +} +abbr, +acronym, +dfn { + border-bottom: 1px dotted #666; + cursor: help; +} +address { + display: block; + line-height: 1.714285714; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; +} +del { + color: #333; +} +ins { + background: #fff9c0; + border: none; + color: #333; + text-decoration: none; +} +sup, +sub { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +input[type="text"] { + border: 1px solid #ccc; + border-radius: 3px; + font-family: inherit; + padding: 6px; + padding: 0.428571429rem; +} +textarea { + border: 1px solid #d5d2ca; + border-radius: 3px; + font-family: inherit; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 1.714285714; + padding: 10px; + padding: 0.714285714rem; + width: 96%; +} + + +/* =Links +-------------------------------------------------------------- */ + +a, +a em, +a strong { + color: #21759b; + outline: none; +} +a:focus, +a:active, +a:hover { + color: #0f3647; +} + + +/* =Alignment +-------------------------------------------------------------- */ + +.alignleft { + display: inline; + float: left; + margin: 12px 24px 12px 0; + margin: 0.857142857rem 1.714285714rem 0.857142857rem 0; +} +.alignright { + display: inline; + float: right; + margin: 12px 0 12px 24px; + margin: 0.857142857rem 0 0.857142857rem 1.714285714rem; +} +.aligncenter { + clear: both; + display: block; + margin-top: 12px; + margin-top: 0.857142857rem; + margin-bottom: 12px; + margin-bottom: 0.857142857rem; +} + + +/* =Tables +-------------------------------------------------------------- */ + +table { + border-bottom: 1px solid #ededed; + border-collapse: collapse; + border-spacing: 0; + color: #757575; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; + width: 100%; +} +tr th { + color: #636363; + font-size: 11px; + font-size: 0.785714286rem; + font-weight: bold; + line-height: 2.181818182; + text-align: left; + text-transform: uppercase; +} +td { + border-top: 1px solid #ededed !important; + color: #757575; + font-size: inherit; + font-weight: normal; + padding: 6px 10px 6px 0; + text-align: left; +} + + +/* =Images +-------------------------------------------------------------- */ + +img, +.editor-attachment { + border: 0; + border-radius: 3px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); + max-width: 100%; +} +img.size-full { + width: auto/9; /* Prevent stretching of full-size images in IE8 */ +} +img[class*="wp-image-"] { + height: auto; + max-width: 100%; +} +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.mce-wp-nextpage { + border-radius: 0; + box-shadow: none; +} +img.wp-smiley { + border: 0; + border-radius: 0; + box-shadow: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} +.wp-caption { + background: transparent; + border: none; + margin: 0; + padding: 4px; + text-align: left; +} +.wp-caption-dt { + margin: 0; +} +.wp-caption .wp-caption-text, +.wp-caption-dd { + color: #757575; + font-style: italic; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + margin: 0 0 24px; + margin: 0 0 1.71429rem; +} diff --git a/sources/wp-content/themes/twentytwelve/footer.php b/sources/wp-content/themes/twentytwelve/footer.php new file mode 100644 index 0000000..79848d3 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/footer.php @@ -0,0 +1,23 @@ + +
    +
    +
    + + +
    +
    +
    + + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/functions.php b/sources/wp-content/themes/twentytwelve/functions.php new file mode 100644 index 0000000..4054481 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/functions.php @@ -0,0 +1,510 @@ + for posts and comments. + add_theme_support( 'automatic-feed-links' ); + + // This theme supports a variety of post formats. + add_theme_support( 'post-formats', array( 'aside', 'image', 'link', 'quote', 'status' ) ); + + // This theme uses wp_nav_menu() in one location. + register_nav_menu( 'primary', __( 'Primary Menu', 'twentytwelve' ) ); + + /* + * This theme supports custom background color and image, + * and here we also set up the default background color. + */ + add_theme_support( 'custom-background', array( + 'default-color' => 'e6e6e6', + ) ); + + // This theme uses a custom image size for featured images, displayed on "standard" posts. + add_theme_support( 'post-thumbnails' ); + set_post_thumbnail_size( 624, 9999 ); // Unlimited height, soft crop +} +add_action( 'after_setup_theme', 'twentytwelve_setup' ); + +/** + * Add support for a custom header image. + */ +require( get_template_directory() . '/inc/custom-header.php' ); + +/** + * Return the Google font stylesheet URL if available. + * + * The use of Open Sans by default is localized. For languages that use + * characters not supported by the font, the font can be disabled. + * + * @since Twenty Twelve 1.2 + * + * @return string Font stylesheet or empty string if disabled. + */ +function twentytwelve_get_font_url() { + $font_url = ''; + + /* 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', 'twentytwelve' ) ) { + $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. + */ + $subset = _x( 'no-subset', 'Open Sans font: add new subset (greek, cyrillic, vietnamese)', 'twentytwelve' ); + + if ( 'cyrillic' == $subset ) + $subsets .= ',cyrillic,cyrillic-ext'; + elseif ( 'greek' == $subset ) + $subsets .= ',greek,greek-ext'; + elseif ( 'vietnamese' == $subset ) + $subsets .= ',vietnamese'; + + $protocol = is_ssl() ? 'https' : 'http'; + $query_args = array( + 'family' => 'Open+Sans:400italic,700italic,400,700', + 'subset' => $subsets, + ); + $font_url = add_query_arg( $query_args, "$protocol://fonts.googleapis.com/css" ); + } + + return $font_url; +} + +/** + * Enqueue scripts and styles for front-end. + * + * @since Twenty Twelve 1.0 + * + * @return void + */ +function twentytwelve_scripts_styles() { + global $wp_styles; + + /* + * Adds JavaScript to pages with the comment form to support + * sites with threaded comments (when in use). + */ + if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) + wp_enqueue_script( 'comment-reply' ); + + // Adds JavaScript for handling the navigation menu hide-and-show behavior. + wp_enqueue_script( 'twentytwelve-navigation', get_template_directory_uri() . '/js/navigation.js', array(), '1.0', true ); + + $font_url = twentytwelve_get_font_url(); + if ( ! empty( $font_url ) ) + wp_enqueue_style( 'twentytwelve-fonts', esc_url_raw( $font_url ), array(), null ); + + // Loads our main stylesheet. + wp_enqueue_style( 'twentytwelve-style', get_stylesheet_uri() ); + + // Loads the Internet Explorer specific stylesheet. + wp_enqueue_style( 'twentytwelve-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentytwelve-style' ), '20121010' ); + $wp_styles->add_data( 'twentytwelve-ie', 'conditional', 'lt IE 9' ); +} +add_action( 'wp_enqueue_scripts', 'twentytwelve_scripts_styles' ); + +/** + * Filter TinyMCE CSS path to include Google Fonts. + * + * Adds additional stylesheets to the TinyMCE editor if needed. + * + * @uses twentytwelve_get_font_url() To get the Google Font stylesheet URL. + * + * @since Twenty Twelve 1.2 + * + * @param string $mce_css CSS path to load in TinyMCE. + * @return string Filtered CSS path. + */ +function twentytwelve_mce_css( $mce_css ) { + $font_url = twentytwelve_get_font_url(); + + if ( empty( $font_url ) ) + return $mce_css; + + if ( ! empty( $mce_css ) ) + $mce_css .= ','; + + $mce_css .= esc_url_raw( str_replace( ',', '%2C', $font_url ) ); + + return $mce_css; +} +add_filter( 'mce_css', 'twentytwelve_mce_css' ); + +/** + * Filter the page title. + * + * Creates a nicely formatted and more specific title element text + * for output in head of document, based on current view. + * + * @since Twenty Twelve 1.0 + * + * @param string $title Default title text for current view. + * @param string $sep Optional separator. + * @return string Filtered title. + */ +function twentytwelve_wp_title( $title, $sep ) { + global $paged, $page; + + if ( is_feed() ) + return $title; + + // Add the site name. + $title .= get_bloginfo( 'name' ); + + // Add the site description for the home/front page. + $site_description = get_bloginfo( 'description', 'display' ); + if ( $site_description && ( is_home() || is_front_page() ) ) + $title = "$title $sep $site_description"; + + // Add a page number if necessary. + if ( $paged >= 2 || $page >= 2 ) + $title = "$title $sep " . sprintf( __( 'Page %s', 'twentytwelve' ), max( $paged, $page ) ); + + return $title; +} +add_filter( 'wp_title', 'twentytwelve_wp_title', 10, 2 ); + +/** + * Filter the page menu arguments. + * + * Makes our wp_nav_menu() fallback -- wp_page_menu() -- show a home link. + * + * @since Twenty Twelve 1.0 + */ +function twentytwelve_page_menu_args( $args ) { + if ( ! isset( $args['show_home'] ) ) + $args['show_home'] = true; + return $args; +} +add_filter( 'wp_page_menu_args', 'twentytwelve_page_menu_args' ); + +/** + * Register sidebars. + * + * Registers our main widget area and the front page widget areas. + * + * @since Twenty Twelve 1.0 + */ +function twentytwelve_widgets_init() { + register_sidebar( array( + 'name' => __( 'Main Sidebar', 'twentytwelve' ), + 'id' => 'sidebar-1', + 'description' => __( 'Appears on posts and pages except the optional Front Page template, which has its own widgets', 'twentytwelve' ), + 'before_widget' => '', + 'before_title' => '

    ', + 'after_title' => '

    ', + ) ); + + register_sidebar( array( + 'name' => __( 'First Front Page Widget Area', 'twentytwelve' ), + 'id' => 'sidebar-2', + 'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'twentytwelve' ), + 'before_widget' => '', + 'before_title' => '

    ', + 'after_title' => '

    ', + ) ); + + register_sidebar( array( + 'name' => __( 'Second Front Page Widget Area', 'twentytwelve' ), + 'id' => 'sidebar-3', + 'description' => __( 'Appears when using the optional Front Page template with a page set as Static Front Page', 'twentytwelve' ), + 'before_widget' => '', + 'before_title' => '

    ', + 'after_title' => '

    ', + ) ); +} +add_action( 'widgets_init', 'twentytwelve_widgets_init' ); + +if ( ! function_exists( 'twentytwelve_content_nav' ) ) : +/** + * Displays navigation to next/previous pages when applicable. + * + * @since Twenty Twelve 1.0 + */ +function twentytwelve_content_nav( $html_id ) { + global $wp_query; + + $html_id = esc_attr( $html_id ); + + if ( $wp_query->max_num_pages > 1 ) : ?> + + comment_type ) : + case 'pingback' : + case 'trackback' : + // Display trackbacks differently than normal comments. + ?> +
  • id="comment-"> +

    ', '' ); ?>

    + +
  • id="li-comment-"> +
    +
    + %1$s %2$s', + get_comment_author_link(), + // If current post author is also comment author, make it known visually. + ( $comment->user_id === $post->post_author ) ? '' . __( 'Post author', 'twentytwelve' ) . '' : '' + ); + printf( '', + esc_url( get_comment_link( $comment->comment_ID ) ), + get_comment_time( 'c' ), + /* translators: 1: date, 2: time */ + sprintf( __( '%1$s at %2$s', 'twentytwelve' ), get_comment_date(), get_comment_time() ) + ); + ?> +
    + + comment_approved ) : ?> +

    + + +
    + + ', '

    ' ); ?> +
    + +
    + __( 'Reply', 'twentytwelve' ), 'after' => ' ', 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?> +
    +
    + ', + esc_url( get_permalink() ), + esc_attr( get_the_time() ), + esc_attr( get_the_date( 'c' ) ), + esc_html( get_the_date() ) + ); + + $author = sprintf( '', + esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ), + esc_attr( sprintf( __( 'View all posts by %s', 'twentytwelve' ), get_the_author() ) ), + get_the_author() + ); + + // Translators: 1 is category, 2 is tag, 3 is the date and 4 is the author's name. + if ( $tag_list ) { + $utility_text = __( 'This entry was posted in %1$s and tagged %2$s on %3$s by %4$s.', 'twentytwelve' ); + } elseif ( $categories_list ) { + $utility_text = __( 'This entry was posted in %1$s on %3$s by %4$s.', 'twentytwelve' ); + } else { + $utility_text = __( 'This entry was posted on %3$s by %4$s.', 'twentytwelve' ); + } + + printf( + $utility_text, + $categories_list, + $tag_list, + $date, + $author + ); +} +endif; + +/** + * Extend the default WordPress body classes. + * + * Extends the default WordPress body class to denote: + * 1. Using a full-width layout, when no active widgets in the sidebar + * or full-width template. + * 2. Front Page template: thumbnail in use and number of sidebars for + * widget areas. + * 3. White or empty background color to change the layout and spacing. + * 4. Custom fonts enabled. + * 5. Single or multiple authors. + * + * @since Twenty Twelve 1.0 + * + * @param array $classes Existing class values. + * @return array Filtered class values. + */ +function twentytwelve_body_class( $classes ) { + $background_color = get_background_color(); + $background_image = get_background_image(); + + if ( ! is_active_sidebar( 'sidebar-1' ) || is_page_template( 'page-templates/full-width.php' ) ) + $classes[] = 'full-width'; + + if ( is_page_template( 'page-templates/front-page.php' ) ) { + $classes[] = 'template-front-page'; + if ( has_post_thumbnail() ) + $classes[] = 'has-post-thumbnail'; + if ( is_active_sidebar( 'sidebar-2' ) && is_active_sidebar( 'sidebar-3' ) ) + $classes[] = 'two-sidebars'; + } + + if ( empty( $background_image ) ) { + if ( empty( $background_color ) ) + $classes[] = 'custom-background-empty'; + elseif ( in_array( $background_color, array( 'fff', 'ffffff' ) ) ) + $classes[] = 'custom-background-white'; + } + + // Enable custom font class only if the font CSS is queued to load. + if ( wp_style_is( 'twentytwelve-fonts', 'queue' ) ) + $classes[] = 'custom-font-enabled'; + + if ( ! is_multi_author() ) + $classes[] = 'single-author'; + + return $classes; +} +add_filter( 'body_class', 'twentytwelve_body_class' ); + +/** + * Adjust content width in certain contexts. + * + * Adjusts content_width value for full-width and single image attachment + * templates, and when there are no active widgets in the sidebar. + * + * @since Twenty Twelve 1.0 + * + * @return void + */ +function twentytwelve_content_width() { + if ( is_page_template( 'page-templates/full-width.php' ) || is_attachment() || ! is_active_sidebar( 'sidebar-1' ) ) { + global $content_width; + $content_width = 960; + } +} +add_action( 'template_redirect', 'twentytwelve_content_width' ); + +/** + * Register postMessage support. + * + * Add postMessage support for site title and description for the Customizer. + * + * @since Twenty Twelve 1.0 + * + * @param WP_Customize_Manager $wp_customize Customizer object. + * @return void + */ +function twentytwelve_customize_register( $wp_customize ) { + $wp_customize->get_setting( 'blogname' )->transport = 'postMessage'; + $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage'; + $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage'; +} +add_action( 'customize_register', 'twentytwelve_customize_register' ); + +/** + * Enqueue Javascript postMessage handlers for the Customizer. + * + * Binds JS handlers to make the Customizer preview reload changes asynchronously. + * + * @since Twenty Twelve 1.0 + * + * @return void + */ +function twentytwelve_customize_preview_js() { + wp_enqueue_script( 'twentytwelve-customizer', get_template_directory_uri() . '/js/theme-customizer.js', array( 'customize-preview' ), '20130301', true ); +} +add_action( 'customize_preview_init', 'twentytwelve_customize_preview_js' ); diff --git a/sources/wp-content/themes/twentytwelve/header.php b/sources/wp-content/themes/twentytwelve/header.php new file mode 100644 index 0000000..eb64b68 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/header.php @@ -0,0 +1,53 @@ + section and everything up till
    + * + * @package WordPress + * @subpackage Twenty_Twelve + * @since Twenty Twelve 1.0 + */ +?> + + + +> + + + + +<?php wp_title( '|', true, 'right' ); ?> + + + + + + + +> +
    + + +
    \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/image.php b/sources/wp-content/themes/twentytwelve/image.php new file mode 100644 index 0000000..285e453 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/image.php @@ -0,0 +1,116 @@ + + +
    +
    + + + +
    > +
    +

    + +
    + Published at %4$s × %5$s in %8$s.', 'twentytwelve' ), + esc_attr( get_the_date( 'c' ) ), + esc_html( get_the_date() ), + esc_url( wp_get_attachment_url() ), + $metadata['width'], + $metadata['height'], + esc_url( get_permalink( $post->post_parent ) ), + esc_attr( strip_tags( get_the_title( $post->post_parent ) ) ), + get_the_title( $post->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; +endforeach; + +$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 ); + endif; +else : + // or, if there's only 1 image, get the URL of the image + $next_attachment_url = wp_get_attachment_url(); +endif; +?> + ID, $attachment_size ); + ?> + + post_excerpt ) ) : ?> +
    + +
    + +
    + +
    + +
    + + '' ) ); ?> +
    + +
    + +
    + + + + + +
    +
    + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/inc/custom-header.php b/sources/wp-content/themes/twentytwelve/inc/custom-header.php new file mode 100644 index 0000000..32fea17 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/inc/custom-header.php @@ -0,0 +1,167 @@ + '515151', + 'default-image' => '', + + // Set height and width, with a maximum value for the width. + 'height' => 250, + 'width' => 960, + 'max-width' => 2000, + + // Support flexible height and width. + 'flex-height' => true, + 'flex-width' => true, + + // Random image rotation off by default. + 'random-default' => false, + + // Callbacks for styling the header and the admin preview. + 'wp-head-callback' => 'twentytwelve_header_style', + 'admin-head-callback' => 'twentytwelve_admin_header_style', + 'admin-preview-callback' => 'twentytwelve_admin_header_image', + ); + + add_theme_support( 'custom-header', $args ); +} +add_action( 'after_setup_theme', 'twentytwelve_custom_header_setup' ); + +/** + * Load our special font CSS file. + * + * @since Twenty Twelve 1.2 + * + * @return void + */ +function twentytwelve_custom_header_fonts() { + $font_url = twentytwelve_get_font_url(); + if ( ! empty( $font_url ) ) + wp_enqueue_style( 'twentytwelve-fonts', esc_url_raw( $font_url ), array(), null ); +} +add_action( 'admin_print_styles-appearance_page_custom-header', 'twentytwelve_custom_header_fonts' ); + +/** + * Style the header text displayed on the blog. + * + * get_header_textcolor() options: 515151 is default, hide text (returns 'blank'), or any hex value. + * + * @since Twenty Twelve 1.0 + */ +function twentytwelve_header_style() { + $text_color = get_header_textcolor(); + + // If no custom options for text are set, let's bail + if ( $text_color == get_theme_support( 'custom-header', 'default-text-color' ) ) + return; + + // If we get this far, we have custom styles. + ?> + + Header admin panel. + * + * @since Twenty Twelve 1.0 + */ +function twentytwelve_admin_header_style() { +?> + + Header admin panel. + * + * This callback overrides the default markup displayed there. + * + * @since Twenty Twelve 1.0 + */ +function twentytwelve_admin_header_image() { + ?> + + + +
    +
    + + + + + + + + + + + +
    + + +
    +

    +
    + +
    +

    Get started here.', 'twentytwelve' ), admin_url( 'post-new.php' ) ); ?>

    +
    + + +
    +

    +
    + +
    +

    + +
    + + +
    + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/js/html5.js b/sources/wp-content/themes/twentytwelve/js/html5.js new file mode 100644 index 0000000..a788916 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/js/html5.js @@ -0,0 +1,7 @@ +/*! HTML5 Shiv v3.6 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ +/* Source: https://github.com/aFarkas/html5shiv */ +(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); +a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; +c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^<|^(?:a|b|button|code|div|fieldset|form|h1|h2|h3|h4|h5|h6|i|iframe|img|input|label|li|link|ol|option|p|param|q|script|select|span|strong|style|table|tbody|td|textarea|tfoot|th|thead|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a"); +var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a, +b){a||(a=f);if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d\n" +"Language-Team: LANGUAGE \n" + +#: 404.php:17 +msgid "This is somewhat embarrassing, isn’t it?" +msgstr "" + +#: 404.php:21 +msgid "" +"It seems we can’t find what you’re looking for. Perhaps " +"searching can help." +msgstr "" + +#: archive.php:29 +msgid "Daily Archives: %s" +msgstr "" + +#: archive.php:31 +msgid "Monthly Archives: %s" +msgstr "" + +#: archive.php:31 +msgctxt "monthly archives date format" +msgid "F Y" +msgstr "" + +#: archive.php:33 +msgid "Yearly Archives: %s" +msgstr "" + +#: archive.php:33 +msgctxt "yearly archives date format" +msgid "Y" +msgstr "" + +#: archive.php:35 +msgid "Archives" +msgstr "" + +#: author.php:32 +msgid "Author Archives: %s" +msgstr "" + +#: author.php:63 content.php:59 +msgid "About %s" +msgstr "" + +#: category.php:21 +msgid "Category Archives: %s" +msgstr "" + +#: comments.php:31 +msgid "One thought on “%2$s”" +msgid_plural "%1$s thoughts on “%2$s”" +msgstr[0] "" +msgstr[1] "" + +#: comments.php:42 +msgid "Comment navigation" +msgstr "" + +#: comments.php:43 +msgid "← Older Comments" +msgstr "" + +#: comments.php:44 +msgid "Newer Comments →" +msgstr "" + +#: comments.php:53 +msgid "Comments are closed." +msgstr "" + +#: content-aside.php:15 content-image.php:13 content-link.php:14 +#: content-quote.php:13 content-status.php:31 content.php:41 +msgid "Continue reading " +msgstr "" + +#: content-aside.php:20 content-link.php:18 content-quote.php:17 +#: content-status.php:15 +msgid "Permalink to %s" +msgstr "" + +#: content-aside.php:23 content-image.php:23 content-link.php:21 +#: content-quote.php:20 content-status.php:37 content.php:30 +msgid "Leave a reply" +msgstr "" + +#: content-aside.php:23 content-image.php:23 content-link.php:21 +#: content-quote.php:20 content-status.php:37 content.php:30 +msgid "1 Reply" +msgstr "" + +#: content-aside.php:23 content-image.php:23 content-link.php:21 +#: content-quote.php:20 content-status.php:37 content.php:30 +msgid "% Replies" +msgstr "" + +#: content-aside.php:26 content-image.php:26 content-link.php:24 +#: content-page.php:24 content-quote.php:23 content-status.php:40 +#: content.php:48 functions.php:349 image.php:37 +msgid "Edit" +msgstr "" + +#: content-link.php:12 +msgid "Link" +msgstr "" + +#: content-none.php:13 index.php:49 search.php:34 +msgid "Nothing Found" +msgstr "" + +#: content-none.php:17 index.php:53 +msgid "" +"Apologies, but no results were found. Perhaps searching will help find a " +"related post." +msgstr "" + +#: content-page.php:21 content.php:42 image.php:102 +msgid "Pages:" +msgstr "" + +#: content.php:16 +msgid "Featured post" +msgstr "" + +#: content.php:63 +msgid "View all posts by %s " +msgstr "" + +#. #-#-#-#-# twentytwelve.pot (Twenty Twelve 1.3) #-#-#-#-# +#. Author URI of the plugin/theme +#: footer.php:16 +msgid "http://wordpress.org/" +msgstr "" + +#: footer.php:16 +msgid "Semantic Personal Publishing Platform" +msgstr "" + +#: footer.php:16 +msgid "Proudly powered by %s" +msgstr "" + +#: functions.php:64 +msgid "Primary Menu" +msgstr "" + +#. 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. +#: functions.php:101 +msgctxt "Open Sans font: on or off" +msgid "on" +msgstr "" + +#. 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. +#: functions.php:107 +msgctxt "Open Sans font: add new subset (greek, cyrillic, vietnamese)" +msgid "no-subset" +msgstr "" + +#: functions.php:215 +msgid "Page %s" +msgstr "" + +#: functions.php:244 +msgid "Main Sidebar" +msgstr "" + +#: functions.php:246 +msgid "" +"Appears on posts and pages except the optional Front Page template, which " +"has its own widgets" +msgstr "" + +#: functions.php:254 +msgid "First Front Page Widget Area" +msgstr "" + +#: functions.php:256 functions.php:266 +msgid "" +"Appears when using the optional Front Page template with a page set as " +"Static Front Page" +msgstr "" + +#: functions.php:264 +msgid "Second Front Page Widget Area" +msgstr "" + +#: functions.php:288 single.php:20 +msgid "Post navigation" +msgstr "" + +#: functions.php:289 +msgid " Older posts" +msgstr "" + +#: functions.php:290 +msgid "Newer posts " +msgstr "" + +#: functions.php:317 +msgid "Pingback:" +msgstr "" + +#: functions.php:317 +msgid "(Edit)" +msgstr "" + +#: functions.php:332 +msgid "Post author" +msgstr "" + +#. translators: 1: date, 2: time +#: functions.php:338 +msgid "%1$s at %2$s" +msgstr "" + +#: functions.php:344 +msgid "Your comment is awaiting moderation." +msgstr "" + +#: functions.php:353 +msgid "Reply" +msgstr "" + +#. Translators: used between list items, there is a space after the comma. +#: functions.php:376 functions.php:379 +msgid ", " +msgstr "" + +#: functions.php:390 +msgid "View all posts by %s" +msgstr "" + +#. Translators: 1 is category, 2 is tag, 3 is the date and 4 is the author's +#. name. +#: functions.php:396 +msgid "" +"This entry was posted in %1$s and tagged %2$s on %3$s by %4$s." +msgstr "" + +#: functions.php:398 +msgid "" +"This entry was posted in %1$s on %3$s by %4$s." +msgstr "" + +#: functions.php:400 +msgid "This entry was posted on %3$s by %4$s." +msgstr "" + +#: header.php:43 +msgid "Menu" +msgstr "" + +#: header.php:44 +msgid "Skip to content" +msgstr "" + +#: image.php:26 +msgid "" +"Published at %4$s × " +"%5$s in %8$s." +msgstr "" + +#: image.php:41 +msgid "← Previous" +msgstr "" + +#: image.php:42 +msgid "Next →" +msgstr "" + +#: index.php:38 +msgid "No posts to display" +msgstr "" + +#: index.php:42 +msgid "Ready to publish your first post? Get started here." +msgstr "" + +#: search.php:18 +msgid "Search Results for: %s" +msgstr "" + +#: search.php:38 +msgid "" +"Sorry, but nothing matched your search criteria. Please try again with some " +"different keywords." +msgstr "" + +#: single.php:21 +msgctxt "Previous post link" +msgid "←" +msgstr "" + +#: single.php:22 +msgctxt "Next post link" +msgid "→" +msgstr "" + +#: tag.php:21 +msgid "Tag Archives: %s" +msgstr "" + +#. Theme Name of the plugin/theme +msgid "Twenty Twelve" +msgstr "" + +#. Theme URI of the plugin/theme +msgid "http://wordpress.org/themes/twentytwelve" +msgstr "" + +#. Description of the plugin/theme +msgid "" +"The 2012 theme for WordPress is a fully responsive theme that looks great on " +"any device. Features include a front page template with its own widgets, an " +"optional display font, styling for post formats on both index and single " +"views, and an optional no-sidebar page template. Make it yours with a custom " +"menu, header image, and background." +msgstr "" + +#. Author of the plugin/theme +msgid "the WordPress team" +msgstr "" + +#. Template Name of the plugin/theme +msgid "Front Page Template" +msgstr "" + +#. Template Name of the plugin/theme +msgid "Full-width Page Template, No Sidebar" +msgstr "" diff --git a/sources/wp-content/themes/twentytwelve/page-templates/front-page.php b/sources/wp-content/themes/twentytwelve/page-templates/front-page.php new file mode 100644 index 0000000..9ae4f27 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/page-templates/front-page.php @@ -0,0 +1,35 @@ + + +
    +
    + + + +
    + +
    + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/page-templates/full-width.php b/sources/wp-content/themes/twentytwelve/page-templates/full-width.php new file mode 100644 index 0000000..b0ce333 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/page-templates/full-width.php @@ -0,0 +1,30 @@ + + +
    +
    + + + + + + +
    +
    + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/page.php b/sources/wp-content/themes/twentytwelve/page.php new file mode 100644 index 0000000..b06cd1f --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/page.php @@ -0,0 +1,29 @@ + + +
    +
    + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/rtl.css b/sources/wp-content/themes/twentytwelve/rtl.css new file mode 100644 index 0000000..1055f9c --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/rtl.css @@ -0,0 +1,237 @@ +/* +Theme Name: Twenty Twelve +Description: Adds support for languages written in a Right To Left (RTL) direction. +It's easy, just a matter of overwriting all the horizontal positioning attributes +of your CSS stylesheet in a separate stylesheet file named rtl.css. + +See http://codex.wordpress.org/Right_to_Left_Language_Support +*/ + + +body { + direction: rtl; + unicode-bidi: embed; +} +caption, +th, +td { + text-align: right; +} + +/* =Repeatable patterns +-------------------------------------------------------------- */ + +/* Images */ +.site-content .gallery-columns-4 .gallery-item { + padding-left: 2%; + padding-right: 0; +} +.site-content .gallery-columns-5 .gallery-item { + padding-left: 2%; + padding-right: 0; +} + +/* Navigation */ +.nav-previous, +.previous-image { + float: right; +} +.nav-next, +.next-image { + float: left; + text-align: left; +} + +/* Author profiles */ +.author-avatar { + float: right; +} +.author-description { + float: right; + margin-right: 15px; + margin-right: 1.071428571rem; + margin-left: auto; +} + + +/* =Main Content +----------------------------------------------- */ + +.comment-content ol, +.comment-content ul { + margin: 0 24px 0 0; + margin: 0 1.714285714rem 0 0; +} + + +/* =Basic post styling +-------------------------------------------------------------- */ + +.entry-content li, +.comment-content li { + margin: 0 24px 0 0; + margin: 0 1.714285714rem 0 0; +} +.entry-content td, +.comment-content td { + padding: 6px 0 6px 10px; +} + + +/* Aside posts */ +article.format-aside .aside { + border-right: 22px solid #a8bfe8; + border-left: none; +} + +/* Link posts */ +article.format-link header { + float: left; +} +article.format-link .entry-content { + float: right; +} + +/* Status posts */ +.format-status .entry-header img { + float: right; + margin-left: 21px; + margin-left: 1.5rem; + margin-right: 0; +} + + +/* =Comment styling +-------------------------------------------------------------- */ + +.comments-area article header img { + float: right; +} +.comments-area article header cite, +.comments-area article header time { + margin-right: 85px; + margin-right: 6.071428571rem; + margin-left: auto; +} +.comments-area article header h4 { + left: 0; + right: auto; +} +.comments-area .bypostauthor cite span { + margin-right: 5px; + margin-right: 0.357142857rem; + margin-left: auto; +} + +/* Comment form */ +#respond h3#reply-title #cancel-comment-reply-link { + margin-right: 10px; + margin-right: 0.714285714rem; + margin-left: auto; +} +label ~ span.required { + float: right; + margin: -18px -16px 0 0; + margin: -1.285714286rem -1.142857143rem 0 0; +} + + +/* =Front page template styling +-------------------------------------------------------------- */ + +.template-front-page .widget-area .widget_text img { + float: right; + margin: 8px 0 8px 24px; + margin: 0.571428571rem 0 0.571428571rem 1.714285714rem; +} + + +/* =Widget styling +-------------------------------------------------------------- */ + +.widget-area .widget ul ul { + margin-right: 12px; + margin-right: 0.857142857rem; + margin-left: auto; +} +.widget-area .textwidget li { + margin-left: auto; + margin-right: 36px; + margin-right: 2.571428571rem; +} +.widget_recent_entries .post-date, +.widget_rss .rss-date { + margin-right: 12px; + margin-right: 0.857142857rem; + margin-left: auto; +} +#wp-calendar th, +#wp-calendar td, +#wp-calendar caption { + text-align: right; +} +#wp-calendar #next { + padding-left: 24px; + padding-left: 1.714285714rem; + text-align: left; + padding-right: 0; +} + +/* =Media queries +-------------------------------------------------------------- */ + +/* Minimum width of 600 pixels. */ +@media screen and (min-width: 600px) { + .site-content, + .template-front-page.has-post-thumbnail article { + float: right; + } + .widget-area, + .entry-page-image { + float: left; + } + .site-header h1, + .site-header h2 { + text-align: right; + } + .template-front-page .widget-area .widget_text img { + float: right; + margin: 8px 0 8px 24px; + } + .template-front-page .widget-area .widget, + .template-front-page.two-sidebars .widget-area .front-widgets { + float: right; + } + .template-front-page .widget-area .widget:nth-child(odd) { + clear: left; + } + .template-front-page .widget-area .widget:nth-child(even), + .template-front-page.two-sidebars .widget-area .front-widgets + .front-widgets { + float: left; + margin: 0 24px 0; + margin: 0 1.714285714rem 0; + } + .main-navigation ul.nav-menu, + .main-navigation div.nav-menu > ul { + text-align: right; + } + .main-navigation li { + margin-left: 40px; + margin-left: 2.857142857rem; + margin-right: auto; + } + .main-navigation li ul ul { + margin-right: 0; + right: 100%; + left: auto; + } + .main-navigation ul li:hover > ul { + border-right: 0; + border-left: none; + } + .commentlist .children { + margin-right: 48px; + margin-right: 3.428571429rem; + margin-left: auto; + } +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/screenshot.png b/sources/wp-content/themes/twentytwelve/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..ee328b9553e8b4f2bb8dd53cfcbc3b0b1d6e4133 GIT binary patch literal 171045 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 i05E@t-TndE@c$dN2|;>(wLQuJ0000 + +

    +
    + + + + + + + + + + + + + + + + +
    +
    +

    +
    + +
    +

    + +
    +
    + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/sidebar-front.php b/sources/wp-content/themes/twentytwelve/sidebar-front.php new file mode 100644 index 0000000..990a09f --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/sidebar-front.php @@ -0,0 +1,35 @@ + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/sidebar.php b/sources/wp-content/themes/twentytwelve/sidebar.php new file mode 100644 index 0000000..a59dcc4 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/sidebar.php @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/single.php b/sources/wp-content/themes/twentytwelve/single.php new file mode 100644 index 0000000..3817524 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/single.php @@ -0,0 +1,33 @@ + + +
    +
    + + + + + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/style.css b/sources/wp-content/themes/twentytwelve/style.css new file mode 100644 index 0000000..4786b50 --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/style.css @@ -0,0 +1,1742 @@ +/* +Theme Name: Twenty Twelve +Theme URI: http://wordpress.org/themes/twentytwelve +Author: the WordPress team +Author URI: http://wordpress.org/ +Description: The 2012 theme for WordPress is a fully responsive theme that looks great on any device. Features include a front page template with its own widgets, an optional display font, styling for post formats on both index and single views, and an optional no-sidebar page template. Make it yours with a custom menu, header image, and background. +Version: 1.3 +License: GNU General Public License v2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html +Tags: light, gray, white, one-column, two-columns, right-sidebar, flexible-width, custom-background, custom-header, custom-menu, editor-style, featured-images, flexible-header, full-width-template, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready +Text Domain: twentytwelve + +This theme, like WordPress, is licensed under the GPL. +Use it to make something cool, have fun, and share what you've learned with others. +*/ + +/* =Notes +-------------------------------------------------------------- +This stylesheet uses rem values with a pixel fallback. The rem +values (and line heights) are calculated using two variables: + +$rembase: 14; +$line-height: 24; + +---------- Examples + +* Use a pixel value with a rem fallback for font-size, padding, margins, etc. + padding: 5px 0; + padding: 0.357142857rem 0; (5 / $rembase) + +* Set a font-size and then set a line-height based on the font-size + font-size: 16px + font-size: 1.142857143rem; (16 / $rembase) + line-height: 1.5; ($line-height / 16) + +---------- Vertical spacing + +Vertical spacing between most elements should use 24px or 48px +to maintain vertical rhythm: + +.my-new-div { + margin: 24px 0; + margin: 1.714285714rem 0; ( 24 / $rembase ) +} + +---------- Further reading + +http://snook.ca/archives/html_and_css/font-size-with-rem +http://blog.typekit.com/2011/11/09/type-study-sizing-the-legible-letter/ + + +/* =Reset +-------------------------------------------------------------- */ + +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, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + vertical-align: baseline; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +caption, +th, +td { + font-weight: normal; + text-align: left; +} +h1, +h2, +h3, +h4, +h5, +h6 { + clear: both; +} +html { + overflow-y: scroll; + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +a:focus { + outline: thin dotted; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} +audio, +canvas, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; +} +del { + color: #333; +} +ins { + background: #fff9c0; + text-decoration: none; +} +hr { + background-color: #ccc; + border: 0; + height: 1px; + margin: 24px; + margin-bottom: 1.714285714rem; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +small { + font-size: smaller; +} +img { + border: 0; + -ms-interpolation-mode: bicubic; +} + +/* Clearing floats */ +.clear:after, +.wrapper:after, +.format-status .entry-header:after { + clear: both; +} +.clear:before, +.clear:after, +.wrapper:before, +.wrapper:after, +.format-status .entry-header:before, +.format-status .entry-header:after { + display: table; + content: ""; +} + + +/* =Repeatable patterns +-------------------------------------------------------------- */ + +/* Small headers */ +.archive-title, +.page-title, +.widget-title, +.entry-content th, +.comment-content th { + font-size: 11px; + font-size: 0.785714286rem; + line-height: 2.181818182; + font-weight: bold; + text-transform: uppercase; + color: #636363; +} + +/* Shared Post Format styling */ +article.format-quote footer.entry-meta, +article.format-link footer.entry-meta, +article.format-status footer.entry-meta { + font-size: 11px; + font-size: 0.785714286rem; + line-height: 2.181818182; +} + +/* Form fields, general styles first */ +button, +input, +textarea { + border: 1px solid #ccc; + border-radius: 3px; + font-family: inherit; + padding: 6px; + padding: 0.428571429rem; +} +button, +input { + line-height: normal; +} +textarea { + font-size: 100%; + overflow: auto; + vertical-align: top; +} + +/* Reset non-text input types */ +input[type="checkbox"], +input[type="radio"], +input[type="file"], +input[type="hidden"], +input[type="image"], +input[type="color"] { + border: 0; + border-radius: 0; + padding: 0; +} + +/* Buttons */ +.menu-toggle, +input[type="submit"], +input[type="button"], +input[type="reset"], +article.post-password-required input[type=submit], +.bypostauthor cite span { + padding: 6px 10px; + padding: 0.428571429rem 0.714285714rem; + font-size: 11px; + font-size: 0.785714286rem; + line-height: 1.428571429; + font-weight: normal; + color: #7c7c7c; + background-color: #e6e6e6; + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, #f4f4f4, #e6e6e6); + background-image: -ms-linear-gradient(top, #f4f4f4, #e6e6e6); + background-image: -webkit-linear-gradient(top, #f4f4f4, #e6e6e6); + background-image: -o-linear-gradient(top, #f4f4f4, #e6e6e6); + background-image: linear-gradient(top, #f4f4f4, #e6e6e6); + border: 1px solid #d2d2d2; + border-radius: 3px; + box-shadow: 0 1px 2px rgba(64, 64, 64, 0.1); +} +.menu-toggle, +button, +input[type="submit"], +input[type="button"], +input[type="reset"] { + cursor: pointer; +} +button[disabled], +input[disabled] { + cursor: default; +} +.menu-toggle:hover, +button:hover, +input[type="submit"]:hover, +input[type="button"]:hover, +input[type="reset"]:hover, +article.post-password-required input[type=submit]:hover { + color: #5e5e5e; + background-color: #ebebeb; + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, #f9f9f9, #ebebeb); + background-image: -ms-linear-gradient(top, #f9f9f9, #ebebeb); + background-image: -webkit-linear-gradient(top, #f9f9f9, #ebebeb); + background-image: -o-linear-gradient(top, #f9f9f9, #ebebeb); + background-image: linear-gradient(top, #f9f9f9, #ebebeb); +} +.menu-toggle:active, +.menu-toggle.toggled-on, +button:active, +input[type="submit"]:active, +input[type="button"]:active, +input[type="reset"]:active { + color: #757575; + background-color: #e1e1e1; + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, #ebebeb, #e1e1e1); + background-image: -ms-linear-gradient(top, #ebebeb, #e1e1e1); + background-image: -webkit-linear-gradient(top, #ebebeb, #e1e1e1); + background-image: -o-linear-gradient(top, #ebebeb, #e1e1e1); + background-image: linear-gradient(top, #ebebeb, #e1e1e1); + box-shadow: inset 0 0 8px 2px #c6c6c6, 0 1px 0 0 #f4f4f4; + border-color: transparent; +} +.bypostauthor cite span { + color: #fff; + background-color: #21759b; + background-image: none; + border: 1px solid #1f6f93; + border-radius: 2px; + box-shadow: none; + padding: 0; +} + +/* Responsive images */ +.entry-content img, +.comment-content img, +.widget img { + max-width: 100%; /* Fluid images for posts, comments, and widgets */ +} +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, +img.header-image, +img.wp-post-image { + max-width: 100%; + height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */ +} + +/* Make sure videos and embeds fit their containers */ +embed, +iframe, +object, +video { + max-width: 100%; +} +.entry-content .twitter-tweet-rendered { + max-width: 100% !important; /* Override the Twitter embed fixed width */ +} + +/* Images */ +.alignleft { + float: left; +} +.alignright { + float: right; +} +.aligncenter { + display: block; + margin-left: auto; + margin-right: auto; +} +.entry-content img, +.comment-content img, +.widget img, +img.header-image, +.author-avatar img, +img.wp-post-image { + /* Add fancy borders to all WordPress-added images but not things like badges and icons and the like */ + border-radius: 3px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); +} +.wp-caption { + max-width: 100%; /* Keep wide captions from overflowing their container. */ + padding: 4px; +} +.wp-caption .wp-caption-text, +.gallery-caption, +.entry-caption { + font-style: italic; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + color: #757575; +} +img.wp-smiley, +.rsswidget img { + border: 0; + border-radius: 0; + box-shadow: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} +.entry-content dl.gallery-item { + margin: 0; +} +.gallery-item a, +.gallery-caption { + width: 90%; +} +.gallery-item a { + display: block; +} +.gallery-caption a { + display: inline; +} +.gallery-columns-1 .gallery-item a { + max-width: 100%; + width: auto; +} +.gallery .gallery-icon img { + height: auto; + max-width: 90%; + padding: 5%; +} +.gallery-columns-1 .gallery-icon img { + padding: 3%; +} + +/* Navigation */ +.site-content nav { + clear: both; + line-height: 2; + overflow: hidden; +} +#nav-above { + padding: 24px 0; + padding: 1.714285714rem 0; +} +#nav-above { + display: none; +} +.paged #nav-above { + display: block; +} +.nav-previous, +.previous-image { + float: left; + width: 50%; +} +.nav-next, +.next-image { + float: right; + text-align: right; + width: 50%; +} +.nav-single + .comments-area, +#comment-nav-above { + margin: 48px 0; + margin: 3.428571429rem 0; +} + +/* Author profiles */ +.author .archive-header { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.author-info { + border-top: 1px solid #ededed; + margin: 24px 0; + margin: 1.714285714rem 0; + padding-top: 24px; + padding-top: 1.714285714rem; + overflow: hidden; +} +.author-description p { + color: #757575; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; +} +.author.archive .author-info { + border-top: 0; + margin: 0 0 48px; + margin: 0 0 3.428571429rem; +} +.author.archive .author-avatar { + margin-top: 0; +} + + +/* =Basic structure +-------------------------------------------------------------- */ + +/* Body, links, basics */ +html { + font-size: 87.5%; +} +body { + font-size: 14px; + font-size: 1rem; + font-family: Helvetica, Arial, sans-serif; + text-rendering: optimizeLegibility; + color: #444; +} +body.custom-font-enabled { + font-family: "Open Sans", Helvetica, Arial, sans-serif; +} +a { + outline: none; + color: #21759b; +} +a:hover { + color: #0f3647; +} + +/* Assistive text */ +.assistive-text, +.site .screen-reader-text { + position: absolute !important; + clip: rect(1px, 1px, 1px, 1px); +} +.main-navigation .assistive-text:focus { + background: #fff; + border: 2px solid #333; + border-radius: 3px; + clip: auto !important; + color: #000; + display: block; + font-size: 12px; + padding: 12px; + position: absolute; + top: 5px; + left: 5px; + z-index: 100000; /* Above WP toolbar */ +} + +/* Page structure */ +.site { + padding: 0 24px; + padding: 0 1.714285714rem; + background-color: #fff; +} +.site-content { + margin: 24px 0 0; + margin: 1.714285714rem 0 0; +} +.widget-area { + margin: 24px 0 0; + margin: 1.714285714rem 0 0; +} + +/* Header */ +.site-header { + padding: 24px 0; + padding: 1.714285714rem 0; +} +.site-header h1, +.site-header h2 { + text-align: center; +} +.site-header h1 a, +.site-header h2 a { + color: #515151; + display: inline-block; + text-decoration: none; +} +.site-header h1 a:hover, +.site-header h2 a:hover { + color: #21759b; +} +.site-header h1 { + font-size: 24px; + font-size: 1.714285714rem; + line-height: 1.285714286; + margin-bottom: 14px; + margin-bottom: 1rem; +} +.site-header h2 { + font-weight: normal; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; + color: #757575; +} +.header-image { + margin-top: 24px; + margin-top: 1.714285714rem; +} + +/* Navigation Menu */ +.main-navigation { + margin-top: 24px; + margin-top: 1.714285714rem; + text-align: center; +} +.main-navigation li { + margin-top: 24px; + margin-top: 1.714285714rem; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 1.42857143; +} +.main-navigation a { + color: #5e5e5e; +} +.main-navigation a:hover { + color: #21759b; +} +.main-navigation ul.nav-menu, +.main-navigation div.nav-menu > ul { + display: none; +} +.main-navigation ul.nav-menu.toggled-on, +.menu-toggle { + display: inline-block; +} + +/* Banner */ +section[role="banner"] { + margin-bottom: 48px; + margin-bottom: 3.428571429rem; +} + +/* Sidebar */ +.widget-area .widget { + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; + margin-bottom: 48px; + margin-bottom: 3.428571429rem; + word-wrap: break-word; +} +.widget-area .widget h3 { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.widget-area .widget p, +.widget-area .widget li, +.widget-area .widget .textwidget { + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; +} +.widget-area .widget p { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.widget-area .textwidget ul { + list-style: disc outside; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; +} +.widget-area .textwidget li { + margin-left: 36px; + margin-left: 2.571428571rem; +} +.widget-area .widget a { + color: #757575; +} +.widget-area .widget a:hover { + color: #21759b; +} +.widget-area .widget a:visited { + color: #9f9f9f; +} +.widget-area #s { + width: 53.66666666666%; /* define a width to avoid dropping a wider submit button */ +} + +/* Footer */ +footer[role="contentinfo"] { + border-top: 1px solid #ededed; + clear: both; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + max-width: 960px; + max-width: 68.571428571rem; + margin-top: 24px; + margin-top: 1.714285714rem; + margin-left: auto; + margin-right: auto; + padding: 24px 0; + padding: 1.714285714rem 0; +} +footer[role="contentinfo"] a { + color: #686868; +} +footer[role="contentinfo"] a:hover { + color: #21759b; +} + + +/* =Main content and comment content +-------------------------------------------------------------- */ + +.entry-meta { + clear: both; +} +.entry-header { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.entry-header img.wp-post-image { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.entry-header .entry-title { + font-size: 20px; + font-size: 1.428571429rem; + line-height: 1.2; + font-weight: normal; +} +.entry-header .entry-title a { + text-decoration: none; +} +.entry-header .entry-format { + margin-top: 24px; + margin-top: 1.714285714rem; + font-weight: normal; +} +.entry-header .comments-link { + margin-top: 24px; + margin-top: 1.714285714rem; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; + color: #757575; +} +.comments-link a, +.entry-meta a { + color: #757575; +} +.comments-link a:hover, +.entry-meta a:hover { + color: #21759b; +} +article.sticky .featured-post { + border-top: 4px double #ededed; + border-bottom: 4px double #ededed; + color: #757575; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 3.692307692; + margin-bottom: 24px; + margin-bottom: 1.714285714rem; + text-align: center; +} +.entry-content, +.entry-summary, +.mu_register { + line-height: 1.714285714; +} +.entry-content h1, +.comment-content h1, +.entry-content h2, +.comment-content h2, +.entry-content h3, +.comment-content h3, +.entry-content h4, +.comment-content h4, +.entry-content h5, +.comment-content h5, +.entry-content h6, +.comment-content h6 { + margin: 24px 0; + margin: 1.714285714rem 0; + line-height: 1.714285714; +} +.entry-content h1, +.comment-content h1 { + font-size: 21px; + font-size: 1.5rem; + line-height: 1.5; +} +.entry-content h2, +.comment-content h2, +.mu_register h2 { + font-size: 18px; + font-size: 1.285714286rem; + line-height: 1.6; +} +.entry-content h3, +.comment-content h3 { + font-size: 16px; + font-size: 1.142857143rem; + line-height: 1.846153846; +} +.entry-content h4, +.comment-content h4 { + font-size: 14px; + font-size: 1rem; + line-height: 1.846153846; +} +.entry-content h5, +.comment-content h5 { + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; +} +.entry-content h6, +.comment-content h6 { + font-size: 12px; + font-size: 0.857142857rem; + line-height: 1.846153846; +} +.entry-content p, +.entry-summary p, +.comment-content p, +.mu_register p { + margin: 0 0 24px; + margin: 0 0 1.714285714rem; + line-height: 1.714285714; +} +.entry-content a:visited, +.comment-content a:visited { + color: #9f9f9f; +} +.entry-content ol, +.comment-content ol, +.entry-content ul, +.comment-content ul, +.mu_register ul { + margin: 0 0 24px; + margin: 0 0 1.714285714rem; + line-height: 1.714285714; +} +.entry-content ul ul, +.comment-content ul ul, +.entry-content ol ol, +.comment-content ol ol, +.entry-content ul ol, +.comment-content ul ol, +.entry-content ol ul, +.comment-content ol ul { + margin-bottom: 0; +} +.entry-content ul, +.comment-content ul, +.mu_register ul { + list-style: disc outside; +} +.entry-content ol, +.comment-content ol { + list-style: decimal outside; +} +.entry-content li, +.comment-content li, +.mu_register li { + margin: 0 0 0 36px; + margin: 0 0 0 2.571428571rem; +} +.entry-content blockquote, +.comment-content blockquote { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; + padding: 24px; + padding: 1.714285714rem; + font-style: italic; +} +.entry-content blockquote p:last-child, +.comment-content blockquote p:last-child { + margin-bottom: 0; +} +.entry-content code, +.comment-content code { + font-family: Consolas, Monaco, Lucida Console, monospace; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; +} +.entry-content pre, +.comment-content pre { + border: 1px solid #ededed; + color: #666; + font-family: Consolas, Monaco, Lucida Console, monospace; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 1.714285714; + margin: 24px 0; + margin: 1.714285714rem 0; + overflow: auto; + padding: 24px; + padding: 1.714285714rem; +} +.entry-content pre code, +.comment-content pre code { + display: block; +} +.entry-content abbr, +.comment-content abbr, +.entry-content dfn, +.comment-content dfn, +.entry-content acronym, +.comment-content acronym { + border-bottom: 1px dotted #666; + cursor: help; +} +.entry-content address, +.comment-content address { + display: block; + line-height: 1.714285714; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; +} +img.alignleft, +.wp-caption.alignleft { + margin: 12px 24px 12px 0; + margin: 0.857142857rem 1.714285714rem 0.857142857rem 0; +} +img.alignright, +.wp-caption.alignright { + margin: 12px 0 12px 24px; + margin: 0.857142857rem 0 0.857142857rem 1.714285714rem; +} +img.aligncenter, +.wp-caption.aligncenter { + clear: both; + margin-top: 12px; + margin-top: 0.857142857rem; + margin-bottom: 12px; + margin-bottom: 0.857142857rem; +} +.entry-content embed, +.entry-content iframe, +.entry-content object, +.entry-content video { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.entry-content dl, +.comment-content dl { + margin: 0 24px; + margin: 0 1.714285714rem; +} +.entry-content dt, +.comment-content dt { + font-weight: bold; + line-height: 1.714285714; +} +.entry-content dd, +.comment-content dd { + line-height: 1.714285714; + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.entry-content table, +.comment-content table { + border-bottom: 1px solid #ededed; + color: #757575; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; + width: 100%; +} +.entry-content table caption, +.comment-content table caption { + font-size: 16px; + font-size: 1.142857143rem; + margin: 24px 0; + margin: 1.714285714rem 0; +} +.entry-content td, +.comment-content td { + border-top: 1px solid #ededed; + padding: 6px 10px 6px 0; +} +.site-content article { + border-bottom: 4px double #ededed; + margin-bottom: 72px; + margin-bottom: 5.142857143rem; + padding-bottom: 24px; + padding-bottom: 1.714285714rem; + word-wrap: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; +} +.page-links { + clear: both; + line-height: 1.714285714; +} +footer.entry-meta { + margin-top: 24px; + margin-top: 1.714285714rem; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; + color: #757575; +} +.single-author .entry-meta .by-author { + display: none; +} +.mu_register h2 { + color: #757575; + font-weight: normal; +} + + +/* =Archives +-------------------------------------------------------------- */ + +.archive-header, +.page-header { + margin-bottom: 48px; + margin-bottom: 3.428571429rem; + padding-bottom: 22px; + padding-bottom: 1.571428571rem; + border-bottom: 1px solid #ededed; +} +.archive-meta { + color: #757575; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + margin-top: 22px; + margin-top: 1.571428571rem; +} + + +/* =Single image attachment view +-------------------------------------------------------------- */ + +.article.attachment { + overflow: hidden; +} +.image-attachment div.attachment { + text-align: center; +} +.image-attachment div.attachment p { + text-align: center; +} +.image-attachment div.attachment img { + display: block; + height: auto; + margin: 0 auto; + max-width: 100%; +} +.image-attachment .entry-caption { + margin-top: 8px; + margin-top: 0.571428571rem; +} + + +/* =Aside post format +-------------------------------------------------------------- */ + +article.format-aside h1 { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +article.format-aside h1 a { + text-decoration: none; + color: #4d525a; +} +article.format-aside h1 a:hover { + color: #2e3542; +} +article.format-aside .aside { + padding: 24px 24px 0; + padding: 1.714285714rem; + background: #d2e0f9; + border-left: 22px solid #a8bfe8; +} +article.format-aside p { + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; + color: #4a5466; +} +article.format-aside blockquote:last-child, +article.format-aside p:last-child { + margin-bottom: 0; +} + + +/* =Post formats +-------------------------------------------------------------- */ + +/* Image posts */ +article.format-image footer h1 { + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; + font-weight: normal; +} +article.format-image footer h2 { + font-size: 11px; + font-size: 0.785714286rem; + line-height: 2.181818182; +} +article.format-image footer a h2 { + font-weight: normal; +} + +/* Link posts */ +article.format-link header { + padding: 0 10px; + padding: 0 0.714285714rem; + float: right; + font-size: 11px; + font-size: 0.785714286rem; + line-height: 2.181818182; + font-weight: bold; + font-style: italic; + text-transform: uppercase; + color: #848484; + background-color: #ebebeb; + border-radius: 3px; +} +article.format-link .entry-content { + max-width: 80%; + float: left; +} +article.format-link .entry-content a { + font-size: 22px; + font-size: 1.571428571rem; + line-height: 1.090909091; + text-decoration: none; +} + +/* Quote posts */ +article.format-quote .entry-content p { + margin: 0; + padding-bottom: 24px; + padding-bottom: 1.714285714rem; +} +article.format-quote .entry-content blockquote { + display: block; + padding: 24px 24px 0; + padding: 1.714285714rem 1.714285714rem 0; + font-size: 15px; + font-size: 1.071428571rem; + line-height: 1.6; + font-style: normal; + color: #6a6a6a; + background: #efefef; +} + +/* Status posts */ +.format-status .entry-header { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +.format-status .entry-header header { + display: inline-block; +} +.format-status .entry-header h1 { + font-size: 15px; + font-size: 1.071428571rem; + font-weight: normal; + line-height: 1.6; + margin: 0; +} +.format-status .entry-header h2 { + font-size: 12px; + font-size: 0.857142857rem; + font-weight: normal; + line-height: 2; + margin: 0; +} +.format-status .entry-header header a { + color: #757575; +} +.format-status .entry-header header a:hover { + color: #21759b; +} +.format-status .entry-header img { + float: left; + margin-right: 21px; + margin-right: 1.5rem; +} + + +/* =Comments +-------------------------------------------------------------- */ + +.comments-title { + margin-bottom: 48px; + margin-bottom: 3.428571429rem; + font-size: 16px; + font-size: 1.142857143rem; + line-height: 1.5; + font-weight: normal; +} +.comments-area article { + margin: 24px 0; + margin: 1.714285714rem 0; +} +.comments-area article header { + margin: 0 0 48px; + margin: 0 0 3.428571429rem; + overflow: hidden; + position: relative; +} +.comments-area article header img { + float: left; + padding: 0; + line-height: 0; +} +.comments-area article header cite, +.comments-area article header time { + display: block; + margin-left: 85px; + margin-left: 6.071428571rem; +} +.comments-area article header cite { + font-style: normal; + font-size: 15px; + font-size: 1.071428571rem; + line-height: 1.42857143; +} +.comments-area cite b { + font-weight: normal; +} +.comments-area article header time { + line-height: 1.714285714; + text-decoration: none; + font-size: 12px; + font-size: 0.857142857rem; + color: #5e5e5e; +} +.comments-area article header a { + text-decoration: none; + color: #5e5e5e; +} +.comments-area article header a:hover { + color: #21759b; +} +.comments-area article header cite a { + color: #444; +} +.comments-area article header cite a:hover { + text-decoration: underline; +} +.comments-area article header h4 { + position: absolute; + top: 0; + right: 0; + padding: 6px 12px; + padding: 0.428571429rem 0.857142857rem; + font-size: 12px; + font-size: 0.857142857rem; + font-weight: normal; + color: #fff; + background-color: #0088d0; + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, #009cee, #0088d0); + background-image: -ms-linear-gradient(top, #009cee, #0088d0); + background-image: -webkit-linear-gradient(top, #009cee, #0088d0); + background-image: -o-linear-gradient(top, #009cee, #0088d0); + background-image: linear-gradient(top, #009cee, #0088d0); + border-radius: 3px; + border: 1px solid #007cbd; +} +.comments-area .bypostauthor cite span { + position: absolute; + margin-left: 5px; + margin-left: 0.357142857rem; + padding: 2px 5px; + padding: 0.142857143rem 0.357142857rem; + font-size: 10px; + font-size: 0.714285714rem; +} +.comments-area .bypostauthor cite b { + font-weight: bold; +} +a.comment-reply-link, +a.comment-edit-link { + color: #686868; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; +} +a.comment-reply-link:hover, +a.comment-edit-link:hover { + color: #21759b; +} +.commentlist .pingback { + line-height: 1.714285714; + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} + +/* Comment form */ +#respond { + margin-top: 48px; + margin-top: 3.428571429rem; +} +#respond h3#reply-title { + font-size: 16px; + font-size: 1.142857143rem; + line-height: 1.5; +} +#respond h3#reply-title #cancel-comment-reply-link { + margin-left: 10px; + margin-left: 0.714285714rem; + font-weight: normal; + font-size: 12px; + font-size: 0.857142857rem; +} +#respond form { + margin: 24px 0; + margin: 1.714285714rem 0; +} +#respond form p { + margin: 11px 0; + margin: 0.785714286rem 0; +} +#respond form p.logged-in-as { + margin-bottom: 24px; + margin-bottom: 1.714285714rem; +} +#respond form label { + display: block; + line-height: 1.714285714; +} +#respond form input[type="text"], +#respond form textarea { + -moz-box-sizing: border-box; + box-sizing: border-box; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 1.714285714; + padding: 10px; + padding: 0.714285714rem; + width: 100%; +} +#respond form p.form-allowed-tags { + margin: 0; + font-size: 12px; + font-size: 0.857142857rem; + line-height: 2; + color: #5e5e5e; +} +.required { + color: red; +} + + +/* =Front page template +-------------------------------------------------------------- */ + +.entry-page-image { + margin-bottom: 14px; + margin-bottom: 1rem; +} +.template-front-page .site-content article { + border: 0; + margin-bottom: 0; +} +.template-front-page .widget-area { + clear: both; + float: none; + width: auto; + padding-top: 24px; + padding-top: 1.714285714rem; + border-top: 1px solid #ededed; +} +.template-front-page .widget-area .widget li { + margin: 8px 0 0; + margin: 0.571428571rem 0 0; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.714285714; + list-style-type: square; + list-style-position: inside; +} +.template-front-page .widget-area .widget li a { + color: #757575; +} +.template-front-page .widget-area .widget li a:hover { + color: #21759b; +} +.template-front-page .widget-area .widget_text img { + float: left; + margin: 8px 24px 8px 0; + margin: 0.571428571rem 1.714285714rem 0.571428571rem 0; +} + + +/* =Widgets +-------------------------------------------------------------- */ + +.widget-area .widget ul ul { + margin-left: 12px; + margin-left: 0.857142857rem; +} +.widget_rss li { + margin: 12px 0; + margin: 0.857142857rem 0; +} +.widget_recent_entries .post-date, +.widget_rss .rss-date { + color: #aaa; + font-size: 11px; + font-size: 0.785714286rem; + margin-left: 12px; + margin-left: 0.857142857rem; +} +#wp-calendar { + margin: 0; + width: 100%; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; + color: #686868; +} +#wp-calendar th, +#wp-calendar td, +#wp-calendar caption { + text-align: left; +} +#wp-calendar #next { + padding-right: 24px; + padding-right: 1.714285714rem; + text-align: right; +} +.widget_search label { + display: block; + font-size: 13px; + font-size: 0.928571429rem; + line-height: 1.846153846; +} +.widget_twitter li { + list-style-type: none; +} +.widget_twitter .timesince { + display: block; + text-align: right; +} + + +/* =Plugins +----------------------------------------------- */ + +img#wpstats { + display: block; + margin: 0 auto 24px; + margin: 0 auto 1.714285714rem; +} + + +/* =Media queries +-------------------------------------------------------------- */ + +/* Minimum width of 600 pixels. */ +@media screen and (min-width: 600px) { + .author-avatar { + float: left; + margin-top: 8px; + margin-top: 0.571428571rem; + } + .author-description { + float: right; + width: 80%; + } + .site { + margin: 0 auto; + max-width: 960px; + max-width: 68.571428571rem; + overflow: hidden; + } + .site-content { + float: left; + width: 65.104166667%; + } + body.template-front-page .site-content, + body.attachment .site-content, + body.full-width .site-content { + width: 100%; + } + .widget-area { + float: right; + width: 26.041666667%; + } + .site-header h1, + .site-header h2 { + text-align: left; + } + .site-header h1 { + font-size: 26px; + font-size: 1.857142857rem; + line-height: 1.846153846; + margin-bottom: 0; + } + .main-navigation ul.nav-menu, + .main-navigation div.nav-menu > ul { + border-bottom: 1px solid #ededed; + border-top: 1px solid #ededed; + display: inline-block !important; + text-align: left; + width: 100%; + } + .main-navigation ul { + margin: 0; + text-indent: 0; + } + .main-navigation li a, + .main-navigation li { + display: inline-block; + text-decoration: none; + } + .main-navigation li a { + border-bottom: 0; + color: #6a6a6a; + line-height: 3.692307692; + text-transform: uppercase; + white-space: nowrap; + } + .main-navigation li a:hover { + color: #000; + } + .main-navigation li { + margin: 0 40px 0 0; + margin: 0 2.857142857rem 0 0; + position: relative; + } + .main-navigation li ul { + display: none; + margin: 0; + padding: 0; + position: absolute; + top: 100%; + z-index: 1; + } + .main-navigation li ul ul { + top: 0; + left: 100%; + } + .main-navigation ul li:hover > ul { + border-left: 0; + display: block; + } + .main-navigation li ul li a { + background: #efefef; + border-bottom: 1px solid #ededed; + display: block; + font-size: 11px; + font-size: 0.785714286rem; + line-height: 2.181818182; + padding: 8px 10px; + padding: 0.571428571rem 0.714285714rem; + width: 180px; + width: 12.85714286rem; + white-space: normal; + } + .main-navigation li ul li a:hover { + background: #e3e3e3; + color: #444; + } + .main-navigation .current-menu-item > a, + .main-navigation .current-menu-ancestor > a, + .main-navigation .current_page_item > a, + .main-navigation .current_page_ancestor > a { + color: #636363; + font-weight: bold; + } + .menu-toggle { + display: none; + } + .entry-header .entry-title { + font-size: 22px; + font-size: 1.571428571rem; + } + #respond form input[type="text"] { + width: 46.333333333%; + } + #respond form textarea.blog-textarea { + width: 79.666666667%; + } + .template-front-page .site-content, + .template-front-page article { + overflow: hidden; + } + .template-front-page.has-post-thumbnail article { + float: left; + width: 47.916666667%; + } + .entry-page-image { + float: right; + margin-bottom: 0; + width: 47.916666667%; + } + .template-front-page .widget-area .widget, + .template-front-page.two-sidebars .widget-area .front-widgets { + float: left; + width: 51.875%; + margin-bottom: 24px; + margin-bottom: 1.714285714rem; + } + .template-front-page .widget-area .widget:nth-child(odd) { + clear: right; + } + .template-front-page .widget-area .widget:nth-child(even), + .template-front-page.two-sidebars .widget-area .front-widgets + .front-widgets { + float: right; + width: 39.0625%; + margin: 0 0 24px; + margin: 0 0 1.714285714rem; + } + .template-front-page.two-sidebars .widget, + .template-front-page.two-sidebars .widget:nth-child(even) { + float: none; + width: auto; + } + .commentlist .children { + margin-left: 48px; + margin-left: 3.428571429rem; + } +} + +/* Minimum width of 960 pixels. */ +@media screen and (min-width: 960px) { + body { + background-color: #e6e6e6; + } + body .site { + padding: 0 40px; + padding: 0 2.857142857rem; + margin-top: 48px; + margin-top: 3.428571429rem; + margin-bottom: 48px; + margin-bottom: 3.428571429rem; + box-shadow: 0 2px 6px rgba(100, 100, 100, 0.3); + } + body.custom-background-empty { + background-color: #fff; + } + body.custom-background-empty .site, + body.custom-background-white .site { + padding: 0; + margin-top: 0; + margin-bottom: 0; + box-shadow: none; + } +} + + +/* =Print +----------------------------------------------- */ + +@media print { + body { + background: none !important; + color: #000; + font-size: 10pt; + } + footer a[rel=bookmark]:link:after, + footer a[rel=bookmark]:visited:after { + content: " [" attr(href) "] "; /* Show URLs */ + } + a { + text-decoration: none; + } + .entry-content img, + .comment-content img, + .author-avatar img, + img.wp-post-image { + border-radius: 0; + box-shadow: none; + } + .site { + clear: both !important; + display: block !important; + float: none !important; + max-width: 100%; + position: relative !important; + } + .site-header { + margin-bottom: 72px; + margin-bottom: 5.142857143rem; + text-align: left; + } + .site-header h1 { + font-size: 21pt; + line-height: 1; + text-align: left; + } + .site-header h2 { + color: #000; + font-size: 10pt; + text-align: left; + } + .site-header h1 a, + .site-header h2 a { + color: #000; + } + .author-avatar, + #colophon, + #respond, + .commentlist .comment-edit-link, + .commentlist .reply, + .entry-header .comments-link, + .entry-meta .edit-link a, + .page-link, + .site-content nav, + .widget-area, + img.header-image, + .main-navigation { + display: none; + } + .wrapper { + border-top: none; + box-shadow: none; + } + .site-content { + margin: 0; + width: auto; + } + .singular .entry-header .entry-meta { + position: static; + } + .singular .site-content, + .singular .entry-header, + .singular .entry-content, + .singular footer.entry-meta, + .singular .comments-title { + margin: 0; + width: 100%; + } + .entry-header .entry-title, + .entry-title, + .singular .entry-title { + font-size: 21pt; + } + footer.entry-meta, + footer.entry-meta a { + color: #444; + font-size: 10pt; + } + .author-description { + float: none; + width: auto; + } + + /* Comments */ + .commentlist > li.comment { + background: none; + position: relative; + width: auto; + } + .commentlist .avatar { + height: 39px; + left: 2.2em; + top: 2.2em; + width: 39px; + } + .comments-area article header cite, + .comments-area article header time { + margin-left: 50px; + margin-left: 3.57142857rem; + } +} \ No newline at end of file diff --git a/sources/wp-content/themes/twentytwelve/tag.php b/sources/wp-content/themes/twentytwelve/tag.php new file mode 100644 index 0000000..4e8b14c --- /dev/null +++ b/sources/wp-content/themes/twentytwelve/tag.php @@ -0,0 +1,52 @@ + + +
    +
    + + +
    +

    ' . single_tag_title( '', false ) . '' ); ?>

    + + +
    + +
    + + + + + + + +
    +
    + + + \ No newline at end of file diff --git a/sources/wp-cron.php b/sources/wp-cron.php new file mode 100644 index 0000000..da2838c --- /dev/null +++ b/sources/wp-cron.php @@ -0,0 +1,112 @@ +get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", '_transient_doing_cron' ) ); + if ( is_object( $row ) ) + $value = $row->option_value; + } + + return $value; +} + +if ( false === $crons = _get_cron_array() ) + die(); + +$keys = array_keys( $crons ); +$gmt_time = microtime( true ); + +if ( isset($keys[0]) && $keys[0] > $gmt_time ) + die(); + +$doing_cron_transient = get_transient( 'doing_cron'); + +// Use global $doing_wp_cron lock otherwise use the GET lock. If no lock, trying grabbing a new lock. +if ( empty( $doing_wp_cron ) ) { + if ( empty( $_GET[ 'doing_wp_cron' ] ) ) { + // Called from external script/job. Try setting a lock. + if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time ) ) + return; + $doing_cron_transient = $doing_wp_cron = sprintf( '%.22F', microtime( true ) ); + set_transient( 'doing_cron', $doing_wp_cron ); + } else { + $doing_wp_cron = $_GET[ 'doing_wp_cron' ]; + } +} + +// Check lock +if ( $doing_cron_transient != $doing_wp_cron ) + return; + +foreach ( $crons as $timestamp => $cronhooks ) { + if ( $timestamp > $gmt_time ) + break; + + foreach ( $cronhooks as $hook => $keys ) { + + foreach ( $keys as $k => $v ) { + + $schedule = $v['schedule']; + + if ( $schedule != false ) { + $new_args = array($timestamp, $schedule, $hook, $v['args']); + call_user_func_array('wp_reschedule_event', $new_args); + } + + wp_unschedule_event( $timestamp, $hook, $v['args'] ); + + /** + * Fires scheduled events. + * + * @since 2.1.0 + * + * @param string $hook Name of the hook that was scheduled to be fired. + * @param array $v['args'] The arguments to be passed to the hook. + */ + do_action_ref_array( $hook, $v['args'] ); + + // If the hook ran too long and another cron process stole the lock, quit. + if ( _get_cron_lock() != $doing_wp_cron ) + return; + } + } +} + +if ( _get_cron_lock() == $doing_wp_cron ) + delete_transient( 'doing_cron' ); + +die(); diff --git a/sources/wp-includes/ID3/getid3.lib.php b/sources/wp-includes/ID3/getid3.lib.php new file mode 100644 index 0000000..f8df233 --- /dev/null +++ b/sources/wp-includes/ID3/getid3.lib.php @@ -0,0 +1,1341 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// // +// getid3.lib.php - part of getID3() // +// See readme.txt for more details // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_lib +{ + + public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') { + $returnstring = ''; + for ($i = 0; $i < strlen($string); $i++) { + if ($hex) { + $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT); + } else { + $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '¤'); + } + if ($spaces) { + $returnstring .= ' '; + } + } + if (!empty($htmlencoding)) { + if ($htmlencoding === true) { + $htmlencoding = 'UTF-8'; // prior to getID3 v1.9.0 the function's 4th parameter was boolean + } + $returnstring = htmlentities($returnstring, ENT_QUOTES, $htmlencoding); + } + return $returnstring; + } + + public static function trunc($floatnumber) { + // truncates a floating-point number at the decimal point + // returns int (if possible, otherwise float) + if ($floatnumber >= 1) { + $truncatednumber = floor($floatnumber); + } elseif ($floatnumber <= -1) { + $truncatednumber = ceil($floatnumber); + } else { + $truncatednumber = 0; + } + if (self::intValueSupported($truncatednumber)) { + $truncatednumber = (int) $truncatednumber; + } + return $truncatednumber; + } + + + public static function safe_inc(&$variable, $increment=1) { + if (isset($variable)) { + $variable += $increment; + } else { + $variable = $increment; + } + return true; + } + + public static function CastAsInt($floatnum) { + // convert to float if not already + $floatnum = (float) $floatnum; + + // convert a float to type int, only if possible + if (self::trunc($floatnum) == $floatnum) { + // it's not floating point + if (self::intValueSupported($floatnum)) { + // it's within int range + $floatnum = (int) $floatnum; + } + } + return $floatnum; + } + + public static function intValueSupported($num) { + // check if integers are 64-bit + static $hasINT64 = null; + if ($hasINT64 === null) { // 10x faster than is_null() + $hasINT64 = is_int(pow(2, 31)); // 32-bit int are limited to (2^31)-1 + if (!$hasINT64 && !defined('PHP_INT_MIN')) { + define('PHP_INT_MIN', ~PHP_INT_MAX); + } + } + // if integers are 64-bit - no other check required + if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) { + return true; + } + return false; + } + + public static function DecimalizeFraction($fraction) { + list($numerator, $denominator) = explode('/', $fraction); + return $numerator / ($denominator ? $denominator : 1); + } + + + public static function DecimalBinary2Float($binarynumerator) { + $numerator = self::Bin2Dec($binarynumerator); + $denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator))); + return ($numerator / $denominator); + } + + + public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) { + // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html + if (strpos($binarypointnumber, '.') === false) { + $binarypointnumber = '0.'.$binarypointnumber; + } elseif ($binarypointnumber{0} == '.') { + $binarypointnumber = '0'.$binarypointnumber; + } + $exponent = 0; + while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) { + if (substr($binarypointnumber, 1, 1) == '.') { + $exponent--; + $binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3); + } else { + $pointpos = strpos($binarypointnumber, '.'); + $exponent += ($pointpos - 1); + $binarypointnumber = str_replace('.', '', $binarypointnumber); + $binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1); + } + } + $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT); + return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent); + } + + + public static function Float2BinaryDecimal($floatvalue) { + // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html + $maxbits = 128; // to how many bits of precision should the calculations be taken? + $intpart = self::trunc($floatvalue); + $floatpart = abs($floatvalue - $intpart); + $pointbitstring = ''; + while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) { + $floatpart *= 2; + $pointbitstring .= (string) self::trunc($floatpart); + $floatpart -= self::trunc($floatpart); + } + $binarypointnumber = decbin($intpart).'.'.$pointbitstring; + return $binarypointnumber; + } + + + public static function Float2String($floatvalue, $bits) { + // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html + switch ($bits) { + case 32: + $exponentbits = 8; + $fractionbits = 23; + break; + + case 64: + $exponentbits = 11; + $fractionbits = 52; + break; + + default: + return false; + break; + } + if ($floatvalue >= 0) { + $signbit = '0'; + } else { + $signbit = '1'; + } + $normalizedbinary = self::NormalizeBinaryPoint(self::Float2BinaryDecimal($floatvalue), $fractionbits); + $biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent + $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT); + $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT); + + return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false); + } + + + public static function LittleEndian2Float($byteword) { + return self::BigEndian2Float(strrev($byteword)); + } + + + public static function BigEndian2Float($byteword) { + // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic + // http://www.psc.edu/general/software/packages/ieee/ieee.html + // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html + + $bitword = self::BigEndian2Bin($byteword); + if (!$bitword) { + return 0; + } + $signbit = $bitword{0}; + + switch (strlen($byteword) * 8) { + case 32: + $exponentbits = 8; + $fractionbits = 23; + break; + + case 64: + $exponentbits = 11; + $fractionbits = 52; + break; + + case 80: + // 80-bit Apple SANE format + // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/ + $exponentstring = substr($bitword, 1, 15); + $isnormalized = intval($bitword{16}); + $fractionstring = substr($bitword, 17, 63); + $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383); + $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring); + $floatvalue = $exponent * $fraction; + if ($signbit == '1') { + $floatvalue *= -1; + } + return $floatvalue; + break; + + default: + return false; + break; + } + $exponentstring = substr($bitword, 1, $exponentbits); + $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits); + $exponent = self::Bin2Dec($exponentstring); + $fraction = self::Bin2Dec($fractionstring); + + if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) { + // Not a Number + $floatvalue = false; + } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) { + if ($signbit == '1') { + $floatvalue = '-infinity'; + } else { + $floatvalue = '+infinity'; + } + } elseif (($exponent == 0) && ($fraction == 0)) { + if ($signbit == '1') { + $floatvalue = -0; + } else { + $floatvalue = 0; + } + $floatvalue = ($signbit ? 0 : -0); + } elseif (($exponent == 0) && ($fraction != 0)) { + // These are 'unnormalized' values + $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring); + if ($signbit == '1') { + $floatvalue *= -1; + } + } elseif ($exponent != 0) { + $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + self::DecimalBinary2Float($fractionstring)); + if ($signbit == '1') { + $floatvalue *= -1; + } + } + return (float) $floatvalue; + } + + + public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) { + $intvalue = 0; + $bytewordlen = strlen($byteword); + if ($bytewordlen == 0) { + return false; + } + for ($i = 0; $i < $bytewordlen; $i++) { + if ($synchsafe) { // disregard MSB, effectively 7-bit bytes + //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems + $intvalue += (ord($byteword{$i}) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7); + } else { + $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i)); + } + } + if ($signed && !$synchsafe) { + // synchsafe ints are not allowed to be signed + if ($bytewordlen <= PHP_INT_SIZE) { + $signMaskBit = 0x80 << (8 * ($bytewordlen - 1)); + if ($intvalue & $signMaskBit) { + $intvalue = 0 - ($intvalue & ($signMaskBit - 1)); + } + } else { + throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()'); + break; + } + } + return self::CastAsInt($intvalue); + } + + + public static function LittleEndian2Int($byteword, $signed=false) { + return self::BigEndian2Int(strrev($byteword), false, $signed); + } + + + public static function BigEndian2Bin($byteword) { + $binvalue = ''; + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT); + } + return $binvalue; + } + + + public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) { + if ($number < 0) { + throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers'); + } + $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF); + $intstring = ''; + if ($signed) { + if ($minbytes > PHP_INT_SIZE) { + throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in self::BigEndian2String()'); + } + $number = $number & (0x80 << (8 * ($minbytes - 1))); + } + while ($number != 0) { + $quotient = ($number / ($maskbyte + 1)); + $intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring; + $number = floor($quotient); + } + return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT); + } + + + public static function Dec2Bin($number) { + while ($number >= 256) { + $bytes[] = (($number / 256) - (floor($number / 256))) * 256; + $number = floor($number / 256); + } + $bytes[] = $number; + $binstring = ''; + for ($i = 0; $i < count($bytes); $i++) { + $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring; + } + return $binstring; + } + + + public static function Bin2Dec($binstring, $signed=false) { + $signmult = 1; + if ($signed) { + if ($binstring{0} == '1') { + $signmult = -1; + } + $binstring = substr($binstring, 1); + } + $decvalue = 0; + for ($i = 0; $i < strlen($binstring); $i++) { + $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i); + } + return self::CastAsInt($decvalue * $signmult); + } + + + public static function Bin2String($binstring) { + // return 'hi' for input of '0110100001101001' + $string = ''; + $binstringreversed = strrev($binstring); + for ($i = 0; $i < strlen($binstringreversed); $i += 8) { + $string = chr(self::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string; + } + return $string; + } + + + public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) { + $intstring = ''; + while ($number > 0) { + if ($synchsafe) { + $intstring = $intstring.chr($number & 127); + $number >>= 7; + } else { + $intstring = $intstring.chr($number & 255); + $number >>= 8; + } + } + return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); + } + + + public static function array_merge_clobber($array1, $array2) { + // written by kcØhireability*com + // taken from http://www.php.net/manual/en/function.array-merge-recursive.php + if (!is_array($array1) || !is_array($array2)) { + return false; + } + $newarray = $array1; + foreach ($array2 as $key => $val) { + if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) { + $newarray[$key] = self::array_merge_clobber($newarray[$key], $val); + } else { + $newarray[$key] = $val; + } + } + return $newarray; + } + + + public static function array_merge_noclobber($array1, $array2) { + if (!is_array($array1) || !is_array($array2)) { + return false; + } + $newarray = $array1; + foreach ($array2 as $key => $val) { + if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) { + $newarray[$key] = self::array_merge_noclobber($newarray[$key], $val); + } elseif (!isset($newarray[$key])) { + $newarray[$key] = $val; + } + } + return $newarray; + } + + + public static function ksort_recursive(&$theArray) { + ksort($theArray); + foreach ($theArray as $key => $value) { + if (is_array($value)) { + self::ksort_recursive($theArray[$key]); + } + } + return true; + } + + public static function fileextension($filename, $numextensions=1) { + if (strstr($filename, '.')) { + $reversedfilename = strrev($filename); + $offset = 0; + for ($i = 0; $i < $numextensions; $i++) { + $offset = strpos($reversedfilename, '.', $offset + 1); + if ($offset === false) { + return ''; + } + } + return strrev(substr($reversedfilename, 0, $offset)); + } + return ''; + } + + + public static function PlaytimeString($seconds) { + $sign = (($seconds < 0) ? '-' : ''); + $seconds = round(abs($seconds)); + $H = (int) floor( $seconds / 3600); + $M = (int) floor(($seconds - (3600 * $H) ) / 60); + $S = (int) round( $seconds - (3600 * $H) - (60 * $M) ); + return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT); + } + + + public static function DateMac2Unix($macdate) { + // Macintosh timestamp: seconds since 00:00h January 1, 1904 + // UNIX timestamp: seconds since 00:00h January 1, 1970 + return self::CastAsInt($macdate - 2082844800); + } + + + public static function FixedPoint8_8($rawdata) { + return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8)); + } + + + public static function FixedPoint16_16($rawdata) { + return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16)); + } + + + public static function FixedPoint2_30($rawdata) { + $binarystring = self::BigEndian2Bin($rawdata); + return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30)); + } + + + public static function CreateDeepArray($ArrayPath, $Separator, $Value) { + // assigns $Value to a nested array path: + // $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt') + // is the same as: + // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt')))); + // or + // $foo['path']['to']['my'] = 'file.txt'; + $ArrayPath = ltrim($ArrayPath, $Separator); + if (($pos = strpos($ArrayPath, $Separator)) !== false) { + $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value); + } else { + $ReturnedArray[$ArrayPath] = $Value; + } + return $ReturnedArray; + } + + public static function array_max($arraydata, $returnkey=false) { + $maxvalue = false; + $maxkey = false; + foreach ($arraydata as $key => $value) { + if (!is_array($value)) { + if ($value > $maxvalue) { + $maxvalue = $value; + $maxkey = $key; + } + } + } + return ($returnkey ? $maxkey : $maxvalue); + } + + public static function array_min($arraydata, $returnkey=false) { + $minvalue = false; + $minkey = false; + foreach ($arraydata as $key => $value) { + if (!is_array($value)) { + if ($value > $minvalue) { + $minvalue = $value; + $minkey = $key; + } + } + } + return ($returnkey ? $minkey : $minvalue); + } + + public static function XML2array($XMLstring) { + if (function_exists('simplexml_load_string')) { + if (function_exists('get_object_vars')) { + $XMLobject = simplexml_load_string($XMLstring); + return self::SimpleXMLelement2array($XMLobject); + } + } + return false; + } + + public static function SimpleXMLelement2array($XMLobject) { + if (!is_object($XMLobject) && !is_array($XMLobject)) { + return $XMLobject; + } + $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject); + foreach ($XMLarray as $key => $value) { + $XMLarray[$key] = self::SimpleXMLelement2array($value); + } + return $XMLarray; + } + + + // Allan Hansen + // self::md5_data() - returns md5sum for a file from startuing position to absolute end position + public static function hash_data($file, $offset, $end, $algorithm) { + static $tempdir = ''; + if (!self::intValueSupported($end)) { + return false; + } + switch ($algorithm) { + case 'md5': + $hash_function = 'md5_file'; + $unix_call = 'md5sum'; + $windows_call = 'md5sum.exe'; + $hash_length = 32; + break; + + case 'sha1': + $hash_function = 'sha1_file'; + $unix_call = 'sha1sum'; + $windows_call = 'sha1sum.exe'; + $hash_length = 40; + break; + + default: + throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()'); + break; + } + $size = $end - $offset; + while (true) { + if (GETID3_OS_ISWINDOWS) { + + // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data + // Fall back to create-temp-file method: + if ($algorithm == 'sha1') { + break; + } + + $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call); + foreach ($RequiredFiles as $required_file) { + if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) { + // helper apps not available - fall back to old method + break 2; + } + } + $commandline = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | '; + $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | '; + $commandline .= GETID3_HELPERAPPSDIR.$windows_call; + + } else { + + $commandline = 'head -c'.$end.' '.escapeshellarg($file).' | '; + $commandline .= 'tail -c'.$size.' | '; + $commandline .= $unix_call; + + } + if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { + //throw new Exception('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm'); + break; + } + return substr(`$commandline`, 0, $hash_length); + } + + if (empty($tempdir)) { + // yes this is ugly, feel free to suggest a better way + require_once(dirname(__FILE__).'/getid3.php'); + $getid3_temp = new getID3(); + $tempdir = $getid3_temp->tempdir; + unset($getid3_temp); + } + // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir + if (($data_filename = tempnam($tempdir, 'gI3')) === false) { + // can't find anywhere to create a temp file, just fail + return false; + } + + // Init + $result = false; + + // copy parts of file + try { + self::CopyFileParts($file, $data_filename, $offset, $end - $offset); + $result = $hash_function($data_filename); + } catch (Exception $e) { + throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage()); + } + unlink($data_filename); + return $result; + } + + public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) { + if (!self::intValueSupported($offset + $length)) { + throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit'); + } + if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) { + if (($fp_dest = fopen($filename_dest, 'wb'))) { + if (fseek($fp_src, $offset, SEEK_SET) == 0) { + $byteslefttowrite = $length; + while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) { + $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite); + $byteslefttowrite -= $byteswritten; + } + return true; + } else { + throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source); + } + fclose($fp_dest); + } else { + throw new Exception('failed to create file for writing '.$filename_dest); + } + fclose($fp_src); + } else { + throw new Exception('failed to open file for reading '.$filename_source); + } + return false; + } + + public static function iconv_fallback_int_utf8($charval) { + if ($charval < 128) { + // 0bbbbbbb + $newcharstring = chr($charval); + } elseif ($charval < 2048) { + // 110bbbbb 10bbbbbb + $newcharstring = chr(($charval >> 6) | 0xC0); + $newcharstring .= chr(($charval & 0x3F) | 0x80); + } elseif ($charval < 65536) { + // 1110bbbb 10bbbbbb 10bbbbbb + $newcharstring = chr(($charval >> 12) | 0xE0); + $newcharstring .= chr(($charval >> 6) | 0xC0); + $newcharstring .= chr(($charval & 0x3F) | 0x80); + } else { + // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb + $newcharstring = chr(($charval >> 18) | 0xF0); + $newcharstring .= chr(($charval >> 12) | 0xC0); + $newcharstring .= chr(($charval >> 6) | 0xC0); + $newcharstring .= chr(($charval & 0x3F) | 0x80); + } + return $newcharstring; + } + + // ISO-8859-1 => UTF-8 + public static function iconv_fallback_iso88591_utf8($string, $bom=false) { + if (function_exists('utf8_encode')) { + return utf8_encode($string); + } + // utf8_encode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support) + $newcharstring = ''; + if ($bom) { + $newcharstring .= "\xEF\xBB\xBF"; + } + for ($i = 0; $i < strlen($string); $i++) { + $charval = ord($string{$i}); + $newcharstring .= self::iconv_fallback_int_utf8($charval); + } + return $newcharstring; + } + + // ISO-8859-1 => UTF-16BE + public static function iconv_fallback_iso88591_utf16be($string, $bom=false) { + $newcharstring = ''; + if ($bom) { + $newcharstring .= "\xFE\xFF"; + } + for ($i = 0; $i < strlen($string); $i++) { + $newcharstring .= "\x00".$string{$i}; + } + return $newcharstring; + } + + // ISO-8859-1 => UTF-16LE + public static function iconv_fallback_iso88591_utf16le($string, $bom=false) { + $newcharstring = ''; + if ($bom) { + $newcharstring .= "\xFF\xFE"; + } + for ($i = 0; $i < strlen($string); $i++) { + $newcharstring .= $string{$i}."\x00"; + } + return $newcharstring; + } + + // ISO-8859-1 => UTF-16LE (BOM) + public static function iconv_fallback_iso88591_utf16($string) { + return self::iconv_fallback_iso88591_utf16le($string, true); + } + + // UTF-8 => ISO-8859-1 + public static function iconv_fallback_utf8_iso88591($string) { + if (function_exists('utf8_decode')) { + return utf8_decode($string); + } + // utf8_decode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support) + $newcharstring = ''; + $offset = 0; + $stringlength = strlen($string); + while ($offset < $stringlength) { + if ((ord($string{$offset}) | 0x07) == 0xF7) { + // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) & + ((ord($string{($offset + 1)}) & 0x3F) << 12) & + ((ord($string{($offset + 2)}) & 0x3F) << 6) & + (ord($string{($offset + 3)}) & 0x3F); + $offset += 4; + } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) { + // 1110bbbb 10bbbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) & + ((ord($string{($offset + 1)}) & 0x3F) << 6) & + (ord($string{($offset + 2)}) & 0x3F); + $offset += 3; + } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) { + // 110bbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) & + (ord($string{($offset + 1)}) & 0x3F); + $offset += 2; + } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) { + // 0bbbbbbb + $charval = ord($string{$offset}); + $offset += 1; + } else { + // error? throw some kind of warning here? + $charval = false; + $offset += 1; + } + if ($charval !== false) { + $newcharstring .= (($charval < 256) ? chr($charval) : '?'); + } + } + return $newcharstring; + } + + // UTF-8 => UTF-16BE + public static function iconv_fallback_utf8_utf16be($string, $bom=false) { + $newcharstring = ''; + if ($bom) { + $newcharstring .= "\xFE\xFF"; + } + $offset = 0; + $stringlength = strlen($string); + while ($offset < $stringlength) { + if ((ord($string{$offset}) | 0x07) == 0xF7) { + // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) & + ((ord($string{($offset + 1)}) & 0x3F) << 12) & + ((ord($string{($offset + 2)}) & 0x3F) << 6) & + (ord($string{($offset + 3)}) & 0x3F); + $offset += 4; + } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) { + // 1110bbbb 10bbbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) & + ((ord($string{($offset + 1)}) & 0x3F) << 6) & + (ord($string{($offset + 2)}) & 0x3F); + $offset += 3; + } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) { + // 110bbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) & + (ord($string{($offset + 1)}) & 0x3F); + $offset += 2; + } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) { + // 0bbbbbbb + $charval = ord($string{$offset}); + $offset += 1; + } else { + // error? throw some kind of warning here? + $charval = false; + $offset += 1; + } + if ($charval !== false) { + $newcharstring .= (($charval < 65536) ? self::BigEndian2String($charval, 2) : "\x00".'?'); + } + } + return $newcharstring; + } + + // UTF-8 => UTF-16LE + public static function iconv_fallback_utf8_utf16le($string, $bom=false) { + $newcharstring = ''; + if ($bom) { + $newcharstring .= "\xFF\xFE"; + } + $offset = 0; + $stringlength = strlen($string); + while ($offset < $stringlength) { + if ((ord($string{$offset}) | 0x07) == 0xF7) { + // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) & + ((ord($string{($offset + 1)}) & 0x3F) << 12) & + ((ord($string{($offset + 2)}) & 0x3F) << 6) & + (ord($string{($offset + 3)}) & 0x3F); + $offset += 4; + } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) { + // 1110bbbb 10bbbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) & + ((ord($string{($offset + 1)}) & 0x3F) << 6) & + (ord($string{($offset + 2)}) & 0x3F); + $offset += 3; + } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) { + // 110bbbbb 10bbbbbb + $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) & + (ord($string{($offset + 1)}) & 0x3F); + $offset += 2; + } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) { + // 0bbbbbbb + $charval = ord($string{$offset}); + $offset += 1; + } else { + // error? maybe throw some warning here? + $charval = false; + $offset += 1; + } + if ($charval !== false) { + $newcharstring .= (($charval < 65536) ? self::LittleEndian2String($charval, 2) : '?'."\x00"); + } + } + return $newcharstring; + } + + // UTF-8 => UTF-16LE (BOM) + public static function iconv_fallback_utf8_utf16($string) { + return self::iconv_fallback_utf8_utf16le($string, true); + } + + // UTF-16BE => UTF-8 + public static function iconv_fallback_utf16be_utf8($string) { + if (substr($string, 0, 2) == "\xFE\xFF") { + // strip BOM + $string = substr($string, 2); + } + $newcharstring = ''; + for ($i = 0; $i < strlen($string); $i += 2) { + $charval = self::BigEndian2Int(substr($string, $i, 2)); + $newcharstring .= self::iconv_fallback_int_utf8($charval); + } + return $newcharstring; + } + + // UTF-16LE => UTF-8 + public static function iconv_fallback_utf16le_utf8($string) { + if (substr($string, 0, 2) == "\xFF\xFE") { + // strip BOM + $string = substr($string, 2); + } + $newcharstring = ''; + for ($i = 0; $i < strlen($string); $i += 2) { + $charval = self::LittleEndian2Int(substr($string, $i, 2)); + $newcharstring .= self::iconv_fallback_int_utf8($charval); + } + return $newcharstring; + } + + // UTF-16BE => ISO-8859-1 + public static function iconv_fallback_utf16be_iso88591($string) { + if (substr($string, 0, 2) == "\xFE\xFF") { + // strip BOM + $string = substr($string, 2); + } + $newcharstring = ''; + for ($i = 0; $i < strlen($string); $i += 2) { + $charval = self::BigEndian2Int(substr($string, $i, 2)); + $newcharstring .= (($charval < 256) ? chr($charval) : '?'); + } + return $newcharstring; + } + + // UTF-16LE => ISO-8859-1 + public static function iconv_fallback_utf16le_iso88591($string) { + if (substr($string, 0, 2) == "\xFF\xFE") { + // strip BOM + $string = substr($string, 2); + } + $newcharstring = ''; + for ($i = 0; $i < strlen($string); $i += 2) { + $charval = self::LittleEndian2Int(substr($string, $i, 2)); + $newcharstring .= (($charval < 256) ? chr($charval) : '?'); + } + return $newcharstring; + } + + // UTF-16 (BOM) => ISO-8859-1 + public static function iconv_fallback_utf16_iso88591($string) { + $bom = substr($string, 0, 2); + if ($bom == "\xFE\xFF") { + return self::iconv_fallback_utf16be_iso88591(substr($string, 2)); + } elseif ($bom == "\xFF\xFE") { + return self::iconv_fallback_utf16le_iso88591(substr($string, 2)); + } + return $string; + } + + // UTF-16 (BOM) => UTF-8 + public static function iconv_fallback_utf16_utf8($string) { + $bom = substr($string, 0, 2); + if ($bom == "\xFE\xFF") { + return self::iconv_fallback_utf16be_utf8(substr($string, 2)); + } elseif ($bom == "\xFF\xFE") { + return self::iconv_fallback_utf16le_utf8(substr($string, 2)); + } + return $string; + } + + public static function iconv_fallback($in_charset, $out_charset, $string) { + + if ($in_charset == $out_charset) { + return $string; + } + + // iconv() availble + if (function_exists('iconv')) { + if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) { + switch ($out_charset) { + case 'ISO-8859-1': + $converted_string = rtrim($converted_string, "\x00"); + break; + } + return $converted_string; + } + + // iconv() may sometimes fail with "illegal character in input string" error message + // and return an empty string, but returning the unconverted string is more useful + return $string; + } + + + // iconv() not available + static $ConversionFunctionList = array(); + if (empty($ConversionFunctionList)) { + $ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8'; + $ConversionFunctionList['ISO-8859-1']['UTF-16'] = 'iconv_fallback_iso88591_utf16'; + $ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be'; + $ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le'; + $ConversionFunctionList['UTF-8']['ISO-8859-1'] = 'iconv_fallback_utf8_iso88591'; + $ConversionFunctionList['UTF-8']['UTF-16'] = 'iconv_fallback_utf8_utf16'; + $ConversionFunctionList['UTF-8']['UTF-16BE'] = 'iconv_fallback_utf8_utf16be'; + $ConversionFunctionList['UTF-8']['UTF-16LE'] = 'iconv_fallback_utf8_utf16le'; + $ConversionFunctionList['UTF-16']['ISO-8859-1'] = 'iconv_fallback_utf16_iso88591'; + $ConversionFunctionList['UTF-16']['UTF-8'] = 'iconv_fallback_utf16_utf8'; + $ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591'; + $ConversionFunctionList['UTF-16LE']['UTF-8'] = 'iconv_fallback_utf16le_utf8'; + $ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591'; + $ConversionFunctionList['UTF-16BE']['UTF-8'] = 'iconv_fallback_utf16be_utf8'; + } + if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) { + $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)]; + return self::$ConversionFunction($string); + } + throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset); + } + + + public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') { + $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string + $HTMLstring = ''; + + switch ($charset) { + case '1251': + case '1252': + case '866': + case '932': + case '936': + case '950': + case 'BIG5': + case 'BIG5-HKSCS': + case 'cp1251': + case 'cp1252': + case 'cp866': + case 'EUC-JP': + case 'EUCJP': + case 'GB2312': + case 'ibm866': + case 'ISO-8859-1': + case 'ISO-8859-15': + case 'ISO8859-1': + case 'ISO8859-15': + case 'KOI8-R': + case 'koi8-ru': + case 'koi8r': + case 'Shift_JIS': + case 'SJIS': + case 'win-1251': + case 'Windows-1251': + case 'Windows-1252': + $HTMLstring = htmlentities($string, ENT_COMPAT, $charset); + break; + + case 'UTF-8': + $strlen = strlen($string); + for ($i = 0; $i < $strlen; $i++) { + $char_ord_val = ord($string{$i}); + $charval = 0; + if ($char_ord_val < 0x80) { + $charval = $char_ord_val; + } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F && $i+3 < $strlen) { + $charval = (($char_ord_val & 0x07) << 18); + $charval += ((ord($string{++$i}) & 0x3F) << 12); + $charval += ((ord($string{++$i}) & 0x3F) << 6); + $charval += (ord($string{++$i}) & 0x3F); + } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07 && $i+2 < $strlen) { + $charval = (($char_ord_val & 0x0F) << 12); + $charval += ((ord($string{++$i}) & 0x3F) << 6); + $charval += (ord($string{++$i}) & 0x3F); + } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03 && $i+1 < $strlen) { + $charval = (($char_ord_val & 0x1F) << 6); + $charval += (ord($string{++$i}) & 0x3F); + } + if (($charval >= 32) && ($charval <= 127)) { + $HTMLstring .= htmlentities(chr($charval)); + } else { + $HTMLstring .= '&#'.$charval.';'; + } + } + break; + + case 'UTF-16LE': + for ($i = 0; $i < strlen($string); $i += 2) { + $charval = self::LittleEndian2Int(substr($string, $i, 2)); + if (($charval >= 32) && ($charval <= 127)) { + $HTMLstring .= chr($charval); + } else { + $HTMLstring .= '&#'.$charval.';'; + } + } + break; + + case 'UTF-16BE': + for ($i = 0; $i < strlen($string); $i += 2) { + $charval = self::BigEndian2Int(substr($string, $i, 2)); + if (($charval >= 32) && ($charval <= 127)) { + $HTMLstring .= chr($charval); + } else { + $HTMLstring .= '&#'.$charval.';'; + } + } + break; + + default: + $HTMLstring = 'ERROR: Character set "'.$charset.'" not supported in MultiByteCharString2HTML()'; + break; + } + return $HTMLstring; + } + + + + public static function RGADnameLookup($namecode) { + static $RGADname = array(); + if (empty($RGADname)) { + $RGADname[0] = 'not set'; + $RGADname[1] = 'Track Gain Adjustment'; + $RGADname[2] = 'Album Gain Adjustment'; + } + + return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : ''); + } + + + public static function RGADoriginatorLookup($originatorcode) { + static $RGADoriginator = array(); + if (empty($RGADoriginator)) { + $RGADoriginator[0] = 'unspecified'; + $RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer'; + $RGADoriginator[2] = 'set by user'; + $RGADoriginator[3] = 'determined automatically'; + } + + return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : ''); + } + + + public static function RGADadjustmentLookup($rawadjustment, $signbit) { + $adjustment = $rawadjustment / 10; + if ($signbit == 1) { + $adjustment *= -1; + } + return (float) $adjustment; + } + + + public static function RGADgainString($namecode, $originatorcode, $replaygain) { + if ($replaygain < 0) { + $signbit = '1'; + } else { + $signbit = '0'; + } + $storedreplaygain = intval(round($replaygain * 10)); + $gainstring = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT); + $gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT); + $gainstring .= $signbit; + $gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT); + + return $gainstring; + } + + public static function RGADamplitude2dB($amplitude) { + return 20 * log10($amplitude); + } + + + public static function GetDataImageSize($imgData, &$imageinfo=array()) { + static $tempdir = ''; + if (empty($tempdir)) { + // yes this is ugly, feel free to suggest a better way + require_once(dirname(__FILE__).'/getid3.php'); + $getid3_temp = new getID3(); + $tempdir = $getid3_temp->tempdir; + unset($getid3_temp); + } + $GetDataImageSize = false; + if ($tempfilename = tempnam($tempdir, 'gI3')) { + if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) { + fwrite($tmp, $imgData); + fclose($tmp); + $GetDataImageSize = @getimagesize($tempfilename, $imageinfo); + } + unlink($tempfilename); + } + return $GetDataImageSize; + } + + public static function ImageExtFromMime($mime_type) { + // temporary way, works OK for now, but should be reworked in the future + return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type); + } + + public static function ImageTypesLookup($imagetypeid) { + static $ImageTypesLookup = array(); + if (empty($ImageTypesLookup)) { + $ImageTypesLookup[1] = 'gif'; + $ImageTypesLookup[2] = 'jpeg'; + $ImageTypesLookup[3] = 'png'; + $ImageTypesLookup[4] = 'swf'; + $ImageTypesLookup[5] = 'psd'; + $ImageTypesLookup[6] = 'bmp'; + $ImageTypesLookup[7] = 'tiff (little-endian)'; + $ImageTypesLookup[8] = 'tiff (big-endian)'; + $ImageTypesLookup[9] = 'jpc'; + $ImageTypesLookup[10] = 'jp2'; + $ImageTypesLookup[11] = 'jpx'; + $ImageTypesLookup[12] = 'jb2'; + $ImageTypesLookup[13] = 'swc'; + $ImageTypesLookup[14] = 'iff'; + } + return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : ''); + } + + public static function CopyTagsToComments(&$ThisFileInfo) { + + // Copy all entries from ['tags'] into common ['comments'] + if (!empty($ThisFileInfo['tags'])) { + foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) { + foreach ($tagarray as $tagname => $tagdata) { + foreach ($tagdata as $key => $value) { + if (!empty($value)) { + if (empty($ThisFileInfo['comments'][$tagname])) { + + // fall through and append value + + } elseif ($tagtype == 'id3v1') { + + $newvaluelength = strlen(trim($value)); + foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { + $oldvaluelength = strlen(trim($existingvalue)); + if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) { + // new value is identical but shorter-than (or equal-length to) one already in comments - skip + break 2; + } + } + + } elseif (!is_array($value)) { + + $newvaluelength = strlen(trim($value)); + foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { + $oldvaluelength = strlen(trim($existingvalue)); + if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { + $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); + break 2; + } + } + + } + if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) { + $value = (is_string($value) ? trim($value) : $value); + $ThisFileInfo['comments'][$tagname][] = $value; + } + } + } + } + } + + // Copy to ['comments_html'] + foreach ($ThisFileInfo['comments'] as $field => $values) { + if ($field == 'picture') { + // pictures can take up a lot of space, and we don't need multiple copies of them + // let there be a single copy in [comments][picture], and not elsewhere + continue; + } + foreach ($values as $index => $value) { + if (is_array($value)) { + $ThisFileInfo['comments_html'][$field][$index] = $value; + } else { + $ThisFileInfo['comments_html'][$field][$index] = str_replace('�', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding'])); + } + } + } + } + return true; + } + + + public static function EmbeddedLookup($key, $begin, $end, $file, $name) { + + // Cached + static $cache; + if (isset($cache[$file][$name])) { + return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : ''); + } + + // Init + $keylength = strlen($key); + $line_count = $end - $begin - 7; + + // Open php file + $fp = fopen($file, 'r'); + + // Discard $begin lines + for ($i = 0; $i < ($begin + 3); $i++) { + fgets($fp, 1024); + } + + // Loop thru line + while (0 < $line_count--) { + + // Read line + $line = ltrim(fgets($fp, 1024), "\t "); + + // METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key + //$keycheck = substr($line, 0, $keylength); + //if ($key == $keycheck) { + // $cache[$file][$name][$keycheck] = substr($line, $keylength + 1); + // break; + //} + + // METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key + //$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1)); + $explodedLine = explode("\t", $line, 2); + $ThisKey = (isset($explodedLine[0]) ? $explodedLine[0] : ''); + $ThisValue = (isset($explodedLine[1]) ? $explodedLine[1] : ''); + $cache[$file][$name][$ThisKey] = trim($ThisValue); + } + + // Close and return + fclose($fp); + return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : ''); + } + + public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) { + global $GETID3_ERRORARRAY; + + if (file_exists($filename)) { + if (include_once($filename)) { + return true; + } else { + $diemessage = basename($sourcefile).' depends on '.$filename.', which has errors'; + } + } else { + $diemessage = basename($sourcefile).' depends on '.$filename.', which is missing'; + } + if ($DieOnFailure) { + throw new Exception($diemessage); + } else { + $GETID3_ERRORARRAY[] = $diemessage; + } + return false; + } + + public static function trimNullByte($string) { + return trim($string, "\x00"); + } + + public static function getFileSizeSyscall($path) { + $filesize = false; + + if (GETID3_OS_ISWINDOWS) { + if (class_exists('COM')) { // From PHP 5.3.15 and 5.4.5, COM and DOTNET is no longer built into the php core.you have to add COM support in php.ini: + $filesystem = new COM('Scripting.FileSystemObject'); + $file = $filesystem->GetFile($path); + $filesize = $file->Size(); + unset($filesystem, $file); + } else { + $commandline = 'for %I in ('.escapeshellarg($path).') do @echo %~zI'; + } + } else { + $commandline = 'ls -l '.escapeshellarg($path).' | awk \'{print $5}\''; + } + if (isset($commandline)) { + $output = trim(`$commandline`); + if (ctype_digit($output)) { + $filesize = (float) $output; + } + } + return $filesize; + } +} \ No newline at end of file diff --git a/sources/wp-includes/ID3/getid3.php b/sources/wp-includes/ID3/getid3.php new file mode 100644 index 0000000..84b9cce --- /dev/null +++ b/sources/wp-includes/ID3/getid3.php @@ -0,0 +1,1776 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// // +// Please see readme.txt for more information // +// /// +///////////////////////////////////////////////////////////////// + +// define a constant rather than looking up every time it is needed +if (!defined('GETID3_OS_ISWINDOWS')) { + define('GETID3_OS_ISWINDOWS', (stripos(PHP_OS, 'WIN') === 0)); +} +// Get base path of getID3() - ONCE +if (!defined('GETID3_INCLUDEPATH')) { + define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR); +} + +// attempt to define temp dir as something flexible but reliable +$temp_dir = ini_get('upload_tmp_dir'); +if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) { + $temp_dir = ''; +} +if (!$temp_dir && function_exists('sys_get_temp_dir')) { + // PHP v5.2.1+ + // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts + $temp_dir = sys_get_temp_dir(); +} +$temp_dir = realpath($temp_dir); +$open_basedir = ini_get('open_basedir'); +if ($open_basedir) { + // e.g. "/var/www/vhosts/getid3.org/httpdocs/:/tmp/" + $temp_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $temp_dir); + $open_basedir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $open_basedir); + if (substr($temp_dir, -1, 1) != DIRECTORY_SEPARATOR) { + $temp_dir .= DIRECTORY_SEPARATOR; + } + $found_valid_tempdir = false; + $open_basedirs = explode(PATH_SEPARATOR, $open_basedir); + foreach ($open_basedirs as $basedir) { + if (substr($basedir, -1, 1) != DIRECTORY_SEPARATOR) { + $basedir .= DIRECTORY_SEPARATOR; + } + if (preg_match('#^'.preg_quote($basedir).'#', $temp_dir)) { + $found_valid_tempdir = true; + break; + } + } + if (!$found_valid_tempdir) { + $temp_dir = ''; + } + unset($open_basedirs, $found_valid_tempdir, $basedir); +} +if (!$temp_dir) { + $temp_dir = '*'; // invalid directory name should force tempnam() to use system default temp dir +} +// $temp_dir = '/something/else/'; // feel free to override temp dir here if it works better for your system +define('GETID3_TEMP_DIR', $temp_dir); +unset($open_basedir, $temp_dir); + +// End: Defines + + +class getID3 +{ + // public: Settings + public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE + public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' + + // public: Optional tag checks - disable for speed. + public $option_tag_id3v1 = true; // Read and process ID3v1 tags + public $option_tag_id3v2 = true; // Read and process ID3v2 tags + public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags + public $option_tag_apetag = true; // Read and process APE tags + public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding + public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities + + // public: Optional tag/comment calucations + public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc + + // public: Optional handling of embedded attachments (e.g. images) + public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility + + // public: Optional calculations + public $option_md5_data = false; // Get MD5 sum of data part - slow + public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG + public $option_sha1_data = false; // Get SHA1 sum of data part - slow + public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX) + + // public: Read buffer size in bytes + public $option_fread_buffer_size = 32768; + + // Public variables + public $filename; // Filename of file being analysed. + public $fp; // Filepointer to file being analysed. + public $info; // Result array. + public $tempdir = GETID3_TEMP_DIR; + + // Protected variables + protected $startup_error = ''; + protected $startup_warning = ''; + protected $memory_limit = 0; + + const VERSION = '1.9.7-20130705'; + const FREAD_BUFFER_SIZE = 32768; + + const ATTACHMENTS_NONE = false; + const ATTACHMENTS_INLINE = true; + + // public: constructor + public function __construct() { + + // Check for PHP version + $required_php_version = '5.0.5'; + if (version_compare(PHP_VERSION, $required_php_version, '<')) { + $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION; + return false; + } + + // Check memory + $this->memory_limit = ini_get('memory_limit'); + if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) { + // could be stored as "16M" rather than 16777216 for example + $this->memory_limit = $matches[1] * 1048576; + } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0 + // could be stored as "2G" rather than 2147483648 for example + $this->memory_limit = $matches[1] * 1073741824; + } + if ($this->memory_limit <= 0) { + // memory limits probably disabled + } elseif ($this->memory_limit <= 4194304) { + $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'; + } elseif ($this->memory_limit <= 12582912) { + $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'; + } + + // Check safe_mode off + if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { + $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.'); + } + + if (intval(ini_get('mbstring.func_overload')) > 0) { + $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.'); + } + + // Check for magic_quotes_runtime + if (function_exists('get_magic_quotes_runtime')) { + if (get_magic_quotes_runtime()) { + return $this->startup_error('magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'); + } + } + + // Check for magic_quotes_gpc + if (function_exists('magic_quotes_gpc')) { + if (get_magic_quotes_gpc()) { + return $this->startup_error('magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'); + } + } + + // Load support library + if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) { + $this->startup_error .= 'getid3.lib.php is missing or corrupt'; + } + + if ($this->option_max_2gb_check === null) { + $this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647); + } + + + // Needed for Windows only: + // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC + // as well as other helper functions such as head, tail, md5sum, etc + // This path cannot contain spaces, but the below code will attempt to get the + // 8.3-equivalent path automatically + // IMPORTANT: This path must include the trailing slash + if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) { + + $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path + + if (!is_dir($helperappsdir)) { + $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'; + } elseif (strpos(realpath($helperappsdir), ' ') !== false) { + $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir)); + $path_so_far = array(); + foreach ($DirPieces as $key => $value) { + if (strpos($value, ' ') !== false) { + if (!empty($path_so_far)) { + $commandline = 'dir /x '.escapeshellarg(implode(DIRECTORY_SEPARATOR, $path_so_far)); + $dir_listing = `$commandline`; + $lines = explode("\n", $dir_listing); + foreach ($lines as $line) { + $line = trim($line); + if (preg_match('#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(
    |[0-9,]+) +([^ ]{0,11}) +(.+)$#', $line, $matches)) { + list($dummy, $date, $time, $ampm, $filesize, $shortname, $filename) = $matches; + if ((strtoupper($filesize) == '') && (strtolower($filename) == strtolower($value))) { + $value = $shortname; + } + } + } + } else { + $this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.'; + } + } + $path_so_far[] = $value; + } + $helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far); + } + define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR); + } + + return true; + } + + public function version() { + return self::VERSION; + } + + public function fread_buffer_size() { + return $this->option_fread_buffer_size; + } + + + // public: setOption + public function setOption($optArray) { + if (!is_array($optArray) || empty($optArray)) { + return false; + } + foreach ($optArray as $opt => $val) { + if (isset($this->$opt) === false) { + continue; + } + $this->$opt = $val; + } + return true; + } + + + public function openfile($filename) { + try { + if (!empty($this->startup_error)) { + throw new getid3_exception($this->startup_error); + } + if (!empty($this->startup_warning)) { + $this->warning($this->startup_warning); + } + + // init result array and set parameters + $this->filename = $filename; + $this->info = array(); + $this->info['GETID3_VERSION'] = $this->version(); + $this->info['php_memory_limit'] = $this->memory_limit; + + // remote files not supported + if (preg_match('/^(ht|f)tp:\/\//', $filename)) { + throw new getid3_exception('Remote files are not supported - please copy the file locally first'); + } + + $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); + $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename); + + // open local file + if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { + // great + } else { + throw new getid3_exception('Could not open "'.$filename.'" (does not exist, or is not a file)'); + } + + $this->info['filesize'] = filesize($filename); + // set redundant parameters - might be needed in some include file + $this->info['filename'] = basename($filename); + $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename))); + $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename']; + + + // option_max_2gb_check + if ($this->option_max_2gb_check) { + // PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB) + // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize + // ftell() returns 0 if seeking to the end is beyond the range of unsigned integer + $fseek = fseek($this->fp, 0, SEEK_END); + if (($fseek < 0) || (($this->info['filesize'] != 0) && (ftell($this->fp) == 0)) || + ($this->info['filesize'] < 0) || + (ftell($this->fp) < 0)) { + $real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']); + + if ($real_filesize === false) { + unset($this->info['filesize']); + fclose($this->fp); + throw new getid3_exception('Unable to determine actual filesize. File is most likely larger than '.round(PHP_INT_MAX / 1073741824).'GB and is not supported by PHP.'); + } elseif (getid3_lib::intValueSupported($real_filesize)) { + unset($this->info['filesize']); + fclose($this->fp); + throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org'); + } + $this->info['filesize'] = $real_filesize; + $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.'); + } + } + + // set more parameters + $this->info['avdataoffset'] = 0; + $this->info['avdataend'] = $this->info['filesize']; + $this->info['fileformat'] = ''; // filled in later + $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used + $this->info['video']['dataformat'] = ''; // filled in later, unset if not used + $this->info['tags'] = array(); // filled in later, unset if not used + $this->info['error'] = array(); // filled in later, unset if not used + $this->info['warning'] = array(); // filled in later, unset if not used + $this->info['comments'] = array(); // filled in later, unset if not used + $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired + + return true; + + } catch (Exception $e) { + $this->error($e->getMessage()); + } + return false; + } + + // public: analyze file + public function analyze($filename) { + try { + if (!$this->openfile($filename)) { + return $this->info; + } + + // Handle tags + foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) { + $option_tag = 'option_tag_'.$tag_name; + if ($this->$option_tag) { + $this->include_module('tag.'.$tag_name); + try { + $tag_class = 'getid3_'.$tag_name; + $tag = new $tag_class($this); + $tag->Analyze(); + } + catch (getid3_exception $e) { + throw $e; + } + } + } + if (isset($this->info['id3v2']['tag_offset_start'])) { + $this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']); + } + foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) { + if (isset($this->info[$tag_key]['tag_offset_start'])) { + $this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']); + } + } + + // ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier + if (!$this->option_tag_id3v2) { + fseek($this->fp, 0, SEEK_SET); + $header = fread($this->fp, 10); + if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) { + $this->info['id3v2']['header'] = true; + $this->info['id3v2']['majorversion'] = ord($header{3}); + $this->info['id3v2']['minorversion'] = ord($header{4}); + $this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length + } + } + + // read 32 kb file data + fseek($this->fp, $this->info['avdataoffset'], SEEK_SET); + $formattest = fread($this->fp, 32774); + + // determine format + $determined_format = $this->GetFileFormat($formattest, $filename); + + // unable to determine file format + if (!$determined_format) { + fclose($this->fp); + return $this->error('unable to determine file format'); + } + + // check for illegal ID3 tags + if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) { + if ($determined_format['fail_id3'] === 'ERROR') { + fclose($this->fp); + return $this->error('ID3 tags not allowed on this file type.'); + } elseif ($determined_format['fail_id3'] === 'WARNING') { + $this->warning('ID3 tags not allowed on this file type.'); + } + } + + // check for illegal APE tags + if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) { + if ($determined_format['fail_ape'] === 'ERROR') { + fclose($this->fp); + return $this->error('APE tags not allowed on this file type.'); + } elseif ($determined_format['fail_ape'] === 'WARNING') { + $this->warning('APE tags not allowed on this file type.'); + } + } + + // set mime type + $this->info['mime_type'] = $determined_format['mime_type']; + + // supported format signature pattern detected, but module deleted + if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) { + fclose($this->fp); + return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.'); + } + + // module requires iconv support + // Check encoding/iconv support + if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) { + $errormessage = 'iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. '; + if (GETID3_OS_ISWINDOWS) { + $errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32'; + } else { + $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch'; + } + return $this->error($errormessage); + } + + // include module + include_once(GETID3_INCLUDEPATH.$determined_format['include']); + + // instantiate module class + $class_name = 'getid3_'.$determined_format['module']; + if (!class_exists($class_name)) { + return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.'); + } + $class = new $class_name($this); + $class->Analyze(); + unset($class); + + // close file + fclose($this->fp); + + // process all tags - copy to 'tags' and convert charsets + if ($this->option_tags_process) { + $this->HandleAllTags(); + } + + // perform more calculations + if ($this->option_extra_info) { + $this->ChannelsBitratePlaytimeCalculations(); + $this->CalculateCompressionRatioVideo(); + $this->CalculateCompressionRatioAudio(); + $this->CalculateReplayGain(); + $this->ProcessAudioStreams(); + } + + // get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags + if ($this->option_md5_data) { + // do not calc md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too + if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) { + $this->getHashdata('md5'); + } + } + + // get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags + if ($this->option_sha1_data) { + $this->getHashdata('sha1'); + } + + // remove undesired keys + $this->CleanUp(); + + } catch (Exception $e) { + $this->error('Caught exception: '.$e->getMessage()); + } + + // return info array + return $this->info; + } + + + // private: error handling + public function error($message) { + $this->CleanUp(); + if (!isset($this->info['error'])) { + $this->info['error'] = array(); + } + $this->info['error'][] = $message; + return $this->info; + } + + + // private: warning handling + public function warning($message) { + $this->info['warning'][] = $message; + return true; + } + + + // private: CleanUp + private function CleanUp() { + + // remove possible empty keys + $AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate'); + foreach ($AVpossibleEmptyKeys as $dummy => $key) { + if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) { + unset($this->info['audio'][$key]); + } + if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) { + unset($this->info['video'][$key]); + } + } + + // remove empty root keys + if (!empty($this->info)) { + foreach ($this->info as $key => $value) { + if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) { + unset($this->info[$key]); + } + } + } + + // remove meaningless entries from unknown-format files + if (empty($this->info['fileformat'])) { + if (isset($this->info['avdataoffset'])) { + unset($this->info['avdataoffset']); + } + if (isset($this->info['avdataend'])) { + unset($this->info['avdataend']); + } + } + + // remove possible duplicated identical entries + if (!empty($this->info['error'])) { + $this->info['error'] = array_values(array_unique($this->info['error'])); + } + if (!empty($this->info['warning'])) { + $this->info['warning'] = array_values(array_unique($this->info['warning'])); + } + + // remove "global variable" type keys + unset($this->info['php_memory_limit']); + + return true; + } + + + // return array containing information about all supported formats + public function GetFileFormatArray() { + static $format_info = array(); + if (empty($format_info)) { + $format_info = array( + + // Audio formats + + // AC-3 - audio - Dolby AC-3 / Dolby Digital + 'ac3' => array( + 'pattern' => '^\x0B\x77', + 'group' => 'audio', + 'module' => 'ac3', + 'mime_type' => 'audio/ac3', + ), + + // AAC - audio - Advanced Audio Coding (AAC) - ADIF format + 'adif' => array( + 'pattern' => '^ADIF', + 'group' => 'audio', + 'module' => 'aac', + 'mime_type' => 'application/octet-stream', + 'fail_ape' => 'WARNING', + ), + +/* + // AA - audio - Audible Audiobook + 'aa' => array( + 'pattern' => '^.{4}\x57\x90\x75\x36', + 'group' => 'audio', + 'module' => 'aa', + 'mime_type' => 'audio/audible', + ), +*/ + // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3) + 'adts' => array( + 'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]', + 'group' => 'audio', + 'module' => 'aac', + 'mime_type' => 'application/octet-stream', + 'fail_ape' => 'WARNING', + ), + + + // AU - audio - NeXT/Sun AUdio (AU) + 'au' => array( + 'pattern' => '^\.snd', + 'group' => 'audio', + 'module' => 'au', + 'mime_type' => 'audio/basic', + ), + + // AVR - audio - Audio Visual Research + 'avr' => array( + 'pattern' => '^2BIT', + 'group' => 'audio', + 'module' => 'avr', + 'mime_type' => 'application/octet-stream', + ), + + // BONK - audio - Bonk v0.9+ + 'bonk' => array( + 'pattern' => '^\x00(BONK|INFO|META| ID3)', + 'group' => 'audio', + 'module' => 'bonk', + 'mime_type' => 'audio/xmms-bonk', + ), + + // DSS - audio - Digital Speech Standard + 'dss' => array( + 'pattern' => '^[\x02-\x03]ds[s2]', + 'group' => 'audio', + 'module' => 'dss', + 'mime_type' => 'application/octet-stream', + ), + + // DTS - audio - Dolby Theatre System + 'dts' => array( + 'pattern' => '^\x7F\xFE\x80\x01', + 'group' => 'audio', + 'module' => 'dts', + 'mime_type' => 'audio/dts', + ), + + // FLAC - audio - Free Lossless Audio Codec + 'flac' => array( + 'pattern' => '^fLaC', + 'group' => 'audio', + 'module' => 'flac', + 'mime_type' => 'audio/x-flac', + ), + + // LA - audio - Lossless Audio (LA) + 'la' => array( + 'pattern' => '^LA0[2-4]', + 'group' => 'audio', + 'module' => 'la', + 'mime_type' => 'application/octet-stream', + ), + + // LPAC - audio - Lossless Predictive Audio Compression (LPAC) + 'lpac' => array( + 'pattern' => '^LPAC', + 'group' => 'audio', + 'module' => 'lpac', + 'mime_type' => 'application/octet-stream', + ), + + // MIDI - audio - MIDI (Musical Instrument Digital Interface) + 'midi' => array( + 'pattern' => '^MThd', + 'group' => 'audio', + 'module' => 'midi', + 'mime_type' => 'audio/midi', + ), + + // MAC - audio - Monkey's Audio Compressor + 'mac' => array( + 'pattern' => '^MAC ', + 'group' => 'audio', + 'module' => 'monkey', + 'mime_type' => 'application/octet-stream', + ), + +// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available +// // MOD - audio - MODule (assorted sub-formats) +// 'mod' => array( +// 'pattern' => '^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)', +// 'group' => 'audio', +// 'module' => 'mod', +// 'option' => 'mod', +// 'mime_type' => 'audio/mod', +// ), + + // MOD - audio - MODule (Impulse Tracker) + 'it' => array( + 'pattern' => '^IMPM', + 'group' => 'audio', + 'module' => 'mod', + //'option' => 'it', + 'mime_type' => 'audio/it', + ), + + // MOD - audio - MODule (eXtended Module, various sub-formats) + 'xm' => array( + 'pattern' => '^Extended Module', + 'group' => 'audio', + 'module' => 'mod', + //'option' => 'xm', + 'mime_type' => 'audio/xm', + ), + + // MOD - audio - MODule (ScreamTracker) + 's3m' => array( + 'pattern' => '^.{44}SCRM', + 'group' => 'audio', + 'module' => 'mod', + //'option' => 's3m', + 'mime_type' => 'audio/s3m', + ), + + // MPC - audio - Musepack / MPEGplus + 'mpc' => array( + 'pattern' => '^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])', + 'group' => 'audio', + 'module' => 'mpc', + 'mime_type' => 'audio/x-musepack', + ), + + // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS) + 'mp3' => array( + 'pattern' => '^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\x0B\x10-\x1B\x20-\x2B\x30-\x3B\x40-\x4B\x50-\x5B\x60-\x6B\x70-\x7B\x80-\x8B\x90-\x9B\xA0-\xAB\xB0-\xBB\xC0-\xCB\xD0-\xDB\xE0-\xEB\xF0-\xFB]', + 'group' => 'audio', + 'module' => 'mp3', + 'mime_type' => 'audio/mpeg', + ), + + // OFR - audio - OptimFROG + 'ofr' => array( + 'pattern' => '^(\*RIFF|OFR)', + 'group' => 'audio', + 'module' => 'optimfrog', + 'mime_type' => 'application/octet-stream', + ), + + // RKAU - audio - RKive AUdio compressor + 'rkau' => array( + 'pattern' => '^RKA', + 'group' => 'audio', + 'module' => 'rkau', + 'mime_type' => 'application/octet-stream', + ), + + // SHN - audio - Shorten + 'shn' => array( + 'pattern' => '^ajkg', + 'group' => 'audio', + 'module' => 'shorten', + 'mime_type' => 'audio/xmms-shn', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org) + 'tta' => array( + 'pattern' => '^TTA', // could also be '^TTA(\x01|\x02|\x03|2|1)' + 'group' => 'audio', + 'module' => 'tta', + 'mime_type' => 'application/octet-stream', + ), + + // VOC - audio - Creative Voice (VOC) + 'voc' => array( + 'pattern' => '^Creative Voice File', + 'group' => 'audio', + 'module' => 'voc', + 'mime_type' => 'audio/voc', + ), + + // VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF) + 'vqf' => array( + 'pattern' => '^TWIN', + 'group' => 'audio', + 'module' => 'vqf', + 'mime_type' => 'application/octet-stream', + ), + + // WV - audio - WavPack (v4.0+) + 'wv' => array( + 'pattern' => '^wvpk', + 'group' => 'audio', + 'module' => 'wavpack', + 'mime_type' => 'application/octet-stream', + ), + + + // Audio-Video formats + + // ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio + 'asf' => array( + 'pattern' => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C', + 'group' => 'audio-video', + 'module' => 'asf', + 'mime_type' => 'video/x-ms-asf', + 'iconv_req' => false, + ), + + // BINK - audio/video - Bink / Smacker + 'bink' => array( + 'pattern' => '^(BIK|SMK)', + 'group' => 'audio-video', + 'module' => 'bink', + 'mime_type' => 'application/octet-stream', + ), + + // FLV - audio/video - FLash Video + 'flv' => array( + 'pattern' => '^FLV\x01', + 'group' => 'audio-video', + 'module' => 'flv', + 'mime_type' => 'video/x-flv', + ), + + // MKAV - audio/video - Mastroka + 'matroska' => array( + 'pattern' => '^\x1A\x45\xDF\xA3', + 'group' => 'audio-video', + 'module' => 'matroska', + 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska + ), + + // MPEG - audio/video - MPEG (Moving Pictures Experts Group) + 'mpeg' => array( + 'pattern' => '^\x00\x00\x01(\xBA|\xB3)', + 'group' => 'audio-video', + 'module' => 'mpeg', + 'mime_type' => 'video/mpeg', + ), + + // NSV - audio/video - Nullsoft Streaming Video (NSV) + 'nsv' => array( + 'pattern' => '^NSV[sf]', + 'group' => 'audio-video', + 'module' => 'nsv', + 'mime_type' => 'application/octet-stream', + ), + + // Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*)) + 'ogg' => array( + 'pattern' => '^OggS', + 'group' => 'audio', + 'module' => 'ogg', + 'mime_type' => 'application/ogg', + 'fail_id3' => 'WARNING', + 'fail_ape' => 'WARNING', + ), + + // QT - audio/video - Quicktime + 'quicktime' => array( + 'pattern' => '^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)', + 'group' => 'audio-video', + 'module' => 'quicktime', + 'mime_type' => 'video/quicktime', + ), + + // RIFF - audio/video - Resource Interchange File Format (RIFF) / WAV / AVI / CD-audio / SDSS = renamed variant used by SmartSound QuickTracks (www.smartsound.com) / FORM = Audio Interchange File Format (AIFF) + 'riff' => array( + 'pattern' => '^(RIFF|SDSS|FORM)', + 'group' => 'audio-video', + 'module' => 'riff', + 'mime_type' => 'audio/x-wave', + 'fail_ape' => 'WARNING', + ), + + // Real - audio/video - RealAudio, RealVideo + 'real' => array( + 'pattern' => '^(\\.RMF|\\.ra)', + 'group' => 'audio-video', + 'module' => 'real', + 'mime_type' => 'audio/x-realaudio', + ), + + // SWF - audio/video - ShockWave Flash + 'swf' => array( + 'pattern' => '^(F|C)WS', + 'group' => 'audio-video', + 'module' => 'swf', + 'mime_type' => 'application/x-shockwave-flash', + ), + + // TS - audio/video - MPEG-2 Transport Stream + 'ts' => array( + 'pattern' => '^(\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern + 'group' => 'audio-video', + 'module' => 'ts', + 'mime_type' => 'video/MP2T', + ), + + + // Still-Image formats + + // BMP - still image - Bitmap (Windows, OS/2; uncompressed, RLE8, RLE4) + 'bmp' => array( + 'pattern' => '^BM', + 'group' => 'graphic', + 'module' => 'bmp', + 'mime_type' => 'image/bmp', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // GIF - still image - Graphics Interchange Format + 'gif' => array( + 'pattern' => '^GIF', + 'group' => 'graphic', + 'module' => 'gif', + 'mime_type' => 'image/gif', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // JPEG - still image - Joint Photographic Experts Group (JPEG) + 'jpg' => array( + 'pattern' => '^\xFF\xD8\xFF', + 'group' => 'graphic', + 'module' => 'jpg', + 'mime_type' => 'image/jpeg', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // PCD - still image - Kodak Photo CD + 'pcd' => array( + 'pattern' => '^.{2048}PCD_IPI\x00', + 'group' => 'graphic', + 'module' => 'pcd', + 'mime_type' => 'image/x-photo-cd', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + + // PNG - still image - Portable Network Graphics (PNG) + 'png' => array( + 'pattern' => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A', + 'group' => 'graphic', + 'module' => 'png', + 'mime_type' => 'image/png', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + + // SVG - still image - Scalable Vector Graphics (SVG) + 'svg' => array( + 'pattern' => '( 'graphic', + 'module' => 'svg', + 'mime_type' => 'image/svg+xml', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + + // TIFF - still image - Tagged Information File Format (TIFF) + 'tiff' => array( + 'pattern' => '^(II\x2A\x00|MM\x00\x2A)', + 'group' => 'graphic', + 'module' => 'tiff', + 'mime_type' => 'image/tiff', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + + // EFAX - still image - eFax (TIFF derivative) + 'efax' => array( + 'pattern' => '^\xDC\xFE', + 'group' => 'graphic', + 'module' => 'efax', + 'mime_type' => 'image/efax', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + + // Data formats + + // ISO - data - International Standards Organization (ISO) CD-ROM Image + 'iso' => array( + 'pattern' => '^.{32769}CD001', + 'group' => 'misc', + 'module' => 'iso', + 'mime_type' => 'application/octet-stream', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + 'iconv_req' => false, + ), + + // RAR - data - RAR compressed data + 'rar' => array( + 'pattern' => '^Rar\!', + 'group' => 'archive', + 'module' => 'rar', + 'mime_type' => 'application/octet-stream', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // SZIP - audio/data - SZIP compressed data + 'szip' => array( + 'pattern' => '^SZ\x0A\x04', + 'group' => 'archive', + 'module' => 'szip', + 'mime_type' => 'application/octet-stream', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // TAR - data - TAR compressed data + 'tar' => array( + 'pattern' => '^.{100}[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20\x00]{12}[0-9\x20\x00]{12}', + 'group' => 'archive', + 'module' => 'tar', + 'mime_type' => 'application/x-tar', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // GZIP - data - GZIP compressed data + 'gz' => array( + 'pattern' => '^\x1F\x8B\x08', + 'group' => 'archive', + 'module' => 'gzip', + 'mime_type' => 'application/x-gzip', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // ZIP - data - ZIP compressed data + 'zip' => array( + 'pattern' => '^PK\x03\x04', + 'group' => 'archive', + 'module' => 'zip', + 'mime_type' => 'application/zip', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + + // Misc other formats + + // PAR2 - data - Parity Volume Set Specification 2.0 + 'par2' => array ( + 'pattern' => '^PAR2\x00PKT', + 'group' => 'misc', + 'module' => 'par2', + 'mime_type' => 'application/octet-stream', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // PDF - data - Portable Document Format + 'pdf' => array( + 'pattern' => '^\x25PDF', + 'group' => 'misc', + 'module' => 'pdf', + 'mime_type' => 'application/pdf', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // MSOFFICE - data - ZIP compressed data + 'msoffice' => array( + 'pattern' => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document + 'group' => 'misc', + 'module' => 'msoffice', + 'mime_type' => 'application/octet-stream', + 'fail_id3' => 'ERROR', + 'fail_ape' => 'ERROR', + ), + + // CUE - data - CUEsheet (index to single-file disc images) + 'cue' => array( + 'pattern' => '', // empty pattern means cannot be automatically detected, will fall through all other formats and match based on filename and very basic file contents + 'group' => 'misc', + 'module' => 'cue', + 'mime_type' => 'application/octet-stream', + ), + + ); + } + + return $format_info; + } + + + + public function GetFileFormat(&$filedata, $filename='') { + // this function will determine the format of a file based on usually + // the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG, + // and in the case of ISO CD image, 6 bytes offset 32kb from the start + // of the file). + + // Identify file format - loop through $format_info and detect with reg expr + foreach ($this->GetFileFormatArray() as $format_name => $info) { + // The /s switch on preg_match() forces preg_match() NOT to treat + // newline (0x0A) characters as special chars but do a binary match + if (!empty($info['pattern']) && preg_match('#'.$info['pattern'].'#s', $filedata)) { + $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; + return $info; + } + } + + + if (preg_match('#\.mp[123a]$#i', $filename)) { + // Too many mp3 encoders on the market put gabage in front of mpeg files + // use assume format on these if format detection failed + $GetFileFormatArray = $this->GetFileFormatArray(); + $info = $GetFileFormatArray['mp3']; + $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; + return $info; + } elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) { + // there's not really a useful consistent "magic" at the beginning of .cue files to identify them + // so until I think of something better, just go by filename if all other format checks fail + // and verify there's at least one instance of "TRACK xx AUDIO" in the file + $GetFileFormatArray = $this->GetFileFormatArray(); + $info = $GetFileFormatArray['cue']; + $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; + return $info; + } + + return false; + } + + + // converts array to $encoding charset from $this->encoding + public function CharConvert(&$array, $encoding) { + + // identical encoding - end here + if ($encoding == $this->encoding) { + return; + } + + // loop thru array + foreach ($array as $key => $value) { + + // go recursive + if (is_array($value)) { + $this->CharConvert($array[$key], $encoding); + } + + // convert string + elseif (is_string($value)) { + $array[$key] = trim(getid3_lib::iconv_fallback($encoding, $this->encoding, $value)); + } + } + } + + + public function HandleAllTags() { + + // key name => array (tag name, character encoding) + static $tags; + if (empty($tags)) { + $tags = array( + 'asf' => array('asf' , 'UTF-16LE'), + 'midi' => array('midi' , 'ISO-8859-1'), + 'nsv' => array('nsv' , 'ISO-8859-1'), + 'ogg' => array('vorbiscomment' , 'UTF-8'), + 'png' => array('png' , 'UTF-8'), + 'tiff' => array('tiff' , 'ISO-8859-1'), + 'quicktime' => array('quicktime' , 'UTF-8'), + 'real' => array('real' , 'ISO-8859-1'), + 'vqf' => array('vqf' , 'ISO-8859-1'), + 'zip' => array('zip' , 'ISO-8859-1'), + 'riff' => array('riff' , 'ISO-8859-1'), + 'lyrics3' => array('lyrics3' , 'ISO-8859-1'), + 'id3v1' => array('id3v1' , $this->encoding_id3v1), + 'id3v2' => array('id3v2' , 'UTF-8'), // not according to the specs (every frame can have a different encoding), but getID3() force-converts all encodings to UTF-8 + 'ape' => array('ape' , 'UTF-8'), + 'cue' => array('cue' , 'ISO-8859-1'), + 'matroska' => array('matroska' , 'UTF-8'), + 'flac' => array('vorbiscomment' , 'UTF-8'), + 'divxtag' => array('divx' , 'ISO-8859-1'), + ); + } + + // loop through comments array + foreach ($tags as $comment_name => $tagname_encoding_array) { + list($tag_name, $encoding) = $tagname_encoding_array; + + // fill in default encoding type if not already present + if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name]['encoding'])) { + $this->info[$comment_name]['encoding'] = $encoding; + } + + // copy comments if key name set + if (!empty($this->info[$comment_name]['comments'])) { + foreach ($this->info[$comment_name]['comments'] as $tag_key => $valuearray) { + foreach ($valuearray as $key => $value) { + if (is_string($value)) { + $value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed! + } + if ($value) { + $this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value; + } + } + if ($tag_key == 'picture') { + unset($this->info[$comment_name]['comments'][$tag_key]); + } + } + + if (!isset($this->info['tags'][$tag_name])) { + // comments are set but contain nothing but empty strings, so skip + continue; + } + + if ($this->option_tags_html) { + foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) { + foreach ($valuearray as $key => $value) { + if (is_string($value)) { + //$this->info['tags_html'][$tag_name][$tag_key][$key] = getid3_lib::MultiByteCharString2HTML($value, $encoding); + $this->info['tags_html'][$tag_name][$tag_key][$key] = str_replace('�', '', trim(getid3_lib::MultiByteCharString2HTML($value, $encoding))); + } else { + $this->info['tags_html'][$tag_name][$tag_key][$key] = $value; + } + } + } + } + + $this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted! + } + + } + + // pictures can take up a lot of space, and we don't need multiple copies of them + // let there be a single copy in [comments][picture], and not elsewhere + if (!empty($this->info['tags'])) { + $unset_keys = array('tags', 'tags_html'); + foreach ($this->info['tags'] as $tagtype => $tagarray) { + foreach ($tagarray as $tagname => $tagdata) { + if ($tagname == 'picture') { + foreach ($tagdata as $key => $tagarray) { + $this->info['comments']['picture'][] = $tagarray; + if (isset($tagarray['data']) && isset($tagarray['image_mime'])) { + if (isset($this->info['tags'][$tagtype][$tagname][$key])) { + unset($this->info['tags'][$tagtype][$tagname][$key]); + } + if (isset($this->info['tags_html'][$tagtype][$tagname][$key])) { + unset($this->info['tags_html'][$tagtype][$tagname][$key]); + } + } + } + } + } + foreach ($unset_keys as $unset_key) { + // remove possible empty keys from (e.g. [tags][id3v2][picture]) + if (empty($this->info[$unset_key][$tagtype]['picture'])) { + unset($this->info[$unset_key][$tagtype]['picture']); + } + if (empty($this->info[$unset_key][$tagtype])) { + unset($this->info[$unset_key][$tagtype]); + } + if (empty($this->info[$unset_key])) { + unset($this->info[$unset_key]); + } + } + // remove duplicate copy of picture data from (e.g. [id3v2][comments][picture]) + if (isset($this->info[$tagtype]['comments']['picture'])) { + unset($this->info[$tagtype]['comments']['picture']); + } + if (empty($this->info[$tagtype]['comments'])) { + unset($this->info[$tagtype]['comments']); + } + if (empty($this->info[$tagtype])) { + unset($this->info[$tagtype]); + } + } + } + return true; + } + + + public function getHashdata($algorithm) { + switch ($algorithm) { + case 'md5': + case 'sha1': + break; + + default: + return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()'); + break; + } + + if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) { + + // We cannot get an identical md5_data value for Ogg files where the comments + // span more than 1 Ogg page (compared to the same audio data with smaller + // comments) using the normal getID3() method of MD5'ing the data between the + // end of the comments and the end of the file (minus any trailing tags), + // because the page sequence numbers of the pages that the audio data is on + // do not match. Under normal circumstances, where comments are smaller than + // the nominal 4-8kB page size, then this is not a problem, but if there are + // very large comments, the only way around it is to strip off the comment + // tags with vorbiscomment and MD5 that file. + // This procedure must be applied to ALL Ogg files, not just the ones with + // comments larger than 1 page, because the below method simply MD5's the + // whole file with the comments stripped, not just the portion after the + // comments block (which is the standard getID3() method. + + // The above-mentioned problem of comments spanning multiple pages and changing + // page sequence numbers likely happens for OggSpeex and OggFLAC as well, but + // currently vorbiscomment only works on OggVorbis files. + + if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { + + $this->warning('Failed making system call to vorbiscomment.exe - '.$algorithm.'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)'); + $this->info[$algorithm.'_data'] = false; + + } else { + + // Prevent user from aborting script + $old_abort = ignore_user_abort(true); + + // Create empty file + $empty = tempnam(GETID3_TEMP_DIR, 'getID3'); + touch($empty); + + // Use vorbiscomment to make temp file without comments + $temp = tempnam(GETID3_TEMP_DIR, 'getID3'); + $file = $this->info['filenamepath']; + + if (GETID3_OS_ISWINDOWS) { + + if (file_exists(GETID3_HELPERAPPSDIR.'vorbiscomment.exe')) { + + $commandline = '"'.GETID3_HELPERAPPSDIR.'vorbiscomment.exe" -w -c "'.$empty.'" "'.$file.'" "'.$temp.'"'; + $VorbisCommentError = `$commandline`; + + } else { + + $VorbisCommentError = 'vorbiscomment.exe not found in '.GETID3_HELPERAPPSDIR; + + } + + } else { + + $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1'; + $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1'; + $VorbisCommentError = `$commandline`; + + } + + if (!empty($VorbisCommentError)) { + + $this->info['warning'][] = 'Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError; + $this->info[$algorithm.'_data'] = false; + + } else { + + // Get hash of newly created file + switch ($algorithm) { + case 'md5': + $this->info[$algorithm.'_data'] = md5_file($temp); + break; + + case 'sha1': + $this->info[$algorithm.'_data'] = sha1_file($temp); + break; + } + } + + // Clean up + unlink($empty); + unlink($temp); + + // Reset abort setting + ignore_user_abort($old_abort); + + } + + } else { + + if (!empty($this->info['avdataoffset']) || (isset($this->info['avdataend']) && ($this->info['avdataend'] < $this->info['filesize']))) { + + // get hash from part of file + $this->info[$algorithm.'_data'] = getid3_lib::hash_data($this->info['filenamepath'], $this->info['avdataoffset'], $this->info['avdataend'], $algorithm); + + } else { + + // get hash from whole file + switch ($algorithm) { + case 'md5': + $this->info[$algorithm.'_data'] = md5_file($this->info['filenamepath']); + break; + + case 'sha1': + $this->info[$algorithm.'_data'] = sha1_file($this->info['filenamepath']); + break; + } + } + + } + return true; + } + + + public function ChannelsBitratePlaytimeCalculations() { + + // set channelmode on audio + if (!empty($this->info['audio']['channelmode']) || !isset($this->info['audio']['channels'])) { + // ignore + } elseif ($this->info['audio']['channels'] == 1) { + $this->info['audio']['channelmode'] = 'mono'; + } elseif ($this->info['audio']['channels'] == 2) { + $this->info['audio']['channelmode'] = 'stereo'; + } + + // Calculate combined bitrate - audio + video + $CombinedBitrate = 0; + $CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0); + $CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0); + if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) { + $this->info['bitrate'] = $CombinedBitrate; + } + //if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) { + // // for example, VBR MPEG video files cannot determine video bitrate: + // // should not set overall bitrate and playtime from audio bitrate only + // unset($this->info['bitrate']); + //} + + // video bitrate undetermined, but calculable + if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) { + // if video bitrate not set + if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) { + // AND if audio bitrate is set to same as overall bitrate + if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) { + // AND if playtime is set + if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) { + // AND if AV data offset start/end is known + // THEN we can calculate the video bitrate + $this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']); + $this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate']; + } + } + } + } + + if ((!isset($this->info['playtime_seconds']) || ($this->info['playtime_seconds'] <= 0)) && !empty($this->info['bitrate'])) { + $this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate']; + } + + if (!isset($this->info['bitrate']) && !empty($this->info['playtime_seconds'])) { + $this->info['bitrate'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']; + } + if (isset($this->info['bitrate']) && empty($this->info['audio']['bitrate']) && empty($this->info['video']['bitrate'])) { + if (isset($this->info['audio']['dataformat']) && empty($this->info['video']['resolution_x'])) { + // audio only + $this->info['audio']['bitrate'] = $this->info['bitrate']; + } elseif (isset($this->info['video']['resolution_x']) && empty($this->info['audio']['dataformat'])) { + // video only + $this->info['video']['bitrate'] = $this->info['bitrate']; + } + } + + // Set playtime string + if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) { + $this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']); + } + } + + + public function CalculateCompressionRatioVideo() { + if (empty($this->info['video'])) { + return false; + } + if (empty($this->info['video']['resolution_x']) || empty($this->info['video']['resolution_y'])) { + return false; + } + if (empty($this->info['video']['bits_per_sample'])) { + return false; + } + + switch ($this->info['video']['dataformat']) { + case 'bmp': + case 'gif': + case 'jpeg': + case 'jpg': + case 'png': + case 'tiff': + $FrameRate = 1; + $PlaytimeSeconds = 1; + $BitrateCompressed = $this->info['filesize'] * 8; + break; + + default: + if (!empty($this->info['video']['frame_rate'])) { + $FrameRate = $this->info['video']['frame_rate']; + } else { + return false; + } + if (!empty($this->info['playtime_seconds'])) { + $PlaytimeSeconds = $this->info['playtime_seconds']; + } else { + return false; + } + if (!empty($this->info['video']['bitrate'])) { + $BitrateCompressed = $this->info['video']['bitrate']; + } else { + return false; + } + break; + } + $BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate; + + $this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed; + return true; + } + + + public function CalculateCompressionRatioAudio() { + if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) { + return false; + } + $this->info['audio']['compression_ratio'] = $this->info['audio']['bitrate'] / ($this->info['audio']['channels'] * $this->info['audio']['sample_rate'] * (!empty($this->info['audio']['bits_per_sample']) ? $this->info['audio']['bits_per_sample'] : 16)); + + if (!empty($this->info['audio']['streams'])) { + foreach ($this->info['audio']['streams'] as $streamnumber => $streamdata) { + if (!empty($streamdata['bitrate']) && !empty($streamdata['channels']) && !empty($streamdata['sample_rate'])) { + $this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16)); + } + } + } + return true; + } + + + public function CalculateReplayGain() { + if (isset($this->info['replay_gain'])) { + if (!isset($this->info['replay_gain']['reference_volume'])) { + $this->info['replay_gain']['reference_volume'] = (double) 89.0; + } + if (isset($this->info['replay_gain']['track']['adjustment'])) { + $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment']; + } + if (isset($this->info['replay_gain']['album']['adjustment'])) { + $this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment']; + } + + if (isset($this->info['replay_gain']['track']['peak'])) { + $this->info['replay_gain']['track']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['track']['peak']); + } + if (isset($this->info['replay_gain']['album']['peak'])) { + $this->info['replay_gain']['album']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['album']['peak']); + } + } + return true; + } + + public function ProcessAudioStreams() { + if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) { + if (!isset($this->info['audio']['streams'])) { + foreach ($this->info['audio'] as $key => $value) { + if ($key != 'streams') { + $this->info['audio']['streams'][0][$key] = $value; + } + } + } + } + return true; + } + + public function getid3_tempnam() { + return tempnam($this->tempdir, 'gI3'); + } + + public function include_module($name) { + //if (!file_exists($this->include_path.'module.'.$name.'.php')) { + if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) { + throw new getid3_exception('Required module.'.$name.'.php is missing.'); + } + include_once(GETID3_INCLUDEPATH.'module.'.$name.'.php'); + return true; + } + +} + + +abstract class getid3_handler +{ + protected $getid3; // pointer + + protected $data_string_flag = false; // analyzing filepointer or string + protected $data_string = ''; // string to analyze + protected $data_string_position = 0; // seek position in string + protected $data_string_length = 0; // string length + + private $dependency_to = null; + + + public function __construct(getID3 $getid3, $call_module=null) { + $this->getid3 = $getid3; + + if ($call_module) { + $this->dependency_to = str_replace('getid3_', '', $call_module); + } + } + + + // Analyze from file pointer + abstract public function Analyze(); + + + // Analyze from string instead + public function AnalyzeString($string) { + // Enter string mode + $this->setStringMode($string); + + // Save info + $saved_avdataoffset = $this->getid3->info['avdataoffset']; + $saved_avdataend = $this->getid3->info['avdataend']; + $saved_filesize = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call + + // Reset some info + $this->getid3->info['avdataoffset'] = 0; + $this->getid3->info['avdataend'] = $this->getid3->info['filesize'] = $this->data_string_length; + + // Analyze + $this->Analyze(); + + // Restore some info + $this->getid3->info['avdataoffset'] = $saved_avdataoffset; + $this->getid3->info['avdataend'] = $saved_avdataend; + $this->getid3->info['filesize'] = $saved_filesize; + + // Exit string mode + $this->data_string_flag = false; + } + + public function setStringMode($string) { + $this->data_string_flag = true; + $this->data_string = $string; + $this->data_string_length = strlen($string); + } + + protected function ftell() { + if ($this->data_string_flag) { + return $this->data_string_position; + } + return ftell($this->getid3->fp); + } + + protected function fread($bytes) { + if ($this->data_string_flag) { + $this->data_string_position += $bytes; + return substr($this->data_string, $this->data_string_position - $bytes, $bytes); + } + $pos = $this->ftell() + $bytes; + if (!getid3_lib::intValueSupported($pos)) { + throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10); + } + return fread($this->getid3->fp, $bytes); + } + + protected function fseek($bytes, $whence=SEEK_SET) { + if ($this->data_string_flag) { + switch ($whence) { + case SEEK_SET: + $this->data_string_position = $bytes; + break; + + case SEEK_CUR: + $this->data_string_position += $bytes; + break; + + case SEEK_END: + $this->data_string_position = $this->data_string_length + $bytes; + break; + } + return 0; + } else { + $pos = $bytes; + if ($whence == SEEK_CUR) { + $pos = $this->ftell() + $bytes; + } elseif ($whence == SEEK_END) { + $pos = $this->info['filesize'] + $bytes; + } + if (!getid3_lib::intValueSupported($pos)) { + throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10); + } + } + return fseek($this->getid3->fp, $bytes, $whence); + } + + protected function feof() { + if ($this->data_string_flag) { + return $this->data_string_position >= $this->data_string_length; + } + return feof($this->getid3->fp); + } + + final protected function isDependencyFor($module) { + return $this->dependency_to == $module; + } + + protected function error($text) + { + $this->getid3->info['error'][] = $text; + + return false; + } + + protected function warning($text) + { + return $this->getid3->warning($text); + } + + protected function notice($text) + { + // does nothing for now + } + + public function saveAttachment($name, $offset, $length, $image_mime=null) { + try { + + // do not extract at all + if ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_NONE) { + + $attachment = null; // do not set any + + // extract to return array + } elseif ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_INLINE) { + + $this->fseek($offset); + $attachment = $this->fread($length); // get whole data in one pass, till it is anyway stored in memory + if ($attachment === false || strlen($attachment) != $length) { + throw new Exception('failed to read attachment data'); + } + + // assume directory path is given + } else { + + // set up destination path + $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); + if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory + throw new Exception('supplied path ('.$dir.') does not exist, or is not writable'); + } + $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : ''); + + // create dest file + if (($fp_dest = fopen($dest, 'wb')) == false) { + throw new Exception('failed to create file '.$dest); + } + + // copy data + $this->fseek($offset); + $buffersize = ($this->data_string_flag ? $length : $this->getid3->fread_buffer_size()); + $bytesleft = $length; + while ($bytesleft > 0) { + if (($buffer = $this->fread(min($buffersize, $bytesleft))) === false || ($byteswritten = fwrite($fp_dest, $buffer)) === false || ($byteswritten === 0)) { + throw new Exception($buffer === false ? 'not enough data to read' : 'failed to write to destination file, may be not enough disk space'); + } + $bytesleft -= $byteswritten; + } + + fclose($fp_dest); + $attachment = $dest; + + } + + } catch (Exception $e) { + + // close and remove dest file if created + if (isset($fp_dest) && is_resource($fp_dest)) { + fclose($fp_dest); + unlink($dest); + } + + // do not set any is case of error + $attachment = null; + $this->warning('Failed to extract attachment '.$name.': '.$e->getMessage()); + + } + + // seek to the end of attachment + $this->fseek($offset + $length); + + return $attachment; + } + +} + + +class getid3_exception extends Exception +{ + public $message; +} \ No newline at end of file diff --git a/sources/wp-includes/ID3/license.commercial.txt b/sources/wp-includes/ID3/license.commercial.txt new file mode 100644 index 0000000..416e5a1 --- /dev/null +++ b/sources/wp-includes/ID3/license.commercial.txt @@ -0,0 +1,27 @@ + getID3() Commercial License + =========================== + +getID3() is licensed under the "GNU Public License" (GPL) and/or the +"getID3() Commercial License" (gCL). This document describes the gCL. + +--------------------------------------------------------------------- + +The license is non-exclusively granted to a single person or company, +per payment of the license fee, for the lifetime of that person or +company. The license is non-transferrable. + +The gCL grants the licensee the right to use getID3() in commercial +closed-source projects. Modifications may be made to getID3() with no +obligation to release the modified source code. getID3() (or pieces +thereof) may be included in any number of projects authored (in whole +or in part) by the licensee. + +The licensee may use any version of getID3(), past, present or future, +as is most convenient. This license does not entitle the licensee to +receive any technical support, updates or bugfixes, except as such are +made publicly available to all getID3() users. + +The licensee may not sub-license getID3() itself, meaning that any +commercially released product containing all or parts of getID3() must +have added functionality beyond what is available in getID3(); +getID3() itself may not be re-licensed by the licensee. diff --git a/sources/wp-includes/ID3/license.txt b/sources/wp-includes/ID3/license.txt new file mode 100644 index 0000000..85f4356 --- /dev/null +++ b/sources/wp-includes/ID3/license.txt @@ -0,0 +1,28 @@ +///////////////////////////////////////////////////////////////// +/// getID3() by James Heinrich // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// + +***************************************************************** +***************************************************************** + + getID3() is released under multiple licenses. You may choose + from the following licenses, and use getID3 according to the + terms of the license most suitable to your project. + +GNU GPL: https://gnu.org/licenses/gpl.html (v3) + https://gnu.org/licenses/old-licenses/gpl-2.0.html (v2) + https://gnu.org/licenses/old-licenses/gpl-1.0.html (v1) + +GNU LGPL: https://gnu.org/licenses/lgpl.html (v3) + +Mozilla MPL: http://www.mozilla.org/MPL/2.0/ (v2) + +getID3 Commercial License: http://getid3.org/#gCL (payment required) + +***************************************************************** +***************************************************************** + +Copies of each of the above licenses are included in the 'licenses' +directory of the getID3 distribution. diff --git a/sources/wp-includes/ID3/module.audio-video.asf.php b/sources/wp-includes/ID3/module.audio-video.asf.php new file mode 100644 index 0000000..cfc60a7 --- /dev/null +++ b/sources/wp-includes/ID3/module.audio-video.asf.php @@ -0,0 +1,2019 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.asf.php // +// module for analyzing ASF, WMA and WMV files // +// dependencies: module.audio-video.riff.php // +// /// +///////////////////////////////////////////////////////////////// + +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); + +class getid3_asf extends getid3_handler +{ + + public function __construct(getID3 $getid3) { + parent::__construct($getid3); // extends getid3_handler::__construct() + + // initialize all GUID constants + $GUIDarray = $this->KnownGUIDs(); + foreach ($GUIDarray as $GUIDname => $hexstringvalue) { + if (!defined($GUIDname)) { + define($GUIDname, $this->GUIDtoBytestring($hexstringvalue)); + } + } + } + + public function Analyze() { + $info = &$this->getid3->info; + + // Shortcuts + $thisfile_audio = &$info['audio']; + $thisfile_video = &$info['video']; + $info['asf'] = array(); + $thisfile_asf = &$info['asf']; + $thisfile_asf['comments'] = array(); + $thisfile_asf_comments = &$thisfile_asf['comments']; + $thisfile_asf['header_object'] = array(); + $thisfile_asf_headerobject = &$thisfile_asf['header_object']; + + + // ASF structure: + // * Header Object [required] + // * File Properties Object [required] (global file attributes) + // * Stream Properties Object [required] (defines media stream & characteristics) + // * Header Extension Object [required] (additional functionality) + // * Content Description Object (bibliographic information) + // * Script Command Object (commands for during playback) + // * Marker Object (named jumped points within the file) + // * Data Object [required] + // * Data Packets + // * Index Object + + // Header Object: (mandatory, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for header object - GETID3_ASF_Header_Object + // Object Size QWORD 64 // size of header object, including 30 bytes of Header Object header + // Number of Header Objects DWORD 32 // number of objects in header object + // Reserved1 BYTE 8 // hardcoded: 0x01 + // Reserved2 BYTE 8 // hardcoded: 0x02 + + $info['fileformat'] = 'asf'; + + fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + $HeaderObjectData = fread($this->getid3->fp, 30); + + $thisfile_asf_headerobject['objectid'] = substr($HeaderObjectData, 0, 16); + $thisfile_asf_headerobject['objectid_guid'] = $this->BytestringToGUID($thisfile_asf_headerobject['objectid']); + if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) { + $info['warning'][] = 'ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}'; + unset($info['fileformat']); + unset($info['asf']); + return false; + break; + } + $thisfile_asf_headerobject['objectsize'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 16, 8)); + $thisfile_asf_headerobject['headerobjects'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 24, 4)); + $thisfile_asf_headerobject['reserved1'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 28, 1)); + $thisfile_asf_headerobject['reserved2'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 29, 1)); + + $NextObjectOffset = ftell($this->getid3->fp); + $ASFHeaderData = fread($this->getid3->fp, $thisfile_asf_headerobject['objectsize'] - 30); + $offset = 0; + + for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { + $NextObjectGUID = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID); + $NextObjectSize = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + switch ($NextObjectGUID) { + + case GETID3_ASF_File_Properties_Object: + // File Properties Object: (mandatory, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for file properties object - GETID3_ASF_File_Properties_Object + // Object Size QWORD 64 // size of file properties object, including 104 bytes of File Properties Object header + // File ID GUID 128 // unique ID - identical to File ID in Data Object + // File Size QWORD 64 // entire file in bytes. Invalid if Broadcast Flag == 1 + // Creation Date QWORD 64 // date & time of file creation. Maybe invalid if Broadcast Flag == 1 + // Data Packets Count QWORD 64 // number of data packets in Data Object. Invalid if Broadcast Flag == 1 + // Play Duration QWORD 64 // playtime, in 100-nanosecond units. Invalid if Broadcast Flag == 1 + // Send Duration QWORD 64 // time needed to send file, in 100-nanosecond units. Players can ignore this value. Invalid if Broadcast Flag == 1 + // Preroll QWORD 64 // time to buffer data before starting to play file, in 1-millisecond units. If <> 0, PlayDuration and PresentationTime have been offset by this amount + // Flags DWORD 32 // + // * Broadcast Flag bits 1 (0x01) // file is currently being written, some header values are invalid + // * Seekable Flag bits 1 (0x02) // is file seekable + // * Reserved bits 30 (0xFFFFFFFC) // reserved - set to zero + // Minimum Data Packet Size DWORD 32 // in bytes. should be same as Maximum Data Packet Size. Invalid if Broadcast Flag == 1 + // Maximum Data Packet Size DWORD 32 // in bytes. should be same as Minimum Data Packet Size. Invalid if Broadcast Flag == 1 + // Maximum Bitrate DWORD 32 // maximum instantaneous bitrate in bits per second for entire file, including all data streams and ASF overhead + + // shortcut + $thisfile_asf['file_properties_object'] = array(); + $thisfile_asf_filepropertiesobject = &$thisfile_asf['file_properties_object']; + + $thisfile_asf_filepropertiesobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_filepropertiesobject['objectid'] = $NextObjectGUID; + $thisfile_asf_filepropertiesobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_filepropertiesobject['objectsize'] = $NextObjectSize; + $thisfile_asf_filepropertiesobject['fileid'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $thisfile_asf_filepropertiesobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_filepropertiesobject['fileid']); + $thisfile_asf_filepropertiesobject['filesize'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_filepropertiesobject['creation_date'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $thisfile_asf_filepropertiesobject['creation_date_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_filepropertiesobject['creation_date']); + $offset += 8; + $thisfile_asf_filepropertiesobject['data_packets'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_filepropertiesobject['play_duration'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_filepropertiesobject['send_duration'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_filepropertiesobject['preroll'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_filepropertiesobject['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_filepropertiesobject['flags']['broadcast'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0001); + $thisfile_asf_filepropertiesobject['flags']['seekable'] = (bool) ($thisfile_asf_filepropertiesobject['flags_raw'] & 0x0002); + + $thisfile_asf_filepropertiesobject['min_packet_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_filepropertiesobject['max_packet_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_filepropertiesobject['max_bitrate'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + + if ($thisfile_asf_filepropertiesobject['flags']['broadcast']) { + + // broadcast flag is set, some values invalid + unset($thisfile_asf_filepropertiesobject['filesize']); + unset($thisfile_asf_filepropertiesobject['data_packets']); + unset($thisfile_asf_filepropertiesobject['play_duration']); + unset($thisfile_asf_filepropertiesobject['send_duration']); + unset($thisfile_asf_filepropertiesobject['min_packet_size']); + unset($thisfile_asf_filepropertiesobject['max_packet_size']); + + } else { + + // broadcast flag NOT set, perform calculations + $info['playtime_seconds'] = ($thisfile_asf_filepropertiesobject['play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject['preroll'] / 1000); + + //$info['bitrate'] = $thisfile_asf_filepropertiesobject['max_bitrate']; + $info['bitrate'] = ((isset($thisfile_asf_filepropertiesobject['filesize']) ? $thisfile_asf_filepropertiesobject['filesize'] : $info['filesize']) * 8) / $info['playtime_seconds']; + } + break; + + case GETID3_ASF_Stream_Properties_Object: + // Stream Properties Object: (mandatory, one per media stream) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for stream properties object - GETID3_ASF_Stream_Properties_Object + // Object Size QWORD 64 // size of stream properties object, including 78 bytes of Stream Properties Object header + // Stream Type GUID 128 // GETID3_ASF_Audio_Media, GETID3_ASF_Video_Media or GETID3_ASF_Command_Media + // Error Correction Type GUID 128 // GETID3_ASF_Audio_Spread for audio-only streams, GETID3_ASF_No_Error_Correction for other stream types + // Time Offset QWORD 64 // 100-nanosecond units. typically zero. added to all timestamps of samples in the stream + // Type-Specific Data Length DWORD 32 // number of bytes for Type-Specific Data field + // Error Correction Data Length DWORD 32 // number of bytes for Error Correction Data field + // Flags WORD 16 // + // * Stream Number bits 7 (0x007F) // number of this stream. 1 <= valid <= 127 + // * Reserved bits 8 (0x7F80) // reserved - set to zero + // * Encrypted Content Flag bits 1 (0x8000) // stream contents encrypted if set + // Reserved DWORD 32 // reserved - set to zero + // Type-Specific Data BYTESTREAM variable // type-specific format data, depending on value of Stream Type + // Error Correction Data BYTESTREAM variable // error-correction-specific format data, depending on value of Error Correct Type + + // There is one GETID3_ASF_Stream_Properties_Object for each stream (audio, video) but the + // stream number isn't known until halfway through decoding the structure, hence it + // it is decoded to a temporary variable and then stuck in the appropriate index later + + $StreamPropertiesObjectData['offset'] = $NextObjectOffset + $offset; + $StreamPropertiesObjectData['objectid'] = $NextObjectGUID; + $StreamPropertiesObjectData['objectid_guid'] = $NextObjectGUIDtext; + $StreamPropertiesObjectData['objectsize'] = $NextObjectSize; + $StreamPropertiesObjectData['stream_type'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $StreamPropertiesObjectData['stream_type_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['stream_type']); + $StreamPropertiesObjectData['error_correct_type'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $StreamPropertiesObjectData['error_correct_guid'] = $this->BytestringToGUID($StreamPropertiesObjectData['error_correct_type']); + $StreamPropertiesObjectData['time_offset'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $StreamPropertiesObjectData['type_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $StreamPropertiesObjectData['error_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $StreamPropertiesObjectData['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $StreamPropertiesObjectStreamNumber = $StreamPropertiesObjectData['flags_raw'] & 0x007F; + $StreamPropertiesObjectData['flags']['encrypted'] = (bool) ($StreamPropertiesObjectData['flags_raw'] & 0x8000); + + $offset += 4; // reserved - DWORD + $StreamPropertiesObjectData['type_specific_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['type_data_length']); + $offset += $StreamPropertiesObjectData['type_data_length']; + $StreamPropertiesObjectData['error_correct_data'] = substr($ASFHeaderData, $offset, $StreamPropertiesObjectData['error_data_length']); + $offset += $StreamPropertiesObjectData['error_data_length']; + + switch ($StreamPropertiesObjectData['stream_type']) { + + case GETID3_ASF_Audio_Media: + $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf'); + $thisfile_audio['bitrate_mode'] = (!empty($thisfile_audio['bitrate_mode']) ? $thisfile_audio['bitrate_mode'] : 'cbr'); + + $audiodata = getid3_riff::parseWAVEFORMATex(substr($StreamPropertiesObjectData['type_specific_data'], 0, 16)); + unset($audiodata['raw']); + $thisfile_audio = getid3_lib::array_merge_noclobber($audiodata, $thisfile_audio); + break; + + case GETID3_ASF_Video_Media: + $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf'); + $thisfile_video['bitrate_mode'] = (!empty($thisfile_video['bitrate_mode']) ? $thisfile_video['bitrate_mode'] : 'cbr'); + break; + + case GETID3_ASF_Command_Media: + default: + // do nothing + break; + + } + + $thisfile_asf['stream_properties_object'][$StreamPropertiesObjectStreamNumber] = $StreamPropertiesObjectData; + unset($StreamPropertiesObjectData); // clear for next stream, if any + break; + + case GETID3_ASF_Header_Extension_Object: + // Header Extension Object: (mandatory, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Header Extension object - GETID3_ASF_Header_Extension_Object + // Object Size QWORD 64 // size of Header Extension object, including 46 bytes of Header Extension Object header + // Reserved Field 1 GUID 128 // hardcoded: GETID3_ASF_Reserved_1 + // Reserved Field 2 WORD 16 // hardcoded: 0x00000006 + // Header Extension Data Size DWORD 32 // in bytes. valid: 0, or > 24. equals object size minus 46 + // Header Extension Data BYTESTREAM variable // array of zero or more extended header objects + + // shortcut + $thisfile_asf['header_extension_object'] = array(); + $thisfile_asf_headerextensionobject = &$thisfile_asf['header_extension_object']; + + $thisfile_asf_headerextensionobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_headerextensionobject['objectid'] = $NextObjectGUID; + $thisfile_asf_headerextensionobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_headerextensionobject['objectsize'] = $NextObjectSize; + $thisfile_asf_headerextensionobject['reserved_1'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']); + if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) { + $info['warning'][] = 'header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')'; + //return false; + break; + } + $thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) { + $info['warning'][] = 'header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"'; + //return false; + break; + } + $thisfile_asf_headerextensionobject['extension_data_size'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_headerextensionobject['extension_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']); + $unhandled_sections = 0; + $thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->ASF_HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections); + if ($unhandled_sections === 0) { + unset($thisfile_asf_headerextensionobject['extension_data']); + } + $offset += $thisfile_asf_headerextensionobject['extension_data_size']; + break; + + case GETID3_ASF_Codec_List_Object: + // Codec List Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Codec List object - GETID3_ASF_Codec_List_Object + // Object Size QWORD 64 // size of Codec List object, including 44 bytes of Codec List Object header + // Reserved GUID 128 // hardcoded: 86D15241-311D-11D0-A3A4-00A0C90348F6 + // Codec Entries Count DWORD 32 // number of entries in Codec Entries array + // Codec Entries array of: variable // + // * Type WORD 16 // 0x0001 = Video Codec, 0x0002 = Audio Codec, 0xFFFF = Unknown Codec + // * Codec Name Length WORD 16 // number of Unicode characters stored in the Codec Name field + // * Codec Name WCHAR variable // array of Unicode characters - name of codec used to create the content + // * Codec Description Length WORD 16 // number of Unicode characters stored in the Codec Description field + // * Codec Description WCHAR variable // array of Unicode characters - description of format used to create the content + // * Codec Information Length WORD 16 // number of Unicode characters stored in the Codec Information field + // * Codec Information BYTESTREAM variable // opaque array of information bytes about the codec used to create the content + + // shortcut + $thisfile_asf['codec_list_object'] = array(); + $thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object']; + + $thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_codeclistobject['objectid'] = $NextObjectGUID; + $thisfile_asf_codeclistobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_codeclistobject['objectsize'] = $NextObjectSize; + $thisfile_asf_codeclistobject['reserved'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']); + if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) { + $info['warning'][] = 'codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}'; + //return false; + break; + } + $thisfile_asf_codeclistobject['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) { + // shortcut + $thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter] = array(); + $thisfile_asf_codeclistobject_codecentries_current = &$thisfile_asf_codeclistobject['codec_entries'][$CodecEntryCounter]; + + $thisfile_asf_codeclistobject_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_codeclistobject_codecentries_current['type'] = $this->ASFCodecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']); + + $CodecNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character + $offset += 2; + $thisfile_asf_codeclistobject_codecentries_current['name'] = substr($ASFHeaderData, $offset, $CodecNameLength); + $offset += $CodecNameLength; + + $CodecDescriptionLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character + $offset += 2; + $thisfile_asf_codeclistobject_codecentries_current['description'] = substr($ASFHeaderData, $offset, $CodecDescriptionLength); + $offset += $CodecDescriptionLength; + + $CodecInformationLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_codeclistobject_codecentries_current['information'] = substr($ASFHeaderData, $offset, $CodecInformationLength); + $offset += $CodecInformationLength; + + if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec + + if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) { + $info['warning'][] = '[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-seperated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"'; + } else { + + list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description'])); + $thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']); + + if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) { + $thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000); + } + //if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) { + if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) { + //$thisfile_video['bitrate'] = $thisfile_asf['file_properties_object']['max_bitrate'] - $thisfile_audio['bitrate']; + $thisfile_video['bitrate'] = $info['bitrate'] - $thisfile_audio['bitrate']; + } + + $AudioCodecFrequency = (int) trim(str_replace('kHz', '', $AudioCodecFrequency)); + switch ($AudioCodecFrequency) { + case 8: + case 8000: + $thisfile_audio['sample_rate'] = 8000; + break; + + case 11: + case 11025: + $thisfile_audio['sample_rate'] = 11025; + break; + + case 12: + case 12000: + $thisfile_audio['sample_rate'] = 12000; + break; + + case 16: + case 16000: + $thisfile_audio['sample_rate'] = 16000; + break; + + case 22: + case 22050: + $thisfile_audio['sample_rate'] = 22050; + break; + + case 24: + case 24000: + $thisfile_audio['sample_rate'] = 24000; + break; + + case 32: + case 32000: + $thisfile_audio['sample_rate'] = 32000; + break; + + case 44: + case 441000: + $thisfile_audio['sample_rate'] = 44100; + break; + + case 48: + case 48000: + $thisfile_audio['sample_rate'] = 48000; + break; + + default: + $info['warning'][] = 'unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')'; + break; + } + + if (!isset($thisfile_audio['channels'])) { + if (strstr($AudioCodecChannels, 'stereo')) { + $thisfile_audio['channels'] = 2; + } elseif (strstr($AudioCodecChannels, 'mono')) { + $thisfile_audio['channels'] = 1; + } + } + + } + } + } + break; + + case GETID3_ASF_Script_Command_Object: + // Script Command Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Script Command object - GETID3_ASF_Script_Command_Object + // Object Size QWORD 64 // size of Script Command object, including 44 bytes of Script Command Object header + // Reserved GUID 128 // hardcoded: 4B1ACBE3-100B-11D0-A39B-00A0C90348F6 + // Commands Count WORD 16 // number of Commands structures in the Script Commands Objects + // Command Types Count WORD 16 // number of Command Types structures in the Script Commands Objects + // Command Types array of: variable // + // * Command Type Name Length WORD 16 // number of Unicode characters for Command Type Name + // * Command Type Name WCHAR variable // array of Unicode characters - name of a type of command + // Commands array of: variable // + // * Presentation Time DWORD 32 // presentation time of that command, in milliseconds + // * Type Index WORD 16 // type of this command, as a zero-based index into the array of Command Types of this object + // * Command Name Length WORD 16 // number of Unicode characters for Command Name + // * Command Name WCHAR variable // array of Unicode characters - name of this command + + // shortcut + $thisfile_asf['script_command_object'] = array(); + $thisfile_asf_scriptcommandobject = &$thisfile_asf['script_command_object']; + + $thisfile_asf_scriptcommandobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_scriptcommandobject['objectid'] = $NextObjectGUID; + $thisfile_asf_scriptcommandobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_scriptcommandobject['objectsize'] = $NextObjectSize; + $thisfile_asf_scriptcommandobject['reserved'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']); + if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) { + $info['warning'][] = 'script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}'; + //return false; + break; + } + $thisfile_asf_scriptcommandobject['commands_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_scriptcommandobject['command_types_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + for ($CommandTypesCounter = 0; $CommandTypesCounter < $thisfile_asf_scriptcommandobject['command_types_count']; $CommandTypesCounter++) { + $CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character + $offset += 2; + $thisfile_asf_scriptcommandobject['command_types'][$CommandTypesCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength); + $offset += $CommandTypeNameLength; + } + for ($CommandsCounter = 0; $CommandsCounter < $thisfile_asf_scriptcommandobject['commands_count']; $CommandsCounter++) { + $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['type_index'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + + $CommandTypeNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character + $offset += 2; + $thisfile_asf_scriptcommandobject['commands'][$CommandsCounter]['name'] = substr($ASFHeaderData, $offset, $CommandTypeNameLength); + $offset += $CommandTypeNameLength; + } + break; + + case GETID3_ASF_Marker_Object: + // Marker Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Marker object - GETID3_ASF_Marker_Object + // Object Size QWORD 64 // size of Marker object, including 48 bytes of Marker Object header + // Reserved GUID 128 // hardcoded: 4CFEDB20-75F6-11CF-9C0F-00A0C90349CB + // Markers Count DWORD 32 // number of Marker structures in Marker Object + // Reserved WORD 16 // hardcoded: 0x0000 + // Name Length WORD 16 // number of bytes in the Name field + // Name WCHAR variable // name of the Marker Object + // Markers array of: variable // + // * Offset QWORD 64 // byte offset into Data Object + // * Presentation Time QWORD 64 // in 100-nanosecond units + // * Entry Length WORD 16 // length in bytes of (Send Time + Flags + Marker Description Length + Marker Description + Padding) + // * Send Time DWORD 32 // in milliseconds + // * Flags DWORD 32 // hardcoded: 0x00000000 + // * Marker Description Length DWORD 32 // number of bytes in Marker Description field + // * Marker Description WCHAR variable // array of Unicode characters - description of marker entry + // * Padding BYTESTREAM variable // optional padding bytes + + // shortcut + $thisfile_asf['marker_object'] = array(); + $thisfile_asf_markerobject = &$thisfile_asf['marker_object']; + + $thisfile_asf_markerobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_markerobject['objectid'] = $NextObjectGUID; + $thisfile_asf_markerobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_markerobject['objectsize'] = $NextObjectSize; + $thisfile_asf_markerobject['reserved'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']); + if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) { + $info['warning'][] = 'marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}'; + break; + } + $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + if ($thisfile_asf_markerobject['reserved_2'] != 0) { + $info['warning'][] = 'marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"'; + break; + } + $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_markerobject['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['name_length']); + $offset += $thisfile_asf_markerobject['name_length']; + for ($MarkersCounter = 0; $MarkersCounter < $thisfile_asf_markerobject['markers_count']; $MarkersCounter++) { + $thisfile_asf_markerobject['markers'][$MarkersCounter]['offset'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_markerobject['markers'][$MarkersCounter]['presentation_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 8)); + $offset += 8; + $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_markerobject['markers'][$MarkersCounter]['send_time'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_markerobject['markers'][$MarkersCounter]['flags'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description'] = substr($ASFHeaderData, $offset, $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']); + $offset += $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']; + $PaddingLength = $thisfile_asf_markerobject['markers'][$MarkersCounter]['entry_length'] - 4 - 4 - 4 - $thisfile_asf_markerobject['markers'][$MarkersCounter]['marker_description_length']; + if ($PaddingLength > 0) { + $thisfile_asf_markerobject['markers'][$MarkersCounter]['padding'] = substr($ASFHeaderData, $offset, $PaddingLength); + $offset += $PaddingLength; + } + } + break; + + case GETID3_ASF_Bitrate_Mutual_Exclusion_Object: + // Bitrate Mutual Exclusion Object: (optional) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Bitrate Mutual Exclusion object - GETID3_ASF_Bitrate_Mutual_Exclusion_Object + // Object Size QWORD 64 // size of Bitrate Mutual Exclusion object, including 42 bytes of Bitrate Mutual Exclusion Object header + // Exlusion Type GUID 128 // nature of mutual exclusion relationship. one of: (GETID3_ASF_Mutex_Bitrate, GETID3_ASF_Mutex_Unknown) + // Stream Numbers Count WORD 16 // number of video streams + // Stream Numbers WORD variable // array of mutually exclusive video stream numbers. 1 <= valid <= 127 + + // shortcut + $thisfile_asf['bitrate_mutual_exclusion_object'] = array(); + $thisfile_asf_bitratemutualexclusionobject = &$thisfile_asf['bitrate_mutual_exclusion_object']; + + $thisfile_asf_bitratemutualexclusionobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_bitratemutualexclusionobject['objectid'] = $NextObjectGUID; + $thisfile_asf_bitratemutualexclusionobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_bitratemutualexclusionobject['objectsize'] = $NextObjectSize; + $thisfile_asf_bitratemutualexclusionobject['reserved'] = substr($ASFHeaderData, $offset, 16); + $thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']); + $offset += 16; + if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) { + $info['warning'][] = 'bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}'; + //return false; + break; + } + $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + for ($StreamNumberCounter = 0; $StreamNumberCounter < $thisfile_asf_bitratemutualexclusionobject['stream_numbers_count']; $StreamNumberCounter++) { + $thisfile_asf_bitratemutualexclusionobject['stream_numbers'][$StreamNumberCounter] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + } + break; + + case GETID3_ASF_Error_Correction_Object: + // Error Correction Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Error Correction object - GETID3_ASF_Error_Correction_Object + // Object Size QWORD 64 // size of Error Correction object, including 44 bytes of Error Correction Object header + // Error Correction Type GUID 128 // type of error correction. one of: (GETID3_ASF_No_Error_Correction, GETID3_ASF_Audio_Spread) + // Error Correction Data Length DWORD 32 // number of bytes in Error Correction Data field + // Error Correction Data BYTESTREAM variable // structure depends on value of Error Correction Type field + + // shortcut + $thisfile_asf['error_correction_object'] = array(); + $thisfile_asf_errorcorrectionobject = &$thisfile_asf['error_correction_object']; + + $thisfile_asf_errorcorrectionobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_errorcorrectionobject['objectid'] = $NextObjectGUID; + $thisfile_asf_errorcorrectionobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_errorcorrectionobject['objectsize'] = $NextObjectSize; + $thisfile_asf_errorcorrectionobject['error_correction_type'] = substr($ASFHeaderData, $offset, 16); + $offset += 16; + $thisfile_asf_errorcorrectionobject['error_correction_guid'] = $this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']); + $thisfile_asf_errorcorrectionobject['error_correction_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + switch ($thisfile_asf_errorcorrectionobject['error_correction_type']) { + case GETID3_ASF_No_Error_Correction: + // should be no data, but just in case there is, skip to the end of the field + $offset += $thisfile_asf_errorcorrectionobject['error_correction_data_length']; + break; + + case GETID3_ASF_Audio_Spread: + // Field Name Field Type Size (bits) + // Span BYTE 8 // number of packets over which audio will be spread. + // Virtual Packet Length WORD 16 // size of largest audio payload found in audio stream + // Virtual Chunk Length WORD 16 // size of largest audio payload found in audio stream + // Silence Data Length WORD 16 // number of bytes in Silence Data field + // Silence Data BYTESTREAM variable // hardcoded: 0x00 * (Silence Data Length) bytes + + $thisfile_asf_errorcorrectionobject['span'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 1)); + $offset += 1; + $thisfile_asf_errorcorrectionobject['virtual_packet_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_errorcorrectionobject['virtual_chunk_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_errorcorrectionobject['silence_data_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_errorcorrectionobject['silence_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_errorcorrectionobject['silence_data_length']); + $offset += $thisfile_asf_errorcorrectionobject['silence_data_length']; + break; + + default: + $info['warning'][] = 'error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}'; + //return false; + break; + } + + break; + + case GETID3_ASF_Content_Description_Object: + // Content Description Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Content Description object - GETID3_ASF_Content_Description_Object + // Object Size QWORD 64 // size of Content Description object, including 34 bytes of Content Description Object header + // Title Length WORD 16 // number of bytes in Title field + // Author Length WORD 16 // number of bytes in Author field + // Copyright Length WORD 16 // number of bytes in Copyright field + // Description Length WORD 16 // number of bytes in Description field + // Rating Length WORD 16 // number of bytes in Rating field + // Title WCHAR 16 // array of Unicode characters - Title + // Author WCHAR 16 // array of Unicode characters - Author + // Copyright WCHAR 16 // array of Unicode characters - Copyright + // Description WCHAR 16 // array of Unicode characters - Description + // Rating WCHAR 16 // array of Unicode characters - Rating + + // shortcut + $thisfile_asf['content_description_object'] = array(); + $thisfile_asf_contentdescriptionobject = &$thisfile_asf['content_description_object']; + + $thisfile_asf_contentdescriptionobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_contentdescriptionobject['objectid'] = $NextObjectGUID; + $thisfile_asf_contentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_contentdescriptionobject['objectsize'] = $NextObjectSize; + $thisfile_asf_contentdescriptionobject['title_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_contentdescriptionobject['author_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_contentdescriptionobject['copyright_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_contentdescriptionobject['description_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_contentdescriptionobject['rating_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_contentdescriptionobject['title'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['title_length']); + $offset += $thisfile_asf_contentdescriptionobject['title_length']; + $thisfile_asf_contentdescriptionobject['author'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['author_length']); + $offset += $thisfile_asf_contentdescriptionobject['author_length']; + $thisfile_asf_contentdescriptionobject['copyright'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['copyright_length']); + $offset += $thisfile_asf_contentdescriptionobject['copyright_length']; + $thisfile_asf_contentdescriptionobject['description'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['description_length']); + $offset += $thisfile_asf_contentdescriptionobject['description_length']; + $thisfile_asf_contentdescriptionobject['rating'] = substr($ASFHeaderData, $offset, $thisfile_asf_contentdescriptionobject['rating_length']); + $offset += $thisfile_asf_contentdescriptionobject['rating_length']; + + $ASFcommentKeysToCopy = array('title'=>'title', 'author'=>'artist', 'copyright'=>'copyright', 'description'=>'comment', 'rating'=>'rating'); + foreach ($ASFcommentKeysToCopy as $keytocopyfrom => $keytocopyto) { + if (!empty($thisfile_asf_contentdescriptionobject[$keytocopyfrom])) { + $thisfile_asf_comments[$keytocopyto][] = $this->TrimTerm($thisfile_asf_contentdescriptionobject[$keytocopyfrom]); + } + } + break; + + case GETID3_ASF_Extended_Content_Description_Object: + // Extended Content Description Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Extended Content Description object - GETID3_ASF_Extended_Content_Description_Object + // Object Size QWORD 64 // size of ExtendedContent Description object, including 26 bytes of Extended Content Description Object header + // Content Descriptors Count WORD 16 // number of entries in Content Descriptors list + // Content Descriptors array of: variable // + // * Descriptor Name Length WORD 16 // size in bytes of Descriptor Name field + // * Descriptor Name WCHAR variable // array of Unicode characters - Descriptor Name + // * Descriptor Value Data Type WORD 16 // Lookup array: + // 0x0000 = Unicode String (variable length) + // 0x0001 = BYTE array (variable length) + // 0x0002 = BOOL (DWORD, 32 bits) + // 0x0003 = DWORD (DWORD, 32 bits) + // 0x0004 = QWORD (QWORD, 64 bits) + // 0x0005 = WORD (WORD, 16 bits) + // * Descriptor Value Length WORD 16 // number of bytes stored in Descriptor Value field + // * Descriptor Value variable variable // value for Content Descriptor + + // shortcut + $thisfile_asf['extended_content_description_object'] = array(); + $thisfile_asf_extendedcontentdescriptionobject = &$thisfile_asf['extended_content_description_object']; + + $thisfile_asf_extendedcontentdescriptionobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_extendedcontentdescriptionobject['objectid'] = $NextObjectGUID; + $thisfile_asf_extendedcontentdescriptionobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_extendedcontentdescriptionobject['objectsize'] = $NextObjectSize; + $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + for ($ExtendedContentDescriptorsCounter = 0; $ExtendedContentDescriptorsCounter < $thisfile_asf_extendedcontentdescriptionobject['content_descriptors_count']; $ExtendedContentDescriptorsCounter++) { + // shortcut + $thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter] = array(); + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current = &$thisfile_asf_extendedcontentdescriptionobject['content_descriptors'][$ExtendedContentDescriptorsCounter]; + + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['base_offset'] = $offset + 30; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'] = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']); + $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name_length']; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = substr($ASFHeaderData, $offset, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']); + $offset += $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length']; + switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) { + case 0x0000: // Unicode string + break; + + case 0x0001: // BYTE array + // do nothing + break; + + case 0x0002: // BOOL + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = (bool) getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + break; + + case 0x0003: // DWORD + case 0x0004: // QWORD + case 0x0005: // WORD + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = getid3_lib::LittleEndian2Int($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + break; + + default: + $info['warning'][] = 'extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')'; + //return false; + break; + } + switch ($this->TrimConvert(strtolower($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']))) { + + case 'wm/albumartist': + case 'artist': + // Note: not 'artist', that comes from 'author' tag + $thisfile_asf_comments['albumartist'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + + case 'wm/albumtitle': + case 'album': + $thisfile_asf_comments['album'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + + case 'wm/genre': + case 'genre': + $thisfile_asf_comments['genre'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + + case 'wm/partofset': + $thisfile_asf_comments['partofset'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + + case 'wm/tracknumber': + case 'tracknumber': + // be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character) + $thisfile_asf_comments['track'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + foreach ($thisfile_asf_comments['track'] as $key => $value) { + if (preg_match('/^[0-9\x00]+$/', $value)) { + $thisfile_asf_comments['track'][$key] = intval(str_replace("\x00", '', $value)); + } + } + break; + + case 'wm/track': + if (empty($thisfile_asf_comments['track'])) { + $thisfile_asf_comments['track'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + } + break; + + case 'wm/year': + case 'year': + case 'date': + $thisfile_asf_comments['year'] = array( $this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + + case 'wm/lyrics': + case 'lyrics': + $thisfile_asf_comments['lyrics'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + break; + + case 'isvbr': + if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']) { + $thisfile_audio['bitrate_mode'] = 'vbr'; + $thisfile_video['bitrate_mode'] = 'vbr'; + } + break; + + case 'id3': + // id3v2 module might not be loaded + if (class_exists('getid3_id3v2')) { + $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3'); + $tempfilehandle = fopen($tempfile, 'wb'); + $tempThisfileInfo = array('encoding'=>$info['encoding']); + fwrite($tempfilehandle, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + fclose($tempfilehandle); + + $getid3_temp = new getID3(); + $getid3_temp->openfile($tempfile); + $getid3_id3v2 = new getid3_id3v2($getid3_temp); + $getid3_id3v2->Analyze(); + $info['id3v2'] = $getid3_temp->info['id3v2']; + unset($getid3_temp, $getid3_id3v2); + + unlink($tempfile); + } + break; + + case 'wm/encodingtime': + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix'] = $this->FILETIMEtoUNIXtime($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + $thisfile_asf_comments['encoding_time_unix'] = array($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['encoding_time_unix']); + break; + + case 'wm/picture': + $WMpicture = $this->ASF_WMpicture($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + foreach ($WMpicture as $key => $value) { + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current[$key] = $value; + } + unset($WMpicture); +/* + $wm_picture_offset = 0; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id'] = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 1)); + $wm_picture_offset += 1; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type'] = $this->WMpictureTypeLookup($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id']); + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 4)); + $wm_picture_offset += 4; + + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] = ''; + do { + $next_byte_pair = substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 2); + $wm_picture_offset += 2; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] .= $next_byte_pair; + } while ($next_byte_pair !== "\x00\x00"); + + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_description'] = ''; + do { + $next_byte_pair = substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 2); + $wm_picture_offset += 2; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_description'] .= $next_byte_pair; + } while ($next_byte_pair !== "\x00\x00"); + + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['dataoffset'] = $wm_picture_offset; + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['data'] = substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset); + unset($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + + $imageinfo = array(); + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] = ''; + $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['data'], $imageinfo); + unset($imageinfo); + if (!empty($imagechunkcheck)) { + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]); + } + if (!isset($thisfile_asf_comments['picture'])) { + $thisfile_asf_comments['picture'] = array(); + } + $thisfile_asf_comments['picture'][] = array('data'=>$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['data'], 'image_mime'=>$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_mime']); +*/ + break; + + default: + switch ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type']) { + case 0: // Unicode string + if (substr($this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name']), 0, 3) == 'WM/') { + $thisfile_asf_comments[str_replace('wm/', '', strtolower($this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['name'])))] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); + } + break; + + case 1: + break; + } + break; + } + + } + break; + + case GETID3_ASF_Stream_Bitrate_Properties_Object: + // Stream Bitrate Properties Object: (optional, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Stream Bitrate Properties object - GETID3_ASF_Stream_Bitrate_Properties_Object + // Object Size QWORD 64 // size of Extended Content Description object, including 26 bytes of Stream Bitrate Properties Object header + // Bitrate Records Count WORD 16 // number of records in Bitrate Records + // Bitrate Records array of: variable // + // * Flags WORD 16 // + // * * Stream Number bits 7 (0x007F) // number of this stream + // * * Reserved bits 9 (0xFF80) // hardcoded: 0 + // * Average Bitrate DWORD 32 // in bits per second + + // shortcut + $thisfile_asf['stream_bitrate_properties_object'] = array(); + $thisfile_asf_streambitratepropertiesobject = &$thisfile_asf['stream_bitrate_properties_object']; + + $thisfile_asf_streambitratepropertiesobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_streambitratepropertiesobject['objectid'] = $NextObjectGUID; + $thisfile_asf_streambitratepropertiesobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_streambitratepropertiesobject['objectsize'] = $NextObjectSize; + $thisfile_asf_streambitratepropertiesobject['bitrate_records_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) { + $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); + $offset += 2; + $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags']['stream_number'] = $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['flags_raw'] & 0x007F; + $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); + $offset += 4; + } + break; + + case GETID3_ASF_Padding_Object: + // Padding Object: (optional) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Padding object - GETID3_ASF_Padding_Object + // Object Size QWORD 64 // size of Padding object, including 24 bytes of ASF Padding Object header + // Padding Data BYTESTREAM variable // ignore + + // shortcut + $thisfile_asf['padding_object'] = array(); + $thisfile_asf_paddingobject = &$thisfile_asf['padding_object']; + + $thisfile_asf_paddingobject['offset'] = $NextObjectOffset + $offset; + $thisfile_asf_paddingobject['objectid'] = $NextObjectGUID; + $thisfile_asf_paddingobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_paddingobject['objectsize'] = $NextObjectSize; + $thisfile_asf_paddingobject['padding_length'] = $thisfile_asf_paddingobject['objectsize'] - 16 - 8; + $thisfile_asf_paddingobject['padding'] = substr($ASFHeaderData, $offset, $thisfile_asf_paddingobject['padding_length']); + $offset += ($NextObjectSize - 16 - 8); + break; + + case GETID3_ASF_Extended_Content_Encryption_Object: + case GETID3_ASF_Content_Encryption_Object: + // WMA DRM - just ignore + $offset += ($NextObjectSize - 16 - 8); + break; + + default: + // Implementations shall ignore any standard or non-standard object that they do not know how to handle. + if ($this->GUIDname($NextObjectGUIDtext)) { + $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8); + } else { + $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8); + } + $offset += ($NextObjectSize - 16 - 8); + break; + } + } + if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) { + $ASFbitrateAudio = 0; + $ASFbitrateVideo = 0; + for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count']; $BitrateRecordsCounter++) { + if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) { + switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) { + case 1: + $ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate']; + break; + + case 2: + $ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate']; + break; + + default: + // do nothing + break; + } + } + } + if ($ASFbitrateAudio > 0) { + $thisfile_audio['bitrate'] = $ASFbitrateAudio; + } + if ($ASFbitrateVideo > 0) { + $thisfile_video['bitrate'] = $ASFbitrateVideo; + } + } + if (isset($thisfile_asf['stream_properties_object']) && is_array($thisfile_asf['stream_properties_object'])) { + + $thisfile_audio['bitrate'] = 0; + $thisfile_video['bitrate'] = 0; + + foreach ($thisfile_asf['stream_properties_object'] as $streamnumber => $streamdata) { + + switch ($streamdata['stream_type']) { + case GETID3_ASF_Audio_Media: + // Field Name Field Type Size (bits) + // Codec ID / Format Tag WORD 16 // unique ID of audio codec - defined as wFormatTag field of WAVEFORMATEX structure + // Number of Channels WORD 16 // number of channels of audio - defined as nChannels field of WAVEFORMATEX structure + // Samples Per Second DWORD 32 // in Hertz - defined as nSamplesPerSec field of WAVEFORMATEX structure + // Average number of Bytes/sec DWORD 32 // bytes/sec of audio stream - defined as nAvgBytesPerSec field of WAVEFORMATEX structure + // Block Alignment WORD 16 // block size in bytes of audio codec - defined as nBlockAlign field of WAVEFORMATEX structure + // Bits per sample WORD 16 // bits per sample of mono data. set to zero for variable bitrate codecs. defined as wBitsPerSample field of WAVEFORMATEX structure + // Codec Specific Data Size WORD 16 // size in bytes of Codec Specific Data buffer - defined as cbSize field of WAVEFORMATEX structure + // Codec Specific Data BYTESTREAM variable // array of codec-specific data bytes + + // shortcut + $thisfile_asf['audio_media'][$streamnumber] = array(); + $thisfile_asf_audiomedia_currentstream = &$thisfile_asf['audio_media'][$streamnumber]; + + $audiomediaoffset = 0; + + $thisfile_asf_audiomedia_currentstream = getid3_riff::parseWAVEFORMATex(substr($streamdata['type_specific_data'], $audiomediaoffset, 16)); + $audiomediaoffset += 16; + + $thisfile_audio['lossless'] = false; + switch ($thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']) { + case 0x0001: // PCM + case 0x0163: // WMA9 Lossless + $thisfile_audio['lossless'] = true; + break; + } + + if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { + foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) { + if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) { + $thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate']; + $thisfile_audio['bitrate'] += $dataarray['bitrate']; + break; + } + } + } else { + if (!empty($thisfile_asf_audiomedia_currentstream['bytes_sec'])) { + $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bytes_sec'] * 8; + } elseif (!empty($thisfile_asf_audiomedia_currentstream['bitrate'])) { + $thisfile_audio['bitrate'] += $thisfile_asf_audiomedia_currentstream['bitrate']; + } + } + $thisfile_audio['streams'][$streamnumber] = $thisfile_asf_audiomedia_currentstream; + $thisfile_audio['streams'][$streamnumber]['wformattag'] = $thisfile_asf_audiomedia_currentstream['raw']['wFormatTag']; + $thisfile_audio['streams'][$streamnumber]['lossless'] = $thisfile_audio['lossless']; + $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate']; + $thisfile_audio['streams'][$streamnumber]['dataformat'] = 'wma'; + unset($thisfile_audio['streams'][$streamnumber]['raw']); + + $thisfile_asf_audiomedia_currentstream['codec_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $audiomediaoffset, 2)); + $audiomediaoffset += 2; + $thisfile_asf_audiomedia_currentstream['codec_data'] = substr($streamdata['type_specific_data'], $audiomediaoffset, $thisfile_asf_audiomedia_currentstream['codec_data_size']); + $audiomediaoffset += $thisfile_asf_audiomedia_currentstream['codec_data_size']; + + break; + + case GETID3_ASF_Video_Media: + // Field Name Field Type Size (bits) + // Encoded Image Width DWORD 32 // width of image in pixels + // Encoded Image Height DWORD 32 // height of image in pixels + // Reserved Flags BYTE 8 // hardcoded: 0x02 + // Format Data Size WORD 16 // size of Format Data field in bytes + // Format Data array of: variable // + // * Format Data Size DWORD 32 // number of bytes in Format Data field, in bytes - defined as biSize field of BITMAPINFOHEADER structure + // * Image Width LONG 32 // width of encoded image in pixels - defined as biWidth field of BITMAPINFOHEADER structure + // * Image Height LONG 32 // height of encoded image in pixels - defined as biHeight field of BITMAPINFOHEADER structure + // * Reserved WORD 16 // hardcoded: 0x0001 - defined as biPlanes field of BITMAPINFOHEADER structure + // * Bits Per Pixel Count WORD 16 // bits per pixel - defined as biBitCount field of BITMAPINFOHEADER structure + // * Compression ID FOURCC 32 // fourcc of video codec - defined as biCompression field of BITMAPINFOHEADER structure + // * Image Size DWORD 32 // image size in bytes - defined as biSizeImage field of BITMAPINFOHEADER structure + // * Horizontal Pixels / Meter DWORD 32 // horizontal resolution of target device in pixels per meter - defined as biXPelsPerMeter field of BITMAPINFOHEADER structure + // * Vertical Pixels / Meter DWORD 32 // vertical resolution of target device in pixels per meter - defined as biYPelsPerMeter field of BITMAPINFOHEADER structure + // * Colors Used Count DWORD 32 // number of color indexes in the color table that are actually used - defined as biClrUsed field of BITMAPINFOHEADER structure + // * Important Colors Count DWORD 32 // number of color index required for displaying bitmap. if zero, all colors are required. defined as biClrImportant field of BITMAPINFOHEADER structure + // * Codec Specific Data BYTESTREAM variable // array of codec-specific data bytes + + // shortcut + $thisfile_asf['video_media'][$streamnumber] = array(); + $thisfile_asf_videomedia_currentstream = &$thisfile_asf['video_media'][$streamnumber]; + + $videomediaoffset = 0; + $thisfile_asf_videomedia_currentstream['image_width'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['image_height'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['flags'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 1)); + $videomediaoffset += 1; + $thisfile_asf_videomedia_currentstream['format_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2)); + $videomediaoffset += 2; + $thisfile_asf_videomedia_currentstream['format_data']['format_data_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['image_width'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['image_height'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['reserved'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2)); + $videomediaoffset += 2; + $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 2)); + $videomediaoffset += 2; + $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc'] = substr($streamdata['type_specific_data'], $videomediaoffset, 4); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['image_size'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['horizontal_pels'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['vertical_pels'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['colors_used'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['colors_important'] = getid3_lib::LittleEndian2Int(substr($streamdata['type_specific_data'], $videomediaoffset, 4)); + $videomediaoffset += 4; + $thisfile_asf_videomedia_currentstream['format_data']['codec_data'] = substr($streamdata['type_specific_data'], $videomediaoffset); + + if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { + foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) { + if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) { + $thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate']; + $thisfile_video['streams'][$streamnumber]['bitrate'] = $dataarray['bitrate']; + $thisfile_video['bitrate'] += $dataarray['bitrate']; + break; + } + } + } + + $thisfile_asf_videomedia_currentstream['format_data']['codec'] = getid3_riff::fourccLookup($thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc']); + + $thisfile_video['streams'][$streamnumber]['fourcc'] = $thisfile_asf_videomedia_currentstream['format_data']['codec_fourcc']; + $thisfile_video['streams'][$streamnumber]['codec'] = $thisfile_asf_videomedia_currentstream['format_data']['codec']; + $thisfile_video['streams'][$streamnumber]['resolution_x'] = $thisfile_asf_videomedia_currentstream['image_width']; + $thisfile_video['streams'][$streamnumber]['resolution_y'] = $thisfile_asf_videomedia_currentstream['image_height']; + $thisfile_video['streams'][$streamnumber]['bits_per_sample'] = $thisfile_asf_videomedia_currentstream['format_data']['bits_per_pixel']; + break; + + default: + break; + } + } + } + + while (ftell($this->getid3->fp) < $info['avdataend']) { + $NextObjectDataHeader = fread($this->getid3->fp, 24); + $offset = 0; + $NextObjectGUID = substr($NextObjectDataHeader, 0, 16); + $offset += 16; + $NextObjectGUIDtext = $this->BytestringToGUID($NextObjectGUID); + $NextObjectSize = getid3_lib::LittleEndian2Int(substr($NextObjectDataHeader, $offset, 8)); + $offset += 8; + + switch ($NextObjectGUID) { + case GETID3_ASF_Data_Object: + // Data Object: (mandatory, one only) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Data object - GETID3_ASF_Data_Object + // Object Size QWORD 64 // size of Data object, including 50 bytes of Data Object header. may be 0 if FilePropertiesObject.BroadcastFlag == 1 + // File ID GUID 128 // unique identifier. identical to File ID field in Header Object + // Total Data Packets QWORD 64 // number of Data Packet entries in Data Object. invalid if FilePropertiesObject.BroadcastFlag == 1 + // Reserved WORD 16 // hardcoded: 0x0101 + + // shortcut + $thisfile_asf['data_object'] = array(); + $thisfile_asf_dataobject = &$thisfile_asf['data_object']; + + $DataObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 50 - 24); + $offset = 24; + + $thisfile_asf_dataobject['objectid'] = $NextObjectGUID; + $thisfile_asf_dataobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_dataobject['objectsize'] = $NextObjectSize; + + $thisfile_asf_dataobject['fileid'] = substr($DataObjectData, $offset, 16); + $offset += 16; + $thisfile_asf_dataobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_dataobject['fileid']); + $thisfile_asf_dataobject['total_data_packets'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 8)); + $offset += 8; + $thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2)); + $offset += 2; + if ($thisfile_asf_dataobject['reserved'] != 0x0101) { + $info['warning'][] = 'data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"'; + //return false; + break; + } + + // Data Packets array of: variable // + // * Error Correction Flags BYTE 8 // + // * * Error Correction Data Length bits 4 // if Error Correction Length Type == 00, size of Error Correction Data in bytes, else hardcoded: 0000 + // * * Opaque Data Present bits 1 // + // * * Error Correction Length Type bits 2 // number of bits for size of the error correction data. hardcoded: 00 + // * * Error Correction Present bits 1 // If set, use Opaque Data Packet structure, else use Payload structure + // * Error Correction Data + + $info['avdataoffset'] = ftell($this->getid3->fp); + fseek($this->getid3->fp, ($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data + $info['avdataend'] = ftell($this->getid3->fp); + break; + + case GETID3_ASF_Simple_Index_Object: + // Simple Index Object: (optional, recommended, one per video stream) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for Simple Index object - GETID3_ASF_Data_Object + // Object Size QWORD 64 // size of Simple Index object, including 56 bytes of Simple Index Object header + // File ID GUID 128 // unique identifier. may be zero or identical to File ID field in Data Object and Header Object + // Index Entry Time Interval QWORD 64 // interval between index entries in 100-nanosecond units + // Maximum Packet Count DWORD 32 // maximum packet count for all index entries + // Index Entries Count DWORD 32 // number of Index Entries structures + // Index Entries array of: variable // + // * Packet Number DWORD 32 // number of the Data Packet associated with this index entry + // * Packet Count WORD 16 // number of Data Packets to sent at this index entry + + // shortcut + $thisfile_asf['simple_index_object'] = array(); + $thisfile_asf_simpleindexobject = &$thisfile_asf['simple_index_object']; + + $SimpleIndexObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 56 - 24); + $offset = 24; + + $thisfile_asf_simpleindexobject['objectid'] = $NextObjectGUID; + $thisfile_asf_simpleindexobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_simpleindexobject['objectsize'] = $NextObjectSize; + + $thisfile_asf_simpleindexobject['fileid'] = substr($SimpleIndexObjectData, $offset, 16); + $offset += 16; + $thisfile_asf_simpleindexobject['fileid_guid'] = $this->BytestringToGUID($thisfile_asf_simpleindexobject['fileid']); + $thisfile_asf_simpleindexobject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 8)); + $offset += 8; + $thisfile_asf_simpleindexobject['maximum_packet_count'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4)); + $offset += 4; + $thisfile_asf_simpleindexobject['index_entries_count'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4)); + $offset += 4; + + $IndexEntriesData = $SimpleIndexObjectData.fread($this->getid3->fp, 6 * $thisfile_asf_simpleindexobject['index_entries_count']); + for ($IndexEntriesCounter = 0; $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count']; $IndexEntriesCounter++) { + $thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4)); + $offset += 4; + $thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_count'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4)); + $offset += 2; + } + + break; + + case GETID3_ASF_Index_Object: + // 6.2 ASF top-level Index Object (optional but recommended when appropriate, 0 or 1) + // Field Name Field Type Size (bits) + // Object ID GUID 128 // GUID for the Index Object - GETID3_ASF_Index_Object + // Object Size QWORD 64 // Specifies the size, in bytes, of the Index Object, including at least 34 bytes of Index Object header + // Index Entry Time Interval DWORD 32 // Specifies the time interval between each index entry in ms. + // Index Specifiers Count WORD 16 // Specifies the number of Index Specifiers structures in this Index Object. + // Index Blocks Count DWORD 32 // Specifies the number of Index Blocks structures in this Index Object. + + // Index Entry Time Interval DWORD 32 // Specifies the time interval between index entries in milliseconds. This value cannot be 0. + // Index Specifiers Count WORD 16 // Specifies the number of entries in the Index Specifiers list. Valid values are 1 and greater. + // Index Specifiers array of: varies // + // * Stream Number WORD 16 // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127. + // * Index Type WORD 16 // Specifies Index Type values as follows: + // 1 = Nearest Past Data Packet - indexes point to the data packet whose presentation time is closest to the index entry time. + // 2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire object or first fragment of an object. + // 3 = Nearest Past Cleanpoint. - indexes point to the closest data packet containing an entire object (or first fragment of an object) that has the Cleanpoint Flag set. + // Nearest Past Cleanpoint is the most common type of index. + // Index Entry Count DWORD 32 // Specifies the number of Index Entries in the block. + // * Block Positions QWORD varies // Specifies a list of byte offsets of the beginnings of the blocks relative to the beginning of the first Data Packet (i.e., the beginning of the Data Object + 50 bytes). The number of entries in this list is specified by the value of the Index Specifiers Count field. The order of those byte offsets is tied to the order in which Index Specifiers are listed. + // * Index Entries array of: varies // + // * * Offsets DWORD varies // An offset value of 0xffffffff indicates an invalid offset value + + // shortcut + $thisfile_asf['asf_index_object'] = array(); + $thisfile_asf_asfindexobject = &$thisfile_asf['asf_index_object']; + + $ASFIndexObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 34 - 24); + $offset = 24; + + $thisfile_asf_asfindexobject['objectid'] = $NextObjectGUID; + $thisfile_asf_asfindexobject['objectid_guid'] = $NextObjectGUIDtext; + $thisfile_asf_asfindexobject['objectsize'] = $NextObjectSize; + + $thisfile_asf_asfindexobject['entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); + $offset += 4; + $thisfile_asf_asfindexobject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); + $offset += 2; + $thisfile_asf_asfindexobject['index_blocks_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); + $offset += 4; + + $ASFIndexObjectData .= fread($this->getid3->fp, 4 * $thisfile_asf_asfindexobject['index_specifiers_count']); + for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { + $IndexSpecifierStreamNumber = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); + $offset += 2; + $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['stream_number'] = $IndexSpecifierStreamNumber; + $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); + $offset += 2; + $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type_text'] = $this->ASFIndexObjectIndexTypeLookup($thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type']); + } + + $ASFIndexObjectData .= fread($this->getid3->fp, 4); + $thisfile_asf_asfindexobject['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); + $offset += 4; + + $ASFIndexObjectData .= fread($this->getid3->fp, 8 * $thisfile_asf_asfindexobject['index_specifiers_count']); + for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { + $thisfile_asf_asfindexobject['block_positions'][$IndexSpecifiersCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 8)); + $offset += 8; + } + + $ASFIndexObjectData .= fread($this->getid3->fp, 4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']); + for ($IndexEntryCounter = 0; $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count']; $IndexEntryCounter++) { + for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { + $thisfile_asf_asfindexobject['offsets'][$IndexSpecifiersCounter][$IndexEntryCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); + $offset += 4; + } + } + break; + + + default: + // Implementations shall ignore any standard or non-standard object that they do not know how to handle. + if ($this->GUIDname($NextObjectGUIDtext)) { + $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8); + } else { + $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.(ftell($this->getid3->fp) - 16 - 8); + } + fseek($this->getid3->fp, ($NextObjectSize - 16 - 8), SEEK_CUR); + break; + } + } + + if (isset($thisfile_asf_codeclistobject['codec_entries']) && is_array($thisfile_asf_codeclistobject['codec_entries'])) { + foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) { + switch ($streamdata['information']) { + case 'WMV1': + case 'WMV2': + case 'WMV3': + case 'MSS1': + case 'MSS2': + case 'WMVA': + case 'WVC1': + case 'WMVP': + case 'WVP2': + $thisfile_video['dataformat'] = 'wmv'; + $info['mime_type'] = 'video/x-ms-wmv'; + break; + + case 'MP42': + case 'MP43': + case 'MP4S': + case 'mp4s': + $thisfile_video['dataformat'] = 'asf'; + $info['mime_type'] = 'video/x-ms-asf'; + break; + + default: + switch ($streamdata['type_raw']) { + case 1: + if (strstr($this->TrimConvert($streamdata['name']), 'Windows Media')) { + $thisfile_video['dataformat'] = 'wmv'; + if ($info['mime_type'] == 'video/x-ms-asf') { + $info['mime_type'] = 'video/x-ms-wmv'; + } + } + break; + + case 2: + if (strstr($this->TrimConvert($streamdata['name']), 'Windows Media')) { + $thisfile_audio['dataformat'] = 'wma'; + if ($info['mime_type'] == 'video/x-ms-asf') { + $info['mime_type'] = 'audio/x-ms-wma'; + } + } + break; + + } + break; + } + } + } + + switch (isset($thisfile_audio['codec']) ? $thisfile_audio['codec'] : '') { + case 'MPEG Layer-3': + $thisfile_audio['dataformat'] = 'mp3'; + break; + + default: + break; + } + + if (isset($thisfile_asf_codeclistobject['codec_entries'])) { + foreach ($thisfile_asf_codeclistobject['codec_entries'] as $streamnumber => $streamdata) { + switch ($streamdata['type_raw']) { + + case 1: // video + $thisfile_video['encoder'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][$streamnumber]['name']); + break; + + case 2: // audio + $thisfile_audio['encoder'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][$streamnumber]['name']); + + // AH 2003-10-01 + $thisfile_audio['encoder_options'] = $this->TrimConvert($thisfile_asf_codeclistobject['codec_entries'][0]['description']); + + $thisfile_audio['codec'] = $thisfile_audio['encoder']; + break; + + default: + $info['warning'][] = 'Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']; + break; + + } + } + } + + if (isset($info['audio'])) { + $thisfile_audio['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false); + $thisfile_audio['dataformat'] = (!empty($thisfile_audio['dataformat']) ? $thisfile_audio['dataformat'] : 'asf'); + } + if (!empty($thisfile_video['dataformat'])) { + $thisfile_video['lossless'] = (isset($thisfile_audio['lossless']) ? $thisfile_audio['lossless'] : false); + $thisfile_video['pixel_aspect_ratio'] = (isset($thisfile_audio['pixel_aspect_ratio']) ? $thisfile_audio['pixel_aspect_ratio'] : (float) 1); + $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf'); + } + if (!empty($thisfile_video['streams'])) { + $thisfile_video['streams']['resolution_x'] = 0; + $thisfile_video['streams']['resolution_y'] = 0; + foreach ($thisfile_video['streams'] as $key => $valuearray) { + if (($valuearray['resolution_x'] > $thisfile_video['streams']['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['streams']['resolution_y'])) { + $thisfile_video['resolution_x'] = $valuearray['resolution_x']; + $thisfile_video['resolution_y'] = $valuearray['resolution_y']; + } + } + } + $info['bitrate'] = (isset($thisfile_audio['bitrate']) ? $thisfile_audio['bitrate'] : 0) + (isset($thisfile_video['bitrate']) ? $thisfile_video['bitrate'] : 0); + + if ((!isset($info['playtime_seconds']) || ($info['playtime_seconds'] <= 0)) && ($info['bitrate'] > 0)) { + $info['playtime_seconds'] = ($info['filesize'] - $info['avdataoffset']) / ($info['bitrate'] / 8); + } + + return true; + } + + public static function ASFCodecListObjectTypeLookup($CodecListType) { + static $ASFCodecListObjectTypeLookup = array(); + if (empty($ASFCodecListObjectTypeLookup)) { + $ASFCodecListObjectTypeLookup[0x0001] = 'Video Codec'; + $ASFCodecListObjectTypeLookup[0x0002] = 'Audio Codec'; + $ASFCodecListObjectTypeLookup[0xFFFF] = 'Unknown Codec'; + } + + return (isset($ASFCodecListObjectTypeLookup[$CodecListType]) ? $ASFCodecListObjectTypeLookup[$CodecListType] : 'Invalid Codec Type'); + } + + public static function KnownGUIDs() { + static $GUIDarray = array( + 'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A', + 'GETID3_ASF_Padding_Object' => '1806D474-CADF-4509-A4BA-9AABCB96AAE8', + 'GETID3_ASF_Payload_Ext_Syst_Pixel_Aspect_Ratio' => '1B1EE554-F9EA-4BC8-821A-376B74E4C4B8', + 'GETID3_ASF_Script_Command_Object' => '1EFB1A30-0B62-11D0-A39B-00A0C90348F6', + 'GETID3_ASF_No_Error_Correction' => '20FB5700-5B55-11CF-A8FD-00805F5C442B', + 'GETID3_ASF_Content_Branding_Object' => '2211B3FA-BD23-11D2-B4B7-00A0C955FC6E', + 'GETID3_ASF_Content_Encryption_Object' => '2211B3FB-BD23-11D2-B4B7-00A0C955FC6E', + 'GETID3_ASF_Digital_Signature_Object' => '2211B3FC-BD23-11D2-B4B7-00A0C955FC6E', + 'GETID3_ASF_Extended_Content_Encryption_Object' => '298AE614-2622-4C17-B935-DAE07EE9289C', + 'GETID3_ASF_Simple_Index_Object' => '33000890-E5B1-11CF-89F4-00A0C90349CB', + 'GETID3_ASF_Degradable_JPEG_Media' => '35907DE0-E415-11CF-A917-00805F5C442B', + 'GETID3_ASF_Payload_Extension_System_Timecode' => '399595EC-8667-4E2D-8FDB-98814CE76C1E', + 'GETID3_ASF_Binary_Media' => '3AFB65E2-47EF-40F2-AC2C-70A90D71D343', + 'GETID3_ASF_Timecode_Index_Object' => '3CB73FD0-0C4A-4803-953D-EDF7B6228F0C', + 'GETID3_ASF_Metadata_Library_Object' => '44231C94-9498-49D1-A141-1D134E457054', + 'GETID3_ASF_Reserved_3' => '4B1ACBE3-100B-11D0-A39B-00A0C90348F6', + 'GETID3_ASF_Reserved_4' => '4CFEDB20-75F6-11CF-9C0F-00A0C90349CB', + 'GETID3_ASF_Command_Media' => '59DACFC0-59E6-11D0-A3AC-00A0C90348F6', + 'GETID3_ASF_Header_Extension_Object' => '5FBF03B5-A92E-11CF-8EE3-00C00C205365', + 'GETID3_ASF_Media_Object_Index_Parameters_Obj' => '6B203BAD-3F11-4E84-ACA8-D7613DE2CFA7', + 'GETID3_ASF_Header_Object' => '75B22630-668E-11CF-A6D9-00AA0062CE6C', + 'GETID3_ASF_Content_Description_Object' => '75B22633-668E-11CF-A6D9-00AA0062CE6C', + 'GETID3_ASF_Error_Correction_Object' => '75B22635-668E-11CF-A6D9-00AA0062CE6C', + 'GETID3_ASF_Data_Object' => '75B22636-668E-11CF-A6D9-00AA0062CE6C', + 'GETID3_ASF_Web_Stream_Media_Subtype' => '776257D4-C627-41CB-8F81-7AC7FF1C40CC', + 'GETID3_ASF_Stream_Bitrate_Properties_Object' => '7BF875CE-468D-11D1-8D82-006097C9A2B2', + 'GETID3_ASF_Language_List_Object' => '7C4346A9-EFE0-4BFC-B229-393EDE415C85', + 'GETID3_ASF_Codec_List_Object' => '86D15240-311D-11D0-A3A4-00A0C90348F6', + 'GETID3_ASF_Reserved_2' => '86D15241-311D-11D0-A3A4-00A0C90348F6', + 'GETID3_ASF_File_Properties_Object' => '8CABDCA1-A947-11CF-8EE4-00C00C205365', + 'GETID3_ASF_File_Transfer_Media' => '91BD222C-F21C-497A-8B6D-5AA86BFC0185', + 'GETID3_ASF_Old_RTP_Extension_Data' => '96800C63-4C94-11D1-837B-0080C7A37F95', + 'GETID3_ASF_Advanced_Mutual_Exclusion_Object' => 'A08649CF-4775-4670-8A16-6E35357566CD', + 'GETID3_ASF_Bandwidth_Sharing_Object' => 'A69609E6-517B-11D2-B6AF-00C04FD908E9', + 'GETID3_ASF_Reserved_1' => 'ABD3D211-A9BA-11cf-8EE6-00C00C205365', + 'GETID3_ASF_Bandwidth_Sharing_Exclusive' => 'AF6060AA-5197-11D2-B6AF-00C04FD908E9', + 'GETID3_ASF_Bandwidth_Sharing_Partial' => 'AF6060AB-5197-11D2-B6AF-00C04FD908E9', + 'GETID3_ASF_JFIF_Media' => 'B61BE100-5B4E-11CF-A8FD-00805F5C442B', + 'GETID3_ASF_Stream_Properties_Object' => 'B7DC0791-A9B7-11CF-8EE6-00C00C205365', + 'GETID3_ASF_Video_Media' => 'BC19EFC0-5B4D-11CF-A8FD-00805F5C442B', + 'GETID3_ASF_Audio_Spread' => 'BFC3CD50-618F-11CF-8BB2-00AA00B4E220', + 'GETID3_ASF_Metadata_Object' => 'C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA', + 'GETID3_ASF_Payload_Ext_Syst_Sample_Duration' => 'C6BD9450-867F-4907-83A3-C77921B733AD', + 'GETID3_ASF_Group_Mutual_Exclusion_Object' => 'D1465A40-5A79-4338-B71B-E36B8FD6C249', + 'GETID3_ASF_Extended_Content_Description_Object' => 'D2D0A440-E307-11D2-97F0-00A0C95EA850', + 'GETID3_ASF_Stream_Prioritization_Object' => 'D4FED15B-88D3-454F-81F0-ED5C45999E24', + 'GETID3_ASF_Payload_Ext_System_Content_Type' => 'D590DC20-07BC-436C-9CF7-F3BBFBF1A4DC', + 'GETID3_ASF_Old_File_Properties_Object' => 'D6E229D0-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_ASF_Header_Object' => 'D6E229D1-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_ASF_Data_Object' => 'D6E229D2-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Index_Object' => 'D6E229D3-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Stream_Properties_Object' => 'D6E229D4-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Content_Description_Object' => 'D6E229D5-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Script_Command_Object' => 'D6E229D6-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Marker_Object' => 'D6E229D7-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Component_Download_Object' => 'D6E229D8-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Stream_Group_Object' => 'D6E229D9-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Scalable_Object' => 'D6E229DA-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Prioritization_Object' => 'D6E229DB-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Bitrate_Mutual_Exclusion_Object' => 'D6E229DC-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Inter_Media_Dependency_Object' => 'D6E229DD-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Rating_Object' => 'D6E229DE-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Index_Parameters_Object' => 'D6E229DF-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Color_Table_Object' => 'D6E229E0-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Language_List_Object' => 'D6E229E1-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Audio_Media' => 'D6E229E2-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Video_Media' => 'D6E229E3-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Image_Media' => 'D6E229E4-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Timecode_Media' => 'D6E229E5-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Text_Media' => 'D6E229E6-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_MIDI_Media' => 'D6E229E7-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Command_Media' => 'D6E229E8-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_No_Error_Concealment' => 'D6E229EA-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Scrambled_Audio' => 'D6E229EB-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_No_Color_Table' => 'D6E229EC-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_SMPTE_Time' => 'D6E229ED-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_ASCII_Text' => 'D6E229EE-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Unicode_Text' => 'D6E229EF-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_HTML_Text' => 'D6E229F0-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_URL_Command' => 'D6E229F1-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Filename_Command' => 'D6E229F2-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_ACM_Codec' => 'D6E229F3-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_VCM_Codec' => 'D6E229F4-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_QuickTime_Codec' => 'D6E229F5-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_DirectShow_Transform_Filter' => 'D6E229F6-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_DirectShow_Rendering_Filter' => 'D6E229F7-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_No_Enhancement' => 'D6E229F8-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Unknown_Enhancement_Type' => 'D6E229F9-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Temporal_Enhancement' => 'D6E229FA-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Spatial_Enhancement' => 'D6E229FB-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Quality_Enhancement' => 'D6E229FC-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Number_of_Channels_Enhancement' => 'D6E229FD-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Frequency_Response_Enhancement' => 'D6E229FE-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Media_Object' => 'D6E229FF-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Mutex_Language' => 'D6E22A00-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Mutex_Bitrate' => 'D6E22A01-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Mutex_Unknown' => 'D6E22A02-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_ASF_Placeholder_Object' => 'D6E22A0E-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Old_Data_Unit_Extension_Object' => 'D6E22A0F-35DA-11D1-9034-00A0C90349BE', + 'GETID3_ASF_Web_Stream_Format' => 'DA1E6B13-8359-4050-B398-388E965BF00C', + 'GETID3_ASF_Payload_Ext_System_File_Name' => 'E165EC0E-19ED-45D7-B4A7-25CBD1E28E9B', + 'GETID3_ASF_Marker_Object' => 'F487CD01-A951-11CF-8EE6-00C00C205365', + 'GETID3_ASF_Timecode_Index_Parameters_Object' => 'F55E496D-9797-4B5D-8C8B-604DFE9BFB24', + 'GETID3_ASF_Audio_Media' => 'F8699E40-5B4D-11CF-A8FD-00805F5C442B', + 'GETID3_ASF_Media_Object_Index_Object' => 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C', + 'GETID3_ASF_Alt_Extended_Content_Encryption_Obj' => 'FF889EF1-ADEE-40DA-9E71-98704BB928CE', + 'GETID3_ASF_Index_Placeholder_Object' => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', // http://cpan.uwinnipeg.ca/htdocs/Audio-WMA/Audio/WMA.pm.html + 'GETID3_ASF_Compatibility_Object' => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', // http://cpan.uwinnipeg.ca/htdocs/Audio-WMA/Audio/WMA.pm.html + ); + return $GUIDarray; + } + + public static function GUIDname($GUIDstring) { + static $GUIDarray = array(); + if (empty($GUIDarray)) { + $GUIDarray = self::KnownGUIDs(); + } + return array_search($GUIDstring, $GUIDarray); + } + + public static function ASFIndexObjectIndexTypeLookup($id) { + static $ASFIndexObjectIndexTypeLookup = array(); + if (empty($ASFIndexObjectIndexTypeLookup)) { + $ASFIndexObjectIndexTypeLookup[1] = 'Nearest Past Data Packet'; + $ASFIndexObjectIndexTypeLookup[2] = 'Nearest Past Media Object'; + $ASFIndexObjectIndexTypeLookup[3] = 'Nearest Past Cleanpoint'; + } + return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid'); + } + + public static function GUIDtoBytestring($GUIDstring) { + // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way: + // first 4 bytes are in little-endian order + // next 2 bytes are appended in little-endian order + // next 2 bytes are appended in little-endian order + // next 2 bytes are appended in big-endian order + // next 6 bytes are appended in big-endian order + + // AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string: + // $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp + + $hexbytecharstring = chr(hexdec(substr($GUIDstring, 6, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 4, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 2, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 0, 2))); + + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 11, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 9, 2))); + + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 16, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 14, 2))); + + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 19, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 21, 2))); + + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 24, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 26, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 28, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 30, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 32, 2))); + $hexbytecharstring .= chr(hexdec(substr($GUIDstring, 34, 2))); + + return $hexbytecharstring; + } + + public static function BytestringToGUID($Bytestring) { + $GUIDstring = str_pad(dechex(ord($Bytestring{3})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{2})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{1})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{0})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= '-'; + $GUIDstring .= str_pad(dechex(ord($Bytestring{5})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{4})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= '-'; + $GUIDstring .= str_pad(dechex(ord($Bytestring{7})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{6})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= '-'; + $GUIDstring .= str_pad(dechex(ord($Bytestring{8})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{9})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= '-'; + $GUIDstring .= str_pad(dechex(ord($Bytestring{10})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{11})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{12})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{13})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{14})), 2, '0', STR_PAD_LEFT); + $GUIDstring .= str_pad(dechex(ord($Bytestring{15})), 2, '0', STR_PAD_LEFT); + + return strtoupper($GUIDstring); + } + + public static function FILETIMEtoUNIXtime($FILETIME, $round=true) { + // FILETIME is a 64-bit unsigned integer representing + // the number of 100-nanosecond intervals since January 1, 1601 + // UNIX timestamp is number of seconds since January 1, 1970 + // 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days + if ($round) { + return intval(round(($FILETIME - 116444736000000000) / 10000000)); + } + return ($FILETIME - 116444736000000000) / 10000000; + } + + public static function WMpictureTypeLookup($WMpictureType) { + static $WMpictureTypeLookup = array(); + if (empty($WMpictureTypeLookup)) { + $WMpictureTypeLookup[0x03] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Front Cover'); + $WMpictureTypeLookup[0x04] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Back Cover'); + $WMpictureTypeLookup[0x00] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'User Defined'); + $WMpictureTypeLookup[0x05] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Leaflet Page'); + $WMpictureTypeLookup[0x06] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Media Label'); + $WMpictureTypeLookup[0x07] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Lead Artist'); + $WMpictureTypeLookup[0x08] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Artist'); + $WMpictureTypeLookup[0x09] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Conductor'); + $WMpictureTypeLookup[0x0A] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Band'); + $WMpictureTypeLookup[0x0B] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Composer'); + $WMpictureTypeLookup[0x0C] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Lyricist'); + $WMpictureTypeLookup[0x0D] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Recording Location'); + $WMpictureTypeLookup[0x0E] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'During Recording'); + $WMpictureTypeLookup[0x0F] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'During Performance'); + $WMpictureTypeLookup[0x10] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Video Screen Capture'); + $WMpictureTypeLookup[0x12] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Illustration'); + $WMpictureTypeLookup[0x13] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Band Logotype'); + $WMpictureTypeLookup[0x14] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Publisher Logotype'); + } + return (isset($WMpictureTypeLookup[$WMpictureType]) ? $WMpictureTypeLookup[$WMpictureType] : ''); + } + + public function ASF_HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { + // http://msdn.microsoft.com/en-us/library/bb643323.aspx + + $offset = 0; + $objectOffset = 0; + $HeaderExtensionObjectParsed = array(); + while ($objectOffset < strlen($asf_header_extension_object_data)) { + $offset = $objectOffset; + $thisObject = array(); + + $thisObject['guid'] = substr($asf_header_extension_object_data, $offset, 16); + $offset += 16; + $thisObject['guid_text'] = $this->BytestringToGUID($thisObject['guid']); + $thisObject['guid_name'] = $this->GUIDname($thisObject['guid_text']); + + $thisObject['size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); + $offset += 8; + if ($thisObject['size'] <= 0) { + break; + } + + switch ($thisObject['guid']) { + case GETID3_ASF_Extended_Stream_Properties_Object: + $thisObject['start_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); + $offset += 8; + $thisObject['start_time_unix'] = $this->FILETIMEtoUNIXtime($thisObject['start_time']); + + $thisObject['end_time'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8)); + $offset += 8; + $thisObject['end_time_unix'] = $this->FILETIMEtoUNIXtime($thisObject['end_time']); + + $thisObject['data_bitrate'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['buffer_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['initial_buffer_fullness'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['alternate_data_bitrate'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['alternate_buffer_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['alternate_initial_buffer_fullness'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['maximum_object_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + $thisObject['flags']['reliable'] = (bool) $thisObject['flags_raw'] & 0x00000001; + $thisObject['flags']['seekable'] = (bool) $thisObject['flags_raw'] & 0x00000002; + $thisObject['flags']['no_cleanpoints'] = (bool) $thisObject['flags_raw'] & 0x00000004; + $thisObject['flags']['resend_live_cleanpoints'] = (bool) $thisObject['flags_raw'] & 0x00000008; + + $thisObject['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $thisObject['stream_language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $thisObject['average_time_per_frame'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $thisObject['stream_name_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $thisObject['payload_extension_system_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + for ($i = 0; $i < $thisObject['stream_name_count']; $i++) { + $streamName = array(); + + $streamName['language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $streamName['stream_name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $streamName['stream_name'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, $streamName['stream_name_length'])); + $offset += $streamName['stream_name_length']; + + $thisObject['stream_names'][$i] = $streamName; + } + + for ($i = 0; $i < $thisObject['payload_extension_system_count']; $i++) { + $payloadExtensionSystem = array(); + + $payloadExtensionSystem['extension_system_id'] = substr($asf_header_extension_object_data, $offset, 16); + $offset += 16; + $payloadExtensionSystem['extension_system_id_text'] = $this->BytestringToGUID($payloadExtensionSystem['extension_system_id']); + + $payloadExtensionSystem['extension_system_size'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + if ($payloadExtensionSystem['extension_system_size'] <= 0) { + break 2; + } + + $payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, $payloadExtensionSystem['extension_system_info_length'])); + $offset += $payloadExtensionSystem['extension_system_info_length']; + + $thisObject['payload_extension_systems'][$i] = $payloadExtensionSystem; + } + + break; + + case GETID3_ASF_Padding_Object: + // padding, skip it + break; + + case GETID3_ASF_Metadata_Object: + $thisObject['description_record_counts'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + for ($i = 0; $i < $thisObject['description_record_counts']; $i++) { + $descriptionRecord = array(); + + $descriptionRecord['reserved_1'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); // must be zero + $offset += 2; + + $descriptionRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $descriptionRecord['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $descriptionRecord['data_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + $descriptionRecord['data_type_text'] = $this->ASFmetadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); + + $descriptionRecord['data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $descriptionRecord['name'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['name_length']); + $offset += $descriptionRecord['name_length']; + + $descriptionRecord['data'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['data_length']); + $offset += $descriptionRecord['data_length']; + switch ($descriptionRecord['data_type']) { + case 0x0000: // Unicode string + break; + + case 0x0001: // BYTE array + // do nothing + break; + + case 0x0002: // BOOL + $descriptionRecord['data'] = (bool) getid3_lib::LittleEndian2Int($descriptionRecord['data']); + break; + + case 0x0003: // DWORD + case 0x0004: // QWORD + case 0x0005: // WORD + $descriptionRecord['data'] = getid3_lib::LittleEndian2Int($descriptionRecord['data']); + break; + + case 0x0006: // GUID + $descriptionRecord['data_text'] = $this->BytestringToGUID($descriptionRecord['data']); + break; + } + + $thisObject['description_record'][$i] = $descriptionRecord; + } + break; + + case GETID3_ASF_Language_List_Object: + $thisObject['language_id_record_counts'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + for ($i = 0; $i < $thisObject['language_id_record_counts']; $i++) { + $languageIDrecord = array(); + + $languageIDrecord['language_id_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1)); + $offset += 1; + + $languageIDrecord['language_id'] = substr($asf_header_extension_object_data, $offset, $languageIDrecord['language_id_length']); + $offset += $languageIDrecord['language_id_length']; + + $thisObject['language_id_record'][$i] = $languageIDrecord; + } + break; + + case GETID3_ASF_Metadata_Library_Object: + $thisObject['description_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + for ($i = 0; $i < $thisObject['description_records_count']; $i++) { + $descriptionRecord = array(); + + $descriptionRecord['language_list_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $descriptionRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $descriptionRecord['name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + + $descriptionRecord['data_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); + $offset += 2; + $descriptionRecord['data_type_text'] = $this->ASFmetadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); + + $descriptionRecord['data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); + $offset += 4; + + $descriptionRecord['name'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['name_length']); + $offset += $descriptionRecord['name_length']; + + $descriptionRecord['data'] = substr($asf_header_extension_object_data, $offset, $descriptionRecord['data_length']); + $offset += $descriptionRecord['data_length']; + + if (preg_match('#^WM/Picture$#', str_replace("\x00", '', trim($descriptionRecord['name'])))) { + $WMpicture = $this->ASF_WMpicture($descriptionRecord['data']); + foreach ($WMpicture as $key => $value) { + $descriptionRecord['data'] = $WMpicture; + } + unset($WMpicture); + } + + $thisObject['description_record'][$i] = $descriptionRecord; + } + break; + + default: + $unhandled_sections++; + if ($this->GUIDname($thisObject['guid_text'])) { + $this->getid3->info['warning'][] = 'unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8); + } else { + $this->getid3->info['warning'][] = 'unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8); + } + break; + } + $HeaderExtensionObjectParsed[] = $thisObject; + + $objectOffset += $thisObject['size']; + } + return $HeaderExtensionObjectParsed; + } + + + public static function ASFmetadataLibraryObjectDataTypeLookup($id) { + static $ASFmetadataLibraryObjectDataTypeLookup = array( + 0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters + 0x0001 => 'BYTE array', // The type of the data is implementation-specific + 0x0002 => 'BOOL', // The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. Only 0x0000 or 0x0001 are permitted values + 0x0003 => 'DWORD', // The data is 4 bytes long and should be interpreted as a 32-bit unsigned integer + 0x0004 => 'QWORD', // The data is 8 bytes long and should be interpreted as a 64-bit unsigned integer + 0x0005 => 'WORD', // The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer + 0x0006 => 'GUID', // The data is 16 bytes long and should be interpreted as a 128-bit GUID + ); + return (isset($ASFmetadataLibraryObjectDataTypeLookup[$id]) ? $ASFmetadataLibraryObjectDataTypeLookup[$id] : 'invalid'); + } + + public function ASF_WMpicture(&$data) { + //typedef struct _WMPicture{ + // LPWSTR pwszMIMEType; + // BYTE bPictureType; + // LPWSTR pwszDescription; + // DWORD dwDataLen; + // BYTE* pbData; + //} WM_PICTURE; + + $WMpicture = array(); + + $offset = 0; + $WMpicture['image_type_id'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 1)); + $offset += 1; + $WMpicture['image_type'] = $this->WMpictureTypeLookup($WMpicture['image_type_id']); + $WMpicture['image_size'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 4)); + $offset += 4; + + $WMpicture['image_mime'] = ''; + do { + $next_byte_pair = substr($data, $offset, 2); + $offset += 2; + $WMpicture['image_mime'] .= $next_byte_pair; + } while ($next_byte_pair !== "\x00\x00"); + + $WMpicture['image_description'] = ''; + do { + $next_byte_pair = substr($data, $offset, 2); + $offset += 2; + $WMpicture['image_description'] .= $next_byte_pair; + } while ($next_byte_pair !== "\x00\x00"); + + $WMpicture['dataoffset'] = $offset; + $WMpicture['data'] = substr($data, $offset); + + $imageinfo = array(); + $WMpicture['image_mime'] = ''; + $imagechunkcheck = getid3_lib::GetDataImageSize($WMpicture['data'], $imageinfo); + unset($imageinfo); + if (!empty($imagechunkcheck)) { + $WMpicture['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]); + } + if (!isset($this->getid3->info['asf']['comments']['picture'])) { + $this->getid3->info['asf']['comments']['picture'] = array(); + } + $this->getid3->info['asf']['comments']['picture'][] = array('data'=>$WMpicture['data'], 'image_mime'=>$WMpicture['image_mime']); + + return $WMpicture; + } + + + // Remove terminator 00 00 and convert UTF-16LE to Latin-1 + public static function TrimConvert($string) { + return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' '); + } + + + // Remove terminator 00 00 + public static function TrimTerm($string) { + // remove terminator, only if present (it should be, but...) + if (substr($string, -2) === "\x00\x00") { + $string = substr($string, 0, -2); + } + return $string; + } + +} diff --git a/sources/wp-includes/ID3/module.audio-video.flv.php b/sources/wp-includes/ID3/module.audio-video.flv.php new file mode 100644 index 0000000..f9c4cf3 --- /dev/null +++ b/sources/wp-includes/ID3/module.audio-video.flv.php @@ -0,0 +1,729 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +// // +// FLV module by Seth Kaufman // +// // +// * version 0.1 (26 June 2005) // +// // +// // +// * version 0.1.1 (15 July 2005) // +// minor modifications by James Heinrich // +// // +// * version 0.2 (22 February 2006) // +// Support for On2 VP6 codec and meta information // +// by Steve Webster // +// // +// * version 0.3 (15 June 2006) // +// Modified to not read entire file into memory // +// by James Heinrich // +// // +// * version 0.4 (07 December 2007) // +// Bugfixes for incorrectly parsed FLV dimensions // +// and incorrect parsing of onMetaTag // +// by Evgeny Moysevich // +// // +// * version 0.5 (21 May 2009) // +// Fixed parsing of audio tags and added additional codec // +// details. The duration is now read from onMetaTag (if // +// exists), rather than parsing whole file // +// by Nigel Barnes // +// // +// * version 0.6 (24 May 2009) // +// Better parsing of files with h264 video // +// by Evgeny Moysevich // +// // +// * version 0.6.1 (30 May 2011) // +// prevent infinite loops in expGolombUe() // +// // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.flv.php // +// module for analyzing Shockwave Flash Video files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + +define('GETID3_FLV_TAG_AUDIO', 8); +define('GETID3_FLV_TAG_VIDEO', 9); +define('GETID3_FLV_TAG_META', 18); + +define('GETID3_FLV_VIDEO_H263', 2); +define('GETID3_FLV_VIDEO_SCREEN', 3); +define('GETID3_FLV_VIDEO_VP6FLV', 4); +define('GETID3_FLV_VIDEO_VP6FLV_ALPHA', 5); +define('GETID3_FLV_VIDEO_SCREENV2', 6); +define('GETID3_FLV_VIDEO_H264', 7); + +define('H264_AVC_SEQUENCE_HEADER', 0); +define('H264_PROFILE_BASELINE', 66); +define('H264_PROFILE_MAIN', 77); +define('H264_PROFILE_EXTENDED', 88); +define('H264_PROFILE_HIGH', 100); +define('H264_PROFILE_HIGH10', 110); +define('H264_PROFILE_HIGH422', 122); +define('H264_PROFILE_HIGH444', 144); +define('H264_PROFILE_HIGH444_PREDICTIVE', 244); + +class getid3_flv extends getid3_handler +{ + public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration + + public function Analyze() { + $info = &$this->getid3->info; + + fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + + $FLVdataLength = $info['avdataend'] - $info['avdataoffset']; + $FLVheader = fread($this->getid3->fp, 5); + + $info['fileformat'] = 'flv'; + $info['flv']['header']['signature'] = substr($FLVheader, 0, 3); + $info['flv']['header']['version'] = getid3_lib::BigEndian2Int(substr($FLVheader, 3, 1)); + $TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1)); + + $magic = 'FLV'; + if ($info['flv']['header']['signature'] != $magic) { + $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"'; + unset($info['flv']); + unset($info['fileformat']); + return false; + } + + $info['flv']['header']['hasAudio'] = (bool) ($TypeFlags & 0x04); + $info['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 0x01); + + $FrameSizeDataLength = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 4)); + $FLVheaderFrameLength = 9; + if ($FrameSizeDataLength > $FLVheaderFrameLength) { + fseek($this->getid3->fp, $FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR); + } + $Duration = 0; + $found_video = false; + $found_audio = false; + $found_meta = false; + $found_valid_meta_playtime = false; + $tagParseCount = 0; + $info['flv']['framecount'] = array('total'=>0, 'audio'=>0, 'video'=>0); + $flv_framecount = &$info['flv']['framecount']; + while (((ftell($this->getid3->fp) + 16) < $info['avdataend']) && (($tagParseCount++ <= $this->max_frames) || !$found_valid_meta_playtime)) { + $ThisTagHeader = fread($this->getid3->fp, 16); + + $PreviousTagLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 0, 4)); + $TagType = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 4, 1)); + $DataLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 5, 3)); + $Timestamp = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 8, 3)); + $LastHeaderByte = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 15, 1)); + $NextOffset = ftell($this->getid3->fp) - 1 + $DataLength; + if ($Timestamp > $Duration) { + $Duration = $Timestamp; + } + + $flv_framecount['total']++; + switch ($TagType) { + case GETID3_FLV_TAG_AUDIO: + $flv_framecount['audio']++; + if (!$found_audio) { + $found_audio = true; + $info['flv']['audio']['audioFormat'] = ($LastHeaderByte >> 4) & 0x0F; + $info['flv']['audio']['audioRate'] = ($LastHeaderByte >> 2) & 0x03; + $info['flv']['audio']['audioSampleSize'] = ($LastHeaderByte >> 1) & 0x01; + $info['flv']['audio']['audioType'] = $LastHeaderByte & 0x01; + } + break; + + case GETID3_FLV_TAG_VIDEO: + $flv_framecount['video']++; + if (!$found_video) { + $found_video = true; + $info['flv']['video']['videoCodec'] = $LastHeaderByte & 0x07; + + $FLVvideoHeader = fread($this->getid3->fp, 11); + + if ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) { + // this code block contributed by: moysevichØgmail*com + + $AVCPacketType = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 0, 1)); + if ($AVCPacketType == H264_AVC_SEQUENCE_HEADER) { + // read AVCDecoderConfigurationRecord + $configurationVersion = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 1)); + $AVCProfileIndication = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 1)); + $profile_compatibility = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 1)); + $lengthSizeMinusOne = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 7, 1)); + $numOfSequenceParameterSets = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 8, 1)); + + if (($numOfSequenceParameterSets & 0x1F) != 0) { + // there is at least one SequenceParameterSet + // read size of the first SequenceParameterSet + //$spsSize = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 9, 2)); + $spsSize = getid3_lib::LittleEndian2Int(substr($FLVvideoHeader, 9, 2)); + // read the first SequenceParameterSet + $sps = fread($this->getid3->fp, $spsSize); + if (strlen($sps) == $spsSize) { // make sure that whole SequenceParameterSet was red + $spsReader = new AVCSequenceParameterSetReader($sps); + $spsReader->readData(); + $info['video']['resolution_x'] = $spsReader->getWidth(); + $info['video']['resolution_y'] = $spsReader->getHeight(); + } + } + } + // end: moysevichØgmail*com + + } elseif ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H263) { + + $PictureSizeType = (getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 3, 2))) >> 7; + $PictureSizeType = $PictureSizeType & 0x0007; + $info['flv']['header']['videoSizeType'] = $PictureSizeType; + switch ($PictureSizeType) { + case 0: + //$PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2)); + //$PictureSizeEnc <<= 1; + //$info['video']['resolution_x'] = ($PictureSizeEnc & 0xFF00) >> 8; + //$PictureSizeEnc = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 2)); + //$PictureSizeEnc <<= 1; + //$info['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8; + + $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2)); + $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2)); + $PictureSizeEnc['x'] >>= 7; + $PictureSizeEnc['y'] >>= 7; + $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFF; + $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFF; + break; + + case 1: + $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3)); + $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3)); + $PictureSizeEnc['x'] >>= 7; + $PictureSizeEnc['y'] >>= 7; + $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFFFF; + $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFFFF; + break; + + case 2: + $info['video']['resolution_x'] = 352; + $info['video']['resolution_y'] = 288; + break; + + case 3: + $info['video']['resolution_x'] = 176; + $info['video']['resolution_y'] = 144; + break; + + case 4: + $info['video']['resolution_x'] = 128; + $info['video']['resolution_y'] = 96; + break; + + case 5: + $info['video']['resolution_x'] = 320; + $info['video']['resolution_y'] = 240; + break; + + case 6: + $info['video']['resolution_x'] = 160; + $info['video']['resolution_y'] = 120; + break; + + default: + $info['video']['resolution_x'] = 0; + $info['video']['resolution_y'] = 0; + break; + + } + } + $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y']; + } + break; + + // Meta tag + case GETID3_FLV_TAG_META: + if (!$found_meta) { + $found_meta = true; + fseek($this->getid3->fp, -1, SEEK_CUR); + $datachunk = fread($this->getid3->fp, $DataLength); + $AMFstream = new AMFStream($datachunk); + $reader = new AMFReader($AMFstream); + $eventName = $reader->readData(); + $info['flv']['meta'][$eventName] = $reader->readData(); + unset($reader); + + $copykeys = array('framerate'=>'frame_rate', 'width'=>'resolution_x', 'height'=>'resolution_y', 'audiodatarate'=>'bitrate', 'videodatarate'=>'bitrate'); + foreach ($copykeys as $sourcekey => $destkey) { + if (isset($info['flv']['meta']['onMetaData'][$sourcekey])) { + switch ($sourcekey) { + case 'width': + case 'height': + $info['video'][$destkey] = intval(round($info['flv']['meta']['onMetaData'][$sourcekey])); + break; + case 'audiodatarate': + $info['audio'][$destkey] = getid3_lib::CastAsInt(round($info['flv']['meta']['onMetaData'][$sourcekey] * 1000)); + break; + case 'videodatarate': + case 'frame_rate': + default: + $info['video'][$destkey] = $info['flv']['meta']['onMetaData'][$sourcekey]; + break; + } + } + } + if (!empty($info['flv']['meta']['onMetaData']['duration'])) { + $found_valid_meta_playtime = true; + } + } + break; + + default: + // noop + break; + } + fseek($this->getid3->fp, $NextOffset, SEEK_SET); + } + + $info['playtime_seconds'] = $Duration / 1000; + if ($info['playtime_seconds'] > 0) { + $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; + } + + if ($info['flv']['header']['hasAudio']) { + $info['audio']['codec'] = $this->FLVaudioFormat($info['flv']['audio']['audioFormat']); + $info['audio']['sample_rate'] = $this->FLVaudioRate($info['flv']['audio']['audioRate']); + $info['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($info['flv']['audio']['audioSampleSize']); + + $info['audio']['channels'] = $info['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo + $info['audio']['lossless'] = ($info['flv']['audio']['audioFormat'] ? false : true); // 0=uncompressed + $info['audio']['dataformat'] = 'flv'; + } + if (!empty($info['flv']['header']['hasVideo'])) { + $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['video']['videoCodec']); + $info['video']['dataformat'] = 'flv'; + $info['video']['lossless'] = false; + } + + // Set information from meta + if (!empty($info['flv']['meta']['onMetaData']['duration'])) { + $info['playtime_seconds'] = $info['flv']['meta']['onMetaData']['duration']; + $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; + } + if (isset($info['flv']['meta']['onMetaData']['audiocodecid'])) { + $info['audio']['codec'] = $this->FLVaudioFormat($info['flv']['meta']['onMetaData']['audiocodecid']); + } + if (isset($info['flv']['meta']['onMetaData']['videocodecid'])) { + $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['meta']['onMetaData']['videocodecid']); + } + return true; + } + + + public function FLVaudioFormat($id) { + $FLVaudioFormat = array( + 0 => 'Linear PCM, platform endian', + 1 => 'ADPCM', + 2 => 'mp3', + 3 => 'Linear PCM, little endian', + 4 => 'Nellymoser 16kHz mono', + 5 => 'Nellymoser 8kHz mono', + 6 => 'Nellymoser', + 7 => 'G.711A-law logarithmic PCM', + 8 => 'G.711 mu-law logarithmic PCM', + 9 => 'reserved', + 10 => 'AAC', + 11 => false, // unknown? + 12 => false, // unknown? + 13 => false, // unknown? + 14 => 'mp3 8kHz', + 15 => 'Device-specific sound', + ); + return (isset($FLVaudioFormat[$id]) ? $FLVaudioFormat[$id] : false); + } + + public function FLVaudioRate($id) { + $FLVaudioRate = array( + 0 => 5500, + 1 => 11025, + 2 => 22050, + 3 => 44100, + ); + return (isset($FLVaudioRate[$id]) ? $FLVaudioRate[$id] : false); + } + + public function FLVaudioBitDepth($id) { + $FLVaudioBitDepth = array( + 0 => 8, + 1 => 16, + ); + return (isset($FLVaudioBitDepth[$id]) ? $FLVaudioBitDepth[$id] : false); + } + + public function FLVvideoCodec($id) { + $FLVvideoCodec = array( + GETID3_FLV_VIDEO_H263 => 'Sorenson H.263', + GETID3_FLV_VIDEO_SCREEN => 'Screen video', + GETID3_FLV_VIDEO_VP6FLV => 'On2 VP6', + GETID3_FLV_VIDEO_VP6FLV_ALPHA => 'On2 VP6 with alpha channel', + GETID3_FLV_VIDEO_SCREENV2 => 'Screen video v2', + GETID3_FLV_VIDEO_H264 => 'Sorenson H.264', + ); + return (isset($FLVvideoCodec[$id]) ? $FLVvideoCodec[$id] : false); + } +} + +class AMFStream { + public $bytes; + public $pos; + + public function AMFStream(&$bytes) { + $this->bytes =& $bytes; + $this->pos = 0; + } + + public function readByte() { + return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1)); + } + + public function readInt() { + return ($this->readByte() << 8) + $this->readByte(); + } + + public function readLong() { + return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte(); + } + + public function readDouble() { + return getid3_lib::BigEndian2Float($this->read(8)); + } + + public function readUTF() { + $length = $this->readInt(); + return $this->read($length); + } + + public function readLongUTF() { + $length = $this->readLong(); + return $this->read($length); + } + + public function read($length) { + $val = substr($this->bytes, $this->pos, $length); + $this->pos += $length; + return $val; + } + + public function peekByte() { + $pos = $this->pos; + $val = $this->readByte(); + $this->pos = $pos; + return $val; + } + + public function peekInt() { + $pos = $this->pos; + $val = $this->readInt(); + $this->pos = $pos; + return $val; + } + + public function peekLong() { + $pos = $this->pos; + $val = $this->readLong(); + $this->pos = $pos; + return $val; + } + + public function peekDouble() { + $pos = $this->pos; + $val = $this->readDouble(); + $this->pos = $pos; + return $val; + } + + public function peekUTF() { + $pos = $this->pos; + $val = $this->readUTF(); + $this->pos = $pos; + return $val; + } + + public function peekLongUTF() { + $pos = $this->pos; + $val = $this->readLongUTF(); + $this->pos = $pos; + return $val; + } +} + +class AMFReader { + public $stream; + + public function AMFReader(&$stream) { + $this->stream =& $stream; + } + + public function readData() { + $value = null; + + $type = $this->stream->readByte(); + switch ($type) { + + // Double + case 0: + $value = $this->readDouble(); + break; + + // Boolean + case 1: + $value = $this->readBoolean(); + break; + + // String + case 2: + $value = $this->readString(); + break; + + // Object + case 3: + $value = $this->readObject(); + break; + + // null + case 6: + return null; + break; + + // Mixed array + case 8: + $value = $this->readMixedArray(); + break; + + // Array + case 10: + $value = $this->readArray(); + break; + + // Date + case 11: + $value = $this->readDate(); + break; + + // Long string + case 13: + $value = $this->readLongString(); + break; + + // XML (handled as string) + case 15: + $value = $this->readXML(); + break; + + // Typed object (handled as object) + case 16: + $value = $this->readTypedObject(); + break; + + // Long string + default: + $value = '(unknown or unsupported data type)'; + break; + } + + return $value; + } + + public function readDouble() { + return $this->stream->readDouble(); + } + + public function readBoolean() { + return $this->stream->readByte() == 1; + } + + public function readString() { + return $this->stream->readUTF(); + } + + public function readObject() { + // Get highest numerical index - ignored +// $highestIndex = $this->stream->readLong(); + + $data = array(); + + while ($key = $this->stream->readUTF()) { + $data[$key] = $this->readData(); + } + // Mixed array record ends with empty string (0x00 0x00) and 0x09 + if (($key == '') && ($this->stream->peekByte() == 0x09)) { + // Consume byte + $this->stream->readByte(); + } + return $data; + } + + public function readMixedArray() { + // Get highest numerical index - ignored + $highestIndex = $this->stream->readLong(); + + $data = array(); + + while ($key = $this->stream->readUTF()) { + if (is_numeric($key)) { + $key = (float) $key; + } + $data[$key] = $this->readData(); + } + // Mixed array record ends with empty string (0x00 0x00) and 0x09 + if (($key == '') && ($this->stream->peekByte() == 0x09)) { + // Consume byte + $this->stream->readByte(); + } + + return $data; + } + + public function readArray() { + $length = $this->stream->readLong(); + $data = array(); + + for ($i = 0; $i < $length; $i++) { + $data[] = $this->readData(); + } + return $data; + } + + public function readDate() { + $timestamp = $this->stream->readDouble(); + $timezone = $this->stream->readInt(); + return $timestamp; + } + + public function readLongString() { + return $this->stream->readLongUTF(); + } + + public function readXML() { + return $this->stream->readLongUTF(); + } + + public function readTypedObject() { + $className = $this->stream->readUTF(); + return $this->readObject(); + } +} + +class AVCSequenceParameterSetReader { + public $sps; + public $start = 0; + public $currentBytes = 0; + public $currentBits = 0; + public $width; + public $height; + + public function AVCSequenceParameterSetReader($sps) { + $this->sps = $sps; + } + + public function readData() { + $this->skipBits(8); + $this->skipBits(8); + $profile = $this->getBits(8); // read profile + $this->skipBits(16); + $this->expGolombUe(); // read sps id + if (in_array($profile, array(H264_PROFILE_HIGH, H264_PROFILE_HIGH10, H264_PROFILE_HIGH422, H264_PROFILE_HIGH444, H264_PROFILE_HIGH444_PREDICTIVE))) { + if ($this->expGolombUe() == 3) { + $this->skipBits(1); + } + $this->expGolombUe(); + $this->expGolombUe(); + $this->skipBits(1); + if ($this->getBit()) { + for ($i = 0; $i < 8; $i++) { + if ($this->getBit()) { + $size = $i < 6 ? 16 : 64; + $lastScale = 8; + $nextScale = 8; + for ($j = 0; $j < $size; $j++) { + if ($nextScale != 0) { + $deltaScale = $this->expGolombUe(); + $nextScale = ($lastScale + $deltaScale + 256) % 256; + } + if ($nextScale != 0) { + $lastScale = $nextScale; + } + } + } + } + } + } + $this->expGolombUe(); + $pocType = $this->expGolombUe(); + if ($pocType == 0) { + $this->expGolombUe(); + } elseif ($pocType == 1) { + $this->skipBits(1); + $this->expGolombSe(); + $this->expGolombSe(); + $pocCycleLength = $this->expGolombUe(); + for ($i = 0; $i < $pocCycleLength; $i++) { + $this->expGolombSe(); + } + } + $this->expGolombUe(); + $this->skipBits(1); + $this->width = ($this->expGolombUe() + 1) * 16; + $heightMap = $this->expGolombUe() + 1; + $this->height = (2 - $this->getBit()) * $heightMap * 16; + } + + public function skipBits($bits) { + $newBits = $this->currentBits + $bits; + $this->currentBytes += (int)floor($newBits / 8); + $this->currentBits = $newBits % 8; + } + + public function getBit() { + $result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01; + $this->skipBits(1); + return $result; + } + + public function getBits($bits) { + $result = 0; + for ($i = 0; $i < $bits; $i++) { + $result = ($result << 1) + $this->getBit(); + } + return $result; + } + + public function expGolombUe() { + $significantBits = 0; + $bit = $this->getBit(); + while ($bit == 0) { + $significantBits++; + $bit = $this->getBit(); + + if ($significantBits > 31) { + // something is broken, this is an emergency escape to prevent infinite loops + return 0; + } + } + return (1 << $significantBits) + $this->getBits($significantBits) - 1; + } + + public function expGolombSe() { + $result = $this->expGolombUe(); + if (($result & 0x01) == 0) { + return -($result >> 1); + } else { + return ($result + 1) >> 1; + } + } + + public function getWidth() { + return $this->width; + } + + public function getHeight() { + return $this->height; + } +} diff --git a/sources/wp-includes/ID3/module.audio-video.matroska.php b/sources/wp-includes/ID3/module.audio-video.matroska.php new file mode 100644 index 0000000..fb0af72 --- /dev/null +++ b/sources/wp-includes/ID3/module.audio-video.matroska.php @@ -0,0 +1,1765 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.matriska.php // +// module for analyzing Matroska containers // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +define('EBML_ID_CHAPTERS', 0x0043A770); // [10][43][A7][70] -- A system to define basic menus and partition data. For more detailed information, look at the Chapters Explanation. +define('EBML_ID_SEEKHEAD', 0x014D9B74); // [11][4D][9B][74] -- Contains the position of other level 1 elements. +define('EBML_ID_TAGS', 0x0254C367); // [12][54][C3][67] -- Element containing elements specific to Tracks/Chapters. A list of valid tags can be found . +define('EBML_ID_INFO', 0x0549A966); // [15][49][A9][66] -- Contains miscellaneous general information and statistics on the file. +define('EBML_ID_TRACKS', 0x0654AE6B); // [16][54][AE][6B] -- A top-level block of information with many tracks described. +define('EBML_ID_SEGMENT', 0x08538067); // [18][53][80][67] -- This element contains all other top-level (level 1) elements. Typically a Matroska file is composed of 1 segment. +define('EBML_ID_ATTACHMENTS', 0x0941A469); // [19][41][A4][69] -- Contain attached files. +define('EBML_ID_EBML', 0x0A45DFA3); // [1A][45][DF][A3] -- Set the EBML characteristics of the data to follow. Each EBML document has to start with this. +define('EBML_ID_CUES', 0x0C53BB6B); // [1C][53][BB][6B] -- A top-level element to speed seeking access. All entries are local to the segment. +define('EBML_ID_CLUSTER', 0x0F43B675); // [1F][43][B6][75] -- The lower level element containing the (monolithic) Block structure. +define('EBML_ID_LANGUAGE', 0x02B59C); // [22][B5][9C] -- Specifies the language of the track in the Matroska languages form. +define('EBML_ID_TRACKTIMECODESCALE', 0x03314F); // [23][31][4F] -- The scale to apply on this track to work at normal speed in relation with other tracks (mostly used to adjust video speed when the audio length differs). +define('EBML_ID_DEFAULTDURATION', 0x03E383); // [23][E3][83] -- Number of nanoseconds (i.e. not scaled) per frame. +define('EBML_ID_CODECNAME', 0x058688); // [25][86][88] -- A human-readable string specifying the codec. +define('EBML_ID_CODECDOWNLOADURL', 0x06B240); // [26][B2][40] -- A URL to download about the codec used. +define('EBML_ID_TIMECODESCALE', 0x0AD7B1); // [2A][D7][B1] -- Timecode scale in nanoseconds (1.000.000 means all timecodes in the segment are expressed in milliseconds). +define('EBML_ID_COLOURSPACE', 0x0EB524); // [2E][B5][24] -- Same value as in AVI (32 bits). +define('EBML_ID_GAMMAVALUE', 0x0FB523); // [2F][B5][23] -- Gamma Value. +define('EBML_ID_CODECSETTINGS', 0x1A9697); // [3A][96][97] -- A string describing the encoding setting used. +define('EBML_ID_CODECINFOURL', 0x1B4040); // [3B][40][40] -- A URL to find information about the codec used. +define('EBML_ID_PREVFILENAME', 0x1C83AB); // [3C][83][AB] -- An escaped filename corresponding to the previous segment. +define('EBML_ID_PREVUID', 0x1CB923); // [3C][B9][23] -- A unique ID to identify the previous chained segment (128 bits). +define('EBML_ID_NEXTFILENAME', 0x1E83BB); // [3E][83][BB] -- An escaped filename corresponding to the next segment. +define('EBML_ID_NEXTUID', 0x1EB923); // [3E][B9][23] -- A unique ID to identify the next chained segment (128 bits). +define('EBML_ID_CONTENTCOMPALGO', 0x0254); // [42][54] -- The compression algorithm used. Algorithms that have been specified so far are: +define('EBML_ID_CONTENTCOMPSETTINGS', 0x0255); // [42][55] -- Settings that might be needed by the decompressor. For Header Stripping (ContentCompAlgo=3), the bytes that were removed from the beggining of each frames of the track. +define('EBML_ID_DOCTYPE', 0x0282); // [42][82] -- A string that describes the type of document that follows this EBML header ('matroska' in our case). +define('EBML_ID_DOCTYPEREADVERSION', 0x0285); // [42][85] -- The minimum DocType version an interpreter has to support to read this file. +define('EBML_ID_EBMLVERSION', 0x0286); // [42][86] -- The version of EBML parser used to create the file. +define('EBML_ID_DOCTYPEVERSION', 0x0287); // [42][87] -- The version of DocType interpreter used to create the file. +define('EBML_ID_EBMLMAXIDLENGTH', 0x02F2); // [42][F2] -- The maximum length of the IDs you'll find in this file (4 or less in Matroska). +define('EBML_ID_EBMLMAXSIZELENGTH', 0x02F3); // [42][F3] -- The maximum length of the sizes you'll find in this file (8 or less in Matroska). This does not override the element size indicated at the beginning of an element. Elements that have an indicated size which is larger than what is allowed by EBMLMaxSizeLength shall be considered invalid. +define('EBML_ID_EBMLREADVERSION', 0x02F7); // [42][F7] -- The minimum EBML version a parser has to support to read this file. +define('EBML_ID_CHAPLANGUAGE', 0x037C); // [43][7C] -- The languages corresponding to the string, in the bibliographic ISO-639-2 form. +define('EBML_ID_CHAPCOUNTRY', 0x037E); // [43][7E] -- The countries corresponding to the string, same 2 octets as in Internet domains. +define('EBML_ID_SEGMENTFAMILY', 0x0444); // [44][44] -- A randomly generated unique ID that all segments related to each other must use (128 bits). +define('EBML_ID_DATEUTC', 0x0461); // [44][61] -- Date of the origin of timecode (value 0), i.e. production date. +define('EBML_ID_TAGLANGUAGE', 0x047A); // [44][7A] -- Specifies the language of the tag specified, in the Matroska languages form. +define('EBML_ID_TAGDEFAULT', 0x0484); // [44][84] -- Indication to know if this is the default/original language to use for the given tag. +define('EBML_ID_TAGBINARY', 0x0485); // [44][85] -- The values of the Tag if it is binary. Note that this cannot be used in the same SimpleTag as TagString. +define('EBML_ID_TAGSTRING', 0x0487); // [44][87] -- The value of the Tag. +define('EBML_ID_DURATION', 0x0489); // [44][89] -- Duration of the segment (based on TimecodeScale). +define('EBML_ID_CHAPPROCESSPRIVATE', 0x050D); // [45][0D] -- Some optional data attached to the ChapProcessCodecID information. For ChapProcessCodecID = 1, it is the "DVD level" equivalent. +define('EBML_ID_CHAPTERFLAGENABLED', 0x0598); // [45][98] -- Specify wether the chapter is enabled. It can be enabled/disabled by a Control Track. When disabled, the movie should skip all the content between the TimeStart and TimeEnd of this chapter. +define('EBML_ID_TAGNAME', 0x05A3); // [45][A3] -- The name of the Tag that is going to be stored. +define('EBML_ID_EDITIONENTRY', 0x05B9); // [45][B9] -- Contains all information about a segment edition. +define('EBML_ID_EDITIONUID', 0x05BC); // [45][BC] -- A unique ID to identify the edition. It's useful for tagging an edition. +define('EBML_ID_EDITIONFLAGHIDDEN', 0x05BD); // [45][BD] -- If an edition is hidden (1), it should not be available to the user interface (but still to Control Tracks). +define('EBML_ID_EDITIONFLAGDEFAULT', 0x05DB); // [45][DB] -- If a flag is set (1) the edition should be used as the default one. +define('EBML_ID_EDITIONFLAGORDERED', 0x05DD); // [45][DD] -- Specify if the chapters can be defined multiple times and the order to play them is enforced. +define('EBML_ID_FILEDATA', 0x065C); // [46][5C] -- The data of the file. +define('EBML_ID_FILEMIMETYPE', 0x0660); // [46][60] -- MIME type of the file. +define('EBML_ID_FILENAME', 0x066E); // [46][6E] -- Filename of the attached file. +define('EBML_ID_FILEREFERRAL', 0x0675); // [46][75] -- A binary value that a track/codec can refer to when the attachment is needed. +define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file. +define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible. +define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values: +define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with. +define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents. +define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with. +define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values: +define('EBML_ID_CONTENTSIGHASHALGO', 0x07E6); // [47][E6] -- The hash algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values: +define('EBML_ID_MUXINGAPP', 0x0D80); // [4D][80] -- Muxing application or library ("libmatroska-0.4.3"). +define('EBML_ID_SEEK', 0x0DBB); // [4D][BB] -- Contains a single seek entry to an EBML element. +define('EBML_ID_CONTENTENCODINGORDER', 0x1031); // [50][31] -- Tells when this modification was used during encoding/muxing starting with 0 and counting upwards. The decoder/demuxer has to start with the highest order number it finds and work its way down. This value has to be unique over all ContentEncodingOrder elements in the segment. +define('EBML_ID_CONTENTENCODINGSCOPE', 0x1032); // [50][32] -- A bit field that describes which elements have been modified in this way. Values (big endian) can be OR'ed. Possible values: +define('EBML_ID_CONTENTENCODINGTYPE', 0x1033); // [50][33] -- A value describing what kind of transformation has been done. Possible values: +define('EBML_ID_CONTENTCOMPRESSION', 0x1034); // [50][34] -- Settings describing the compression used. Must be present if the value of ContentEncodingType is 0 and absent otherwise. Each block must be decompressable even if no previous block is available in order not to prevent seeking. +define('EBML_ID_CONTENTENCRYPTION', 0x1035); // [50][35] -- Settings describing the encryption used. Must be present if the value of ContentEncodingType is 1 and absent otherwise. +define('EBML_ID_CUEREFNUMBER', 0x135F); // [53][5F] -- Number of the referenced Block of Track X in the specified Cluster. +define('EBML_ID_NAME', 0x136E); // [53][6E] -- A human-readable track name. +define('EBML_ID_CUEBLOCKNUMBER', 0x1378); // [53][78] -- Number of the Block in the specified Cluster. +define('EBML_ID_TRACKOFFSET', 0x137F); // [53][7F] -- A value to add to the Block's Timecode. This can be used to adjust the playback offset of a track. +define('EBML_ID_SEEKID', 0x13AB); // [53][AB] -- The binary ID corresponding to the element name. +define('EBML_ID_SEEKPOSITION', 0x13AC); // [53][AC] -- The position of the element in the segment in octets (0 = first level 1 element). +define('EBML_ID_STEREOMODE', 0x13B8); // [53][B8] -- Stereo-3D video mode. +define('EBML_ID_OLDSTEREOMODE', 0x13B9); // [53][B9] -- Bogus StereoMode value used in old versions of libmatroska. DO NOT USE. (0: mono, 1: right eye, 2: left eye, 3: both eyes). +define('EBML_ID_PIXELCROPBOTTOM', 0x14AA); // [54][AA] -- The number of video pixels to remove at the bottom of the image (for HDTV content). +define('EBML_ID_DISPLAYWIDTH', 0x14B0); // [54][B0] -- Width of the video frames to display. +define('EBML_ID_DISPLAYUNIT', 0x14B2); // [54][B2] -- Type of the unit for DisplayWidth/Height (0: pixels, 1: centimeters, 2: inches). +define('EBML_ID_ASPECTRATIOTYPE', 0x14B3); // [54][B3] -- Specify the possible modifications to the aspect ratio (0: free resizing, 1: keep aspect ratio, 2: fixed). +define('EBML_ID_DISPLAYHEIGHT', 0x14BA); // [54][BA] -- Height of the video frames to display. +define('EBML_ID_PIXELCROPTOP', 0x14BB); // [54][BB] -- The number of video pixels to remove at the top of the image. +define('EBML_ID_PIXELCROPLEFT', 0x14CC); // [54][CC] -- The number of video pixels to remove on the left of the image. +define('EBML_ID_PIXELCROPRIGHT', 0x14DD); // [54][DD] -- The number of video pixels to remove on the right of the image. +define('EBML_ID_FLAGFORCED', 0x15AA); // [55][AA] -- Set if that track MUST be used during playback. There can be many forced track for a kind (audio, video or subs), the player should select the one which language matches the user preference or the default + forced track. Overlay MAY happen between a forced and non-forced track of the same kind. +define('EBML_ID_MAXBLOCKADDITIONID', 0x15EE); // [55][EE] -- The maximum value of BlockAddID. A value 0 means there is no BlockAdditions for this track. +define('EBML_ID_WRITINGAPP', 0x1741); // [57][41] -- Writing application ("mkvmerge-0.3.3"). +define('EBML_ID_CLUSTERSILENTTRACKS', 0x1854); // [58][54] -- The list of tracks that are not used in that part of the stream. It is useful when using overlay tracks on seeking. Then you should decide what track to use. +define('EBML_ID_CLUSTERSILENTTRACKNUMBER', 0x18D7); // [58][D7] -- One of the track number that are not used from now on in the stream. It could change later if not specified as silent in a further Cluster. +define('EBML_ID_ATTACHEDFILE', 0x21A7); // [61][A7] -- An attached file. +define('EBML_ID_CONTENTENCODING', 0x2240); // [62][40] -- Settings for one content encoding like compression or encryption. +define('EBML_ID_BITDEPTH', 0x2264); // [62][64] -- Bits per sample, mostly used for PCM. +define('EBML_ID_CODECPRIVATE', 0x23A2); // [63][A2] -- Private data only known to the codec. +define('EBML_ID_TARGETS', 0x23C0); // [63][C0] -- Contain all UIDs where the specified meta data apply. It is void to describe everything in the segment. +define('EBML_ID_CHAPTERPHYSICALEQUIV', 0x23C3); // [63][C3] -- Specify the physical equivalent of this ChapterAtom like "DVD" (60) or "SIDE" (50), see complete list of values. +define('EBML_ID_TAGCHAPTERUID', 0x23C4); // [63][C4] -- A unique ID to identify the Chapter(s) the tags belong to. If the value is 0 at this level, the tags apply to all chapters in the Segment. +define('EBML_ID_TAGTRACKUID', 0x23C5); // [63][C5] -- A unique ID to identify the Track(s) the tags belong to. If the value is 0 at this level, the tags apply to all tracks in the Segment. +define('EBML_ID_TAGATTACHMENTUID', 0x23C6); // [63][C6] -- A unique ID to identify the Attachment(s) the tags belong to. If the value is 0 at this level, the tags apply to all the attachments in the Segment. +define('EBML_ID_TAGEDITIONUID', 0x23C9); // [63][C9] -- A unique ID to identify the EditionEntry(s) the tags belong to. If the value is 0 at this level, the tags apply to all editions in the Segment. +define('EBML_ID_TARGETTYPE', 0x23CA); // [63][CA] -- An informational string that can be used to display the logical level of the target like "ALBUM", "TRACK", "MOVIE", "CHAPTER", etc (see TargetType). +define('EBML_ID_TRACKTRANSLATE', 0x2624); // [66][24] -- The track identification for the given Chapter Codec. +define('EBML_ID_TRACKTRANSLATETRACKID', 0x26A5); // [66][A5] -- The binary value used to represent this track in the chapter codec data. The format depends on the ChapProcessCodecID used. +define('EBML_ID_TRACKTRANSLATECODEC', 0x26BF); // [66][BF] -- The chapter codec using this ID (0: Matroska Script, 1: DVD-menu). +define('EBML_ID_TRACKTRANSLATEEDITIONUID', 0x26FC); // [66][FC] -- Specify an edition UID on which this translation applies. When not specified, it means for all editions found in the segment. +define('EBML_ID_SIMPLETAG', 0x27C8); // [67][C8] -- Contains general information about the target. +define('EBML_ID_TARGETTYPEVALUE', 0x28CA); // [68][CA] -- A number to indicate the logical level of the target (see TargetType). +define('EBML_ID_CHAPPROCESSCOMMAND', 0x2911); // [69][11] -- Contains all the commands associated to the Atom. +define('EBML_ID_CHAPPROCESSTIME', 0x2922); // [69][22] -- Defines when the process command should be handled (0: during the whole chapter, 1: before starting playback, 2: after playback of the chapter). +define('EBML_ID_CHAPTERTRANSLATE', 0x2924); // [69][24] -- A tuple of corresponding ID used by chapter codecs to represent this segment. +define('EBML_ID_CHAPPROCESSDATA', 0x2933); // [69][33] -- Contains the command information. The data should be interpreted depending on the ChapProcessCodecID value. For ChapProcessCodecID = 1, the data correspond to the binary DVD cell pre/post commands. +define('EBML_ID_CHAPPROCESS', 0x2944); // [69][44] -- Contains all the commands associated to the Atom. +define('EBML_ID_CHAPPROCESSCODECID', 0x2955); // [69][55] -- Contains the type of the codec used for the processing. A value of 0 means native Matroska processing (to be defined), a value of 1 means the DVD command set is used. More codec IDs can be added later. +define('EBML_ID_CHAPTERTRANSLATEID', 0x29A5); // [69][A5] -- The binary value used to represent this segment in the chapter codec data. The format depends on the ChapProcessCodecID used. +define('EBML_ID_CHAPTERTRANSLATECODEC', 0x29BF); // [69][BF] -- The chapter codec using this ID (0: Matroska Script, 1: DVD-menu). +define('EBML_ID_CHAPTERTRANSLATEEDITIONUID', 0x29FC); // [69][FC] -- Specify an edition UID on which this correspondance applies. When not specified, it means for all editions found in the segment. +define('EBML_ID_CONTENTENCODINGS', 0x2D80); // [6D][80] -- Settings for several content encoding mechanisms like compression or encryption. +define('EBML_ID_MINCACHE', 0x2DE7); // [6D][E7] -- The minimum number of frames a player should be able to cache during playback. If set to 0, the reference pseudo-cache system is not used. +define('EBML_ID_MAXCACHE', 0x2DF8); // [6D][F8] -- The maximum cache size required to store referenced frames in and the current frame. 0 means no cache is needed. +define('EBML_ID_CHAPTERSEGMENTUID', 0x2E67); // [6E][67] -- A segment to play in place of this chapter. Edition ChapterSegmentEditionUID should be used for this segment, otherwise no edition is used. +define('EBML_ID_CHAPTERSEGMENTEDITIONUID', 0x2EBC); // [6E][BC] -- The edition to play from the segment linked in ChapterSegmentUID. +define('EBML_ID_TRACKOVERLAY', 0x2FAB); // [6F][AB] -- Specify that this track is an overlay track for the Track specified (in the u-integer). That means when this track has a gap (see SilentTracks) the overlay track should be used instead. The order of multiple TrackOverlay matters, the first one is the one that should be used. If not found it should be the second, etc. +define('EBML_ID_TAG', 0x3373); // [73][73] -- Element containing elements specific to Tracks/Chapters. +define('EBML_ID_SEGMENTFILENAME', 0x3384); // [73][84] -- A filename corresponding to this segment. +define('EBML_ID_SEGMENTUID', 0x33A4); // [73][A4] -- A randomly generated unique ID to identify the current segment between many others (128 bits). +define('EBML_ID_CHAPTERUID', 0x33C4); // [73][C4] -- A unique ID to identify the Chapter. +define('EBML_ID_TRACKUID', 0x33C5); // [73][C5] -- A unique ID to identify the Track. This should be kept the same when making a direct stream copy of the Track to another file. +define('EBML_ID_ATTACHMENTLINK', 0x3446); // [74][46] -- The UID of an attachment that is used by this codec. +define('EBML_ID_CLUSTERBLOCKADDITIONS', 0x35A1); // [75][A1] -- Contain additional blocks to complete the main one. An EBML parser that has no knowledge of the Block structure could still see and use/skip these data. +define('EBML_ID_CHANNELPOSITIONS', 0x347B); // [7D][7B] -- Table of horizontal angles for each successive channel, see appendix. +define('EBML_ID_OUTPUTSAMPLINGFREQUENCY', 0x38B5); // [78][B5] -- Real output sampling frequency in Hz (used for SBR techniques). +define('EBML_ID_TITLE', 0x3BA9); // [7B][A9] -- General name of the segment. +define('EBML_ID_CHAPTERDISPLAY', 0x00); // [80] -- Contains all possible strings to use for the chapter display. +define('EBML_ID_TRACKTYPE', 0x03); // [83] -- A set of track types coded on 8 bits (1: video, 2: audio, 3: complex, 0x10: logo, 0x11: subtitle, 0x12: buttons, 0x20: control). +define('EBML_ID_CHAPSTRING', 0x05); // [85] -- Contains the string to use as the chapter atom. +define('EBML_ID_CODECID', 0x06); // [86] -- An ID corresponding to the codec, see the codec page for more info. +define('EBML_ID_FLAGDEFAULT', 0x08); // [88] -- Set if that track (audio, video or subs) SHOULD be used if no language found matches the user preference. +define('EBML_ID_CHAPTERTRACKNUMBER', 0x09); // [89] -- UID of the Track to apply this chapter too. In the absense of a control track, choosing this chapter will select the listed Tracks and deselect unlisted tracks. Absense of this element indicates that the Chapter should be applied to any currently used Tracks. +define('EBML_ID_CLUSTERSLICES', 0x0E); // [8E] -- Contains slices description. +define('EBML_ID_CHAPTERTRACK', 0x0F); // [8F] -- List of tracks on which the chapter applies. If this element is not present, all tracks apply +define('EBML_ID_CHAPTERTIMESTART', 0x11); // [91] -- Timecode of the start of Chapter (not scaled). +define('EBML_ID_CHAPTERTIMEEND', 0x12); // [92] -- Timecode of the end of Chapter (timecode excluded, not scaled). +define('EBML_ID_CUEREFTIME', 0x16); // [96] -- Timecode of the referenced Block. +define('EBML_ID_CUEREFCLUSTER', 0x17); // [97] -- Position of the Cluster containing the referenced Block. +define('EBML_ID_CHAPTERFLAGHIDDEN', 0x18); // [98] -- If a chapter is hidden (1), it should not be available to the user interface (but still to Control Tracks). +define('EBML_ID_FLAGINTERLACED', 0x1A); // [9A] -- Set if the video is interlaced. +define('EBML_ID_CLUSTERBLOCKDURATION', 0x1B); // [9B] -- The duration of the Block (based on TimecodeScale). This element is mandatory when DefaultDuration is set for the track. When not written and with no DefaultDuration, the value is assumed to be the difference between the timecode of this Block and the timecode of the next Block in "display" order (not coding order). This element can be useful at the end of a Track (as there is not other Block available), or when there is a break in a track like for subtitle tracks. +define('EBML_ID_FLAGLACING', 0x1C); // [9C] -- Set if the track may contain blocks using lacing. +define('EBML_ID_CHANNELS', 0x1F); // [9F] -- Numbers of channels in the track. +define('EBML_ID_CLUSTERBLOCKGROUP', 0x20); // [A0] -- Basic container of information containing a single Block or BlockVirtual, and information specific to that Block/VirtualBlock. +define('EBML_ID_CLUSTERBLOCK', 0x21); // [A1] -- Block containing the actual data to be rendered and a timecode relative to the Cluster Timecode. +define('EBML_ID_CLUSTERBLOCKVIRTUAL', 0x22); // [A2] -- A Block with no data. It must be stored in the stream at the place the real Block should be in display order. +define('EBML_ID_CLUSTERSIMPLEBLOCK', 0x23); // [A3] -- Similar to Block but without all the extra information, mostly used to reduced overhead when no extra feature is needed. +define('EBML_ID_CLUSTERCODECSTATE', 0x24); // [A4] -- The new codec state to use. Data interpretation is private to the codec. This information should always be referenced by a seek entry. +define('EBML_ID_CLUSTERBLOCKADDITIONAL', 0x25); // [A5] -- Interpreted by the codec as it wishes (using the BlockAddID). +define('EBML_ID_CLUSTERBLOCKMORE', 0x26); // [A6] -- Contain the BlockAdditional and some parameters. +define('EBML_ID_CLUSTERPOSITION', 0x27); // [A7] -- Position of the Cluster in the segment (0 in live broadcast streams). It might help to resynchronise offset on damaged streams. +define('EBML_ID_CODECDECODEALL', 0x2A); // [AA] -- The codec can decode potentially damaged data. +define('EBML_ID_CLUSTERPREVSIZE', 0x2B); // [AB] -- Size of the previous Cluster, in octets. Can be useful for backward playing. +define('EBML_ID_TRACKENTRY', 0x2E); // [AE] -- Describes a track with all elements. +define('EBML_ID_CLUSTERENCRYPTEDBLOCK', 0x2F); // [AF] -- Similar to SimpleBlock but the data inside the Block are Transformed (encrypt and/or signed). +define('EBML_ID_PIXELWIDTH', 0x30); // [B0] -- Width of the encoded video frames in pixels. +define('EBML_ID_CUETIME', 0x33); // [B3] -- Absolute timecode according to the segment time base. +define('EBML_ID_SAMPLINGFREQUENCY', 0x35); // [B5] -- Sampling frequency in Hz. +define('EBML_ID_CHAPTERATOM', 0x36); // [B6] -- Contains the atom information to use as the chapter atom (apply to all tracks). +define('EBML_ID_CUETRACKPOSITIONS', 0x37); // [B7] -- Contain positions for different tracks corresponding to the timecode. +define('EBML_ID_FLAGENABLED', 0x39); // [B9] -- Set if the track is used. +define('EBML_ID_PIXELHEIGHT', 0x3A); // [BA] -- Height of the encoded video frames in pixels. +define('EBML_ID_CUEPOINT', 0x3B); // [BB] -- Contains all information relative to a seek point in the segment. +define('EBML_ID_CRC32', 0x3F); // [BF] -- The CRC is computed on all the data of the Master element it's in, regardless of its position. It's recommended to put the CRC value at the beggining of the Master element for easier reading. All level 1 elements should include a CRC-32. +define('EBML_ID_CLUSTERBLOCKADDITIONID', 0x4B); // [CB] -- The ID of the BlockAdditional element (0 is the main Block). +define('EBML_ID_CLUSTERLACENUMBER', 0x4C); // [CC] -- The reverse number of the frame in the lace (0 is the last frame, 1 is the next to last, etc). While there are a few files in the wild with this element, it is no longer in use and has been deprecated. Being able to interpret this element is not required for playback. +define('EBML_ID_CLUSTERFRAMENUMBER', 0x4D); // [CD] -- The number of the frame to generate from this lace with this delay (allow you to generate many frames from the same Block/Frame). +define('EBML_ID_CLUSTERDELAY', 0x4E); // [CE] -- The (scaled) delay to apply to the element. +define('EBML_ID_CLUSTERDURATION', 0x4F); // [CF] -- The (scaled) duration to apply to the element. +define('EBML_ID_TRACKNUMBER', 0x57); // [D7] -- The track number as used in the Block Header (using more than 127 tracks is not encouraged, though the design allows an unlimited number). +define('EBML_ID_CUEREFERENCE', 0x5B); // [DB] -- The Clusters containing the required referenced Blocks. +define('EBML_ID_VIDEO', 0x60); // [E0] -- Video settings. +define('EBML_ID_AUDIO', 0x61); // [E1] -- Audio settings. +define('EBML_ID_CLUSTERTIMESLICE', 0x68); // [E8] -- Contains extra time information about the data contained in the Block. While there are a few files in the wild with this element, it is no longer in use and has been deprecated. Being able to interpret this element is not required for playback. +define('EBML_ID_CUECODECSTATE', 0x6A); // [EA] -- The position of the Codec State corresponding to this Cue element. 0 means that the data is taken from the initial Track Entry. +define('EBML_ID_CUEREFCODECSTATE', 0x6B); // [EB] -- The position of the Codec State corresponding to this referenced element. 0 means that the data is taken from the initial Track Entry. +define('EBML_ID_VOID', 0x6C); // [EC] -- Used to void damaged data, to avoid unexpected behaviors when using damaged data. The content is discarded. Also used to reserve space in a sub-element for later use. +define('EBML_ID_CLUSTERTIMECODE', 0x67); // [E7] -- Absolute timecode of the cluster (based on TimecodeScale). +define('EBML_ID_CLUSTERBLOCKADDID', 0x6E); // [EE] -- An ID to identify the BlockAdditional level. +define('EBML_ID_CUECLUSTERPOSITION', 0x71); // [F1] -- The position of the Cluster containing the required Block. +define('EBML_ID_CUETRACK', 0x77); // [F7] -- The track for which a position is given. +define('EBML_ID_CLUSTERREFERENCEPRIORITY', 0x7A); // [FA] -- This frame is referenced and has the specified cache priority. In cache only a frame of the same or higher priority can replace this frame. A value of 0 means the frame is not referenced. +define('EBML_ID_CLUSTERREFERENCEBLOCK', 0x7B); // [FB] -- Timecode of another frame used as a reference (ie: B or P frame). The timecode is relative to the block it's attached to. +define('EBML_ID_CLUSTERREFERENCEVIRTUAL', 0x7D); // [FD] -- Relative position of the data that should be in position of the virtual block. + + +/** +* @tutorial http://www.matroska.org/technical/specs/index.html +* +* @todo Rewrite EBML parser to reduce it's size and honor default element values +* @todo After rewrite implement stream size calculation, that will provide additional useful info and enable AAC/FLAC audio bitrate detection +*/ +class getid3_matroska extends getid3_handler +{ + // public options + public static $hide_clusters = true; // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE] + public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE] + + // private parser settings/placeholders + private $EBMLbuffer = ''; + private $EBMLbuffer_offset = 0; + private $EBMLbuffer_length = 0; + private $current_offset = 0; + private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID); + + public function Analyze() + { + $info = &$this->getid3->info; + + // parse container + try { + $this->parseEBML($info); + } catch (Exception $e) { + $info['error'][] = 'EBML parser: '.$e->getMessage(); + } + + // calculate playtime + if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) { + foreach ($info['matroska']['info'] as $key => $infoarray) { + if (isset($infoarray['Duration'])) { + // TimecodeScale is how many nanoseconds each Duration unit is + $info['playtime_seconds'] = $infoarray['Duration'] * ((isset($infoarray['TimecodeScale']) ? $infoarray['TimecodeScale'] : 1000000) / 1000000000); + break; + } + } + } + + // extract tags + if (isset($info['matroska']['tags']) && is_array($info['matroska']['tags'])) { + foreach ($info['matroska']['tags'] as $key => $infoarray) { + $this->ExtractCommentsSimpleTag($infoarray); + } + } + + // process tracks + if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) { + foreach ($info['matroska']['tracks']['tracks'] as $key => $trackarray) { + + $track_info = array(); + $track_info['dataformat'] = self::CodecIDtoCommonName($trackarray['CodecID']); + $track_info['default'] = (isset($trackarray['FlagDefault']) ? $trackarray['FlagDefault'] : true); + if (isset($trackarray['Name'])) { $track_info['name'] = $trackarray['Name']; } + + switch ($trackarray['TrackType']) { + + case 1: // Video + $track_info['resolution_x'] = $trackarray['PixelWidth']; + $track_info['resolution_y'] = $trackarray['PixelHeight']; + $track_info['display_unit'] = self::displayUnit(isset($trackarray['DisplayUnit']) ? $trackarray['DisplayUnit'] : 0); + $track_info['display_x'] = (isset($trackarray['DisplayWidth']) ? $trackarray['DisplayWidth'] : $trackarray['PixelWidth']); + $track_info['display_y'] = (isset($trackarray['DisplayHeight']) ? $trackarray['DisplayHeight'] : $trackarray['PixelHeight']); + + if (isset($trackarray['PixelCropBottom'])) { $track_info['crop_bottom'] = $trackarray['PixelCropBottom']; } + if (isset($trackarray['PixelCropTop'])) { $track_info['crop_top'] = $trackarray['PixelCropTop']; } + if (isset($trackarray['PixelCropLeft'])) { $track_info['crop_left'] = $trackarray['PixelCropLeft']; } + if (isset($trackarray['PixelCropRight'])) { $track_info['crop_right'] = $trackarray['PixelCropRight']; } + if (isset($trackarray['DefaultDuration'])) { $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3); } + if (isset($trackarray['CodecName'])) { $track_info['codec'] = $trackarray['CodecName']; } + + switch ($trackarray['CodecID']) { + case 'V_MS/VFW/FOURCC': + if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) { + $this->warning('Unable to parse codec private data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"'); + break; + } + $parsed = getid3_riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']); + $track_info['codec'] = getid3_riff::fourccLookup($parsed['fourcc']); + $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed; + break; + + /*case 'V_MPEG4/ISO/AVC': + $h264['profile'] = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 1, 1)); + $h264['level'] = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 3, 1)); + $rn = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 4, 1)); + $h264['NALUlength'] = ($rn & 3) + 1; + $rn = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 5, 1)); + $nsps = ($rn & 31); + $offset = 6; + for ($i = 0; $i < $nsps; $i ++) { + $length = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2)); + $h264['SPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length); + $offset += 2 + $length; + } + $npps = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 1)); + $offset += 1; + for ($i = 0; $i < $npps; $i ++) { + $length = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2)); + $h264['PPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length); + $offset += 2 + $length; + } + $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $h264; + break;*/ + } + + $info['video']['streams'][] = $track_info; + break; + + case 2: // Audio + $track_info['sample_rate'] = (isset($trackarray['SamplingFrequency']) ? $trackarray['SamplingFrequency'] : 8000.0); + $track_info['channels'] = (isset($trackarray['Channels']) ? $trackarray['Channels'] : 1); + $track_info['language'] = (isset($trackarray['Language']) ? $trackarray['Language'] : 'eng'); + if (isset($trackarray['BitDepth'])) { $track_info['bits_per_sample'] = $trackarray['BitDepth']; } + if (isset($trackarray['CodecName'])) { $track_info['codec'] = $trackarray['CodecName']; } + + switch ($trackarray['CodecID']) { + case 'A_PCM/INT/LIT': + case 'A_PCM/INT/BIG': + $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth']; + break; + + case 'A_AC3': + case 'A_DTS': + case 'A_MPEG/L3': + case 'A_MPEG/L2': + case 'A_FLAC': + if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, false)) { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.'.$track_info['dataformat'].'.php"'); + break; + } + + if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set'); + break; + } + + // create temp instance + $getid3_temp = new getID3(); + if ($track_info['dataformat'] != 'flac') { + $getid3_temp->openfile($this->getid3->filename); + } + $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset']; + if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') { + $getid3_temp->info['avdataend'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'] + $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['length']; + } + + // analyze + $class = 'getid3_'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']); + $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat']; + $getid3_audio = new $class($getid3_temp, __CLASS__); + if ($track_info['dataformat'] == 'flac') { + $getid3_audio->AnalyzeString($trackarray['CodecPrivate']); + } + else { + $getid3_audio->Analyze(); + } + if (!empty($getid3_temp->info[$header_data_key])) { + $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key]; + if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { + foreach ($getid3_temp->info['audio'] as $key => $value) { + $track_info[$key] = $value; + } + } + } + else { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because '.$class.'::Analyze() failed at offset '.$getid3_temp->info['avdataoffset']); + } + + // copy errors and warnings + if (!empty($getid3_temp->info['error'])) { + foreach ($getid3_temp->info['error'] as $newerror) { + $this->warning($class.'() says: ['.$newerror.']'); + } + } + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $newerror) { + if ($track_info['dataformat'] == 'mp3' && preg_match('/^Probable truncated file: expecting \d+ bytes of audio data, only found \d+ \(short by \d+ bytes\)$/', $newerror)) { + // LAME/Xing header is probably set, but audio data is chunked into Matroska file and near-impossible to verify if audio stream is complete, so ignore useless warning + continue; + } + $this->warning($class.'() says: ['.$newerror.']'); + } + } + unset($getid3_temp, $getid3_audio); + break; + + case 'A_AAC': + case 'A_AAC/MPEG2/LC': + case 'A_AAC/MPEG2/LC/SBR': + case 'A_AAC/MPEG4/LC': + case 'A_AAC/MPEG4/LC/SBR': + $this->warning($trackarray['CodecID'].' audio data contains no header, audio/video bitrates can\'t be calculated'); + break; + + case 'A_VORBIS': + if (!isset($trackarray['CodecPrivate'])) { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because CodecPrivate data not set'); + break; + } + $vorbis_offset = strpos($trackarray['CodecPrivate'], 'vorbis', 1); + if ($vorbis_offset === false) { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because CodecPrivate data does not contain "vorbis" keyword'); + break; + } + $vorbis_offset -= 1; + + if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, false)) { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.ogg.php"'); + break; + } + + // create temp instance + $getid3_temp = new getID3(); + + // analyze + $getid3_ogg = new getid3_ogg($getid3_temp); + $oggpageinfo['page_seqno'] = 0; + $getid3_ogg->ParseVorbisPageHeader($trackarray['CodecPrivate'], $vorbis_offset, $oggpageinfo); + if (!empty($getid3_temp->info['ogg'])) { + $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg']; + if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { + foreach ($getid3_temp->info['audio'] as $key => $value) { + $track_info[$key] = $value; + } + } + } + + // copy errors and warnings + if (!empty($getid3_temp->info['error'])) { + foreach ($getid3_temp->info['error'] as $newerror) { + $this->warning('getid3_ogg() says: ['.$newerror.']'); + } + } + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $newerror) { + $this->warning('getid3_ogg() says: ['.$newerror.']'); + } + } + + if (!empty($getid3_temp->info['ogg']['bitrate_nominal'])) { + $track_info['bitrate'] = $getid3_temp->info['ogg']['bitrate_nominal']; + } + unset($getid3_temp, $getid3_ogg, $oggpageinfo, $vorbis_offset); + break; + + case 'A_MS/ACM': + if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) { + $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"'); + break; + } + + $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']); + foreach ($parsed as $key => $value) { + if ($key != 'raw') { + $track_info[$key] = $value; + } + } + $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed; + break; + + default: + $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"'); + } + + $info['audio']['streams'][] = $track_info; + break; + } + } + + if (!empty($info['video']['streams'])) { + $info['video'] = self::getDefaultStreamInfo($info['video']['streams']); + } + if (!empty($info['audio']['streams'])) { + $info['audio'] = self::getDefaultStreamInfo($info['audio']['streams']); + } + } + + // process attachments + if (isset($info['matroska']['attachments']) && $this->getid3->option_save_attachments !== getID3::ATTACHMENTS_NONE) { + foreach ($info['matroska']['attachments'] as $i => $entry) { + if (strpos($entry['FileMimeType'], 'image/') === 0 && !empty($entry['FileData'])) { + $info['matroska']['comments']['picture'][] = array('data' => $entry['FileData'], 'image_mime' => $entry['FileMimeType'], 'filename' => $entry['FileName']); + } + } + } + + // determine mime type + if (!empty($info['video']['streams'])) { + $info['mime_type'] = ($info['matroska']['doctype'] == 'webm' ? 'video/webm' : 'video/x-matroska'); + } elseif (!empty($info['audio']['streams'])) { + $info['mime_type'] = ($info['matroska']['doctype'] == 'webm' ? 'audio/webm' : 'audio/x-matroska'); + } elseif (isset($info['mime_type'])) { + unset($info['mime_type']); + } + + return true; + } + + private function parseEBML(&$info) { + // http://www.matroska.org/technical/specs/index.html#EBMLBasics + $this->current_offset = $info['avdataoffset']; + + while ($this->getEBMLelement($top_element, $info['avdataend'])) { + switch ($top_element['id']) { + + case EBML_ID_EBML: + $info['fileformat'] = 'matroska'; + $info['matroska']['header']['offset'] = $top_element['offset']; + $info['matroska']['header']['length'] = $top_element['length']; + + while ($this->getEBMLelement($element_data, $top_element['end'], true)) { + switch ($element_data['id']) { + + case EBML_ID_EBMLVERSION: + case EBML_ID_EBMLREADVERSION: + case EBML_ID_EBMLMAXIDLENGTH: + case EBML_ID_EBMLMAXSIZELENGTH: + case EBML_ID_DOCTYPEVERSION: + case EBML_ID_DOCTYPEREADVERSION: + $element_data['data'] = getid3_lib::BigEndian2Int($element_data['data']); + break; + + case EBML_ID_DOCTYPE: + $element_data['data'] = getid3_lib::trimNullByte($element_data['data']); + $info['matroska']['doctype'] = $element_data['data']; + break; + + default: + $this->unhandledElement('header', __LINE__, $element_data); + } + + unset($element_data['offset'], $element_data['end']); + $info['matroska']['header']['elements'][] = $element_data; + } + break; + + case EBML_ID_SEGMENT: + $info['matroska']['segment'][0]['offset'] = $top_element['offset']; + $info['matroska']['segment'][0]['length'] = $top_element['length']; + + while ($this->getEBMLelement($element_data, $top_element['end'])) { + if ($element_data['id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required + $info['matroska']['segments'][] = $element_data; + } + switch ($element_data['id']) { + + case EBML_ID_SEEKHEAD: // Contains the position of other level 1 elements. + + while ($this->getEBMLelement($seek_entry, $element_data['end'])) { + switch ($seek_entry['id']) { + + case EBML_ID_SEEK: // Contains a single seek entry to an EBML element + while ($this->getEBMLelement($sub_seek_entry, $seek_entry['end'], true)) { + + switch ($sub_seek_entry['id']) { + + case EBML_ID_SEEKID: + $seek_entry['target_id'] = self::EBML2Int($sub_seek_entry['data']); + $seek_entry['target_name'] = self::EBMLidName($seek_entry['target_id']); + break; + + case EBML_ID_SEEKPOSITION: + $seek_entry['target_offset'] = $element_data['offset'] + getid3_lib::BigEndian2Int($sub_seek_entry['data']); + break; + + default: + $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); } + } + + if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required + $info['matroska']['seek'][] = $seek_entry; + } + break; + + default: + $this->unhandledElement('seekhead', __LINE__, $seek_entry); + } + } + break; + + case EBML_ID_TRACKS: // A top-level block of information with many tracks described. + $info['matroska']['tracks'] = $element_data; + + while ($this->getEBMLelement($track_entry, $element_data['end'])) { + switch ($track_entry['id']) { + + case EBML_ID_TRACKENTRY: //subelements: Describes a track with all elements. + + while ($this->getEBMLelement($subelement, $track_entry['end'], array(EBML_ID_VIDEO, EBML_ID_AUDIO, EBML_ID_CONTENTENCODINGS, EBML_ID_CODECPRIVATE))) { + switch ($subelement['id']) { + + case EBML_ID_TRACKNUMBER: + case EBML_ID_TRACKUID: + case EBML_ID_TRACKTYPE: + case EBML_ID_MINCACHE: + case EBML_ID_MAXCACHE: + case EBML_ID_MAXBLOCKADDITIONID: + case EBML_ID_DEFAULTDURATION: // nanoseconds per frame + $track_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']); + break; + + case EBML_ID_TRACKTIMECODESCALE: + $track_entry[$subelement['id_name']] = getid3_lib::BigEndian2Float($subelement['data']); + break; + + case EBML_ID_CODECID: + case EBML_ID_LANGUAGE: + case EBML_ID_NAME: + case EBML_ID_CODECNAME: + $track_entry[$subelement['id_name']] = getid3_lib::trimNullByte($subelement['data']); + break; + + case EBML_ID_CODECPRIVATE: + $track_entry[$subelement['id_name']] = $this->readEBMLelementData($subelement['length'], true); + break; + + case EBML_ID_FLAGENABLED: + case EBML_ID_FLAGDEFAULT: + case EBML_ID_FLAGFORCED: + case EBML_ID_FLAGLACING: + case EBML_ID_CODECDECODEALL: + $track_entry[$subelement['id_name']] = (bool) getid3_lib::BigEndian2Int($subelement['data']); + break; + + case EBML_ID_VIDEO: + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) { + switch ($sub_subelement['id']) { + + case EBML_ID_PIXELWIDTH: + case EBML_ID_PIXELHEIGHT: + case EBML_ID_PIXELCROPBOTTOM: + case EBML_ID_PIXELCROPTOP: + case EBML_ID_PIXELCROPLEFT: + case EBML_ID_PIXELCROPRIGHT: + case EBML_ID_DISPLAYWIDTH: + case EBML_ID_DISPLAYHEIGHT: + case EBML_ID_DISPLAYUNIT: + case EBML_ID_ASPECTRATIOTYPE: + case EBML_ID_STEREOMODE: + case EBML_ID_OLDSTEREOMODE: + $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_FLAGINTERLACED: + $track_entry[$sub_subelement['id_name']] = (bool)getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_GAMMAVALUE: + $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Float($sub_subelement['data']); + break; + + case EBML_ID_COLOURSPACE: + $track_entry[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']); + break; + + default: + $this->unhandledElement('track.video', __LINE__, $sub_subelement); + } + } + break; + + case EBML_ID_AUDIO: + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) { + switch ($sub_subelement['id']) { + + case EBML_ID_CHANNELS: + case EBML_ID_BITDEPTH: + $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_SAMPLINGFREQUENCY: + case EBML_ID_OUTPUTSAMPLINGFREQUENCY: + $track_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Float($sub_subelement['data']); + break; + + case EBML_ID_CHANNELPOSITIONS: + $track_entry[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']); + break; + + default: + $this->unhandledElement('track.audio', __LINE__, $sub_subelement); + } + } + break; + + case EBML_ID_CONTENTENCODINGS: + + while ($this->getEBMLelement($sub_subelement, $subelement['end'])) { + switch ($sub_subelement['id']) { + + case EBML_ID_CONTENTENCODING: + + while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], array(EBML_ID_CONTENTCOMPRESSION, EBML_ID_CONTENTENCRYPTION))) { + switch ($sub_sub_subelement['id']) { + + case EBML_ID_CONTENTENCODINGORDER: + case EBML_ID_CONTENTENCODINGSCOPE: + case EBML_ID_CONTENTENCODINGTYPE: + $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + break; + + case EBML_ID_CONTENTCOMPRESSION: + + while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) { + switch ($sub_sub_sub_subelement['id']) { + + case EBML_ID_CONTENTCOMPALGO: + $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_sub_subelement['data']); + break; + + case EBML_ID_CONTENTCOMPSETTINGS: + $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = $sub_sub_sub_subelement['data']; + break; + + default: + $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement); + } + } + break; + + case EBML_ID_CONTENTENCRYPTION: + + while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) { + switch ($sub_sub_sub_subelement['id']) { + + case EBML_ID_CONTENTENCALGO: + case EBML_ID_CONTENTSIGALGO: + case EBML_ID_CONTENTSIGHASHALGO: + $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_sub_subelement['data']); + break; + + case EBML_ID_CONTENTENCKEYID: + case EBML_ID_CONTENTSIGNATURE: + case EBML_ID_CONTENTSIGKEYID: + $track_entry[$sub_subelement['id_name']][$sub_sub_subelement['id_name']][$sub_sub_sub_subelement['id_name']] = $sub_sub_sub_subelement['data']; + break; + + default: + $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement); + } + } + break; + + default: + $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement); + } + } + break; + + default: + $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement); + } + } + break; + + default: + $this->unhandledElement('track', __LINE__, $subelement); + } + } + + $info['matroska']['tracks']['tracks'][] = $track_entry; + break; + + default: + $this->unhandledElement('tracks', __LINE__, $track_entry); + } + } + break; + + case EBML_ID_INFO: // Contains miscellaneous general information and statistics on the file. + $info_entry = array(); + + while ($this->getEBMLelement($subelement, $element_data['end'], true)) { + switch ($subelement['id']) { + + case EBML_ID_TIMECODESCALE: + $info_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']); + break; + + case EBML_ID_DURATION: + $info_entry[$subelement['id_name']] = getid3_lib::BigEndian2Float($subelement['data']); + break; + + case EBML_ID_DATEUTC: + $info_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']); + $info_entry[$subelement['id_name'].'_unix'] = self::EBMLdate2unix($info_entry[$subelement['id_name']]); + break; + + case EBML_ID_SEGMENTUID: + case EBML_ID_PREVUID: + case EBML_ID_NEXTUID: + $info_entry[$subelement['id_name']] = getid3_lib::trimNullByte($subelement['data']); + break; + + case EBML_ID_SEGMENTFAMILY: + $info_entry[$subelement['id_name']][] = getid3_lib::trimNullByte($subelement['data']); + break; + + case EBML_ID_SEGMENTFILENAME: + case EBML_ID_PREVFILENAME: + case EBML_ID_NEXTFILENAME: + case EBML_ID_TITLE: + case EBML_ID_MUXINGAPP: + case EBML_ID_WRITINGAPP: + $info_entry[$subelement['id_name']] = getid3_lib::trimNullByte($subelement['data']); + $info['matroska']['comments'][strtolower($subelement['id_name'])][] = $info_entry[$subelement['id_name']]; + break; + + case EBML_ID_CHAPTERTRANSLATE: + $chaptertranslate_entry = array(); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) { + switch ($sub_subelement['id']) { + + case EBML_ID_CHAPTERTRANSLATEEDITIONUID: + $chaptertranslate_entry[$sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_CHAPTERTRANSLATECODEC: + $chaptertranslate_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_CHAPTERTRANSLATEID: + $chaptertranslate_entry[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']); + break; + + default: + $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement); + } + } + $info_entry[$subelement['id_name']] = $chaptertranslate_entry; + break; + + default: + $this->unhandledElement('info', __LINE__, $subelement); + } + } + $info['matroska']['info'][] = $info_entry; + break; + + case EBML_ID_CUES: // A top-level element to speed seeking access. All entries are local to the segment. Should be mandatory for non "live" streams. + if (self::$hide_clusters) { // do not parse cues if hide clusters is "ON" till they point to clusters anyway + $this->current_offset = $element_data['end']; + break; + } + $cues_entry = array(); + + while ($this->getEBMLelement($subelement, $element_data['end'])) { + switch ($subelement['id']) { + + case EBML_ID_CUEPOINT: + $cuepoint_entry = array(); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_CUETRACKPOSITIONS))) { + switch ($sub_subelement['id']) { + + case EBML_ID_CUETRACKPOSITIONS: + $cuetrackpositions_entry = array(); + + while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], true)) { + switch ($sub_sub_subelement['id']) { + + case EBML_ID_CUETRACK: + case EBML_ID_CUECLUSTERPOSITION: + case EBML_ID_CUEBLOCKNUMBER: + case EBML_ID_CUECODECSTATE: + $cuetrackpositions_entry[$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + break; + + default: + $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement); + } + } + $cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry; + break; + + case EBML_ID_CUETIME: + $cuepoint_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + default: + $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement); + } + } + $cues_entry[] = $cuepoint_entry; + break; + + default: + $this->unhandledElement('cues', __LINE__, $subelement); + } + } + $info['matroska']['cues'] = $cues_entry; + break; + + case EBML_ID_TAGS: // Element containing elements specific to Tracks/Chapters. + $tags_entry = array(); + + while ($this->getEBMLelement($subelement, $element_data['end'], false)) { + switch ($subelement['id']) { + + case EBML_ID_TAG: + $tag_entry = array(); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], false)) { + switch ($sub_subelement['id']) { + + case EBML_ID_TARGETS: + $targets_entry = array(); + + while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], true)) { + switch ($sub_sub_subelement['id']) { + + case EBML_ID_TARGETTYPEVALUE: + $targets_entry[$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + $targets_entry[strtolower($sub_sub_subelement['id_name']).'_long'] = self::TargetTypeValue($targets_entry[$sub_sub_subelement['id_name']]); + break; + + case EBML_ID_TARGETTYPE: + $targets_entry[$sub_sub_subelement['id_name']] = $sub_sub_subelement['data']; + break; + + case EBML_ID_TAGTRACKUID: + case EBML_ID_TAGEDITIONUID: + case EBML_ID_TAGCHAPTERUID: + case EBML_ID_TAGATTACHMENTUID: + $targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + break; + + default: + $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement); + } + } + $tag_entry[$sub_subelement['id_name']] = $targets_entry; + break; + + case EBML_ID_SIMPLETAG: + $tag_entry[$sub_subelement['id_name']][] = $this->HandleEMBLSimpleTag($sub_subelement['end']); + break; + + default: + $this->unhandledElement('tags.tag', __LINE__, $sub_subelement); + } + } + $tags_entry[] = $tag_entry; + break; + + default: + $this->unhandledElement('tags', __LINE__, $subelement); + } + } + $info['matroska']['tags'] = $tags_entry; + break; + + case EBML_ID_ATTACHMENTS: // Contain attached files. + + while ($this->getEBMLelement($subelement, $element_data['end'])) { + switch ($subelement['id']) { + + case EBML_ID_ATTACHEDFILE: + $attachedfile_entry = array(); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_FILEDATA))) { + switch ($sub_subelement['id']) { + + case EBML_ID_FILEDESCRIPTION: + case EBML_ID_FILENAME: + case EBML_ID_FILEMIMETYPE: + $attachedfile_entry[$sub_subelement['id_name']] = $sub_subelement['data']; + break; + + case EBML_ID_FILEDATA: + $attachedfile_entry['data_offset'] = $this->current_offset; + $attachedfile_entry['data_length'] = $sub_subelement['length']; + + $attachedfile_entry[$sub_subelement['id_name']] = $this->saveAttachment( + $attachedfile_entry['FileName'], + $attachedfile_entry['data_offset'], + $attachedfile_entry['data_length']); + + $this->current_offset = $sub_subelement['end']; + break; + + case EBML_ID_FILEUID: + $attachedfile_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + default: + $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement); + } + } + $info['matroska']['attachments'][] = $attachedfile_entry; + break; + + default: + $this->unhandledElement('attachments', __LINE__, $subelement); + } + } + break; + + case EBML_ID_CHAPTERS: + + while ($this->getEBMLelement($subelement, $element_data['end'])) { + switch ($subelement['id']) { + + case EBML_ID_EDITIONENTRY: + $editionentry_entry = array(); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_CHAPTERATOM))) { + switch ($sub_subelement['id']) { + + case EBML_ID_EDITIONUID: + $editionentry_entry[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_EDITIONFLAGHIDDEN: + case EBML_ID_EDITIONFLAGDEFAULT: + case EBML_ID_EDITIONFLAGORDERED: + $editionentry_entry[$sub_subelement['id_name']] = (bool)getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_CHAPTERATOM: + $chapteratom_entry = array(); + + while ($this->getEBMLelement($sub_sub_subelement, $sub_subelement['end'], array(EBML_ID_CHAPTERTRACK, EBML_ID_CHAPTERDISPLAY))) { + switch ($sub_sub_subelement['id']) { + + case EBML_ID_CHAPTERSEGMENTUID: + case EBML_ID_CHAPTERSEGMENTEDITIONUID: + $chapteratom_entry[$sub_sub_subelement['id_name']] = $sub_sub_subelement['data']; + break; + + case EBML_ID_CHAPTERFLAGENABLED: + case EBML_ID_CHAPTERFLAGHIDDEN: + $chapteratom_entry[$sub_sub_subelement['id_name']] = (bool)getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + break; + + case EBML_ID_CHAPTERUID: + case EBML_ID_CHAPTERTIMESTART: + case EBML_ID_CHAPTERTIMEEND: + $chapteratom_entry[$sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + break; + + case EBML_ID_CHAPTERTRACK: + $chaptertrack_entry = array(); + + while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) { + switch ($sub_sub_sub_subelement['id']) { + + case EBML_ID_CHAPTERTRACKNUMBER: + $chaptertrack_entry[$sub_sub_sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_sub_sub_subelement['data']); + break; + + default: + $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement); + } + } + $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry; + break; + + case EBML_ID_CHAPTERDISPLAY: + $chapterdisplay_entry = array(); + + while ($this->getEBMLelement($sub_sub_sub_subelement, $sub_sub_subelement['end'], true)) { + switch ($sub_sub_sub_subelement['id']) { + + case EBML_ID_CHAPSTRING: + case EBML_ID_CHAPLANGUAGE: + case EBML_ID_CHAPCOUNTRY: + $chapterdisplay_entry[$sub_sub_sub_subelement['id_name']] = $sub_sub_sub_subelement['data']; + break; + + default: + $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement); + } + } + $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry; + break; + + default: + $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement); + } + } + $editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry; + break; + + default: + $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement); + } + } + $info['matroska']['chapters'][] = $editionentry_entry; + break; + + default: + $this->unhandledElement('chapters', __LINE__, $subelement); + } + } + break; + + case EBML_ID_CLUSTER: // The lower level element containing the (monolithic) Block structure. + $cluster_entry = array(); + + while ($this->getEBMLelement($subelement, $element_data['end'], array(EBML_ID_CLUSTERSILENTTRACKS, EBML_ID_CLUSTERBLOCKGROUP, EBML_ID_CLUSTERSIMPLEBLOCK))) { + switch ($subelement['id']) { + + case EBML_ID_CLUSTERTIMECODE: + case EBML_ID_CLUSTERPOSITION: + case EBML_ID_CLUSTERPREVSIZE: + $cluster_entry[$subelement['id_name']] = getid3_lib::BigEndian2Int($subelement['data']); + break; + + case EBML_ID_CLUSTERSILENTTRACKS: + $cluster_silent_tracks = array(); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], true)) { + switch ($sub_subelement['id']) { + + case EBML_ID_CLUSTERSILENTTRACKNUMBER: + $cluster_silent_tracks[] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + default: + $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement); + } + } + $cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks; + break; + + case EBML_ID_CLUSTERBLOCKGROUP: + $cluster_block_group = array('offset' => $this->current_offset); + + while ($this->getEBMLelement($sub_subelement, $subelement['end'], array(EBML_ID_CLUSTERBLOCK))) { + switch ($sub_subelement['id']) { + + case EBML_ID_CLUSTERBLOCK: + $cluster_block_group[$sub_subelement['id_name']] = $this->HandleEMBLClusterBlock($sub_subelement, EBML_ID_CLUSTERBLOCK, $info); + break; + + case EBML_ID_CLUSTERREFERENCEPRIORITY: // unsigned-int + case EBML_ID_CLUSTERBLOCKDURATION: // unsigned-int + $cluster_block_group[$sub_subelement['id_name']] = getid3_lib::BigEndian2Int($sub_subelement['data']); + break; + + case EBML_ID_CLUSTERREFERENCEBLOCK: // signed-int + $cluster_block_group[$sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_subelement['data'], false, true); + break; + + case EBML_ID_CLUSTERCODECSTATE: + $cluster_block_group[$sub_subelement['id_name']] = getid3_lib::trimNullByte($sub_subelement['data']); + break; + + default: + $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement); + } + } + $cluster_entry[$subelement['id_name']][] = $cluster_block_group; + break; + + case EBML_ID_CLUSTERSIMPLEBLOCK: + $cluster_entry[$subelement['id_name']][] = $this->HandleEMBLClusterBlock($subelement, EBML_ID_CLUSTERSIMPLEBLOCK, $info); + break; + + default: + $this->unhandledElement('cluster', __LINE__, $subelement); + } + $this->current_offset = $subelement['end']; + } + if (!self::$hide_clusters) { + $info['matroska']['cluster'][] = $cluster_entry; + } + + // check to see if all the data we need exists already, if so, break out of the loop + if (!self::$parse_whole_file) { + if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) { + if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) { + if (count($info['matroska']['track_data_offsets']) == count($info['matroska']['tracks']['tracks'])) { + return; + } + } + } + } + break; + + default: + $this->unhandledElement('segment', __LINE__, $element_data); + } + } + break; + + default: + $this->unhandledElement('root', __LINE__, $top_element); + } + } + } + + private function EnsureBufferHasEnoughData($min_data=1024) { + if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) { + $read_bytes = max($min_data, $this->getid3->fread_buffer_size()); + + try { + $this->fseek($this->current_offset); + $this->EBMLbuffer_offset = $this->current_offset; + $this->EBMLbuffer = $this->fread($read_bytes); + $this->EBMLbuffer_length = strlen($this->EBMLbuffer); + } catch (getid3_exception $e) { + $this->warning('EBML parser: '.$e->getMessage()); + return false; + } + + if ($this->EBMLbuffer_length == 0 && $this->feof()) { + return $this->error('EBML parser: ran out of file at offset '.$this->current_offset); + } + } + return true; + } + + private function readEBMLint() { + $actual_offset = $this->current_offset - $this->EBMLbuffer_offset; + + // get length of integer + $first_byte_int = ord($this->EBMLbuffer[$actual_offset]); + if (0x80 & $first_byte_int) { + $length = 1; + } elseif (0x40 & $first_byte_int) { + $length = 2; + } elseif (0x20 & $first_byte_int) { + $length = 3; + } elseif (0x10 & $first_byte_int) { + $length = 4; + } elseif (0x08 & $first_byte_int) { + $length = 5; + } elseif (0x04 & $first_byte_int) { + $length = 6; + } elseif (0x02 & $first_byte_int) { + $length = 7; + } elseif (0x01 & $first_byte_int) { + $length = 8; + } else { + throw new Exception('invalid EBML integer (leading 0x00) at '.$this->current_offset); + } + + // read + $int_value = self::EBML2Int(substr($this->EBMLbuffer, $actual_offset, $length)); + $this->current_offset += $length; + + return $int_value; + } + + private function readEBMLelementData($length, $check_buffer=false) { + if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) { + return false; + } + $data = substr($this->EBMLbuffer, $this->current_offset - $this->EBMLbuffer_offset, $length); + $this->current_offset += $length; + return $data; + } + + private function getEBMLelement(&$element, $parent_end, $get_data=false) { + if ($this->current_offset >= $parent_end) { + return false; + } + + if (!$this->EnsureBufferHasEnoughData()) { + $this->current_offset = PHP_INT_MAX; // do not exit parser right now, allow to finish current loop to gather maximum information + return false; + } + + $element = array(); + + // set offset + $element['offset'] = $this->current_offset; + + // get ID + $element['id'] = $this->readEBMLint(); + + // get name + $element['id_name'] = self::EBMLidName($element['id']); + + // get length + $element['length'] = $this->readEBMLint(); + + // get end offset + $element['end'] = $this->current_offset + $element['length']; + + // get raw data + $dont_parse = (in_array($element['id'], $this->unuseful_elements) || $element['id_name'] == dechex($element['id'])); + if (($get_data === true || (is_array($get_data) && !in_array($element['id'], $get_data))) && !$dont_parse) { + $element['data'] = $this->readEBMLelementData($element['length'], $element); + } + + return true; + } + + private function unhandledElement($type, $line, $element) { + // warn only about unknown and missed elements, not about unuseful + if (!in_array($element['id'], $this->unuseful_elements)) { + $this->warning('Unhandled '.$type.' element ['.basename(__FILE__).':'.$line.'] ('.$element['id'].'::'.$element['id_name'].' ['.$element['length'].' bytes]) at '.$element['offset']); + } + + // increase offset for unparsed elements + if (!isset($element['data'])) { + $this->current_offset = $element['end']; + } + } + + private function ExtractCommentsSimpleTag($SimpleTagArray) { + if (!empty($SimpleTagArray['SimpleTag'])) { + foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) { + if (!empty($SimpleTagData['TagName']) && !empty($SimpleTagData['TagString'])) { + $this->getid3->info['matroska']['comments'][strtolower($SimpleTagData['TagName'])][] = $SimpleTagData['TagString']; + } + if (!empty($SimpleTagData['SimpleTag'])) { + $this->ExtractCommentsSimpleTag($SimpleTagData); + } + } + } + + return true; + } + + private function HandleEMBLSimpleTag($parent_end) { + $simpletag_entry = array(); + + while ($this->getEBMLelement($element, $parent_end, array(EBML_ID_SIMPLETAG))) { + switch ($element['id']) { + + case EBML_ID_TAGNAME: + case EBML_ID_TAGLANGUAGE: + case EBML_ID_TAGSTRING: + case EBML_ID_TAGBINARY: + $simpletag_entry[$element['id_name']] = $element['data']; + break; + + case EBML_ID_SIMPLETAG: + $simpletag_entry[$element['id_name']][] = $this->HandleEMBLSimpleTag($element['end']); + break; + + case EBML_ID_TAGDEFAULT: + $simpletag_entry[$element['id_name']] = (bool)getid3_lib::BigEndian2Int($element['data']); + break; + + default: + $this->unhandledElement('tag.simpletag', __LINE__, $element); + } + } + + return $simpletag_entry; + } + + private function HandleEMBLClusterBlock($element, $block_type, &$info) { + // http://www.matroska.org/technical/specs/index.html#block_structure + // http://www.matroska.org/technical/specs/index.html#simpleblock_structure + + $block_data = array(); + $block_data['tracknumber'] = $this->readEBMLint(); + $block_data['timecode'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(2), false, true); + $block_data['flags_raw'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(1)); + + if ($block_type == EBML_ID_CLUSTERSIMPLEBLOCK) { + $block_data['flags']['keyframe'] = (($block_data['flags_raw'] & 0x80) >> 7); + //$block_data['flags']['reserved1'] = (($block_data['flags_raw'] & 0x70) >> 4); + } + else { + //$block_data['flags']['reserved1'] = (($block_data['flags_raw'] & 0xF0) >> 4); + } + $block_data['flags']['invisible'] = (bool)(($block_data['flags_raw'] & 0x08) >> 3); + $block_data['flags']['lacing'] = (($block_data['flags_raw'] & 0x06) >> 1); // 00=no lacing; 01=Xiph lacing; 11=EBML lacing; 10=fixed-size lacing + if ($block_type == EBML_ID_CLUSTERSIMPLEBLOCK) { + $block_data['flags']['discardable'] = (($block_data['flags_raw'] & 0x01)); + } + else { + //$block_data['flags']['reserved2'] = (($block_data['flags_raw'] & 0x01) >> 0); + } + $block_data['flags']['lacing_type'] = self::BlockLacingType($block_data['flags']['lacing']); + + // Lace (when lacing bit is set) + if ($block_data['flags']['lacing'] > 0) { + $block_data['lace_frames'] = getid3_lib::BigEndian2Int($this->readEBMLelementData(1)) + 1; // Number of frames in the lace-1 (uint8) + if ($block_data['flags']['lacing'] != 0x02) { + for ($i = 1; $i < $block_data['lace_frames']; $i ++) { // Lace-coded size of each frame of the lace, except for the last one (multiple uint8). *This is not used with Fixed-size lacing as it is calculated automatically from (total size of lace) / (number of frames in lace). + if ($block_data['flags']['lacing'] == 0x03) { // EBML lacing + $block_data['lace_frames_size'][$i] = $this->readEBMLint(); // TODO: read size correctly, calc size for the last frame. For now offsets are deteminded OK with readEBMLint() and that's the most important thing. + } + else { // Xiph lacing + $block_data['lace_frames_size'][$i] = 0; + do { + $size = getid3_lib::BigEndian2Int($this->readEBMLelementData(1)); + $block_data['lace_frames_size'][$i] += $size; + } + while ($size == 255); + } + } + if ($block_data['flags']['lacing'] == 0x01) { // calc size of the last frame only for Xiph lacing, till EBML sizes are now anyway determined incorrectly + $block_data['lace_frames_size'][] = $element['end'] - $this->current_offset - array_sum($block_data['lace_frames_size']); + } + } + } + + if (!isset($info['matroska']['track_data_offsets'][$block_data['tracknumber']])) { + $info['matroska']['track_data_offsets'][$block_data['tracknumber']]['offset'] = $this->current_offset; + $info['matroska']['track_data_offsets'][$block_data['tracknumber']]['length'] = $element['end'] - $this->current_offset; + //$info['matroska']['track_data_offsets'][$block_data['tracknumber']]['total_length'] = 0; + } + //$info['matroska']['track_data_offsets'][$block_data['tracknumber']]['total_length'] += $info['matroska']['track_data_offsets'][$block_data['tracknumber']]['length']; + //$info['matroska']['track_data_offsets'][$block_data['tracknumber']]['duration'] = $block_data['timecode'] * ((isset($info['matroska']['info'][0]['TimecodeScale']) ? $info['matroska']['info'][0]['TimecodeScale'] : 1000000) / 1000000000); + + // set offset manually + $this->current_offset = $element['end']; + + return $block_data; + } + + private static function EBML2Int($EBMLstring) { + // http://matroska.org/specs/ + + // Element ID coded with an UTF-8 like system: + // 1xxx xxxx - Class A IDs (2^7 -2 possible values) (base 0x8X) + // 01xx xxxx xxxx xxxx - Class B IDs (2^14-2 possible values) (base 0x4X 0xXX) + // 001x xxxx xxxx xxxx xxxx xxxx - Class C IDs (2^21-2 possible values) (base 0x2X 0xXX 0xXX) + // 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - Class D IDs (2^28-2 possible values) (base 0x1X 0xXX 0xXX 0xXX) + // Values with all x at 0 and 1 are reserved (hence the -2). + + // Data size, in octets, is also coded with an UTF-8 like system : + // 1xxx xxxx - value 0 to 2^7-2 + // 01xx xxxx xxxx xxxx - value 0 to 2^14-2 + // 001x xxxx xxxx xxxx xxxx xxxx - value 0 to 2^21-2 + // 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^28-2 + // 0000 1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^35-2 + // 0000 01xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^42-2 + // 0000 001x xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^49-2 + // 0000 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^56-2 + + $first_byte_int = ord($EBMLstring[0]); + if (0x80 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x7F); + } elseif (0x40 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x3F); + } elseif (0x20 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x1F); + } elseif (0x10 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x0F); + } elseif (0x08 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x07); + } elseif (0x04 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x03); + } elseif (0x02 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x01); + } elseif (0x01 & $first_byte_int) { + $EBMLstring[0] = chr($first_byte_int & 0x00); + } + + return getid3_lib::BigEndian2Int($EBMLstring); + } + + private static function EBMLdate2unix($EBMLdatestamp) { + // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC) + // 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC + return round(($EBMLdatestamp / 1000000000) + 978307200); + } + + public static function TargetTypeValue($target_type) { + // http://www.matroska.org/technical/specs/tagging/index.html + static $TargetTypeValue = array(); + if (empty($TargetTypeValue)) { + $TargetTypeValue[10] = 'A: ~ V:shot'; // the lowest hierarchy found in music or movies + $TargetTypeValue[20] = 'A:subtrack/part/movement ~ V:scene'; // corresponds to parts of a track for audio (like a movement) + $TargetTypeValue[30] = 'A:track/song ~ V:chapter'; // the common parts of an album or a movie + $TargetTypeValue[40] = 'A:part/session ~ V:part/session'; // when an album or episode has different logical parts + $TargetTypeValue[50] = 'A:album/opera/concert ~ V:movie/episode/concert'; // the most common grouping level of music and video (equals to an episode for TV series) + $TargetTypeValue[60] = 'A:edition/issue/volume/opus ~ V:season/sequel/volume'; // a list of lower levels grouped together + $TargetTypeValue[70] = 'A:collection ~ V:collection'; // the high hierarchy consisting of many different lower items + } + return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type); + } + + public static function BlockLacingType($lacingtype) { + // http://matroska.org/technical/specs/index.html#block_structure + static $BlockLacingType = array(); + if (empty($BlockLacingType)) { + $BlockLacingType[0x00] = 'no lacing'; + $BlockLacingType[0x01] = 'Xiph lacing'; + $BlockLacingType[0x02] = 'fixed-size lacing'; + $BlockLacingType[0x03] = 'EBML lacing'; + } + return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype); + } + + public static function CodecIDtoCommonName($codecid) { + // http://www.matroska.org/technical/specs/codecid/index.html + static $CodecIDlist = array(); + if (empty($CodecIDlist)) { + $CodecIDlist['A_AAC'] = 'aac'; + $CodecIDlist['A_AAC/MPEG2/LC'] = 'aac'; + $CodecIDlist['A_AC3'] = 'ac3'; + $CodecIDlist['A_DTS'] = 'dts'; + $CodecIDlist['A_FLAC'] = 'flac'; + $CodecIDlist['A_MPEG/L1'] = 'mp1'; + $CodecIDlist['A_MPEG/L2'] = 'mp2'; + $CodecIDlist['A_MPEG/L3'] = 'mp3'; + $CodecIDlist['A_PCM/INT/LIT'] = 'pcm'; // PCM Integer Little Endian + $CodecIDlist['A_PCM/INT/BIG'] = 'pcm'; // PCM Integer Big Endian + $CodecIDlist['A_QUICKTIME/QDMC'] = 'quicktime'; // Quicktime: QDesign Music + $CodecIDlist['A_QUICKTIME/QDM2'] = 'quicktime'; // Quicktime: QDesign Music v2 + $CodecIDlist['A_VORBIS'] = 'vorbis'; + $CodecIDlist['V_MPEG1'] = 'mpeg'; + $CodecIDlist['V_THEORA'] = 'theora'; + $CodecIDlist['V_REAL/RV40'] = 'real'; + $CodecIDlist['V_REAL/RV10'] = 'real'; + $CodecIDlist['V_REAL/RV20'] = 'real'; + $CodecIDlist['V_REAL/RV30'] = 'real'; + $CodecIDlist['V_QUICKTIME'] = 'quicktime'; // Quicktime + $CodecIDlist['V_MPEG4/ISO/AP'] = 'mpeg4'; + $CodecIDlist['V_MPEG4/ISO/ASP'] = 'mpeg4'; + $CodecIDlist['V_MPEG4/ISO/AVC'] = 'h264'; + $CodecIDlist['V_MPEG4/ISO/SP'] = 'mpeg4'; + $CodecIDlist['V_VP8'] = 'vp8'; + $CodecIDlist['V_MS/VFW/FOURCC'] = 'riff'; + $CodecIDlist['A_MS/ACM'] = 'riff'; + } + return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid); + } + + private static function EBMLidName($value) { + static $EBMLidList = array(); + if (empty($EBMLidList)) { + $EBMLidList[EBML_ID_ASPECTRATIOTYPE] = 'AspectRatioType'; + $EBMLidList[EBML_ID_ATTACHEDFILE] = 'AttachedFile'; + $EBMLidList[EBML_ID_ATTACHMENTLINK] = 'AttachmentLink'; + $EBMLidList[EBML_ID_ATTACHMENTS] = 'Attachments'; + $EBMLidList[EBML_ID_AUDIO] = 'Audio'; + $EBMLidList[EBML_ID_BITDEPTH] = 'BitDepth'; + $EBMLidList[EBML_ID_CHANNELPOSITIONS] = 'ChannelPositions'; + $EBMLidList[EBML_ID_CHANNELS] = 'Channels'; + $EBMLidList[EBML_ID_CHAPCOUNTRY] = 'ChapCountry'; + $EBMLidList[EBML_ID_CHAPLANGUAGE] = 'ChapLanguage'; + $EBMLidList[EBML_ID_CHAPPROCESS] = 'ChapProcess'; + $EBMLidList[EBML_ID_CHAPPROCESSCODECID] = 'ChapProcessCodecID'; + $EBMLidList[EBML_ID_CHAPPROCESSCOMMAND] = 'ChapProcessCommand'; + $EBMLidList[EBML_ID_CHAPPROCESSDATA] = 'ChapProcessData'; + $EBMLidList[EBML_ID_CHAPPROCESSPRIVATE] = 'ChapProcessPrivate'; + $EBMLidList[EBML_ID_CHAPPROCESSTIME] = 'ChapProcessTime'; + $EBMLidList[EBML_ID_CHAPSTRING] = 'ChapString'; + $EBMLidList[EBML_ID_CHAPTERATOM] = 'ChapterAtom'; + $EBMLidList[EBML_ID_CHAPTERDISPLAY] = 'ChapterDisplay'; + $EBMLidList[EBML_ID_CHAPTERFLAGENABLED] = 'ChapterFlagEnabled'; + $EBMLidList[EBML_ID_CHAPTERFLAGHIDDEN] = 'ChapterFlagHidden'; + $EBMLidList[EBML_ID_CHAPTERPHYSICALEQUIV] = 'ChapterPhysicalEquiv'; + $EBMLidList[EBML_ID_CHAPTERS] = 'Chapters'; + $EBMLidList[EBML_ID_CHAPTERSEGMENTEDITIONUID] = 'ChapterSegmentEditionUID'; + $EBMLidList[EBML_ID_CHAPTERSEGMENTUID] = 'ChapterSegmentUID'; + $EBMLidList[EBML_ID_CHAPTERTIMEEND] = 'ChapterTimeEnd'; + $EBMLidList[EBML_ID_CHAPTERTIMESTART] = 'ChapterTimeStart'; + $EBMLidList[EBML_ID_CHAPTERTRACK] = 'ChapterTrack'; + $EBMLidList[EBML_ID_CHAPTERTRACKNUMBER] = 'ChapterTrackNumber'; + $EBMLidList[EBML_ID_CHAPTERTRANSLATE] = 'ChapterTranslate'; + $EBMLidList[EBML_ID_CHAPTERTRANSLATECODEC] = 'ChapterTranslateCodec'; + $EBMLidList[EBML_ID_CHAPTERTRANSLATEEDITIONUID] = 'ChapterTranslateEditionUID'; + $EBMLidList[EBML_ID_CHAPTERTRANSLATEID] = 'ChapterTranslateID'; + $EBMLidList[EBML_ID_CHAPTERUID] = 'ChapterUID'; + $EBMLidList[EBML_ID_CLUSTER] = 'Cluster'; + $EBMLidList[EBML_ID_CLUSTERBLOCK] = 'ClusterBlock'; + $EBMLidList[EBML_ID_CLUSTERBLOCKADDID] = 'ClusterBlockAddID'; + $EBMLidList[EBML_ID_CLUSTERBLOCKADDITIONAL] = 'ClusterBlockAdditional'; + $EBMLidList[EBML_ID_CLUSTERBLOCKADDITIONID] = 'ClusterBlockAdditionID'; + $EBMLidList[EBML_ID_CLUSTERBLOCKADDITIONS] = 'ClusterBlockAdditions'; + $EBMLidList[EBML_ID_CLUSTERBLOCKDURATION] = 'ClusterBlockDuration'; + $EBMLidList[EBML_ID_CLUSTERBLOCKGROUP] = 'ClusterBlockGroup'; + $EBMLidList[EBML_ID_CLUSTERBLOCKMORE] = 'ClusterBlockMore'; + $EBMLidList[EBML_ID_CLUSTERBLOCKVIRTUAL] = 'ClusterBlockVirtual'; + $EBMLidList[EBML_ID_CLUSTERCODECSTATE] = 'ClusterCodecState'; + $EBMLidList[EBML_ID_CLUSTERDELAY] = 'ClusterDelay'; + $EBMLidList[EBML_ID_CLUSTERDURATION] = 'ClusterDuration'; + $EBMLidList[EBML_ID_CLUSTERENCRYPTEDBLOCK] = 'ClusterEncryptedBlock'; + $EBMLidList[EBML_ID_CLUSTERFRAMENUMBER] = 'ClusterFrameNumber'; + $EBMLidList[EBML_ID_CLUSTERLACENUMBER] = 'ClusterLaceNumber'; + $EBMLidList[EBML_ID_CLUSTERPOSITION] = 'ClusterPosition'; + $EBMLidList[EBML_ID_CLUSTERPREVSIZE] = 'ClusterPrevSize'; + $EBMLidList[EBML_ID_CLUSTERREFERENCEBLOCK] = 'ClusterReferenceBlock'; + $EBMLidList[EBML_ID_CLUSTERREFERENCEPRIORITY] = 'ClusterReferencePriority'; + $EBMLidList[EBML_ID_CLUSTERREFERENCEVIRTUAL] = 'ClusterReferenceVirtual'; + $EBMLidList[EBML_ID_CLUSTERSILENTTRACKNUMBER] = 'ClusterSilentTrackNumber'; + $EBMLidList[EBML_ID_CLUSTERSILENTTRACKS] = 'ClusterSilentTracks'; + $EBMLidList[EBML_ID_CLUSTERSIMPLEBLOCK] = 'ClusterSimpleBlock'; + $EBMLidList[EBML_ID_CLUSTERTIMECODE] = 'ClusterTimecode'; + $EBMLidList[EBML_ID_CLUSTERTIMESLICE] = 'ClusterTimeSlice'; + $EBMLidList[EBML_ID_CODECDECODEALL] = 'CodecDecodeAll'; + $EBMLidList[EBML_ID_CODECDOWNLOADURL] = 'CodecDownloadURL'; + $EBMLidList[EBML_ID_CODECID] = 'CodecID'; + $EBMLidList[EBML_ID_CODECINFOURL] = 'CodecInfoURL'; + $EBMLidList[EBML_ID_CODECNAME] = 'CodecName'; + $EBMLidList[EBML_ID_CODECPRIVATE] = 'CodecPrivate'; + $EBMLidList[EBML_ID_CODECSETTINGS] = 'CodecSettings'; + $EBMLidList[EBML_ID_COLOURSPACE] = 'ColourSpace'; + $EBMLidList[EBML_ID_CONTENTCOMPALGO] = 'ContentCompAlgo'; + $EBMLidList[EBML_ID_CONTENTCOMPRESSION] = 'ContentCompression'; + $EBMLidList[EBML_ID_CONTENTCOMPSETTINGS] = 'ContentCompSettings'; + $EBMLidList[EBML_ID_CONTENTENCALGO] = 'ContentEncAlgo'; + $EBMLidList[EBML_ID_CONTENTENCKEYID] = 'ContentEncKeyID'; + $EBMLidList[EBML_ID_CONTENTENCODING] = 'ContentEncoding'; + $EBMLidList[EBML_ID_CONTENTENCODINGORDER] = 'ContentEncodingOrder'; + $EBMLidList[EBML_ID_CONTENTENCODINGS] = 'ContentEncodings'; + $EBMLidList[EBML_ID_CONTENTENCODINGSCOPE] = 'ContentEncodingScope'; + $EBMLidList[EBML_ID_CONTENTENCODINGTYPE] = 'ContentEncodingType'; + $EBMLidList[EBML_ID_CONTENTENCRYPTION] = 'ContentEncryption'; + $EBMLidList[EBML_ID_CONTENTSIGALGO] = 'ContentSigAlgo'; + $EBMLidList[EBML_ID_CONTENTSIGHASHALGO] = 'ContentSigHashAlgo'; + $EBMLidList[EBML_ID_CONTENTSIGKEYID] = 'ContentSigKeyID'; + $EBMLidList[EBML_ID_CONTENTSIGNATURE] = 'ContentSignature'; + $EBMLidList[EBML_ID_CRC32] = 'CRC32'; + $EBMLidList[EBML_ID_CUEBLOCKNUMBER] = 'CueBlockNumber'; + $EBMLidList[EBML_ID_CUECLUSTERPOSITION] = 'CueClusterPosition'; + $EBMLidList[EBML_ID_CUECODECSTATE] = 'CueCodecState'; + $EBMLidList[EBML_ID_CUEPOINT] = 'CuePoint'; + $EBMLidList[EBML_ID_CUEREFCLUSTER] = 'CueRefCluster'; + $EBMLidList[EBML_ID_CUEREFCODECSTATE] = 'CueRefCodecState'; + $EBMLidList[EBML_ID_CUEREFERENCE] = 'CueReference'; + $EBMLidList[EBML_ID_CUEREFNUMBER] = 'CueRefNumber'; + $EBMLidList[EBML_ID_CUEREFTIME] = 'CueRefTime'; + $EBMLidList[EBML_ID_CUES] = 'Cues'; + $EBMLidList[EBML_ID_CUETIME] = 'CueTime'; + $EBMLidList[EBML_ID_CUETRACK] = 'CueTrack'; + $EBMLidList[EBML_ID_CUETRACKPOSITIONS] = 'CueTrackPositions'; + $EBMLidList[EBML_ID_DATEUTC] = 'DateUTC'; + $EBMLidList[EBML_ID_DEFAULTDURATION] = 'DefaultDuration'; + $EBMLidList[EBML_ID_DISPLAYHEIGHT] = 'DisplayHeight'; + $EBMLidList[EBML_ID_DISPLAYUNIT] = 'DisplayUnit'; + $EBMLidList[EBML_ID_DISPLAYWIDTH] = 'DisplayWidth'; + $EBMLidList[EBML_ID_DOCTYPE] = 'DocType'; + $EBMLidList[EBML_ID_DOCTYPEREADVERSION] = 'DocTypeReadVersion'; + $EBMLidList[EBML_ID_DOCTYPEVERSION] = 'DocTypeVersion'; + $EBMLidList[EBML_ID_DURATION] = 'Duration'; + $EBMLidList[EBML_ID_EBML] = 'EBML'; + $EBMLidList[EBML_ID_EBMLMAXIDLENGTH] = 'EBMLMaxIDLength'; + $EBMLidList[EBML_ID_EBMLMAXSIZELENGTH] = 'EBMLMaxSizeLength'; + $EBMLidList[EBML_ID_EBMLREADVERSION] = 'EBMLReadVersion'; + $EBMLidList[EBML_ID_EBMLVERSION] = 'EBMLVersion'; + $EBMLidList[EBML_ID_EDITIONENTRY] = 'EditionEntry'; + $EBMLidList[EBML_ID_EDITIONFLAGDEFAULT] = 'EditionFlagDefault'; + $EBMLidList[EBML_ID_EDITIONFLAGHIDDEN] = 'EditionFlagHidden'; + $EBMLidList[EBML_ID_EDITIONFLAGORDERED] = 'EditionFlagOrdered'; + $EBMLidList[EBML_ID_EDITIONUID] = 'EditionUID'; + $EBMLidList[EBML_ID_FILEDATA] = 'FileData'; + $EBMLidList[EBML_ID_FILEDESCRIPTION] = 'FileDescription'; + $EBMLidList[EBML_ID_FILEMIMETYPE] = 'FileMimeType'; + $EBMLidList[EBML_ID_FILENAME] = 'FileName'; + $EBMLidList[EBML_ID_FILEREFERRAL] = 'FileReferral'; + $EBMLidList[EBML_ID_FILEUID] = 'FileUID'; + $EBMLidList[EBML_ID_FLAGDEFAULT] = 'FlagDefault'; + $EBMLidList[EBML_ID_FLAGENABLED] = 'FlagEnabled'; + $EBMLidList[EBML_ID_FLAGFORCED] = 'FlagForced'; + $EBMLidList[EBML_ID_FLAGINTERLACED] = 'FlagInterlaced'; + $EBMLidList[EBML_ID_FLAGLACING] = 'FlagLacing'; + $EBMLidList[EBML_ID_GAMMAVALUE] = 'GammaValue'; + $EBMLidList[EBML_ID_INFO] = 'Info'; + $EBMLidList[EBML_ID_LANGUAGE] = 'Language'; + $EBMLidList[EBML_ID_MAXBLOCKADDITIONID] = 'MaxBlockAdditionID'; + $EBMLidList[EBML_ID_MAXCACHE] = 'MaxCache'; + $EBMLidList[EBML_ID_MINCACHE] = 'MinCache'; + $EBMLidList[EBML_ID_MUXINGAPP] = 'MuxingApp'; + $EBMLidList[EBML_ID_NAME] = 'Name'; + $EBMLidList[EBML_ID_NEXTFILENAME] = 'NextFilename'; + $EBMLidList[EBML_ID_NEXTUID] = 'NextUID'; + $EBMLidList[EBML_ID_OUTPUTSAMPLINGFREQUENCY] = 'OutputSamplingFrequency'; + $EBMLidList[EBML_ID_PIXELCROPBOTTOM] = 'PixelCropBottom'; + $EBMLidList[EBML_ID_PIXELCROPLEFT] = 'PixelCropLeft'; + $EBMLidList[EBML_ID_PIXELCROPRIGHT] = 'PixelCropRight'; + $EBMLidList[EBML_ID_PIXELCROPTOP] = 'PixelCropTop'; + $EBMLidList[EBML_ID_PIXELHEIGHT] = 'PixelHeight'; + $EBMLidList[EBML_ID_PIXELWIDTH] = 'PixelWidth'; + $EBMLidList[EBML_ID_PREVFILENAME] = 'PrevFilename'; + $EBMLidList[EBML_ID_PREVUID] = 'PrevUID'; + $EBMLidList[EBML_ID_SAMPLINGFREQUENCY] = 'SamplingFrequency'; + $EBMLidList[EBML_ID_SEEK] = 'Seek'; + $EBMLidList[EBML_ID_SEEKHEAD] = 'SeekHead'; + $EBMLidList[EBML_ID_SEEKID] = 'SeekID'; + $EBMLidList[EBML_ID_SEEKPOSITION] = 'SeekPosition'; + $EBMLidList[EBML_ID_SEGMENT] = 'Segment'; + $EBMLidList[EBML_ID_SEGMENTFAMILY] = 'SegmentFamily'; + $EBMLidList[EBML_ID_SEGMENTFILENAME] = 'SegmentFilename'; + $EBMLidList[EBML_ID_SEGMENTUID] = 'SegmentUID'; + $EBMLidList[EBML_ID_SIMPLETAG] = 'SimpleTag'; + $EBMLidList[EBML_ID_CLUSTERSLICES] = 'ClusterSlices'; + $EBMLidList[EBML_ID_STEREOMODE] = 'StereoMode'; + $EBMLidList[EBML_ID_OLDSTEREOMODE] = 'OldStereoMode'; + $EBMLidList[EBML_ID_TAG] = 'Tag'; + $EBMLidList[EBML_ID_TAGATTACHMENTUID] = 'TagAttachmentUID'; + $EBMLidList[EBML_ID_TAGBINARY] = 'TagBinary'; + $EBMLidList[EBML_ID_TAGCHAPTERUID] = 'TagChapterUID'; + $EBMLidList[EBML_ID_TAGDEFAULT] = 'TagDefault'; + $EBMLidList[EBML_ID_TAGEDITIONUID] = 'TagEditionUID'; + $EBMLidList[EBML_ID_TAGLANGUAGE] = 'TagLanguage'; + $EBMLidList[EBML_ID_TAGNAME] = 'TagName'; + $EBMLidList[EBML_ID_TAGTRACKUID] = 'TagTrackUID'; + $EBMLidList[EBML_ID_TAGS] = 'Tags'; + $EBMLidList[EBML_ID_TAGSTRING] = 'TagString'; + $EBMLidList[EBML_ID_TARGETS] = 'Targets'; + $EBMLidList[EBML_ID_TARGETTYPE] = 'TargetType'; + $EBMLidList[EBML_ID_TARGETTYPEVALUE] = 'TargetTypeValue'; + $EBMLidList[EBML_ID_TIMECODESCALE] = 'TimecodeScale'; + $EBMLidList[EBML_ID_TITLE] = 'Title'; + $EBMLidList[EBML_ID_TRACKENTRY] = 'TrackEntry'; + $EBMLidList[EBML_ID_TRACKNUMBER] = 'TrackNumber'; + $EBMLidList[EBML_ID_TRACKOFFSET] = 'TrackOffset'; + $EBMLidList[EBML_ID_TRACKOVERLAY] = 'TrackOverlay'; + $EBMLidList[EBML_ID_TRACKS] = 'Tracks'; + $EBMLidList[EBML_ID_TRACKTIMECODESCALE] = 'TrackTimecodeScale'; + $EBMLidList[EBML_ID_TRACKTRANSLATE] = 'TrackTranslate'; + $EBMLidList[EBML_ID_TRACKTRANSLATECODEC] = 'TrackTranslateCodec'; + $EBMLidList[EBML_ID_TRACKTRANSLATEEDITIONUID] = 'TrackTranslateEditionUID'; + $EBMLidList[EBML_ID_TRACKTRANSLATETRACKID] = 'TrackTranslateTrackID'; + $EBMLidList[EBML_ID_TRACKTYPE] = 'TrackType'; + $EBMLidList[EBML_ID_TRACKUID] = 'TrackUID'; + $EBMLidList[EBML_ID_VIDEO] = 'Video'; + $EBMLidList[EBML_ID_VOID] = 'Void'; + $EBMLidList[EBML_ID_WRITINGAPP] = 'WritingApp'; + } + + return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value)); + } + + public static function displayUnit($value) { + // http://www.matroska.org/technical/specs/index.html#DisplayUnit + static $units = array( + 0 => 'pixels', + 1 => 'centimeters', + 2 => 'inches', + 3 => 'Display Aspect Ratio'); + + return (isset($units[$value]) ? $units[$value] : 'unknown'); + } + + private static function getDefaultStreamInfo($streams) + { + foreach (array_reverse($streams) as $stream) { + if ($stream['default']) { + break; + } + } + + $unset = array('default', 'name'); + foreach ($unset as $u) { + if (isset($stream[$u])) { + unset($stream[$u]); + } + } + + $info = $stream; + $info['streams'] = $streams; + + return $info; + } + +} diff --git a/sources/wp-includes/ID3/module.audio-video.quicktime.php b/sources/wp-includes/ID3/module.audio-video.quicktime.php new file mode 100644 index 0000000..1b5ad5f --- /dev/null +++ b/sources/wp-includes/ID3/module.audio-video.quicktime.php @@ -0,0 +1,2221 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.quicktime.php // +// module for analyzing Quicktime and MP3-in-MP4 files // +// dependencies: module.audio.mp3.php // +// dependencies: module.tag.id3v2.php // +// /// +///////////////////////////////////////////////////////////////// + +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true); +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); // needed for ISO 639-2 language code lookup + +class getid3_quicktime extends getid3_handler +{ + + public $ReturnAtomData = true; + public $ParseAllPossibleAtoms = false; + + public function Analyze() { + $info = &$this->getid3->info; + + $info['fileformat'] = 'quicktime'; + $info['quicktime']['hinting'] = false; + $info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present + + fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + + $offset = 0; + $atomcounter = 0; + + while ($offset < $info['avdataend']) { + if (!getid3_lib::intValueSupported($offset)) { + $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions'; + break; + } + fseek($this->getid3->fp, $offset, SEEK_SET); + $AtomHeader = fread($this->getid3->fp, 8); + + $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4)); + $atomname = substr($AtomHeader, 4, 4); + + // 64-bit MOV patch by jlegateØktnc*com + if ($atomsize == 1) { + $atomsize = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 8)); + } + + $info['quicktime'][$atomname]['name'] = $atomname; + $info['quicktime'][$atomname]['size'] = $atomsize; + $info['quicktime'][$atomname]['offset'] = $offset; + + if (($offset + $atomsize) > $info['avdataend']) { + $info['error'][] = 'Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)'; + return false; + } + + if ($atomsize == 0) { + // Furthermore, for historical reasons the list of atoms is optionally + // terminated by a 32-bit integer set to 0. If you are writing a program + // to read user data atoms, you should allow for the terminating 0. + break; + } + switch ($atomname) { + case 'mdat': // Media DATa atom + // 'mdat' contains the actual data for the audio/video + if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { + + $info['avdataoffset'] = $info['quicktime'][$atomname]['offset'] + 8; + $OldAVDataEnd = $info['avdataend']; + $info['avdataend'] = $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size']; + + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; + $getid3_temp->info['avdataend'] = $info['avdataend']; + $getid3_mp3 = new getid3_mp3($getid3_temp); + if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode(fread($this->getid3->fp, 4)))) { + $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $value) { + $info['warning'][] = $value; + } + } + if (!empty($getid3_temp->info['mpeg'])) { + $info['mpeg'] = $getid3_temp->info['mpeg']; + if (isset($info['mpeg']['audio'])) { + $info['audio']['dataformat'] = 'mp3'; + $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + $info['audio']['channels'] = $info['mpeg']['audio']['channels']; + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; + $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); + $info['bitrate'] = $info['audio']['bitrate']; + } + } + } + unset($getid3_mp3, $getid3_temp); + $info['avdataend'] = $OldAVDataEnd; + unset($OldAVDataEnd); + + } + break; + + case 'free': // FREE space atom + case 'skip': // SKIP atom + case 'wide': // 64-bit expansion placeholder atom + // 'free', 'skip' and 'wide' are just padding, contains no useful data at all + break; + + default: + $atomHierarchy = array(); + $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($this->getid3->fp, $atomsize), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms); + break; + } + + $offset += $atomsize; + $atomcounter++; + } + + if (!empty($info['avdataend_tmp'])) { + // this value is assigned to a temp value and then erased because + // otherwise any atoms beyond the 'mdat' atom would not get parsed + $info['avdataend'] = $info['avdataend_tmp']; + unset($info['avdataend_tmp']); + } + + if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) { + $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; + } + if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) { + $info['audio']['bitrate'] = $info['bitrate']; + } + if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) { + foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) { + $samples_per_second = $samples_count / $info['playtime_seconds']; + if ($samples_per_second > 240) { + // has to be audio samples + } else { + $info['video']['frame_rate'] = $samples_per_second; + break; + } + } + } + if (($info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) { + $info['fileformat'] = 'mp4'; + $info['mime_type'] = 'audio/mp4'; + unset($info['video']['dataformat']); + } + + if (!$this->ReturnAtomData) { + unset($info['quicktime']['moov']); + } + + if (empty($info['audio']['dataformat']) && !empty($info['quicktime']['audio'])) { + $info['audio']['dataformat'] = 'quicktime'; + } + if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) { + $info['video']['dataformat'] = 'quicktime'; + } + + return true; + } + + public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { + // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm + + $info = &$this->getid3->info; + + //$atom_parent = array_pop($atomHierarchy); + $atom_parent = end($atomHierarchy); // http://www.getid3.org/phpBB3/viewtopic.php?t=1717 + array_push($atomHierarchy, $atomname); + $atom_structure['hierarchy'] = implode(' ', $atomHierarchy); + $atom_structure['name'] = $atomname; + $atom_structure['size'] = $atomsize; + $atom_structure['offset'] = $baseoffset; +//echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'
    '; +//echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'

    '; + switch ($atomname) { + case 'moov': // MOVie container atom + case 'trak': // TRAcK container atom + case 'clip': // CLIPping container atom + case 'matt': // track MATTe container atom + case 'edts': // EDiTS container atom + case 'tref': // Track REFerence container atom + case 'mdia': // MeDIA container atom + case 'minf': // Media INFormation container atom + case 'dinf': // Data INFormation container atom + case 'udta': // User DaTA container atom + case 'cmov': // Compressed MOVie container atom + case 'rmra': // Reference Movie Record Atom + case 'rmda': // Reference Movie Descriptor Atom + case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + break; + + case 'ilst': // Item LiST container atom + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + + // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted + $allnumericnames = true; + foreach ($atom_structure['subatoms'] as $subatomarray) { + if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { + $allnumericnames = false; + break; + } + } + if ($allnumericnames) { + $newData = array(); + foreach ($atom_structure['subatoms'] as $subatomarray) { + foreach ($subatomarray['subatoms'] as $newData_subatomarray) { + unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); + $newData[$subatomarray['name']] = $newData_subatomarray; + break; + } + } + $atom_structure['data'] = $newData; + unset($atom_structure['subatoms']); + } + break; + + case "\x00\x00\x00\x01": + case "\x00\x00\x00\x02": + case "\x00\x00\x00\x03": + case "\x00\x00\x00\x04": + case "\x00\x00\x00\x05": + $atomname = getid3_lib::BigEndian2Int($atomname); + $atom_structure['name'] = $atomname; + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + break; + + case 'stbl': // Sample TaBLe container atom + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + $isVideo = false; + $framerate = 0; + $framecount = 0; + foreach ($atom_structure['subatoms'] as $key => $value_array) { + if (isset($value_array['sample_description_table'])) { + foreach ($value_array['sample_description_table'] as $key2 => $value_array2) { + if (isset($value_array2['data_format'])) { + switch ($value_array2['data_format']) { + case 'avc1': + case 'mp4v': + // video data + $isVideo = true; + break; + case 'mp4a': + // audio data + break; + } + } + } + } elseif (isset($value_array['time_to_sample_table'])) { + foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) { + if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) { + $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3); + $framecount = $value_array2['sample_count']; + } + } + } + } + if ($isVideo && $framerate) { + $info['quicktime']['video']['frame_rate'] = $framerate; + $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate']; + } + if ($isVideo && $framecount) { + $info['quicktime']['video']['frame_count'] = $framecount; + } + break; + + + case 'aART': // Album ARTist + case 'catg': // CaTeGory + case 'covr': // COVeR artwork + case 'cpil': // ComPILation + case 'cprt': // CoPyRighT + case 'desc': // DESCription + case 'disk': // DISK number + case 'egid': // Episode Global ID + case 'gnre': // GeNRE + case 'keyw': // KEYWord + case 'ldes': + case 'pcst': // PodCaST + case 'pgap': // GAPless Playback + case 'purd': // PURchase Date + case 'purl': // Podcast URL + case 'rati': + case 'rndu': + case 'rpdu': + case 'rtng': // RaTiNG + case 'stik': + case 'tmpo': // TeMPO (BPM) + case 'trkn': // TRacK Number + case 'tves': // TV EpiSode + case 'tvnn': // TV Network Name + case 'tvsh': // TV SHow Name + case 'tvsn': // TV SeasoN + case 'akID': // iTunes store account type + case 'apID': + case 'atID': + case 'cmID': + case 'cnID': + case 'geID': + case 'plID': + case 'sfID': // iTunes store country + case '©alb': // ALBum + case '©art': // ARTist + case '©ART': + case '©aut': + case '©cmt': // CoMmenT + case '©com': // COMposer + case '©cpy': + case '©day': // content created year + case '©dir': + case '©ed1': + case '©ed2': + case '©ed3': + case '©ed4': + case '©ed5': + case '©ed6': + case '©ed7': + case '©ed8': + case '©ed9': + case '©enc': + case '©fmt': + case '©gen': // GENre + case '©grp': // GRouPing + case '©hst': + case '©inf': + case '©lyr': // LYRics + case '©mak': + case '©mod': + case '©nam': // full NAMe + case '©ope': + case '©PRD': + case '©prd': + case '©prf': + case '©req': + case '©src': + case '©swr': + case '©too': // encoder + case '©trk': // TRacK + case '©url': + case '©wrn': + case '©wrt': // WRiTer + case '----': // itunes specific + if ($atom_parent == 'udta') { + // User data atom handler + $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); + $atom_structure['data'] = substr($atom_data, 4); + + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { + $info['comments']['language'][] = $atom_structure['language']; + } + } else { + // Apple item list box atom handler + $atomoffset = 0; + if (substr($atom_data, 2, 2) == "\x10\xB5") { + // not sure what it means, but observed on iPhone4 data. + // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data + while ($atomoffset < strlen($atom_data)) { + $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); + $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); + $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); + if ($boxsmallsize <= 1) { + $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset); + $atom_structure['data'] = null; + $atomoffset = strlen($atom_data); + break; + } + switch ($boxsmalltype) { + case "\x10\xB5": + $atom_structure['data'] = $boxsmalldata; + break; + default: + $info['warning'][] = 'Unknown QuickTime smallbox type: "'.getid3_lib::PrintHexBytes($boxsmalltype).'" at offset '.$baseoffset; + $atom_structure['data'] = $atom_data; + break; + } + $atomoffset += (4 + $boxsmallsize); + } + } else { + while ($atomoffset < strlen($atom_data)) { + $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4)); + $boxtype = substr($atom_data, $atomoffset + 4, 4); + $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); + if ($boxsize <= 1) { + $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset); + $atom_structure['data'] = null; + $atomoffset = strlen($atom_data); + break; + } + $atomoffset += $boxsize; + + switch ($boxtype) { + case 'mean': + case 'name': + $atom_structure[$boxtype] = substr($boxdata, 4); + break; + + case 'data': + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3)); + switch ($atom_structure['flags_raw']) { + case 0: // data flag + case 21: // tmpo/cpil flag + switch ($atomname) { + case 'cpil': + case 'pcst': + case 'pgap': + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); + break; + + case 'tmpo': + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2)); + break; + + case 'disk': + case 'trkn': + $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2)); + $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2)); + $atom_structure['data'] = empty($num) ? '' : $num; + $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total; + break; + + case 'gnre': + $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); + $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1); + break; + + case 'rtng': + $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); + $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]); + break; + + case 'stik': + $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); + $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]); + break; + + case 'sfID': + $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); + $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]); + break; + + case 'egid': + case 'purl': + $atom_structure['data'] = substr($boxdata, 8); + break; + + default: + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); + } + break; + + case 1: // text flag + case 13: // image flag + default: + $atom_structure['data'] = substr($boxdata, 8); + break; + + } + break; + + default: + $info['warning'][] = 'Unknown QuickTime box type: "'.getid3_lib::PrintHexBytes($boxtype).'" at offset '.$baseoffset; + $atom_structure['data'] = $atom_data; + + } + } + } + } + $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']); + break; + + + case 'play': // auto-PLAY atom + $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + + $info['quicktime']['autoplay'] = $atom_structure['autoplay']; + break; + + + case 'WLOC': // Window LOCation atom + $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); + $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); + break; + + + case 'LOOP': // LOOPing atom + case 'SelO': // play SELection Only atom + case 'AllF': // play ALL Frames atom + $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data); + break; + + + case 'name': // + case 'MCPS': // Media Cleaner PRo + case '@PRM': // adobe PReMiere version + case '@PRQ': // adobe PRemiere Quicktime version + $atom_structure['data'] = $atom_data; + break; + + + case 'cmvd': // Compressed MooV Data atom + // Code by ubergeekØubergeek*tv based on information from + // http://developer.apple.com/quicktime/icefloe/dispatch012.html + $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + + $CompressedFileData = substr($atom_data, 4); + if ($UncompressedHeader = @gzuncompress($CompressedFileData)) { + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms); + } else { + $info['warning'][] = 'Error decompressing compressed MOV atom at offset '.$atom_structure['offset']; + } + break; + + + case 'dcom': // Data COMpression atom + $atom_structure['compression_id'] = $atom_data; + $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data); + break; + + + case 'rdrf': // Reference movie Data ReFerence atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001); + + $atom_structure['reference_type_name'] = substr($atom_data, 4, 4); + $atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + switch ($atom_structure['reference_type_name']) { + case 'url ': + $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); + break; + + case 'alis': + $atom_structure['file_alias'] = substr($atom_data, 12); + break; + + case 'rsrc': + $atom_structure['resource_alias'] = substr($atom_data, 12); + break; + + default: + $atom_structure['data'] = substr($atom_data, 12); + break; + } + break; + + + case 'rmqu': // Reference Movie QUality atom + $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data); + break; + + + case 'rmcs': // Reference Movie Cpu Speed atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + break; + + + case 'rmvc': // Reference Movie Version Check atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['gestalt_selector'] = substr($atom_data, 4, 4); + $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); + break; + + + case 'rmcd': // Reference Movie Component check atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['component_type'] = substr($atom_data, 4, 4); + $atom_structure['component_subtype'] = substr($atom_data, 8, 4); + $atom_structure['component_manufacturer'] = substr($atom_data, 12, 4); + $atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); + $atom_structure['component_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4)); + break; + + + case 'rmdr': // Reference Movie Data Rate atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + + $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10; + break; + + + case 'rmla': // Reference Movie Language Atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { + $info['comments']['language'][] = $atom_structure['language']; + } + break; + + + case 'rmla': // Reference Movie Language Atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + break; + + + case 'ptv ': // Print To Video - defines a movie's full screen mode + // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm + $atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); + $atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000 + $atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000 + $atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1)); + $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1)); + + $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag']; + $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; + + $ptv_lookup[0] = 'normal'; + $ptv_lookup[1] = 'double'; + $ptv_lookup[2] = 'half'; + $ptv_lookup[3] = 'full'; + $ptv_lookup[4] = 'current'; + if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { + $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; + } else { + $info['warning'][] = 'unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'; + } + break; + + + case 'stsd': // Sample Table Sample Description atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stsdEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4)); + $stsdEntriesDataOffset += 4; + $atom_structure['sample_description_table'][$i]['data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4); + $stsdEntriesDataOffset += 4; + $atom_structure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6)); + $stsdEntriesDataOffset += 6; + $atom_structure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2)); + $stsdEntriesDataOffset += 2; + $atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2)); + $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2); + + $atom_structure['sample_description_table'][$i]['encoder_version'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 0, 2)); + $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 2, 2)); + $atom_structure['sample_description_table'][$i]['encoder_vendor'] = substr($atom_structure['sample_description_table'][$i]['data'], 4, 4); + + switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) { + + case "\x00\x00\x00\x00": + // audio tracks + $atom_structure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 2)); + $atom_structure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10, 2)); + $atom_structure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 2)); + $atom_structure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14, 2)); + $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4)); + + // video tracks + // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html + $atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); + $atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); + $atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); + $atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); + $atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); + $atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); + $atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4)); + $atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2)); + $atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4); + $atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2)); + $atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2)); + + switch ($atom_structure['sample_description_table'][$i]['data_format']) { + case '2vuY': + case 'avc1': + case 'cvid': + case 'dvc ': + case 'dvcp': + case 'gif ': + case 'h263': + case 'jpeg': + case 'kpcd': + case 'mjpa': + case 'mjpb': + case 'mp4v': + case 'png ': + case 'raw ': + case 'rle ': + case 'rpza': + case 'smc ': + case 'SVQ1': + case 'SVQ3': + case 'tiff': + case 'v210': + case 'v216': + case 'v308': + case 'v408': + case 'v410': + case 'yuv2': + $info['fileformat'] = 'mp4'; + $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; +// http://www.getid3.org/phpBB3/viewtopic.php?t=1550 +//if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers +if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) { + // assume that values stored here are more important than values stored in [tkhd] atom + $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width']; + $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height']; + $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; + $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; +} + break; + + case 'qtvr': + $info['video']['dataformat'] = 'quicktimevr'; + break; + + case 'mp4a': + default: + $info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate']; + $info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels']; + $info['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth']; + $info['audio']['codec'] = $info['quicktime']['audio']['codec']; + $info['audio']['sample_rate'] = $info['quicktime']['audio']['sample_rate']; + $info['audio']['channels'] = $info['quicktime']['audio']['channels']; + $info['audio']['bits_per_sample'] = $info['quicktime']['audio']['bit_depth']; + switch ($atom_structure['sample_description_table'][$i]['data_format']) { + case 'raw ': // PCM + case 'alac': // Apple Lossless Audio Codec + $info['audio']['lossless'] = true; + break; + default: + $info['audio']['lossless'] = false; + break; + } + break; + } + break; + + default: + switch ($atom_structure['sample_description_table'][$i]['data_format']) { + case 'mp4s': + $info['fileformat'] = 'mp4'; + break; + + default: + // video atom + $atom_structure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); + $atom_structure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); + $atom_structure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); + $atom_structure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); + $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4)); + $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); + $atom_structure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); + $atom_structure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 2)); + $atom_structure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34, 1)); + $atom_structure['sample_description_table'][$i]['video_encoder_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']); + $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2)); + $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); + + $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); + $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); + + if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') { + $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; + $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; + $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; + + $info['video']['codec'] = $info['quicktime']['video']['codec']; + $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth']; + } + $info['video']['lossless'] = false; + $info['video']['pixel_aspect_ratio'] = (float) 1; + break; + } + break; + } + switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) { + case 'mp4a': + $info['audio']['dataformat'] = 'mp4'; + $info['quicktime']['audio']['codec'] = 'mp4'; + break; + + case '3ivx': + case '3iv1': + case '3iv2': + $info['video']['dataformat'] = '3ivx'; + break; + + case 'xvid': + $info['video']['dataformat'] = 'xvid'; + break; + + case 'mp4v': + $info['video']['dataformat'] = 'mpeg4'; + break; + + case 'divx': + case 'div1': + case 'div2': + case 'div3': + case 'div4': + case 'div5': + case 'div6': + $info['video']['dataformat'] = 'divx'; + break; + + default: + // do nothing + break; + } + unset($atom_structure['sample_description_table'][$i]['data']); + } + break; + + + case 'stts': // Sample Table Time-to-Sample atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $sttsEntriesDataOffset = 8; + //$FrameRateCalculatorArray = array(); + $frames_count = 0; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); + $sttsEntriesDataOffset += 4; + $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); + $sttsEntriesDataOffset += 4; + + $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count']; + + // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM + //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { + // $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; + // if ($stts_new_framerate <= 60) { + // // some atoms have durations of "1" giving a very large framerate, which probably is not right + // $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate); + // } + //} + // + //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count']; + } + $info['quicktime']['stts_framecount'][] = $frames_count; + //$sttsFramesTotal = 0; + //$sttsSecondsTotal = 0; + //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) { + // if (($frames_per_second > 60) || ($frames_per_second < 1)) { + // // not video FPS information, probably audio information + // $sttsFramesTotal = 0; + // $sttsSecondsTotal = 0; + // break; + // } + // $sttsFramesTotal += $frame_count; + // $sttsSecondsTotal += $frame_count / $frames_per_second; + //} + //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) { + // if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) { + // $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal; + // } + //} + break; + + + case 'stss': // Sample Table Sync Sample (key frames) atom + if ($ParseAllPossibleAtoms) { + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stssEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4)); + $stssEntriesDataOffset += 4; + } + } + break; + + + case 'stsc': // Sample Table Sample-to-Chunk atom + if ($ParseAllPossibleAtoms) { + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stscEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); + $stscEntriesDataOffset += 4; + $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); + $stscEntriesDataOffset += 4; + $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); + $stscEntriesDataOffset += 4; + } + } + break; + + + case 'stsz': // Sample Table SiZe atom + if ($ParseAllPossibleAtoms) { + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['sample_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $stszEntriesDataOffset = 12; + if ($atom_structure['sample_size'] == 0) { + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4)); + $stszEntriesDataOffset += 4; + } + } + } + break; + + + case 'stco': // Sample Table Chunk Offset atom + if ($ParseAllPossibleAtoms) { + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stcoEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4)); + $stcoEntriesDataOffset += 4; + } + } + break; + + + case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files) + if ($ParseAllPossibleAtoms) { + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stcoEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8)); + $stcoEntriesDataOffset += 8; + } + } + break; + + + case 'dref': // Data REFerence atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $drefDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4)); + $drefDataOffset += 4; + $atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4); + $drefDataOffset += 4; + $atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1)); + $drefDataOffset += 1; + $atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000 + $drefDataOffset += 3; + $atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3)); + $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3); + + $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001); + } + break; + + + case 'gmin': // base Media INformation atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); + $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2)); + $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); + $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2)); + $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); + break; + + + case 'smhd': // Sound Media information HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); + break; + + + case 'vmhd': // Video Media information HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); + $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2)); + $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); + + $atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001); + break; + + + case 'hdlr': // HanDLeR reference atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['component_type'] = substr($atom_data, 4, 4); + $atom_structure['component_subtype'] = substr($atom_data, 8, 4); + $atom_structure['component_manufacturer'] = substr($atom_data, 12, 4); + $atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); + $atom_structure['component_name'] = $this->Pascal2String(substr($atom_data, 24)); + + if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) { + $info['video']['dataformat'] = 'quicktimevr'; + } + break; + + + case 'mdhd': // MeDia HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2)); + $atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2)); + + if ($atom_structure['time_scale'] == 0) { + $info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero'; + return false; + } + $info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']); + + $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); + $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); + $atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { + $info['comments']['language'][] = $atom_structure['language']; + } + break; + + + case 'pnot': // Preview atom + $atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format" + $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00 + $atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT' + $atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01 + + $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']); + break; + + + case 'crgn': // Clipping ReGioN atom + $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box, + $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields + $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region. + break; + + + case 'load': // track LOAD settings atom + $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + $atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + + $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020); + $atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x0100); + break; + + + case 'tmcd': // TiMe CoDe atom + case 'chap': // CHAPter list atom + case 'sync': // SYNChronization atom + case 'scpt': // tranSCriPT atom + case 'ssrc': // non-primary SouRCe atom + for ($i = 0; $i < (strlen($atom_data) % 4); $i++) { + $atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4)); + } + break; + + + case 'elst': // Edit LiST atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) { + $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4)); + $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4)); + $atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4)); + } + break; + + + case 'kmat': // compressed MATte atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 + $atom_structure['matte_data_raw'] = substr($atom_data, 4); + break; + + + case 'ctab': // Color TABle atom + $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000 + $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000 + $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1; + for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) { + $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2)); + $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2)); + $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2)); + $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2)); + } + break; + + + case 'mvhd': // MoVie HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4)); + $atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2)); + $atom_structure['reserved'] = substr($atom_data, 26, 10); + $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4)); + $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4)); + $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4)); + $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4)); + $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4)); + $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4)); + $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4)); + $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4)); + $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4)); + $atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4)); + $atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4)); + $atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4)); + $atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4)); + $atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4)); + $atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4)); + $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4)); + + if ($atom_structure['time_scale'] == 0) { + $info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero'; + return false; + } + $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); + $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); + $info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']); + $info['quicktime']['display_scale'] = $atom_structure['matrix_a']; + $info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; + break; + + + case 'tkhd': // TracK HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); + $atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8)); + $atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2)); + $atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2)); + $atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2)); + $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2)); +// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html +// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737 + $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4)); + $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4)); + $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4)); + $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4)); + $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4)); + $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4)); + $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4)); + $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4)); + $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4)); + $atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4)); + $atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4)); + $atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x0001); + $atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x0002); + $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004); + $atom_structure['flags']['in_poster'] = (bool) ($atom_structure['flags_raw'] & 0x0008); + $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); + $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); + + if ($atom_structure['flags']['enabled'] == 1) { + if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) { + $info['video']['resolution_x'] = $atom_structure['width']; + $info['video']['resolution_y'] = $atom_structure['height']; + } + $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']); + $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']); + $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; + $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; + } else { + // see: http://www.getid3.org/phpBB3/viewtopic.php?t=1295 + //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); } + //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); } + //if (isset($info['quicktime']['video'])) { unset($info['quicktime']['video']); } + } + break; + + + case 'iods': // Initial Object DeScriptor atom + // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h + // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html + $offset = 0; + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3)); + $offset += 3; + $atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset); + //$offset already adjusted by quicktime_read_mp4_descr_length() + $atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); + $offset += 2; + $atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + + $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields + for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) { + $atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset); + //$offset already adjusted by quicktime_read_mp4_descr_length() + $atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); + $offset += 4; + } + + $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']); + $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']); + break; + + case 'ftyp': // FileTYPe (?) atom (for MP4 it seems) + $atom_structure['signature'] = substr($atom_data, 0, 4); + $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['fourcc'] = substr($atom_data, 8, 4); + break; + + case 'mdat': // Media DATa atom + case 'free': // FREE space atom + case 'skip': // SKIP atom + case 'wide': // 64-bit expansion placeholder atom + // 'mdat' data is too big to deal with, contains no useful metadata + // 'free', 'skip' and 'wide' are just padding, contains no useful data at all + + // When writing QuickTime files, it is sometimes necessary to update an atom's size. + // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom + // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime + // puts an 8-byte placeholder atom before any atoms it may have to update the size of. + // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the + // placeholder atom can be overwritten to obtain the necessary 8 extra bytes. + // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ). + break; + + + case 'nsav': // NoSAVe atom + // http://developer.apple.com/technotes/tn/tn2038.html + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + break; + + case 'ctyp': // Controller TYPe atom (seen on QTVR) + // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt + // some controller names are: + // 0x00 + 'std' for linear movie + // 'none' for no controls + $atom_structure['ctyp'] = substr($atom_data, 0, 4); + $info['quicktime']['controller'] = $atom_structure['ctyp']; + switch ($atom_structure['ctyp']) { + case 'qtvr': + $info['video']['dataformat'] = 'quicktimevr'; + break; + } + break; + + case 'pano': // PANOrama track (seen on QTVR) + $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + break; + + case 'hint': // HINT track + case 'hinf': // + case 'hinv': // + case 'hnti': // + $info['quicktime']['hinting'] = true; + break; + + case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR) + for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) { + $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); + } + break; + + + // Observed-but-not-handled atom types are just listed here to prevent warnings being generated + case 'FXTC': // Something to do with Adobe After Effects (?) + case 'PrmA': + case 'code': + case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html + case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html + // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838] + // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html + // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html + case 'ctts':// STCompositionOffsetAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + case 'cslg':// STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + case 'sdtp':// STSampleDependencyAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + case 'stps':// STPartialSyncSampleAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + //$atom_structure['data'] = $atom_data; + break; + + case '©xyz': // GPS latitude+longitude+altitude + $atom_structure['data'] = $atom_data; + if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) { + @list($all, $latitude, $longitude, $altitude) = $matches; + $info['quicktime']['comments']['gps_latitude'][] = floatval($latitude); + $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude); + if (!empty($altitude)) { + $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude); + } + } else { + $info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.'; + } + break; + + case 'NCDT': + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms); + break; + case 'NCTH': // Nikon Camera THumbnail image + case 'NCVW': // Nikon Camera preVieW image + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) { + $atom_structure['data'] = $atom_data; + $atom_structure['image_mime'] = 'image/jpeg'; + $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); + $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); + } + break; + case 'NCHD': // MakerNoteVersion + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + $atom_structure['data'] = $atom_data; + break; + case 'NCTG': // NikonTags + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG + $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); + break; + case 'NCDB': // NikonTags + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + $atom_structure['data'] = $atom_data; + break; + + case "\x00\x00\x00\x00": + case 'meta': // METAdata atom + // some kind of metacontainer, may contain a big data dump such as: + // mdta keys  mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst   data DEApple 0  (data DE2011-05-11T17:54:04+0200 2  *data DE+52.4936+013.3897+040.247/   data DE4.3.1  data DEiPhone 4 + // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt + + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + //$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + break; + + case 'data': // metaDATA atom + // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data + $atom_structure['language'] = substr($atom_data, 4 + 0, 2); + $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2)); + $atom_structure['data'] = substr($atom_data, 4 + 4); + break; + + default: + $info['warning'][] = 'Unknown QuickTime atom type: "'.$atomname.'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset; + $atom_structure['data'] = $atom_data; + break; + } + array_pop($atomHierarchy); + return $atom_structure; + } + + public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { +//echo 'QuicktimeParseContainerAtom('.substr($atom_data, 4, 4).') @ '.$baseoffset.'

    '; + $atom_structure = false; + $subatomoffset = 0; + $subatomcounter = 0; + if ((strlen($atom_data) == 4) && (getid3_lib::BigEndian2Int($atom_data) == 0x00000000)) { + return false; + } + while ($subatomoffset < strlen($atom_data)) { + $subatomsize = getid3_lib::BigEndian2Int(substr($atom_data, $subatomoffset + 0, 4)); + $subatomname = substr($atom_data, $subatomoffset + 4, 4); + $subatomdata = substr($atom_data, $subatomoffset + 8, $subatomsize - 8); + if ($subatomsize == 0) { + // Furthermore, for historical reasons the list of atoms is optionally + // terminated by a 32-bit integer set to 0. If you are writing a program + // to read user data atoms, you should allow for the terminating 0. + return $atom_structure; + } + + $atom_structure[$subatomcounter] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms); + + $subatomoffset += $subatomsize; + $subatomcounter++; + } + return $atom_structure; + } + + + public function quicktime_read_mp4_descr_length($data, &$offset) { + // http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html + $num_bytes = 0; + $length = 0; + do { + $b = ord(substr($data, $offset++, 1)); + $length = ($length << 7) | ($b & 0x7F); + } while (($b & 0x80) && ($num_bytes++ < 4)); + return $length; + } + + + public function QuicktimeLanguageLookup($languageid) { + // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-34353 + static $QuicktimeLanguageLookup = array(); + if (empty($QuicktimeLanguageLookup)) { + $QuicktimeLanguageLookup[0] = 'English'; + $QuicktimeLanguageLookup[1] = 'French'; + $QuicktimeLanguageLookup[2] = 'German'; + $QuicktimeLanguageLookup[3] = 'Italian'; + $QuicktimeLanguageLookup[4] = 'Dutch'; + $QuicktimeLanguageLookup[5] = 'Swedish'; + $QuicktimeLanguageLookup[6] = 'Spanish'; + $QuicktimeLanguageLookup[7] = 'Danish'; + $QuicktimeLanguageLookup[8] = 'Portuguese'; + $QuicktimeLanguageLookup[9] = 'Norwegian'; + $QuicktimeLanguageLookup[10] = 'Hebrew'; + $QuicktimeLanguageLookup[11] = 'Japanese'; + $QuicktimeLanguageLookup[12] = 'Arabic'; + $QuicktimeLanguageLookup[13] = 'Finnish'; + $QuicktimeLanguageLookup[14] = 'Greek'; + $QuicktimeLanguageLookup[15] = 'Icelandic'; + $QuicktimeLanguageLookup[16] = 'Maltese'; + $QuicktimeLanguageLookup[17] = 'Turkish'; + $QuicktimeLanguageLookup[18] = 'Croatian'; + $QuicktimeLanguageLookup[19] = 'Chinese (Traditional)'; + $QuicktimeLanguageLookup[20] = 'Urdu'; + $QuicktimeLanguageLookup[21] = 'Hindi'; + $QuicktimeLanguageLookup[22] = 'Thai'; + $QuicktimeLanguageLookup[23] = 'Korean'; + $QuicktimeLanguageLookup[24] = 'Lithuanian'; + $QuicktimeLanguageLookup[25] = 'Polish'; + $QuicktimeLanguageLookup[26] = 'Hungarian'; + $QuicktimeLanguageLookup[27] = 'Estonian'; + $QuicktimeLanguageLookup[28] = 'Lettish'; + $QuicktimeLanguageLookup[28] = 'Latvian'; + $QuicktimeLanguageLookup[29] = 'Saamisk'; + $QuicktimeLanguageLookup[29] = 'Lappish'; + $QuicktimeLanguageLookup[30] = 'Faeroese'; + $QuicktimeLanguageLookup[31] = 'Farsi'; + $QuicktimeLanguageLookup[31] = 'Persian'; + $QuicktimeLanguageLookup[32] = 'Russian'; + $QuicktimeLanguageLookup[33] = 'Chinese (Simplified)'; + $QuicktimeLanguageLookup[34] = 'Flemish'; + $QuicktimeLanguageLookup[35] = 'Irish'; + $QuicktimeLanguageLookup[36] = 'Albanian'; + $QuicktimeLanguageLookup[37] = 'Romanian'; + $QuicktimeLanguageLookup[38] = 'Czech'; + $QuicktimeLanguageLookup[39] = 'Slovak'; + $QuicktimeLanguageLookup[40] = 'Slovenian'; + $QuicktimeLanguageLookup[41] = 'Yiddish'; + $QuicktimeLanguageLookup[42] = 'Serbian'; + $QuicktimeLanguageLookup[43] = 'Macedonian'; + $QuicktimeLanguageLookup[44] = 'Bulgarian'; + $QuicktimeLanguageLookup[45] = 'Ukrainian'; + $QuicktimeLanguageLookup[46] = 'Byelorussian'; + $QuicktimeLanguageLookup[47] = 'Uzbek'; + $QuicktimeLanguageLookup[48] = 'Kazakh'; + $QuicktimeLanguageLookup[49] = 'Azerbaijani'; + $QuicktimeLanguageLookup[50] = 'AzerbaijanAr'; + $QuicktimeLanguageLookup[51] = 'Armenian'; + $QuicktimeLanguageLookup[52] = 'Georgian'; + $QuicktimeLanguageLookup[53] = 'Moldavian'; + $QuicktimeLanguageLookup[54] = 'Kirghiz'; + $QuicktimeLanguageLookup[55] = 'Tajiki'; + $QuicktimeLanguageLookup[56] = 'Turkmen'; + $QuicktimeLanguageLookup[57] = 'Mongolian'; + $QuicktimeLanguageLookup[58] = 'MongolianCyr'; + $QuicktimeLanguageLookup[59] = 'Pashto'; + $QuicktimeLanguageLookup[60] = 'Kurdish'; + $QuicktimeLanguageLookup[61] = 'Kashmiri'; + $QuicktimeLanguageLookup[62] = 'Sindhi'; + $QuicktimeLanguageLookup[63] = 'Tibetan'; + $QuicktimeLanguageLookup[64] = 'Nepali'; + $QuicktimeLanguageLookup[65] = 'Sanskrit'; + $QuicktimeLanguageLookup[66] = 'Marathi'; + $QuicktimeLanguageLookup[67] = 'Bengali'; + $QuicktimeLanguageLookup[68] = 'Assamese'; + $QuicktimeLanguageLookup[69] = 'Gujarati'; + $QuicktimeLanguageLookup[70] = 'Punjabi'; + $QuicktimeLanguageLookup[71] = 'Oriya'; + $QuicktimeLanguageLookup[72] = 'Malayalam'; + $QuicktimeLanguageLookup[73] = 'Kannada'; + $QuicktimeLanguageLookup[74] = 'Tamil'; + $QuicktimeLanguageLookup[75] = 'Telugu'; + $QuicktimeLanguageLookup[76] = 'Sinhalese'; + $QuicktimeLanguageLookup[77] = 'Burmese'; + $QuicktimeLanguageLookup[78] = 'Khmer'; + $QuicktimeLanguageLookup[79] = 'Lao'; + $QuicktimeLanguageLookup[80] = 'Vietnamese'; + $QuicktimeLanguageLookup[81] = 'Indonesian'; + $QuicktimeLanguageLookup[82] = 'Tagalog'; + $QuicktimeLanguageLookup[83] = 'MalayRoman'; + $QuicktimeLanguageLookup[84] = 'MalayArabic'; + $QuicktimeLanguageLookup[85] = 'Amharic'; + $QuicktimeLanguageLookup[86] = 'Tigrinya'; + $QuicktimeLanguageLookup[87] = 'Galla'; + $QuicktimeLanguageLookup[87] = 'Oromo'; + $QuicktimeLanguageLookup[88] = 'Somali'; + $QuicktimeLanguageLookup[89] = 'Swahili'; + $QuicktimeLanguageLookup[90] = 'Ruanda'; + $QuicktimeLanguageLookup[91] = 'Rundi'; + $QuicktimeLanguageLookup[92] = 'Chewa'; + $QuicktimeLanguageLookup[93] = 'Malagasy'; + $QuicktimeLanguageLookup[94] = 'Esperanto'; + $QuicktimeLanguageLookup[128] = 'Welsh'; + $QuicktimeLanguageLookup[129] = 'Basque'; + $QuicktimeLanguageLookup[130] = 'Catalan'; + $QuicktimeLanguageLookup[131] = 'Latin'; + $QuicktimeLanguageLookup[132] = 'Quechua'; + $QuicktimeLanguageLookup[133] = 'Guarani'; + $QuicktimeLanguageLookup[134] = 'Aymara'; + $QuicktimeLanguageLookup[135] = 'Tatar'; + $QuicktimeLanguageLookup[136] = 'Uighur'; + $QuicktimeLanguageLookup[137] = 'Dzongkha'; + $QuicktimeLanguageLookup[138] = 'JavaneseRom'; + $QuicktimeLanguageLookup[32767] = 'Unspecified'; + } + if (($languageid > 138) && ($languageid < 32767)) { + /* + ISO Language Codes - http://www.loc.gov/standards/iso639-2/php/code_list.php + Because the language codes specified by ISO 639-2/T are three characters long, they must be packed to fit into a 16-bit field. + The packing algorithm must map each of the three characters, which are always lowercase, into a 5-bit integer and then concatenate + these integers into the least significant 15 bits of a 16-bit integer, leaving the 16-bit integer's most significant bit set to zero. + + One algorithm for performing this packing is to treat each ISO character as a 16-bit integer. Subtract 0x60 from the first character + and multiply by 2^10 (0x400), subtract 0x60 from the second character and multiply by 2^5 (0x20), subtract 0x60 from the third character, + and add the three 16-bit values. This will result in a single 16-bit value with the three codes correctly packed into the 15 least + significant bits and the most significant bit set to zero. + */ + $iso_language_id = ''; + $iso_language_id .= chr((($languageid & 0x7C00) >> 10) + 0x60); + $iso_language_id .= chr((($languageid & 0x03E0) >> 5) + 0x60); + $iso_language_id .= chr((($languageid & 0x001F) >> 0) + 0x60); + $QuicktimeLanguageLookup[$languageid] = getid3_id3v2::LanguageLookup($iso_language_id); + } + return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid'); + } + + public function QuicktimeVideoCodecLookup($codecid) { + static $QuicktimeVideoCodecLookup = array(); + if (empty($QuicktimeVideoCodecLookup)) { + $QuicktimeVideoCodecLookup['.SGI'] = 'SGI'; + $QuicktimeVideoCodecLookup['3IV1'] = '3ivx MPEG-4 v1'; + $QuicktimeVideoCodecLookup['3IV2'] = '3ivx MPEG-4 v2'; + $QuicktimeVideoCodecLookup['3IVX'] = '3ivx MPEG-4'; + $QuicktimeVideoCodecLookup['8BPS'] = 'Planar RGB'; + $QuicktimeVideoCodecLookup['avc1'] = 'H.264/MPEG-4 AVC'; + $QuicktimeVideoCodecLookup['avr '] = 'AVR-JPEG'; + $QuicktimeVideoCodecLookup['b16g'] = '16Gray'; + $QuicktimeVideoCodecLookup['b32a'] = '32AlphaGray'; + $QuicktimeVideoCodecLookup['b48r'] = '48RGB'; + $QuicktimeVideoCodecLookup['b64a'] = '64ARGB'; + $QuicktimeVideoCodecLookup['base'] = 'Base'; + $QuicktimeVideoCodecLookup['clou'] = 'Cloud'; + $QuicktimeVideoCodecLookup['cmyk'] = 'CMYK'; + $QuicktimeVideoCodecLookup['cvid'] = 'Cinepak'; + $QuicktimeVideoCodecLookup['dmb1'] = 'OpenDML JPEG'; + $QuicktimeVideoCodecLookup['dvc '] = 'DVC-NTSC'; + $QuicktimeVideoCodecLookup['dvcp'] = 'DVC-PAL'; + $QuicktimeVideoCodecLookup['dvpn'] = 'DVCPro-NTSC'; + $QuicktimeVideoCodecLookup['dvpp'] = 'DVCPro-PAL'; + $QuicktimeVideoCodecLookup['fire'] = 'Fire'; + $QuicktimeVideoCodecLookup['flic'] = 'FLC'; + $QuicktimeVideoCodecLookup['gif '] = 'GIF'; + $QuicktimeVideoCodecLookup['h261'] = 'H261'; + $QuicktimeVideoCodecLookup['h263'] = 'H263'; + $QuicktimeVideoCodecLookup['IV41'] = 'Indeo4'; + $QuicktimeVideoCodecLookup['jpeg'] = 'JPEG'; + $QuicktimeVideoCodecLookup['kpcd'] = 'PhotoCD'; + $QuicktimeVideoCodecLookup['mjpa'] = 'Motion JPEG-A'; + $QuicktimeVideoCodecLookup['mjpb'] = 'Motion JPEG-B'; + $QuicktimeVideoCodecLookup['msvc'] = 'Microsoft Video1'; + $QuicktimeVideoCodecLookup['myuv'] = 'MPEG YUV420'; + $QuicktimeVideoCodecLookup['path'] = 'Vector'; + $QuicktimeVideoCodecLookup['png '] = 'PNG'; + $QuicktimeVideoCodecLookup['PNTG'] = 'MacPaint'; + $QuicktimeVideoCodecLookup['qdgx'] = 'QuickDrawGX'; + $QuicktimeVideoCodecLookup['qdrw'] = 'QuickDraw'; + $QuicktimeVideoCodecLookup['raw '] = 'RAW'; + $QuicktimeVideoCodecLookup['ripl'] = 'WaterRipple'; + $QuicktimeVideoCodecLookup['rpza'] = 'Video'; + $QuicktimeVideoCodecLookup['smc '] = 'Graphics'; + $QuicktimeVideoCodecLookup['SVQ1'] = 'Sorenson Video 1'; + $QuicktimeVideoCodecLookup['SVQ1'] = 'Sorenson Video 3'; + $QuicktimeVideoCodecLookup['syv9'] = 'Sorenson YUV9'; + $QuicktimeVideoCodecLookup['tga '] = 'Targa'; + $QuicktimeVideoCodecLookup['tiff'] = 'TIFF'; + $QuicktimeVideoCodecLookup['WRAW'] = 'Windows RAW'; + $QuicktimeVideoCodecLookup['WRLE'] = 'BMP'; + $QuicktimeVideoCodecLookup['y420'] = 'YUV420'; + $QuicktimeVideoCodecLookup['yuv2'] = 'ComponentVideo'; + $QuicktimeVideoCodecLookup['yuvs'] = 'ComponentVideoUnsigned'; + $QuicktimeVideoCodecLookup['yuvu'] = 'ComponentVideoSigned'; + } + return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : ''); + } + + public function QuicktimeAudioCodecLookup($codecid) { + static $QuicktimeAudioCodecLookup = array(); + if (empty($QuicktimeAudioCodecLookup)) { + $QuicktimeAudioCodecLookup['.mp3'] = 'Fraunhofer MPEG Layer-III alias'; + $QuicktimeAudioCodecLookup['aac '] = 'ISO/IEC 14496-3 AAC'; + $QuicktimeAudioCodecLookup['agsm'] = 'Apple GSM 10:1'; + $QuicktimeAudioCodecLookup['alac'] = 'Apple Lossless Audio Codec'; + $QuicktimeAudioCodecLookup['alaw'] = 'A-law 2:1'; + $QuicktimeAudioCodecLookup['conv'] = 'Sample Format'; + $QuicktimeAudioCodecLookup['dvca'] = 'DV'; + $QuicktimeAudioCodecLookup['dvi '] = 'DV 4:1'; + $QuicktimeAudioCodecLookup['eqal'] = 'Frequency Equalizer'; + $QuicktimeAudioCodecLookup['fl32'] = '32-bit Floating Point'; + $QuicktimeAudioCodecLookup['fl64'] = '64-bit Floating Point'; + $QuicktimeAudioCodecLookup['ima4'] = 'Interactive Multimedia Association 4:1'; + $QuicktimeAudioCodecLookup['in24'] = '24-bit Integer'; + $QuicktimeAudioCodecLookup['in32'] = '32-bit Integer'; + $QuicktimeAudioCodecLookup['lpc '] = 'LPC 23:1'; + $QuicktimeAudioCodecLookup['MAC3'] = 'Macintosh Audio Compression/Expansion (MACE) 3:1'; + $QuicktimeAudioCodecLookup['MAC6'] = 'Macintosh Audio Compression/Expansion (MACE) 6:1'; + $QuicktimeAudioCodecLookup['mixb'] = '8-bit Mixer'; + $QuicktimeAudioCodecLookup['mixw'] = '16-bit Mixer'; + $QuicktimeAudioCodecLookup['mp4a'] = 'ISO/IEC 14496-3 AAC'; + $QuicktimeAudioCodecLookup['MS'."\x00\x02"] = 'Microsoft ADPCM'; + $QuicktimeAudioCodecLookup['MS'."\x00\x11"] = 'DV IMA'; + $QuicktimeAudioCodecLookup['MS'."\x00\x55"] = 'Fraunhofer MPEG Layer III'; + $QuicktimeAudioCodecLookup['NONE'] = 'No Encoding'; + $QuicktimeAudioCodecLookup['Qclp'] = 'Qualcomm PureVoice'; + $QuicktimeAudioCodecLookup['QDM2'] = 'QDesign Music 2'; + $QuicktimeAudioCodecLookup['QDMC'] = 'QDesign Music 1'; + $QuicktimeAudioCodecLookup['ratb'] = '8-bit Rate'; + $QuicktimeAudioCodecLookup['ratw'] = '16-bit Rate'; + $QuicktimeAudioCodecLookup['raw '] = 'raw PCM'; + $QuicktimeAudioCodecLookup['sour'] = 'Sound Source'; + $QuicktimeAudioCodecLookup['sowt'] = 'signed/two\'s complement (Little Endian)'; + $QuicktimeAudioCodecLookup['str1'] = 'Iomega MPEG layer II'; + $QuicktimeAudioCodecLookup['str2'] = 'Iomega MPEG *layer II'; + $QuicktimeAudioCodecLookup['str3'] = 'Iomega MPEG **layer II'; + $QuicktimeAudioCodecLookup['str4'] = 'Iomega MPEG ***layer II'; + $QuicktimeAudioCodecLookup['twos'] = 'signed/two\'s complement (Big Endian)'; + $QuicktimeAudioCodecLookup['ulaw'] = 'mu-law 2:1'; + } + return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : ''); + } + + public function QuicktimeDCOMLookup($compressionid) { + static $QuicktimeDCOMLookup = array(); + if (empty($QuicktimeDCOMLookup)) { + $QuicktimeDCOMLookup['zlib'] = 'ZLib Deflate'; + $QuicktimeDCOMLookup['adec'] = 'Apple Compression'; + } + return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : ''); + } + + public function QuicktimeColorNameLookup($colordepthid) { + static $QuicktimeColorNameLookup = array(); + if (empty($QuicktimeColorNameLookup)) { + $QuicktimeColorNameLookup[1] = '2-color (monochrome)'; + $QuicktimeColorNameLookup[2] = '4-color'; + $QuicktimeColorNameLookup[4] = '16-color'; + $QuicktimeColorNameLookup[8] = '256-color'; + $QuicktimeColorNameLookup[16] = 'thousands (16-bit color)'; + $QuicktimeColorNameLookup[24] = 'millions (24-bit color)'; + $QuicktimeColorNameLookup[32] = 'millions+ (32-bit color)'; + $QuicktimeColorNameLookup[33] = 'black & white'; + $QuicktimeColorNameLookup[34] = '4-gray'; + $QuicktimeColorNameLookup[36] = '16-gray'; + $QuicktimeColorNameLookup[40] = '256-gray'; + } + return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid'); + } + + public function QuicktimeSTIKLookup($stik) { + static $QuicktimeSTIKLookup = array(); + if (empty($QuicktimeSTIKLookup)) { + $QuicktimeSTIKLookup[0] = 'Movie'; + $QuicktimeSTIKLookup[1] = 'Normal'; + $QuicktimeSTIKLookup[2] = 'Audiobook'; + $QuicktimeSTIKLookup[5] = 'Whacked Bookmark'; + $QuicktimeSTIKLookup[6] = 'Music Video'; + $QuicktimeSTIKLookup[9] = 'Short Film'; + $QuicktimeSTIKLookup[10] = 'TV Show'; + $QuicktimeSTIKLookup[11] = 'Booklet'; + $QuicktimeSTIKLookup[14] = 'Ringtone'; + $QuicktimeSTIKLookup[21] = 'Podcast'; + } + return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid'); + } + + public function QuicktimeIODSaudioProfileName($audio_profile_id) { + static $QuicktimeIODSaudioProfileNameLookup = array(); + if (empty($QuicktimeIODSaudioProfileNameLookup)) { + $QuicktimeIODSaudioProfileNameLookup = array( + 0x00 => 'ISO Reserved (0x00)', + 0x01 => 'Main Audio Profile @ Level 1', + 0x02 => 'Main Audio Profile @ Level 2', + 0x03 => 'Main Audio Profile @ Level 3', + 0x04 => 'Main Audio Profile @ Level 4', + 0x05 => 'Scalable Audio Profile @ Level 1', + 0x06 => 'Scalable Audio Profile @ Level 2', + 0x07 => 'Scalable Audio Profile @ Level 3', + 0x08 => 'Scalable Audio Profile @ Level 4', + 0x09 => 'Speech Audio Profile @ Level 1', + 0x0A => 'Speech Audio Profile @ Level 2', + 0x0B => 'Synthetic Audio Profile @ Level 1', + 0x0C => 'Synthetic Audio Profile @ Level 2', + 0x0D => 'Synthetic Audio Profile @ Level 3', + 0x0E => 'High Quality Audio Profile @ Level 1', + 0x0F => 'High Quality Audio Profile @ Level 2', + 0x10 => 'High Quality Audio Profile @ Level 3', + 0x11 => 'High Quality Audio Profile @ Level 4', + 0x12 => 'High Quality Audio Profile @ Level 5', + 0x13 => 'High Quality Audio Profile @ Level 6', + 0x14 => 'High Quality Audio Profile @ Level 7', + 0x15 => 'High Quality Audio Profile @ Level 8', + 0x16 => 'Low Delay Audio Profile @ Level 1', + 0x17 => 'Low Delay Audio Profile @ Level 2', + 0x18 => 'Low Delay Audio Profile @ Level 3', + 0x19 => 'Low Delay Audio Profile @ Level 4', + 0x1A => 'Low Delay Audio Profile @ Level 5', + 0x1B => 'Low Delay Audio Profile @ Level 6', + 0x1C => 'Low Delay Audio Profile @ Level 7', + 0x1D => 'Low Delay Audio Profile @ Level 8', + 0x1E => 'Natural Audio Profile @ Level 1', + 0x1F => 'Natural Audio Profile @ Level 2', + 0x20 => 'Natural Audio Profile @ Level 3', + 0x21 => 'Natural Audio Profile @ Level 4', + 0x22 => 'Mobile Audio Internetworking Profile @ Level 1', + 0x23 => 'Mobile Audio Internetworking Profile @ Level 2', + 0x24 => 'Mobile Audio Internetworking Profile @ Level 3', + 0x25 => 'Mobile Audio Internetworking Profile @ Level 4', + 0x26 => 'Mobile Audio Internetworking Profile @ Level 5', + 0x27 => 'Mobile Audio Internetworking Profile @ Level 6', + 0x28 => 'AAC Profile @ Level 1', + 0x29 => 'AAC Profile @ Level 2', + 0x2A => 'AAC Profile @ Level 4', + 0x2B => 'AAC Profile @ Level 5', + 0x2C => 'High Efficiency AAC Profile @ Level 2', + 0x2D => 'High Efficiency AAC Profile @ Level 3', + 0x2E => 'High Efficiency AAC Profile @ Level 4', + 0x2F => 'High Efficiency AAC Profile @ Level 5', + 0xFE => 'Not part of MPEG-4 audio profiles', + 0xFF => 'No audio capability required', + ); + } + return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private'); + } + + + public function QuicktimeIODSvideoProfileName($video_profile_id) { + static $QuicktimeIODSvideoProfileNameLookup = array(); + if (empty($QuicktimeIODSvideoProfileNameLookup)) { + $QuicktimeIODSvideoProfileNameLookup = array( + 0x00 => 'Reserved (0x00) Profile', + 0x01 => 'Simple Profile @ Level 1', + 0x02 => 'Simple Profile @ Level 2', + 0x03 => 'Simple Profile @ Level 3', + 0x08 => 'Simple Profile @ Level 0', + 0x10 => 'Simple Scalable Profile @ Level 0', + 0x11 => 'Simple Scalable Profile @ Level 1', + 0x12 => 'Simple Scalable Profile @ Level 2', + 0x15 => 'AVC/H264 Profile', + 0x21 => 'Core Profile @ Level 1', + 0x22 => 'Core Profile @ Level 2', + 0x32 => 'Main Profile @ Level 2', + 0x33 => 'Main Profile @ Level 3', + 0x34 => 'Main Profile @ Level 4', + 0x42 => 'N-bit Profile @ Level 2', + 0x51 => 'Scalable Texture Profile @ Level 1', + 0x61 => 'Simple Face Animation Profile @ Level 1', + 0x62 => 'Simple Face Animation Profile @ Level 2', + 0x63 => 'Simple FBA Profile @ Level 1', + 0x64 => 'Simple FBA Profile @ Level 2', + 0x71 => 'Basic Animated Texture Profile @ Level 1', + 0x72 => 'Basic Animated Texture Profile @ Level 2', + 0x81 => 'Hybrid Profile @ Level 1', + 0x82 => 'Hybrid Profile @ Level 2', + 0x91 => 'Advanced Real Time Simple Profile @ Level 1', + 0x92 => 'Advanced Real Time Simple Profile @ Level 2', + 0x93 => 'Advanced Real Time Simple Profile @ Level 3', + 0x94 => 'Advanced Real Time Simple Profile @ Level 4', + 0xA1 => 'Core Scalable Profile @ Level1', + 0xA2 => 'Core Scalable Profile @ Level2', + 0xA3 => 'Core Scalable Profile @ Level3', + 0xB1 => 'Advanced Coding Efficiency Profile @ Level 1', + 0xB2 => 'Advanced Coding Efficiency Profile @ Level 2', + 0xB3 => 'Advanced Coding Efficiency Profile @ Level 3', + 0xB4 => 'Advanced Coding Efficiency Profile @ Level 4', + 0xC1 => 'Advanced Core Profile @ Level 1', + 0xC2 => 'Advanced Core Profile @ Level 2', + 0xD1 => 'Advanced Scalable Texture @ Level1', + 0xD2 => 'Advanced Scalable Texture @ Level2', + 0xE1 => 'Simple Studio Profile @ Level 1', + 0xE2 => 'Simple Studio Profile @ Level 2', + 0xE3 => 'Simple Studio Profile @ Level 3', + 0xE4 => 'Simple Studio Profile @ Level 4', + 0xE5 => 'Core Studio Profile @ Level 1', + 0xE6 => 'Core Studio Profile @ Level 2', + 0xE7 => 'Core Studio Profile @ Level 3', + 0xE8 => 'Core Studio Profile @ Level 4', + 0xF0 => 'Advanced Simple Profile @ Level 0', + 0xF1 => 'Advanced Simple Profile @ Level 1', + 0xF2 => 'Advanced Simple Profile @ Level 2', + 0xF3 => 'Advanced Simple Profile @ Level 3', + 0xF4 => 'Advanced Simple Profile @ Level 4', + 0xF5 => 'Advanced Simple Profile @ Level 5', + 0xF7 => 'Advanced Simple Profile @ Level 3b', + 0xF8 => 'Fine Granularity Scalable Profile @ Level 0', + 0xF9 => 'Fine Granularity Scalable Profile @ Level 1', + 0xFA => 'Fine Granularity Scalable Profile @ Level 2', + 0xFB => 'Fine Granularity Scalable Profile @ Level 3', + 0xFC => 'Fine Granularity Scalable Profile @ Level 4', + 0xFD => 'Fine Granularity Scalable Profile @ Level 5', + 0xFE => 'Not part of MPEG-4 Visual profiles', + 0xFF => 'No visual capability required', + ); + } + return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile'); + } + + + public function QuicktimeContentRatingLookup($rtng) { + static $QuicktimeContentRatingLookup = array(); + if (empty($QuicktimeContentRatingLookup)) { + $QuicktimeContentRatingLookup[0] = 'None'; + $QuicktimeContentRatingLookup[2] = 'Clean'; + $QuicktimeContentRatingLookup[4] = 'Explicit'; + } + return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid'); + } + + public function QuicktimeStoreAccountTypeLookup($akid) { + static $QuicktimeStoreAccountTypeLookup = array(); + if (empty($QuicktimeStoreAccountTypeLookup)) { + $QuicktimeStoreAccountTypeLookup[0] = 'iTunes'; + $QuicktimeStoreAccountTypeLookup[1] = 'AOL'; + } + return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid'); + } + + public function QuicktimeStoreFrontCodeLookup($sfid) { + static $QuicktimeStoreFrontCodeLookup = array(); + if (empty($QuicktimeStoreFrontCodeLookup)) { + $QuicktimeStoreFrontCodeLookup[143460] = 'Australia'; + $QuicktimeStoreFrontCodeLookup[143445] = 'Austria'; + $QuicktimeStoreFrontCodeLookup[143446] = 'Belgium'; + $QuicktimeStoreFrontCodeLookup[143455] = 'Canada'; + $QuicktimeStoreFrontCodeLookup[143458] = 'Denmark'; + $QuicktimeStoreFrontCodeLookup[143447] = 'Finland'; + $QuicktimeStoreFrontCodeLookup[143442] = 'France'; + $QuicktimeStoreFrontCodeLookup[143443] = 'Germany'; + $QuicktimeStoreFrontCodeLookup[143448] = 'Greece'; + $QuicktimeStoreFrontCodeLookup[143449] = 'Ireland'; + $QuicktimeStoreFrontCodeLookup[143450] = 'Italy'; + $QuicktimeStoreFrontCodeLookup[143462] = 'Japan'; + $QuicktimeStoreFrontCodeLookup[143451] = 'Luxembourg'; + $QuicktimeStoreFrontCodeLookup[143452] = 'Netherlands'; + $QuicktimeStoreFrontCodeLookup[143461] = 'New Zealand'; + $QuicktimeStoreFrontCodeLookup[143457] = 'Norway'; + $QuicktimeStoreFrontCodeLookup[143453] = 'Portugal'; + $QuicktimeStoreFrontCodeLookup[143454] = 'Spain'; + $QuicktimeStoreFrontCodeLookup[143456] = 'Sweden'; + $QuicktimeStoreFrontCodeLookup[143459] = 'Switzerland'; + $QuicktimeStoreFrontCodeLookup[143444] = 'United Kingdom'; + $QuicktimeStoreFrontCodeLookup[143441] = 'United States'; + } + return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid'); + } + + public function QuicktimeParseNikonNCTG($atom_data) { + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG + // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 + // Data is stored as records of: + // * 4 bytes record type + // * 2 bytes size of data field type: + // 0x0001 = flag (size field *= 1-byte) + // 0x0002 = char (size field *= 1-byte) + // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB + // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD + // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together + // 0x0007 = bytes (size field *= 1-byte), values are stored as ?????? + // 0x0008 = ????? (size field *= 2-byte), values are stored as ?????? + // * 2 bytes data size field + // * ? bytes data (string data may be null-padded; datestamp fields are in the format "2011:05:25 20:24:15") + // all integers are stored BigEndian + + $NCTGtagName = array( + 0x00000001 => 'Make', + 0x00000002 => 'Model', + 0x00000003 => 'Software', + 0x00000011 => 'CreateDate', + 0x00000012 => 'DateTimeOriginal', + 0x00000013 => 'FrameCount', + 0x00000016 => 'FrameRate', + 0x00000022 => 'FrameWidth', + 0x00000023 => 'FrameHeight', + 0x00000032 => 'AudioChannels', + 0x00000033 => 'AudioBitsPerSample', + 0x00000034 => 'AudioSampleRate', + 0x02000001 => 'MakerNoteVersion', + 0x02000005 => 'WhiteBalance', + 0x0200000b => 'WhiteBalanceFineTune', + 0x0200001e => 'ColorSpace', + 0x02000023 => 'PictureControlData', + 0x02000024 => 'WorldTime', + 0x02000032 => 'UnknownInfo', + 0x02000083 => 'LensType', + 0x02000084 => 'Lens', + ); + + $offset = 0; + $datalength = strlen($atom_data); + $parsed = array(); + while ($offset < $datalength) { +//echo getid3_lib::PrintHexBytes(substr($atom_data, $offset, 4)).'
    '; + $record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4; + $data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; + $data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; + switch ($data_size_type) { + case 0x0001: // 0x0001 = flag (size field *= 1-byte) + $data = getid3_lib::BigEndian2Int(substr($atom_data, $offset, $data_size * 1)); + $offset += ($data_size * 1); + break; + case 0x0002: // 0x0002 = char (size field *= 1-byte) + $data = substr($atom_data, $offset, $data_size * 1); + $offset += ($data_size * 1); + $data = rtrim($data, "\x00"); + break; + case 0x0003: // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB + $data = ''; + for ($i = $data_size - 1; $i >= 0; $i--) { + $data .= substr($atom_data, $offset + ($i * 2), 2); + } + $data = getid3_lib::BigEndian2Int($data); + $offset += ($data_size * 2); + break; + case 0x0004: // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD + $data = ''; + for ($i = $data_size - 1; $i >= 0; $i--) { + $data .= substr($atom_data, $offset + ($i * 4), 4); + } + $data = getid3_lib::BigEndian2Int($data); + $offset += ($data_size * 4); + break; + case 0x0005: // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together + $data = array(); + for ($i = 0; $i < $data_size; $i++) { + $numerator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 0, 4)); + $denomninator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 4, 4)); + if ($denomninator == 0) { + $data[$i] = false; + } else { + $data[$i] = (double) $numerator / $denomninator; + } + } + $offset += (8 * $data_size); + if (count($data) == 1) { + $data = $data[0]; + } + break; + case 0x0007: // 0x0007 = bytes (size field *= 1-byte), values are stored as ?????? + $data = substr($atom_data, $offset, $data_size * 1); + $offset += ($data_size * 1); + break; + case 0x0008: // 0x0008 = ????? (size field *= 2-byte), values are stored as ?????? + $data = substr($atom_data, $offset, $data_size * 2); + $offset += ($data_size * 2); + break; + default: +echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
    '; + break 2; + } + + switch ($record_type) { + case 0x00000011: // CreateDate + case 0x00000012: // DateTimeOriginal + $data = strtotime($data); + break; + case 0x0200001e: // ColorSpace + switch ($data) { + case 1: + $data = 'sRGB'; + break; + case 2: + $data = 'Adobe RGB'; + break; + } + break; + case 0x02000023: // PictureControlData + $PictureControlAdjust = array(0=>'default', 1=>'quick', 2=>'full'); + $FilterEffect = array(0x80=>'off', 0x81=>'yellow', 0x82=>'orange', 0x83=>'red', 0x84=>'green', 0xff=>'n/a'); + $ToningEffect = array(0x80=>'b&w', 0x81=>'sepia', 0x82=>'cyanotype', 0x83=>'red', 0x84=>'yellow', 0x85=>'green', 0x86=>'blue-green', 0x87=>'blue', 0x88=>'purple-blue', 0x89=>'red-purple', 0xff=>'n/a'); + $data = array( + 'PictureControlVersion' => substr($data, 0, 4), + 'PictureControlName' => rtrim(substr($data, 4, 20), "\x00"), + 'PictureControlBase' => rtrim(substr($data, 24, 20), "\x00"), + //'?' => substr($data, 44, 4), + 'PictureControlAdjust' => $PictureControlAdjust[ord(substr($data, 48, 1))], + 'PictureControlQuickAdjust' => ord(substr($data, 49, 1)), + 'Sharpness' => ord(substr($data, 50, 1)), + 'Contrast' => ord(substr($data, 51, 1)), + 'Brightness' => ord(substr($data, 52, 1)), + 'Saturation' => ord(substr($data, 53, 1)), + 'HueAdjustment' => ord(substr($data, 54, 1)), + 'FilterEffect' => $FilterEffect[ord(substr($data, 55, 1))], + 'ToningEffect' => $ToningEffect[ord(substr($data, 56, 1))], + 'ToningSaturation' => ord(substr($data, 57, 1)), + ); + break; + case 0x02000024: // WorldTime + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#WorldTime + // timezone is stored as offset from GMT in minutes + $timezone = getid3_lib::BigEndian2Int(substr($data, 0, 2)); + if ($timezone & 0x8000) { + $timezone = 0 - (0x10000 - $timezone); + } + $timezone /= 60; + + $dst = (bool) getid3_lib::BigEndian2Int(substr($data, 2, 1)); + switch (getid3_lib::BigEndian2Int(substr($data, 3, 1))) { + case 2: + $datedisplayformat = 'D/M/Y'; break; + case 1: + $datedisplayformat = 'M/D/Y'; break; + case 0: + default: + $datedisplayformat = 'Y/M/D'; break; + } + + $data = array('timezone'=>floatval($timezone), 'dst'=>$dst, 'display'=>$datedisplayformat); + break; + case 0x02000083: // LensType + $data = array( + //'_' => $data, + 'mf' => (bool) ($data & 0x01), + 'd' => (bool) ($data & 0x02), + 'g' => (bool) ($data & 0x04), + 'vr' => (bool) ($data & 0x08), + ); + break; + } + $tag_name = (isset($NCTGtagName[$record_type]) ? $NCTGtagName[$record_type] : '0x'.str_pad(dechex($record_type), 8, '0', STR_PAD_LEFT)); + $parsed[$tag_name] = $data; + } + return $parsed; + } + + + public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') { + static $handyatomtranslatorarray = array(); + if (empty($handyatomtranslatorarray)) { + $handyatomtranslatorarray['©cpy'] = 'copyright'; + $handyatomtranslatorarray['©day'] = 'creation_date'; // iTunes 4.0 + $handyatomtranslatorarray['©dir'] = 'director'; + $handyatomtranslatorarray['©ed1'] = 'edit1'; + $handyatomtranslatorarray['©ed2'] = 'edit2'; + $handyatomtranslatorarray['©ed3'] = 'edit3'; + $handyatomtranslatorarray['©ed4'] = 'edit4'; + $handyatomtranslatorarray['©ed5'] = 'edit5'; + $handyatomtranslatorarray['©ed6'] = 'edit6'; + $handyatomtranslatorarray['©ed7'] = 'edit7'; + $handyatomtranslatorarray['©ed8'] = 'edit8'; + $handyatomtranslatorarray['©ed9'] = 'edit9'; + $handyatomtranslatorarray['©fmt'] = 'format'; + $handyatomtranslatorarray['©inf'] = 'information'; + $handyatomtranslatorarray['©prd'] = 'producer'; + $handyatomtranslatorarray['©prf'] = 'performers'; + $handyatomtranslatorarray['©req'] = 'system_requirements'; + $handyatomtranslatorarray['©src'] = 'source_credit'; + $handyatomtranslatorarray['©wrt'] = 'writer'; + + // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt + $handyatomtranslatorarray['©nam'] = 'title'; // iTunes 4.0 + $handyatomtranslatorarray['©cmt'] = 'comment'; // iTunes 4.0 + $handyatomtranslatorarray['©wrn'] = 'warning'; + $handyatomtranslatorarray['©hst'] = 'host_computer'; + $handyatomtranslatorarray['©mak'] = 'make'; + $handyatomtranslatorarray['©mod'] = 'model'; + $handyatomtranslatorarray['©PRD'] = 'product'; + $handyatomtranslatorarray['©swr'] = 'software'; + $handyatomtranslatorarray['©aut'] = 'author'; + $handyatomtranslatorarray['©ART'] = 'artist'; + $handyatomtranslatorarray['©trk'] = 'track'; + $handyatomtranslatorarray['©alb'] = 'album'; // iTunes 4.0 + $handyatomtranslatorarray['©com'] = 'comment'; + $handyatomtranslatorarray['©gen'] = 'genre'; // iTunes 4.0 + $handyatomtranslatorarray['©ope'] = 'composer'; + $handyatomtranslatorarray['©url'] = 'url'; + $handyatomtranslatorarray['©enc'] = 'encoder'; + + // http://atomicparsley.sourceforge.net/mpeg-4files.html + $handyatomtranslatorarray['©art'] = 'artist'; // iTunes 4.0 + $handyatomtranslatorarray['aART'] = 'album_artist'; + $handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0 + $handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0 + $handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0 + $handyatomtranslatorarray['©too'] = 'encoder'; // iTunes 4.0 + $handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0 + $handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0? + $handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0 + $handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0 + $handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0 + $handyatomtranslatorarray['©grp'] = 'grouping'; // iTunes 4.2 + $handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9 + $handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9 + $handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9 + $handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9 + $handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9 + $handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9 + $handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0 + $handyatomtranslatorarray['©lyr'] = 'lyrics'; // iTunes 5.0 + $handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0 + $handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0 + $handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0 + $handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0 + $handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2 + $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0 + + // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt + + + + // boxnames: + /* + $handyatomtranslatorarray['iTunSMPB'] = 'iTunSMPB'; + $handyatomtranslatorarray['iTunNORM'] = 'iTunNORM'; + $handyatomtranslatorarray['Encoding Params'] = 'Encoding Params'; + $handyatomtranslatorarray['replaygain_track_gain'] = 'replaygain_track_gain'; + $handyatomtranslatorarray['replaygain_track_peak'] = 'replaygain_track_peak'; + $handyatomtranslatorarray['replaygain_track_minmax'] = 'replaygain_track_minmax'; + $handyatomtranslatorarray['MusicIP PUID'] = 'MusicIP PUID'; + $handyatomtranslatorarray['MusicBrainz Artist Id'] = 'MusicBrainz Artist Id'; + $handyatomtranslatorarray['MusicBrainz Album Id'] = 'MusicBrainz Album Id'; + $handyatomtranslatorarray['MusicBrainz Album Artist Id'] = 'MusicBrainz Album Artist Id'; + $handyatomtranslatorarray['MusicBrainz Track Id'] = 'MusicBrainz Track Id'; + $handyatomtranslatorarray['MusicBrainz Disc Id'] = 'MusicBrainz Disc Id'; + + // http://age.hobba.nl/audio/tag_frame_reference.html + $handyatomtranslatorarray['PLAY_COUNTER'] = 'play_counter'; // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355 + $handyatomtranslatorarray['MEDIATYPE'] = 'mediatype'; // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355 + */ + } + $info = &$this->getid3->info; + $comment_key = ''; + if ($boxname && ($boxname != $keyname)) { + $comment_key = (isset($handyatomtranslatorarray[$boxname]) ? $handyatomtranslatorarray[$boxname] : $boxname); + } elseif (isset($handyatomtranslatorarray[$keyname])) { + $comment_key = $handyatomtranslatorarray[$keyname]; + } + if ($comment_key) { + if ($comment_key == 'picture') { + if (!is_array($data)) { + $image_mime = ''; + if (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $data)) { + $image_mime = 'image/png'; + } elseif (preg_match('#^\xFF\xD8\xFF#', $data)) { + $image_mime = 'image/jpeg'; + } elseif (preg_match('#^GIF#', $data)) { + $image_mime = 'image/gif'; + } elseif (preg_match('#^BM#', $data)) { + $image_mime = 'image/bmp'; + } + $data = array('data'=>$data, 'image_mime'=>$image_mime); + } + } + $info['quicktime']['comments'][$comment_key][] = $data; + } + return true; + } + + public function NoNullString($nullterminatedstring) { + // remove the single null terminator on null terminated strings + if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") { + return substr($nullterminatedstring, 0, strlen($nullterminatedstring) - 1); + } + return $nullterminatedstring; + } + + public function Pascal2String($pascalstring) { + // Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string + return substr($pascalstring, 1); + } + +} diff --git a/sources/wp-includes/ID3/module.audio-video.riff.php b/sources/wp-includes/ID3/module.audio-video.riff.php new file mode 100644 index 0000000..8f43100 --- /dev/null +++ b/sources/wp-includes/ID3/module.audio-video.riff.php @@ -0,0 +1,2435 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.riff.php // +// module for analyzing RIFF files // +// multiple formats supported by this module: // +// Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX // +// dependencies: module.audio.mp3.php // +// module.audio.ac3.php // +// module.audio.dts.php // +// /// +///////////////////////////////////////////////////////////////// + +/** +* @todo Parse AC-3/DTS audio inside WAVE correctly +* @todo Rewrite RIFF parser totally +*/ + +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true); +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true); +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true); + +class getid3_riff extends getid3_handler +{ + + public function Analyze() { + $info = &$this->getid3->info; + + // initialize these values to an empty array, otherwise they default to NULL + // and you can't append array values to a NULL value + $info['riff'] = array('raw'=>array()); + + // Shortcuts + $thisfile_riff = &$info['riff']; + $thisfile_riff_raw = &$thisfile_riff['raw']; + $thisfile_audio = &$info['audio']; + $thisfile_video = &$info['video']; + $thisfile_audio_dataformat = &$thisfile_audio['dataformat']; + $thisfile_riff_audio = &$thisfile_riff['audio']; + $thisfile_riff_video = &$thisfile_riff['video']; + + $Original['avdataoffset'] = $info['avdataoffset']; + $Original['avdataend'] = $info['avdataend']; + + $this->fseek($info['avdataoffset']); + $RIFFheader = $this->fread(12); + $offset = $this->ftell(); + $RIFFtype = substr($RIFFheader, 0, 4); + $RIFFsize = substr($RIFFheader, 4, 4); + $RIFFsubtype = substr($RIFFheader, 8, 4); + + switch ($RIFFtype) { + + case 'FORM': // AIFF, AIFC + $info['fileformat'] = 'aiff'; + $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); + $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); + break; + + case 'RIFF': // AVI, WAV, etc + case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) + case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s + $info['fileformat'] = 'riff'; + $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); + if ($RIFFsubtype == 'RMP3') { + // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s + $RIFFsubtype = 'WAVE'; + } + $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); + if (($info['avdataend'] - $info['filesize']) == 1) { + // LiteWave appears to incorrectly *not* pad actual output file + // to nearest WORD boundary so may appear to be short by one + // byte, in which case - skip warning + $info['avdataend'] = $info['filesize']; + } + + $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset + while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) { + try { + $this->fseek($nextRIFFoffset); + } catch (getid3_exception $e) { + if ($e->getCode() == 10) { + //$this->warning('RIFF parser: '.$e->getMessage()); + $this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong'); + $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present'); + break; + } else { + throw $e; + } + } + $nextRIFFheader = $this->fread(12); + if ($nextRIFFoffset == ($info['avdataend'] - 1)) { + if (substr($nextRIFFheader, 0, 1) == "\x00") { + // RIFF padded to WORD boundary, we're actually already at the end + break; + } + } + $nextRIFFheaderID = substr($nextRIFFheader, 0, 4); + $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4)); + $nextRIFFtype = substr($nextRIFFheader, 8, 4); + $chunkdata = array(); + $chunkdata['offset'] = $nextRIFFoffset + 8; + $chunkdata['size'] = $nextRIFFsize; + $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size']; + + switch ($nextRIFFheaderID) { + + case 'RIFF': + $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset); + + if (!isset($thisfile_riff[$nextRIFFtype])) { + $thisfile_riff[$nextRIFFtype] = array(); + } + $thisfile_riff[$nextRIFFtype][] = $chunkdata; + break; + + case 'JUNK': + // ignore + $thisfile_riff[$nextRIFFheaderID][] = $chunkdata; + break; + + case 'IDVX': + $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size'])); + break; + + default: + if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) { + $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12); + if (substr($DIVXTAG, -7) == 'DIVXTAG') { + // DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file + $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway'); + $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG); + break 2; + } + } + $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file'); + break 2; + + } + + } + if ($RIFFsubtype == 'WAVE') { + $thisfile_riff_WAVE = &$thisfile_riff['WAVE']; + } + break; + + default: + $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead'); + unset($info['fileformat']); + return false; + } + + $streamindex = 0; + switch ($RIFFsubtype) { + case 'WAVE': + if (empty($thisfile_audio['bitrate_mode'])) { + $thisfile_audio['bitrate_mode'] = 'cbr'; + } + if (empty($thisfile_audio_dataformat)) { + $thisfile_audio_dataformat = 'wav'; + } + + if (isset($thisfile_riff_WAVE['data'][0]['offset'])) { + $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8; + $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size']; + } + if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) { + + $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']); + $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; + if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) { + $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero'; + return false; + } + $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw']; + unset($thisfile_riff_audio[$streamindex]['raw']); + $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; + + $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); + if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') { + $info['warning'][] = 'Audio codec = '.$thisfile_audio['codec']; + } + $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; + + if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV) + $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); + } + + $thisfile_audio['lossless'] = false; + if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) { + switch ($thisfile_riff_raw['fmt ']['wFormatTag']) { + + case 0x0001: // PCM + $thisfile_audio['lossless'] = true; + break; + + case 0x2000: // AC-3 + $thisfile_audio_dataformat = 'ac3'; + break; + + default: + // do nothing + break; + + } + } + $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag']; + $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; + $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless']; + $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat; + } + + if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) { + + // shortcuts + $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data']; + $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array()); + $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad']; + $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track']; + $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album']; + + $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4)); + $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2)); + $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2)); + + $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT); + $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT); + $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3)); + $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3)); + $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1)); + $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9)); + $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3)); + $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3)); + $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1)); + $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9)); + + $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude']; + if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) { + $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']); + $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']); + $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']); + } + if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) { + $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']); + $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']); + $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']); + } + } + + if (isset($thisfile_riff_WAVE['fact'][0]['data'])) { + $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4)); + + // This should be a good way of calculating exact playtime, + // but some sample files have had incorrect number of samples, + // so cannot use this method + + // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) { + // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec']; + // } + } + if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) { + $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8); + } + + if (isset($thisfile_riff_WAVE['bext'][0]['data'])) { + // shortcut + $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0]; + + $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256)); + $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32)); + $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32)); + $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10); + $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8); + $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8)); + $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1)); + $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254); + $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601))); + if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) { + if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) { + list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date; + list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time; + $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']); + } else { + $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid'; + } + } else { + $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid'; + } + $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author']; + $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title']; + } + + if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) { + // shortcut + $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0]; + + $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2)); + $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001); + if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) { + $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true; + $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004); + $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008); + + $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2)); + } + $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2)); + $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2)); + $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001); + $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002); + $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004); + } + + if (isset($thisfile_riff_WAVE['cart'][0]['data'])) { + // shortcut + $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0]; + + $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4); + $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64)); + $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64)); + $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64)); + $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64)); + $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64)); + $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64)); + $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64)); + $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10)); + $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8)); + $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10)); + $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8)); + $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64)); + $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64)); + $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64)); + $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true); + for ($i = 0; $i < 8; $i++) { + $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4); + $thisfile_riff_WAVE_cart_0['post_time'][$i]['timer_value'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8) + 4, 4)); + } + $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024)); + $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772))); + + $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist']; + $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title']; + } + + if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) { + // SoundMiner metadata + + // shortcuts + $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0]; + $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data']; + $SNDM_startoffset = 0; + $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size']; + + while ($SNDM_startoffset < $SNDM_endoffset) { + $SNDM_thisTagOffset = 0; + $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4)); + $SNDM_thisTagOffset += 4; + $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4); + $SNDM_thisTagOffset += 4; + $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2)); + $SNDM_thisTagOffset += 2; + $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2)); + $SNDM_thisTagOffset += 2; + $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize); + $SNDM_thisTagOffset += $SNDM_thisTagDataSize; + + if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) { + $info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'; + break; + } elseif ($SNDM_thisTagSize <= 0) { + $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'; + break; + } + $SNDM_startoffset += $SNDM_thisTagSize; + + $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText; + if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) { + $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText; + } else { + $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'; + } + } + + $tagmapping = array( + 'tracktitle'=>'title', + 'category' =>'genre', + 'cdtitle' =>'album', + 'tracktitle'=>'title', + ); + foreach ($tagmapping as $fromkey => $tokey) { + if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) { + $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey]; + } + } + } + + if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) { + // requires functions simplexml_load_string and get_object_vars + if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) { + $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML; + if (isset($parsedXML['SPEED']['MASTER_SPEED'])) { + @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']); + $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000); + } + if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) { + @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']); + $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000); + } + if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) { + $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0')); + $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']; + $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600); + $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60); + $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60)); + $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate']; + $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f); + $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f)); + } + unset($parsedXML); + } + } + + + + if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) { + $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; + $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); + } + + if (!empty($info['wavpack'])) { + $thisfile_audio_dataformat = 'wavpack'; + $thisfile_audio['bitrate_mode'] = 'vbr'; + $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version']; + + // Reset to the way it was - RIFF parsing will have messed this up + $info['avdataend'] = $Original['avdataend']; + $thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; + + $this->fseek($info['avdataoffset'] - 44); + $RIFFdata = $this->fread(44); + $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8; + $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44; + + if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) { + $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize); + $this->fseek($info['avdataend']); + $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize); + } + + // move the data chunk after all other chunks (if any) + // so that the RIFF parser doesn't see EOF when trying + // to skip over the data chunk + $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8); + $getid3_riff = new getid3_riff($this->getid3); + $getid3_riff->ParseRIFFdata($RIFFdata); + unset($getid3_riff); + } + + if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) { + switch ($thisfile_riff_raw['fmt ']['wFormatTag']) { + case 0x0001: // PCM + if (!empty($info['ac3'])) { + // Dolby Digital WAV files masquerade as PCM-WAV, but they're not + $thisfile_audio['wformattag'] = 0x2000; + $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']); + $thisfile_audio['lossless'] = false; + $thisfile_audio['bitrate'] = $info['ac3']['bitrate']; + $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate']; + } + if (!empty($info['dts'])) { + // Dolby DTS files masquerade as PCM-WAV, but they're not + $thisfile_audio['wformattag'] = 0x2001; + $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']); + $thisfile_audio['lossless'] = false; + $thisfile_audio['bitrate'] = $info['dts']['bitrate']; + $thisfile_audio['sample_rate'] = $info['dts']['sample_rate']; + } + break; + case 0x08AE: // ClearJump LiteWave + $thisfile_audio['bitrate_mode'] = 'vbr'; + $thisfile_audio_dataformat = 'litewave'; + + //typedef struct tagSLwFormat { + // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags + // DWORD m_dwScale; // scale factor for lossy compression + // DWORD m_dwBlockSize; // number of samples in encoded blocks + // WORD m_wQuality; // alias for the scale factor + // WORD m_wMarkDistance; // distance between marks in bytes + // WORD m_wReserved; + // + // //following paramters are ignored if CF_FILESRC is not set + // DWORD m_dwOrgSize; // original file size in bytes + // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file + // DWORD m_dwRiffChunkSize; // riff chunk size in the original file + // + // PCMWAVEFORMAT m_OrgWf; // original wave format + // }SLwFormat, *PSLwFormat; + + // shortcut + $thisfile_riff['litewave']['raw'] = array(); + $riff_litewave = &$thisfile_riff['litewave']; + $riff_litewave_raw = &$riff_litewave['raw']; + + $flags = array( + 'compression_method' => 1, + 'compression_flags' => 1, + 'm_dwScale' => 4, + 'm_dwBlockSize' => 4, + 'm_wQuality' => 2, + 'm_wMarkDistance' => 2, + 'm_wReserved' => 2, + 'm_dwOrgSize' => 4, + 'm_bFactExists' => 2, + 'm_dwRiffChunkSize' => 4, + ); + $litewave_offset = 18; + foreach ($flags as $flag => $length) { + $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length)); + $litewave_offset += $length; + } + + //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20)); + $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality']; + + $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true; + $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true; + $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04); + + $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false); + $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor']; + break; + + default: + break; + } + } + if ($info['avdataend'] > $info['filesize']) { + switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') { + case 'wavpack': // WavPack + case 'lpac': // LPAC + case 'ofr': // OptimFROG + case 'ofs': // OptimFROG DualStream + // lossless compressed audio formats that keep original RIFF headers - skip warning + break; + + case 'litewave': + if (($info['avdataend'] - $info['filesize']) == 1) { + // LiteWave appears to incorrectly *not* pad actual output file + // to nearest WORD boundary so may appear to be short by one + // byte, in which case - skip warning + } else { + // Short by more than one byte, throw warning + $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)'; + $info['avdataend'] = $info['filesize']; + } + break; + + default: + if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) { + // output file appears to be incorrectly *not* padded to nearest WORD boundary + // Output less severe warning + $info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)'; + $info['avdataend'] = $info['filesize']; + } else { + // Short by more than one byte, throw warning + $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)'; + $info['avdataend'] = $info['filesize']; + } + break; + } + } + if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) { + if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) { + $info['avdataend']--; + $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'; + } + } + if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) { + unset($thisfile_audio['bits_per_sample']); + if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) { + $thisfile_audio['bitrate'] = $info['ac3']['bitrate']; + } + } + break; + + case 'AVI ': + $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably + $thisfile_video['dataformat'] = 'avi'; + $info['mime_type'] = 'video/avi'; + + if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) { + $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8; + if (isset($thisfile_riff['AVIX'])) { + $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size']; + } else { + $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size']; + } + if ($info['avdataend'] > $info['filesize']) { + $info['warning'][] = 'Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)'; + $info['avdataend'] = $info['filesize']; + } + } + + if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) { + //$bIndexType = array( + // 0x00 => 'AVI_INDEX_OF_INDEXES', + // 0x01 => 'AVI_INDEX_OF_CHUNKS', + // 0x80 => 'AVI_INDEX_IS_DATA', + //); + //$bIndexSubtype = array( + // 0x01 => array( + // 0x01 => 'AVI_INDEX_2FIELD', + // ), + //); + foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) { + $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data']; + + $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2)); + $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1)); + $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1)); + $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4)); + $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4); + $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4)); + + //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']]; + //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']]; + + unset($ahsisd); + } + } + if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) { + $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data']; + + // shortcut + $thisfile_riff_raw['avih'] = array(); + $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih']; + + $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L) + if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) { + $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero'; + return false; + } + + $flags = array( + 'dwMaxBytesPerSec', // max. transfer rate + 'dwPaddingGranularity', // pad to multiples of this size; normally 2K. + 'dwFlags', // the ever-present flags + 'dwTotalFrames', // # frames in file + 'dwInitialFrames', // + 'dwStreams', // + 'dwSuggestedBufferSize', // + 'dwWidth', // + 'dwHeight', // + 'dwScale', // + 'dwRate', // + 'dwStart', // + 'dwLength', // + ); + $avih_offset = 4; + foreach ($flags as $flag) { + $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4)); + $avih_offset += 4; + } + + $flags = array( + 'hasindex' => 0x00000010, + 'mustuseindex' => 0x00000020, + 'interleaved' => 0x00000100, + 'trustcktype' => 0x00000800, + 'capturedfile' => 0x00010000, + 'copyrighted' => 0x00020010, + ); + foreach ($flags as $flag => $value) { + $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value); + } + + // shortcut + $thisfile_riff_video[$streamindex] = array(); + $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex]; + + if ($thisfile_riff_raw_avih['dwWidth'] > 0) { + $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth']; + $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width']; + } + if ($thisfile_riff_raw_avih['dwHeight'] > 0) { + $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight']; + $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height']; + } + if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { + $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames']; + $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames']; + } + + $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3); + $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate']; + } + if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) { + if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) { + for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) { + if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) { + $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data']; + $strhfccType = substr($strhData, 0, 4); + + if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) { + $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data']; + + // shortcut + $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex]; + + switch ($strhfccType) { + case 'auds': + $thisfile_audio['bitrate_mode'] = 'cbr'; + $thisfile_audio_dataformat = 'wav'; + if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) { + $streamindex = count($thisfile_riff_audio); + } + + $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData); + $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; + + // shortcut + $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; + $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex]; + + if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) { + unset($thisfile_audio_streams_currentstream['bits_per_sample']); + } + $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag']; + unset($thisfile_audio_streams_currentstream['raw']); + + // shortcut + $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw']; + + unset($thisfile_riff_audio[$streamindex]['raw']); + $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); + + $thisfile_audio['lossless'] = false; + switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) { + case 0x0001: // PCM + $thisfile_audio_dataformat = 'wav'; + $thisfile_audio['lossless'] = true; + break; + + case 0x0050: // MPEG Layer 2 or Layer 1 + $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2 + break; + + case 0x0055: // MPEG Layer 3 + $thisfile_audio_dataformat = 'mp3'; + break; + + case 0x00FF: // AAC + $thisfile_audio_dataformat = 'aac'; + break; + + case 0x0161: // Windows Media v7 / v8 / v9 + case 0x0162: // Windows Media Professional v9 + case 0x0163: // Windows Media Lossess v9 + $thisfile_audio_dataformat = 'wma'; + break; + + case 0x2000: // AC-3 + $thisfile_audio_dataformat = 'ac3'; + break; + + case 0x2001: // DTS + $thisfile_audio_dataformat = 'dts'; + break; + + default: + $thisfile_audio_dataformat = 'wav'; + break; + } + $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat; + $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless']; + $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode']; + break; + + + case 'iavs': + case 'vids': + // shortcut + $thisfile_riff_raw['strh'][$i] = array(); + $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i]; + + $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType; + $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4); + $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags + $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2)); + $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2)); + $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4)); + $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4)); + $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4)); + $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4)); + $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4)); + $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4)); + $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4)); + $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4)); + $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4)); + + $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']); + $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler']; + if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { + $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']); + $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; + } + $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; + $thisfile_video['pixel_aspect_ratio'] = (float) 1; + switch ($thisfile_riff_raw_strh_current['fccHandler']) { + case 'HFYU': // Huffman Lossless Codec + case 'IRAW': // Intel YUV Uncompressed + case 'YUY2': // Uncompressed YUV 4:2:2 + $thisfile_video['lossless'] = true; + break; + + default: + $thisfile_video['lossless'] = false; + break; + } + + switch ($strhfccType) { + case 'vids': + $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($info['fileformat'] == 'riff')); + $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount']; + + if ($thisfile_riff_video_current['codec'] == 'DV') { + $thisfile_riff_video_current['dv_type'] = 2; + } + break; + + case 'iavs': + $thisfile_riff_video_current['dv_type'] = 1; + break; + } + break; + + default: + $info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"'; + break; + + } + } + } + + if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { + + $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; + if (self::fourccLookup($thisfile_video['fourcc'])) { + $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']); + $thisfile_video['codec'] = $thisfile_riff_video_current['codec']; + } + + switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) { + case 'HFYU': // Huffman Lossless Codec + case 'IRAW': // Intel YUV Uncompressed + case 'YUY2': // Uncompressed YUV 4:2:2 + $thisfile_video['lossless'] = true; + //$thisfile_video['bits_per_sample'] = 24; + break; + + default: + $thisfile_video['lossless'] = false; + //$thisfile_video['bits_per_sample'] = 24; + break; + } + + } + } + } + } + break; + + case 'CDDA': + $thisfile_audio['bitrate_mode'] = 'cbr'; + $thisfile_audio_dataformat = 'cda'; + $thisfile_audio['lossless'] = true; + unset($info['mime_type']); + + $info['avdataoffset'] = 44; + + if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) { + // shortcut + $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0]; + + $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2)); + $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2)); + $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4)); + $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4)); + $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4)); + $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4)); + $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4)); + + $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75; + $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75; + $info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num']; + $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds']; + + // hardcoded data for CD-audio + $thisfile_audio['sample_rate'] = 44100; + $thisfile_audio['channels'] = 2; + $thisfile_audio['bits_per_sample'] = 16; + $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample']; + $thisfile_audio['bitrate_mode'] = 'cbr'; + } + break; + + + case 'AIFF': + case 'AIFC': + $thisfile_audio['bitrate_mode'] = 'cbr'; + $thisfile_audio_dataformat = 'aiff'; + $thisfile_audio['lossless'] = true; + $info['mime_type'] = 'audio/x-aiff'; + + if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) { + $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8; + $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size']; + if ($info['avdataend'] > $info['filesize']) { + if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) { + // structures rounded to 2-byte boundary, but dumb encoders + // forget to pad end of file to make this actually work + } else { + $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'; + } + $info['avdataend'] = $info['filesize']; + } + } + + if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) { + + // shortcut + $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data']; + + $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true); + $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false); + $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true); + $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10)); + + if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) { + $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4); + $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false); + $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize); + switch ($thisfile_riff_audio['codec_name']) { + case 'NONE': + $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; + $thisfile_audio['lossless'] = true; + break; + + case '': + switch ($thisfile_riff_audio['codec_fourcc']) { + // http://developer.apple.com/qa/snd/snd07.html + case 'sowt': + $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM'; + $thisfile_audio['lossless'] = true; + break; + + case 'twos': + $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM'; + $thisfile_audio['lossless'] = true; + break; + + default: + break; + } + break; + + default: + $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name']; + $thisfile_audio['lossless'] = false; + break; + } + } + + $thisfile_audio['channels'] = $thisfile_riff_audio['channels']; + if ($thisfile_riff_audio['bits_per_sample'] > 0) { + $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample']; + } + $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate']; + if ($thisfile_audio['sample_rate'] == 0) { + $info['error'][] = 'Corrupted AIFF file: sample_rate == zero'; + return false; + } + $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate']; + } + + if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) { + $offset = 0; + $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); + $offset += 2; + for ($i = 0; $i < $CommentCount; $i++) { + $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false); + $offset += 4; + $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true); + $offset += 2; + $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false); + $offset += 2; + $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength); + $offset += $CommentLength; + + $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']); + $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment']; + } + } + + $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); + foreach ($CommentsChunkNames as $key => $value) { + if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { + $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; + } + } +/* + if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) { + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_id3v2 = new getid3_id3v2($getid3_temp); + $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8; + if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) { + $info['id3v2'] = $getid3_temp->info['id3v2']; + } + unset($getid3_temp, $getid3_id3v2); + } +*/ + break; + + case '8SVX': + $thisfile_audio['bitrate_mode'] = 'cbr'; + $thisfile_audio_dataformat = '8svx'; + $thisfile_audio['bits_per_sample'] = 8; + $thisfile_audio['channels'] = 1; // overridden below, if need be + $info['mime_type'] = 'audio/x-aiff'; + + if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { + $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; + $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size']; + if ($info['avdataend'] > $info['filesize']) { + $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'; + } + } + + if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) { + // shortcut + $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0]; + + $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4)); + $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4)); + $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4)); + $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2)); + $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1)); + $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1)); + $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4)); + + $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec']; + + switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) { + case 0: + $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)'; + $thisfile_audio['lossless'] = true; + $ActualBitsPerSample = 8; + break; + + case 1: + $thisfile_audio['codec'] = 'Fibonacci-delta encoding'; + $thisfile_audio['lossless'] = false; + $ActualBitsPerSample = 4; + break; + + default: + $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"'; + break; + } + } + + if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) { + $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4)); + switch ($ChannelsIndex) { + case 6: // Stereo + $thisfile_audio['channels'] = 2; + break; + + case 2: // Left channel only + case 4: // Right channel only + $thisfile_audio['channels'] = 1; + break; + + default: + $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"'; + break; + } + + } + + $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment'); + foreach ($CommentsChunkNames as $key => $value) { + if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) { + $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data']; + } + } + + $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels']; + if (!empty($thisfile_audio['bitrate'])) { + $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8); + } + break; + + + case 'CDXA': + $info['mime_type'] = 'video/mpeg'; + if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) { + if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, false)) { + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_mpeg = new getid3_mpeg($getid3_temp); + $getid3_mpeg->Analyze(); + if (empty($getid3_temp->info['error'])) { + $info['audio'] = $getid3_temp->info['audio']; + $info['video'] = $getid3_temp->info['video']; + $info['mpeg'] = $getid3_temp->info['mpeg']; + $info['warning'] = $getid3_temp->info['warning']; + } + unset($getid3_temp, $getid3_mpeg); + } + } + break; + + + default: + $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead'; + unset($info['fileformat']); + break; + } + + switch ($RIFFsubtype) { + case 'WAVE': + case 'AIFF': + case 'AIFC': + $ID3v2_key_good = 'id3 '; + $ID3v2_keys_bad = array('ID3 ', 'tag '); + foreach ($ID3v2_keys_bad as $ID3v2_key_bad) { + if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) { + $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]; + $info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"'; + } + } + + if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) { + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_id3v2 = new getid3_id3v2($getid3_temp); + $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8; + if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) { + $info['id3v2'] = $getid3_temp->info['id3v2']; + } + unset($getid3_temp, $getid3_id3v2); + } + break; + } + + if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) { + $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4)); + } + if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) { + self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']); + } + if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) { + self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']); + } + + if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) { + $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version']; + } + + if (!isset($info['playtime_seconds'])) { + $info['playtime_seconds'] = 0; + } + if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { + // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie + $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); + } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { + $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); + } + + if ($info['playtime_seconds'] > 0) { + if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { + + if (!isset($info['bitrate'])) { + $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); + } + + } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) { + + if (!isset($thisfile_audio['bitrate'])) { + $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); + } + + } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) { + + if (!isset($thisfile_video['bitrate'])) { + $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); + } + + } + } + + + if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) { + + $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8); + $thisfile_audio['bitrate'] = 0; + $thisfile_video['bitrate'] = $info['bitrate']; + foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) { + $thisfile_video['bitrate'] -= $audioinfoarray['bitrate']; + $thisfile_audio['bitrate'] += $audioinfoarray['bitrate']; + } + if ($thisfile_video['bitrate'] <= 0) { + unset($thisfile_video['bitrate']); + } + if ($thisfile_audio['bitrate'] <= 0) { + unset($thisfile_audio['bitrate']); + } + } + + if (isset($info['mpeg']['audio'])) { + $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer']; + $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + $thisfile_audio['channels'] = $info['mpeg']['audio']['channels']; + $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate']; + $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); + if (!empty($info['mpeg']['audio']['codec'])) { + $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec']; + } + if (!empty($thisfile_audio['streams'])) { + foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) { + if ($streamdata['dataformat'] == $thisfile_audio_dataformat) { + $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate']; + $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels']; + $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate']; + $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode']; + $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec']; + } + } + } + $getid3_mp3 = new getid3_mp3($this->getid3); + $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions(); + unset($getid3_mp3); + } + + + if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) { + switch ($thisfile_audio_dataformat) { + case 'ac3': + // ignore bits_per_sample + break; + + default: + $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample']; + break; + } + } + + + if (empty($thisfile_riff_raw)) { + unset($thisfile_riff['raw']); + } + if (empty($thisfile_riff_audio)) { + unset($thisfile_riff['audio']); + } + if (empty($thisfile_riff_video)) { + unset($thisfile_riff['video']); + } + + return true; + } + + public function ParseRIFF($startoffset, $maxoffset) { + $info = &$this->getid3->info; + + $RIFFchunk = false; + $FoundAllChunksWeNeed = false; + + try { + $this->fseek($startoffset); + $maxoffset = min($maxoffset, $info['avdataend']); + while ($this->ftell() < $maxoffset) { + $chunknamesize = $this->fread(8); + //$chunkname = substr($chunknamesize, 0, 4); + $chunkname = str_replace("\x00", '_', substr($chunknamesize, 0, 4)); // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult + $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4)); + //if (strlen(trim($chunkname, "\x00")) < 4) { + if (strlen($chunkname) < 4) { + $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.'); + break; + } + if (($chunksize == 0) && ($chunkname != 'JUNK')) { + $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.'); + break; + } + if (($chunksize % 2) != 0) { + // all structures are packed on word boundaries + $chunksize++; + } + + switch ($chunkname) { + case 'LIST': + $listname = $this->fread(4); + if (preg_match('#^(movi|rec )$#i', $listname)) { + $RIFFchunk[$listname]['offset'] = $this->ftell() - 4; + $RIFFchunk[$listname]['size'] = $chunksize; + + if (!$FoundAllChunksWeNeed) { + $WhereWeWere = $this->ftell(); + $AudioChunkHeader = $this->fread(12); + $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2); + $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2); + $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4)); + + if ($AudioChunkStreamType == 'wb') { + $FirstFourBytes = substr($AudioChunkHeader, 8, 4); + if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) { + // MP3 + if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) { + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; + $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; + $getid3_mp3 = new getid3_mp3($getid3_temp); + $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); + if (isset($getid3_temp->info['mpeg']['audio'])) { + $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio']; + $info['audio'] = $getid3_temp->info['audio']; + $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer']; + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + $info['audio']['channels'] = $info['mpeg']['audio']['channels']; + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; + $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); + //$info['bitrate'] = $info['audio']['bitrate']; + } + unset($getid3_temp, $getid3_mp3); + } + + } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) { + + // AC3 + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; + $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; + $getid3_ac3 = new getid3_ac3($getid3_temp); + $getid3_ac3->Analyze(); + if (empty($getid3_temp->info['error'])) { + $info['audio'] = $getid3_temp->info['audio']; + $info['ac3'] = $getid3_temp->info['ac3']; + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $key => $value) { + $info['warning'][] = $value; + } + } + } + unset($getid3_temp, $getid3_ac3); + } + } + $FoundAllChunksWeNeed = true; + $this->fseek($WhereWeWere); + } + $this->fseek($chunksize - 4, SEEK_CUR); + + } else { + + if (!isset($RIFFchunk[$listname])) { + $RIFFchunk[$listname] = array(); + } + $LISTchunkParent = $listname; + $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize; + if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) { + $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk); + } + + } + break; + + default: + if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) { + $this->fseek($chunksize, SEEK_CUR); + break; + } + $thisindex = 0; + if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) { + $thisindex = count($RIFFchunk[$chunkname]); + } + $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8; + $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize; + switch ($chunkname) { + case 'data': + $info['avdataoffset'] = $this->ftell(); + $info['avdataend'] = $info['avdataoffset'] + $chunksize; + + $testData = $this->fread(36); + if ($testData === '') { + break; + } + if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) { + + // Probably is MP3 data + if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) { + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; + $getid3_temp->info['avdataend'] = $info['avdataend']; + $getid3_mp3 = new getid3_mp3($getid3_temp); + $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false); + if (empty($getid3_temp->info['error'])) { + $info['audio'] = $getid3_temp->info['audio']; + $info['mpeg'] = $getid3_temp->info['mpeg']; + } + unset($getid3_temp, $getid3_mp3); + } + + } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) { + + // This is probably AC-3 data + $getid3_temp = new getID3(); + if ($isRegularAC3) { + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; + $getid3_temp->info['avdataend'] = $info['avdataend']; + } + $getid3_ac3 = new getid3_ac3($getid3_temp); + if ($isRegularAC3) { + $getid3_ac3->Analyze(); + } else { + // Dolby Digital WAV + // AC-3 content, but not encoded in same format as normal AC-3 file + // For one thing, byte order is swapped + $ac3_data = ''; + for ($i = 0; $i < 28; $i += 2) { + $ac3_data .= substr($testData, 8 + $i + 1, 1); + $ac3_data .= substr($testData, 8 + $i + 0, 1); + } + $getid3_ac3->AnalyzeString($ac3_data); + } + + if (empty($getid3_temp->info['error'])) { + $info['audio'] = $getid3_temp->info['audio']; + $info['ac3'] = $getid3_temp->info['ac3']; + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $newerror) { + $this->warning('getid3_ac3() says: ['.$newerror.']'); + } + } + } + unset($getid3_temp, $getid3_ac3); + + } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) { + + // This is probably DTS data + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; + $getid3_dts = new getid3_dts($getid3_temp); + $getid3_dts->Analyze(); + if (empty($getid3_temp->info['error'])) { + $info['audio'] = $getid3_temp->info['audio']; + $info['dts'] = $getid3_temp->info['dts']; + $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $newerror) { + $this->warning('getid3_dts() says: ['.$newerror.']'); + } + } + } + + unset($getid3_temp, $getid3_dts); + + } elseif (substr($testData, 0, 4) == 'wvpk') { + + // This is WavPack data + $info['wavpack']['offset'] = $info['avdataoffset']; + $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4)); + $this->parseWavPackHeader(substr($testData, 8, 28)); + + } else { + // This is some other kind of data (quite possibly just PCM) + // do nothing special, just skip it + } + $nextoffset = $info['avdataend']; + $this->fseek($nextoffset); + break; + + case 'iXML': + case 'bext': + case 'cart': + case 'fmt ': + case 'strh': + case 'strf': + case 'indx': + case 'MEXT': + case 'DISP': + // always read data in + case 'JUNK': + // should be: never read data in + // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc) + if ($chunksize < 1048576) { + if ($chunksize > 0) { + $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); + if ($chunkname == 'JUNK') { + if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) { + // only keep text characters [chr(32)-chr(127)] + $info['riff']['comments']['junk'][] = trim($matches[1]); + } + // but if nothing there, ignore + // remove the key in either case + unset($RIFFchunk[$chunkname][$thisindex]['data']); + } + } + } else { + $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data'); + $this->fseek($chunksize, SEEK_CUR); + } + break; + + //case 'IDVX': + // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize)); + // break; + + default: + if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) { + $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset']; + $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size']; + unset($RIFFchunk[$chunkname][$thisindex]['offset']); + unset($RIFFchunk[$chunkname][$thisindex]['size']); + if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) { + unset($RIFFchunk[$chunkname][$thisindex]); + } + if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) { + unset($RIFFchunk[$chunkname]); + } + $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize); + } elseif ($chunksize < 2048) { + // only read data in if smaller than 2kB + $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize); + } else { + $this->fseek($chunksize, SEEK_CUR); + } + break; + } + break; + } + } + + } catch (getid3_exception $e) { + if ($e->getCode() == 10) { + $this->warning('RIFF parser: '.$e->getMessage()); + } else { + throw $e; + } + } + + return $RIFFchunk; + } + + public function ParseRIFFdata(&$RIFFdata) { + $info = &$this->getid3->info; + if ($RIFFdata) { + $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3'); + $fp_temp = fopen($tempfile, 'wb'); + $RIFFdataLength = strlen($RIFFdata); + $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4); + for ($i = 0; $i < 4; $i++) { + $RIFFdata[($i + 4)] = $NewLengthString[$i]; + } + fwrite($fp_temp, $RIFFdata); + fclose($fp_temp); + + $getid3_temp = new getID3(); + $getid3_temp->openfile($tempfile); + $getid3_temp->info['filesize'] = $RIFFdataLength; + $getid3_temp->info['filenamepath'] = $info['filenamepath']; + $getid3_temp->info['tags'] = $info['tags']; + $getid3_temp->info['warning'] = $info['warning']; + $getid3_temp->info['error'] = $info['error']; + $getid3_temp->info['comments'] = $info['comments']; + $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array()); + $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array()); + $getid3_riff = new getid3_riff($getid3_temp); + $getid3_riff->Analyze(); + + $info['riff'] = $getid3_temp->info['riff']; + $info['warning'] = $getid3_temp->info['warning']; + $info['error'] = $getid3_temp->info['error']; + $info['tags'] = $getid3_temp->info['tags']; + $info['comments'] = $getid3_temp->info['comments']; + unset($getid3_riff, $getid3_temp); + unlink($tempfile); + } + return false; + } + + public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) { + $RIFFinfoKeyLookup = array( + 'IARL'=>'archivallocation', + 'IART'=>'artist', + 'ICDS'=>'costumedesigner', + 'ICMS'=>'commissionedby', + 'ICMT'=>'comment', + 'ICNT'=>'country', + 'ICOP'=>'copyright', + 'ICRD'=>'creationdate', + 'IDIM'=>'dimensions', + 'IDIT'=>'digitizationdate', + 'IDPI'=>'resolution', + 'IDST'=>'distributor', + 'IEDT'=>'editor', + 'IENG'=>'engineers', + 'IFRM'=>'accountofparts', + 'IGNR'=>'genre', + 'IKEY'=>'keywords', + 'ILGT'=>'lightness', + 'ILNG'=>'language', + 'IMED'=>'orignalmedium', + 'IMUS'=>'composer', + 'INAM'=>'title', + 'IPDS'=>'productiondesigner', + 'IPLT'=>'palette', + 'IPRD'=>'product', + 'IPRO'=>'producer', + 'IPRT'=>'part', + 'IRTD'=>'rating', + 'ISBJ'=>'subject', + 'ISFT'=>'software', + 'ISGN'=>'secondarygenre', + 'ISHP'=>'sharpness', + 'ISRC'=>'sourcesupplier', + 'ISRF'=>'digitizationsource', + 'ISTD'=>'productionstudio', + 'ISTR'=>'starring', + 'ITCH'=>'encoded_by', + 'IWEB'=>'url', + 'IWRI'=>'writer', + '____'=>'comment', + ); + foreach ($RIFFinfoKeyLookup as $key => $value) { + if (isset($RIFFinfoArray[$key])) { + foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) { + if (trim($commentdata['data']) != '') { + if (isset($CommentsTargetArray[$value])) { + $CommentsTargetArray[$value][] = trim($commentdata['data']); + } else { + $CommentsTargetArray[$value] = array(trim($commentdata['data'])); + } + } + } + } + } + return true; + } + + public static function parseWAVEFORMATex($WaveFormatExData) { + // shortcut + $WaveFormatEx['raw'] = array(); + $WaveFormatEx_raw = &$WaveFormatEx['raw']; + + $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2); + $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2); + $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4); + $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4); + $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2); + $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2); + if (strlen($WaveFormatExData) > 16) { + $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2); + } + $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw); + + $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']); + $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels']; + $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec']; + $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8; + $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample']; + + return $WaveFormatEx; + } + + public function parseWavPackHeader($WavPackChunkData) { + // typedef struct { + // char ckID [4]; + // long ckSize; + // short version; + // short bits; // added for version 2.00 + // short flags, shift; // added for version 3.00 + // long total_samples, crc, crc2; + // char extension [4], extra_bc, extras [3]; + // } WavpackHeader; + + // shortcut + $info = &$this->getid3->info; + $info['wavpack'] = array(); + $thisfile_wavpack = &$info['wavpack']; + + $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2)); + if ($thisfile_wavpack['version'] >= 2) { + $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2)); + } + if ($thisfile_wavpack['version'] >= 3) { + $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2)); + $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2)); + $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4)); + $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4)); + $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4)); + $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4); + $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1)); + for ($i = 0; $i <= 2; $i++) { + $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1)); + } + + // shortcut + $thisfile_wavpack['flags'] = array(); + $thisfile_wavpack_flags = &$thisfile_wavpack['flags']; + + $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001); + $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002); + $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004); + $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008); + $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010); + $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020); + $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040); + $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080); + $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100); + $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200); + $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400); + $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800); + $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000); + $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000); + $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000); + $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000); + $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000); + $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000); + $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000); + $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000); + } + + return true; + } + + public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { + + $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure + $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels + $parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner + $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1 + $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels + $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures) + $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device + $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device + $parsed['biClrUsed'] = substr($BITMAPINFOHEADER, 32, 4); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression + $parsed['biClrImportant'] = substr($BITMAPINFOHEADER, 36, 4); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important + $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed); + + $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier + + return $parsed; + } + + public static function ParseDIVXTAG($DIVXTAG, $raw=false) { + // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/ + // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip + // 'Byte Layout: '1111111111111111 + // '32 for Movie - 1 '1111111111111111 + // '28 for Author - 6 '6666666666666666 + // '4 for year - 2 '6666666666662222 + // '3 for genre - 3 '7777777777777777 + // '48 for Comments - 7 '7777777777777777 + // '1 for Rating - 4 '7777777777777777 + // '5 for Future Additions - 0 '333400000DIVXTAG + // '128 bytes total + + static $DIVXTAGgenre = array( + 0 => 'Action', + 1 => 'Action/Adventure', + 2 => 'Adventure', + 3 => 'Adult', + 4 => 'Anime', + 5 => 'Cartoon', + 6 => 'Claymation', + 7 => 'Comedy', + 8 => 'Commercial', + 9 => 'Documentary', + 10 => 'Drama', + 11 => 'Home Video', + 12 => 'Horror', + 13 => 'Infomercial', + 14 => 'Interactive', + 15 => 'Mystery', + 16 => 'Music Video', + 17 => 'Other', + 18 => 'Religion', + 19 => 'Sci Fi', + 20 => 'Thriller', + 21 => 'Western', + ), + $DIVXTAGrating = array( + 0 => 'Unrated', + 1 => 'G', + 2 => 'PG', + 3 => 'PG-13', + 4 => 'R', + 5 => 'NC-17', + ); + + $parsed['title'] = trim(substr($DIVXTAG, 0, 32)); + $parsed['artist'] = trim(substr($DIVXTAG, 32, 28)); + $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4))); + $parsed['comment'] = trim(substr($DIVXTAG, 64, 48)); + $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3))); + $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1)); + //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null + //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG" + + $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']); + $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']); + + if (!$raw) { + unset($parsed['genre_id'], $parsed['rating_id']); + foreach ($parsed as $key => $value) { + if (!$value === '') { + unset($parsed['key']); + } + } + } + + foreach ($parsed as $tag => $value) { + $parsed[$tag] = array($value); + } + + return $parsed; + } + + public static function waveSNDMtagLookup($tagshortname) { + $begin = __LINE__; + + /** This is not a comment! + + ©kwd keywords + ©BPM bpm + ©trt tracktitle + ©des description + ©gen category + ©fin featuredinstrument + ©LID longid + ©bex bwdescription + ©pub publisher + ©cdt cdtitle + ©alb library + ©com composer + + */ + + return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm'); + } + + public static function wFormatTagLookup($wFormatTag) { + + $begin = __LINE__; + + /** This is not a comment! + + 0x0000 Microsoft Unknown Wave Format + 0x0001 Pulse Code Modulation (PCM) + 0x0002 Microsoft ADPCM + 0x0003 IEEE Float + 0x0004 Compaq Computer VSELP + 0x0005 IBM CVSD + 0x0006 Microsoft A-Law + 0x0007 Microsoft mu-Law + 0x0008 Microsoft DTS + 0x0010 OKI ADPCM + 0x0011 Intel DVI/IMA ADPCM + 0x0012 Videologic MediaSpace ADPCM + 0x0013 Sierra Semiconductor ADPCM + 0x0014 Antex Electronics G.723 ADPCM + 0x0015 DSP Solutions DigiSTD + 0x0016 DSP Solutions DigiFIX + 0x0017 Dialogic OKI ADPCM + 0x0018 MediaVision ADPCM + 0x0019 Hewlett-Packard CU + 0x0020 Yamaha ADPCM + 0x0021 Speech Compression Sonarc + 0x0022 DSP Group TrueSpeech + 0x0023 Echo Speech EchoSC1 + 0x0024 Audiofile AF36 + 0x0025 Audio Processing Technology APTX + 0x0026 AudioFile AF10 + 0x0027 Prosody 1612 + 0x0028 LRC + 0x0030 Dolby AC2 + 0x0031 Microsoft GSM 6.10 + 0x0032 MSNAudio + 0x0033 Antex Electronics ADPCME + 0x0034 Control Resources VQLPC + 0x0035 DSP Solutions DigiREAL + 0x0036 DSP Solutions DigiADPCM + 0x0037 Control Resources CR10 + 0x0038 Natural MicroSystems VBXADPCM + 0x0039 Crystal Semiconductor IMA ADPCM + 0x003A EchoSC3 + 0x003B Rockwell ADPCM + 0x003C Rockwell Digit LK + 0x003D Xebec + 0x0040 Antex Electronics G.721 ADPCM + 0x0041 G.728 CELP + 0x0042 MSG723 + 0x0050 MPEG Layer-2 or Layer-1 + 0x0052 RT24 + 0x0053 PAC + 0x0055 MPEG Layer-3 + 0x0059 Lucent G.723 + 0x0060 Cirrus + 0x0061 ESPCM + 0x0062 Voxware + 0x0063 Canopus Atrac + 0x0064 G.726 ADPCM + 0x0065 G.722 ADPCM + 0x0066 DSAT + 0x0067 DSAT Display + 0x0069 Voxware Byte Aligned + 0x0070 Voxware AC8 + 0x0071 Voxware AC10 + 0x0072 Voxware AC16 + 0x0073 Voxware AC20 + 0x0074 Voxware MetaVoice + 0x0075 Voxware MetaSound + 0x0076 Voxware RT29HW + 0x0077 Voxware VR12 + 0x0078 Voxware VR18 + 0x0079 Voxware TQ40 + 0x0080 Softsound + 0x0081 Voxware TQ60 + 0x0082 MSRT24 + 0x0083 G.729A + 0x0084 MVI MV12 + 0x0085 DF G.726 + 0x0086 DF GSM610 + 0x0088 ISIAudio + 0x0089 Onlive + 0x0091 SBC24 + 0x0092 Dolby AC3 SPDIF + 0x0093 MediaSonic G.723 + 0x0094 Aculab PLC Prosody 8kbps + 0x0097 ZyXEL ADPCM + 0x0098 Philips LPCBB + 0x0099 Packed + 0x00FF AAC + 0x0100 Rhetorex ADPCM + 0x0101 IBM mu-law + 0x0102 IBM A-law + 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM) + 0x0111 Vivo G.723 + 0x0112 Vivo Siren + 0x0123 Digital G.723 + 0x0125 Sanyo LD ADPCM + 0x0130 Sipro Lab Telecom ACELP NET + 0x0131 Sipro Lab Telecom ACELP 4800 + 0x0132 Sipro Lab Telecom ACELP 8V3 + 0x0133 Sipro Lab Telecom G.729 + 0x0134 Sipro Lab Telecom G.729A + 0x0135 Sipro Lab Telecom Kelvin + 0x0140 Windows Media Video V8 + 0x0150 Qualcomm PureVoice + 0x0151 Qualcomm HalfRate + 0x0155 Ring Zero Systems TUB GSM + 0x0160 Microsoft Audio 1 + 0x0161 Windows Media Audio V7 / V8 / V9 + 0x0162 Windows Media Audio Professional V9 + 0x0163 Windows Media Audio Lossless V9 + 0x0200 Creative Labs ADPCM + 0x0202 Creative Labs Fastspeech8 + 0x0203 Creative Labs Fastspeech10 + 0x0210 UHER Informatic GmbH ADPCM + 0x0220 Quarterdeck + 0x0230 I-link Worldwide VC + 0x0240 Aureal RAW Sport + 0x0250 Interactive Products HSX + 0x0251 Interactive Products RPELP + 0x0260 Consistent Software CS2 + 0x0270 Sony SCX + 0x0300 Fujitsu FM Towns Snd + 0x0400 BTV Digital + 0x0401 Intel Music Coder + 0x0450 QDesign Music + 0x0680 VME VMPCM + 0x0681 AT&T Labs TPC + 0x08AE ClearJump LiteWave + 0x1000 Olivetti GSM + 0x1001 Olivetti ADPCM + 0x1002 Olivetti CELP + 0x1003 Olivetti SBC + 0x1004 Olivetti OPR + 0x1100 Lernout & Hauspie Codec (0x1100) + 0x1101 Lernout & Hauspie CELP Codec (0x1101) + 0x1102 Lernout & Hauspie SBC Codec (0x1102) + 0x1103 Lernout & Hauspie SBC Codec (0x1103) + 0x1104 Lernout & Hauspie SBC Codec (0x1104) + 0x1400 Norris + 0x1401 AT&T ISIAudio + 0x1500 Soundspace Music Compression + 0x181C VoxWare RT24 Speech + 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com) + 0x2000 Dolby AC3 + 0x2001 Dolby DTS + 0x2002 WAVE_FORMAT_14_4 + 0x2003 WAVE_FORMAT_28_8 + 0x2004 WAVE_FORMAT_COOK + 0x2005 WAVE_FORMAT_DNET + 0x674F Ogg Vorbis 1 + 0x6750 Ogg Vorbis 2 + 0x6751 Ogg Vorbis 3 + 0x676F Ogg Vorbis 1+ + 0x6770 Ogg Vorbis 2+ + 0x6771 Ogg Vorbis 3+ + 0x7A21 GSM-AMR (CBR, no SID) + 0x7A22 GSM-AMR (VBR, including SID) + 0xFFFE WAVE_FORMAT_EXTENSIBLE + 0xFFFF WAVE_FORMAT_DEVELOPMENT + + */ + + return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag'); + } + + public static function fourccLookup($fourcc) { + + $begin = __LINE__; + + /** This is not a comment! + + swot http://developer.apple.com/qa/snd/snd07.html + ____ No Codec (____) + _BIT BI_BITFIELDS (Raw RGB) + _JPG JPEG compressed + _PNG PNG compressed W3C/ISO/IEC (RFC-2083) + _RAW Full Frames (Uncompressed) + _RGB Raw RGB Bitmap + _RL4 RLE 4bpp RGB + _RL8 RLE 8bpp RGB + 3IV1 3ivx MPEG-4 v1 + 3IV2 3ivx MPEG-4 v2 + 3IVX 3ivx MPEG-4 + AASC Autodesk Animator + ABYR Kensington ?ABYR? + AEMI Array Microsystems VideoONE MPEG1-I Capture + AFLC Autodesk Animator FLC + AFLI Autodesk Animator FLI + AMPG Array Microsystems VideoONE MPEG + ANIM Intel RDX (ANIM) + AP41 AngelPotion Definitive + ASV1 Asus Video v1 + ASV2 Asus Video v2 + ASVX Asus Video 2.0 (audio) + AUR2 AuraVision Aura 2 Codec - YUV 4:2:2 + AURA AuraVision Aura 1 Codec - YUV 4:1:1 + AVDJ Independent JPEG Group\'s codec (AVDJ) + AVRN Independent JPEG Group\'s codec (AVRN) + AYUV 4:4:4 YUV (AYUV) + AZPR Quicktime Apple Video (AZPR) + BGR Raw RGB32 + BLZ0 Blizzard DivX MPEG-4 + BTVC Conexant Composite Video + BINK RAD Game Tools Bink Video + BT20 Conexant Prosumer Video + BTCV Conexant Composite Video Codec + BW10 Data Translation Broadway MPEG Capture + CC12 Intel YUV12 + CDVC Canopus DV + CFCC Digital Processing Systems DPS Perception + CGDI Microsoft Office 97 Camcorder Video + CHAM Winnov Caviara Champagne + CJPG Creative WebCam JPEG + CLJR Cirrus Logic YUV 4:1:1 + CMYK Common Data Format in Printing (Colorgraph) + CPLA Weitek 4:2:0 YUV Planar + CRAM Microsoft Video 1 (CRAM) + cvid Radius Cinepak + CVID Radius Cinepak + CWLT Microsoft Color WLT DIB + CYUV Creative Labs YUV + CYUY ATI YUV + D261 H.261 + D263 H.263 + DIB Device Independent Bitmap + DIV1 FFmpeg OpenDivX + DIV2 Microsoft MPEG-4 v1/v2 + DIV3 DivX ;-) MPEG-4 v3.x Low-Motion + DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion + DIV5 DivX MPEG-4 v5.x + DIV6 DivX ;-) (MS MPEG-4 v3.x) + DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo) + divx DivX MPEG-4 + DMB1 Matrox Rainbow Runner hardware MJPEG + DMB2 Paradigm MJPEG + DSVD ?DSVD? + DUCK Duck TrueMotion 1.0 + DPS0 DPS/Leitch Reality Motion JPEG + DPSC DPS/Leitch PAR Motion JPEG + DV25 Matrox DVCPRO codec + DV50 Matrox DVCPRO50 codec + DVC IEC 61834 and SMPTE 314M (DVC/DV Video) + DVCP IEC 61834 and SMPTE 314M (DVC/DV Video) + DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps + DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com) + DVSL IEC Standard DV compressed in SD (SDL) + DVAN ?DVAN? + DVE2 InSoft DVE-2 Videoconferencing + dvsd IEC 61834 and SMPTE 314M DVC/DV Video + DVSD IEC 61834 and SMPTE 314M DVC/DV Video + DVX1 Lucent DVX1000SP Video Decoder + DVX2 Lucent DVX2000S Video Decoder + DVX3 Lucent DVX3000S Video Decoder + DX50 DivX v5 + DXT1 Microsoft DirectX Compressed Texture (DXT1) + DXT2 Microsoft DirectX Compressed Texture (DXT2) + DXT3 Microsoft DirectX Compressed Texture (DXT3) + DXT4 Microsoft DirectX Compressed Texture (DXT4) + DXT5 Microsoft DirectX Compressed Texture (DXT5) + DXTC Microsoft DirectX Compressed Texture (DXTC) + DXTn Microsoft DirectX Compressed Texture (DXTn) + EM2V Etymonix MPEG-2 I-frame (www.etymonix.com) + EKQ0 Elsa ?EKQ0? + ELK0 Elsa ?ELK0? + ESCP Eidos Escape + ETV1 eTreppid Video ETV1 + ETV2 eTreppid Video ETV2 + ETVC eTreppid Video ETVC + FLIC Autodesk FLI/FLC Animation + FLV1 Sorenson Spark + FLV4 On2 TrueMotion VP6 + FRWT Darim Vision Forward Motion JPEG (www.darvision.com) + FRWU Darim Vision Forward Uncompressed (www.darvision.com) + FLJP D-Vision Field Encoded Motion JPEG + FPS1 FRAPS v1 + FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel + FRWD SoftLab-Nsk Forward Motion JPEG + FVF1 Iterated Systems Fractal Video Frame + GLZW Motion LZW (gabest@freemail.hu) + GPEG Motion JPEG (gabest@freemail.hu) + GWLT Microsoft Greyscale WLT DIB + H260 Intel ITU H.260 Videoconferencing + H261 Intel ITU H.261 Videoconferencing + H262 Intel ITU H.262 Videoconferencing + H263 Intel ITU H.263 Videoconferencing + H264 Intel ITU H.264 Videoconferencing + H265 Intel ITU H.265 Videoconferencing + H266 Intel ITU H.266 Videoconferencing + H267 Intel ITU H.267 Videoconferencing + H268 Intel ITU H.268 Videoconferencing + H269 Intel ITU H.269 Videoconferencing + HFYU Huffman Lossless Codec + HMCR Rendition Motion Compensation Format (HMCR) + HMRR Rendition Motion Compensation Format (HMRR) + I263 FFmpeg I263 decoder + IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane") + IUYV Interlaced version of UYVY (www.leadtools.com) + IY41 Interlaced version of Y41P (www.leadtools.com) + IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard + IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard + IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes) + i263 Intel ITU H.263 Videoconferencing (i263) + I420 Intel Indeo 4 + IAN Intel Indeo 4 (RDX) + ICLB InSoft CellB Videoconferencing + IGOR Power DVD + IJPG Intergraph JPEG + ILVC Intel Layered Video + ILVR ITU-T H.263+ + IPDV I-O Data Device Giga AVI DV Codec + IR21 Intel Indeo 2.1 + IRAW Intel YUV Uncompressed + IV30 Intel Indeo 3.0 + IV31 Intel Indeo 3.1 + IV32 Ligos Indeo 3.2 + IV33 Ligos Indeo 3.3 + IV34 Ligos Indeo 3.4 + IV35 Ligos Indeo 3.5 + IV36 Ligos Indeo 3.6 + IV37 Ligos Indeo 3.7 + IV38 Ligos Indeo 3.8 + IV39 Ligos Indeo 3.9 + IV40 Ligos Indeo Interactive 4.0 + IV41 Ligos Indeo Interactive 4.1 + IV42 Ligos Indeo Interactive 4.2 + IV43 Ligos Indeo Interactive 4.3 + IV44 Ligos Indeo Interactive 4.4 + IV45 Ligos Indeo Interactive 4.5 + IV46 Ligos Indeo Interactive 4.6 + IV47 Ligos Indeo Interactive 4.7 + IV48 Ligos Indeo Interactive 4.8 + IV49 Ligos Indeo Interactive 4.9 + IV50 Ligos Indeo Interactive 5.0 + JBYR Kensington ?JBYR? + JPEG Still Image JPEG DIB + JPGL Pegasus Lossless Motion JPEG + KMVC Team17 Software Karl Morton\'s Video Codec + LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com) + LEAD LEAD Video Codec + Ljpg LEAD MJPEG Codec + MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de) + MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com) + MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com) + MMES Matrox MPEG-2 I-frame + MP2v Microsoft S-Mpeg 4 version 1 (MP2v) + MP42 Microsoft S-Mpeg 4 version 2 (MP42) + MP43 Microsoft S-Mpeg 4 version 3 (MP43) + MP4S Microsoft S-Mpeg 4 version 3 (MP4S) + MP4V FFmpeg MPEG-4 + MPG1 FFmpeg MPEG 1/2 + MPG2 FFmpeg MPEG 1/2 + MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3) + MPG4 Microsoft MPEG-4 + MPGI Sigma Designs MPEG + MPNG PNG images decoder + MSS1 Microsoft Windows Screen Video + MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) + M261 Microsoft H.261 + M263 Microsoft H.263 + M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2) + m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2) + MC12 ATI Motion Compensation Format (MC12) + MCAM ATI Motion Compensation Format (MCAM) + MJ2C Morgan Multimedia Motion JPEG2000 + mJPG IBM Motion JPEG w/ Huffman Tables + MJPG Microsoft Motion JPEG DIB + MP42 Microsoft MPEG-4 (low-motion) + MP43 Microsoft MPEG-4 (fast-motion) + MP4S Microsoft MPEG-4 (MP4S) + mp4s Microsoft MPEG-4 (mp4s) + MPEG Chromatic Research MPEG-1 Video I-Frame + MPG4 Microsoft MPEG-4 Video High Speed Compressor + MPGI Sigma Designs MPEG + MRCA FAST Multimedia Martin Regen Codec + MRLE Microsoft Run Length Encoding + MSVC Microsoft Video 1 + MTX1 Matrox ?MTX1? + MTX2 Matrox ?MTX2? + MTX3 Matrox ?MTX3? + MTX4 Matrox ?MTX4? + MTX5 Matrox ?MTX5? + MTX6 Matrox ?MTX6? + MTX7 Matrox ?MTX7? + MTX8 Matrox ?MTX8? + MTX9 Matrox ?MTX9? + MV12 Motion Pixels Codec (old) + MWV1 Aware Motion Wavelets + nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm) + NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com) + NUV1 NuppelVideo + NTN1 Nogatech Video Compression 1 + NVS0 nVidia GeForce Texture (NVS0) + NVS1 nVidia GeForce Texture (NVS1) + NVS2 nVidia GeForce Texture (NVS2) + NVS3 nVidia GeForce Texture (NVS3) + NVS4 nVidia GeForce Texture (NVS4) + NVS5 nVidia GeForce Texture (NVS5) + NVT0 nVidia GeForce Texture (NVT0) + NVT1 nVidia GeForce Texture (NVT1) + NVT2 nVidia GeForce Texture (NVT2) + NVT3 nVidia GeForce Texture (NVT3) + NVT4 nVidia GeForce Texture (NVT4) + NVT5 nVidia GeForce Texture (NVT5) + PIXL MiroXL, Pinnacle PCTV + PDVC I-O Data Device Digital Video Capture DV codec + PGVV Radius Video Vision + PHMO IBM Photomotion + PIM1 MPEG Realtime (Pinnacle Cards) + PIM2 Pegasus Imaging ?PIM2? + PIMJ Pegasus Imaging Lossless JPEG + PVEZ Horizons Technology PowerEZ + PVMM PacketVideo Corporation MPEG-4 + PVW2 Pegasus Imaging Wavelet Compression + Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de) + Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de) + QPEG Q-Team QPEG 1.0 + qpeq Q-Team QPEG 1.1 + RGB Raw BGR32 + RGBA Raw RGB w/ Alpha + RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com) + ROQV Id RoQ File Video Decoder + RPZA Quicktime Apple Video (RPZA) + RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/) + RV10 RealVideo 1.0 (aka RealVideo 5.0) + RV13 RealVideo 1.0 (RV13) + RV20 RealVideo G2 + RV30 RealVideo 8 + RV40 RealVideo 9 + RGBT Raw RGB w/ Transparency + RLE Microsoft Run Length Encoder + RLE4 Run Length Encoded (4bpp, 16-color) + RLE8 Run Length Encoded (8bpp, 256-color) + RT21 Intel Indeo RealTime Video 2.1 + rv20 RealVideo G2 + rv30 RealVideo 8 + RVX Intel RDX (RVX ) + SMC Apple Graphics (SMC ) + SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2 + SPIG Radius Spigot + SVQ3 Sorenson Video 3 (Apple Quicktime 5) + s422 Tekram VideoCap C210 YUV 4:2:2 + SDCC Sun Communication Digital Camera Codec + SFMC CrystalNet Surface Fitting Method + SMSC Radius SMSC + SMSD Radius SMSD + smsv WorldConnect Wavelet Video + SPIG Radius Spigot + SPLC Splash Studios ACM Audio Codec (www.splashstudios.net) + SQZ2 Microsoft VXTreme Video Codec V2 + STVA ST Microelectronics CMOS Imager Data (Bayer) + STVB ST Microelectronics CMOS Imager Data (Nudged Bayer) + STVC ST Microelectronics CMOS Imager Data (Bunched) + STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format) + STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data) + SV10 Sorenson Video R1 + SVQ1 Sorenson Video + T420 Toshiba YUV 4:2:0 + TM2A Duck TrueMotion Archiver 2.0 (www.duck.com) + TVJP Pinnacle/Truevision Targa 2000 board (TVJP) + TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ) + TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com) + TY2C Trident Decompression Driver + TLMS TeraLogic Motion Intraframe Codec (TLMS) + TLST TeraLogic Motion Intraframe Codec (TLST) + TM20 Duck TrueMotion 2.0 + TM2X Duck TrueMotion 2X + TMIC TeraLogic Motion Intraframe Codec (TMIC) + TMOT Horizons Technology TrueMotion S + tmot Horizons TrueMotion Video Compression + TR20 Duck TrueMotion RealTime 2.0 + TSCC TechSmith Screen Capture Codec + TV10 Tecomac Low-Bit Rate Codec + TY2N Trident ?TY2N? + U263 UB Video H.263/H.263+/H.263++ Decoder + UMP4 UB Video MPEG 4 (www.ubvideo.com) + UYNV Nvidia UYVY packed 4:2:2 + UYVP Evans & Sutherland YCbCr 4:2:2 extended precision + UCOD eMajix.com ClearVideo + ULTI IBM Ultimotion + UYVY UYVY packed 4:2:2 + V261 Lucent VX2000S + VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/) + VIV1 FFmpeg H263+ decoder + VIV2 Vivo H.263 + VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf) + VTLP Alaris VideoGramPiX + VYU9 ATI YUV (VYU9) + VYUY ATI YUV (VYUY) + V261 Lucent VX2000S + V422 Vitec Multimedia 24-bit YUV 4:2:2 Format + V655 Vitec Multimedia 16-bit YUV 4:2:2 Format + VCR1 ATI Video Codec 1 + VCR2 ATI Video Codec 2 + VCR3 ATI VCR 3.0 + VCR4 ATI VCR 4.0 + VCR5 ATI VCR 5.0 + VCR6 ATI VCR 6.0 + VCR7 ATI VCR 7.0 + VCR8 ATI VCR 8.0 + VCR9 ATI VCR 9.0 + VDCT Vitec Multimedia Video Maker Pro DIB + VDOM VDOnet VDOWave + VDOW VDOnet VDOLive (H.263) + VDTZ Darim Vison VideoTizer YUV + VGPX Alaris VideoGramPiX + VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422 + VIVO Vivo H.263 v2.00 + vivo Vivo H.263 + VIXL Miro/Pinnacle Video XL + VLV1 VideoLogic/PURE Digital Videologic Capture + VP30 On2 VP3.0 + VP31 On2 VP3.1 + VP6F On2 TrueMotion VP6 + VX1K Lucent VX1000S Video Codec + VX2K Lucent VX2000S Video Codec + VXSP Lucent VX1000SP Video Codec + WBVC Winbond W9960 + WHAM Microsoft Video 1 (WHAM) + WINX Winnov Software Compression + WJPG AverMedia Winbond JPEG + WMV1 Windows Media Video V7 + WMV2 Windows Media Video V8 + WMV3 Windows Media Video V9 + WNV1 Winnov Hardware Compression + XYZP Extended PAL format XYZ palette (www.riff.org) + x263 Xirlink H.263 + XLV0 NetXL Video Decoder + XMPG Xing MPEG (I-Frame only) + XVID XviD MPEG-4 (www.xvid.org) + XXAN ?XXAN? + YU92 Intel YUV (YU92) + YUNV Nvidia Uncompressed YUV 4:2:2 + YUVP Extended PAL format YUV palette (www.riff.org) + Y211 YUV 2:1:1 Packed + Y411 YUV 4:1:1 Packed + Y41B Weitek YUV 4:1:1 Planar + Y41P Brooktree PC1 YUV 4:1:1 Packed + Y41T Brooktree PC1 YUV 4:1:1 with transparency + Y42B Weitek YUV 4:2:2 Planar + Y42T Brooktree UYUV 4:2:2 with transparency + Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera + Y800 Simple, single Y plane for monochrome images + Y8 Grayscale video + YC12 Intel YUV 12 codec + YUV8 Winnov Caviar YUV8 + YUV9 Intel YUV9 + YUY2 Uncompressed YUV 4:2:2 + YUYV Canopus YUV + YV12 YVU12 Planar + YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes) + YVYU YVYU 4:2:2 Packed + ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm) + ZPEG Metheus Video Zipper + + */ + + return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc'); + } + + private function EitherEndian2Int($byteword, $signed=false) { + if ($this->getid3->info['fileformat'] == 'riff') { + return getid3_lib::LittleEndian2Int($byteword, $signed); + } + return getid3_lib::BigEndian2Int($byteword, false, $signed); + } + +} diff --git a/sources/wp-includes/ID3/module.audio.ac3.php b/sources/wp-includes/ID3/module.audio.ac3.php new file mode 100644 index 0000000..9834feb --- /dev/null +++ b/sources/wp-includes/ID3/module.audio.ac3.php @@ -0,0 +1,473 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio.ac3.php // +// module for analyzing AC-3 (aka Dolby Digital) audio files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_ac3 extends getid3_handler +{ + private $AC3header = array(); + private $BSIoffset = 0; + + const syncword = "\x0B\x77"; + + public function Analyze() { + $info = &$this->getid3->info; + + ///AH + $info['ac3']['raw']['bsi'] = array(); + $thisfile_ac3 = &$info['ac3']; + $thisfile_ac3_raw = &$thisfile_ac3['raw']; + $thisfile_ac3_raw_bsi = &$thisfile_ac3_raw['bsi']; + + + // http://www.atsc.org/standards/a_52a.pdf + + $info['fileformat'] = 'ac3'; + + // An AC-3 serial coded audio bit stream is made up of a sequence of synchronization frames + // Each synchronization frame contains 6 coded audio blocks (AB), each of which represent 256 + // new audio samples per channel. A synchronization information (SI) header at the beginning + // of each frame contains information needed to acquire and maintain synchronization. A + // bit stream information (BSI) header follows SI, and contains parameters describing the coded + // audio service. The coded audio blocks may be followed by an auxiliary data (Aux) field. At the + // end of each frame is an error check field that includes a CRC word for error detection. An + // additional CRC word is located in the SI header, the use of which, by a decoder, is optional. + // + // syncinfo() | bsi() | AB0 | AB1 | AB2 | AB3 | AB4 | AB5 | Aux | CRC + + // syncinfo() { + // syncword 16 + // crc1 16 + // fscod 2 + // frmsizecod 6 + // } /* end of syncinfo */ + + $this->fseek($info['avdataoffset']); + $this->AC3header['syncinfo'] = $this->fread(5); + + if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) { + $thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword; + $offset = 2; + } else { + if (!$this->isDependencyFor('matroska')) { + unset($info['fileformat'], $info['ac3']); + return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"'); + } + $offset = 0; + $this->fseek(-2, SEEK_CUR); + } + + $info['audio']['dataformat'] = 'ac3'; + $info['audio']['bitrate_mode'] = 'cbr'; + $info['audio']['lossless'] = false; + + $thisfile_ac3_raw['synchinfo']['crc1'] = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2)); + $ac3_synchinfo_fscod_frmsizecod = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1)); + $thisfile_ac3_raw['synchinfo']['fscod'] = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6; + $thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F); + + $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']); + if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) { + $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate']; + } + + $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']); + $thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']); + $info['audio']['bitrate'] = $thisfile_ac3['bitrate']; + + $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15)); + $ac3_bsi_offset = 0; + + $thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); + if ($thisfile_ac3_raw_bsi['bsid'] > 8) { + // Decoders which can decode version 8 will thus be able to decode version numbers less than 8. + // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used. + // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8. + $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8'); + unset($info['ac3']); + return false; + } + + $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3); + $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3); + + $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); + $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']); + foreach($ac3_coding_mode as $key => $value) { + $thisfile_ac3[$key] = $value; + } + switch ($thisfile_ac3_raw_bsi['acmod']) { + case 0: + case 1: + $info['audio']['channelmode'] = 'mono'; + break; + case 3: + case 4: + $info['audio']['channelmode'] = 'stereo'; + break; + default: + $info['audio']['channelmode'] = 'surround'; + break; + } + $info['audio']['channels'] = $thisfile_ac3['num_channels']; + + if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) { + // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream. + $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2); + $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']); + } + + if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { + // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream. + $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2); + $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']); + } + + if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) { + // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround. + $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2); + $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']); + } + + $thisfile_ac3_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1); + $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon']; + if ($thisfile_ac3_raw_bsi['lfeon']) { + //$info['audio']['channels']++; + $info['audio']['channels'] .= '.1'; + } + + $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']); + + // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. + // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent. + $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); + $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB'; + + $thisfile_ac3_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['compre_flag']) { + $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); + $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']); + } + + $thisfile_ac3_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['langcode_flag']) { + $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8); + } + + $thisfile_ac3_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['audprodie']) { + $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); + $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); + + $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB'; + $thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']); + } + + if ($thisfile_ac3_raw_bsi['acmod'] == 0x00) { + // If acmod is 0, then two completely independent program channels (dual mono) + // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case, + // a number of additional items are present in BSI or audblk to fully describe Ch2. + + // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. + // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent. + $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); + $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB'; + + $thisfile_ac3_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['compre_flag2']) { + $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); + $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']); + } + + $thisfile_ac3_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['langcode_flag2']) { + $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8); + } + + $thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['audprodie2']) { + $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); + $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); + + $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB'; + $thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']); + } + + } + + $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); + + $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); + + $thisfile_ac3_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['timecode1_flag']) { + $thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14); + } + + $thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['timecode2_flag']) { + $thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14); + } + + $thisfile_ac3_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1); + if ($thisfile_ac3_raw_bsi['addbsi_flag']) { + $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6); + + $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length'])); + + $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8); + $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8; + } + + return true; + } + + private function readHeaderBSI($length) { + $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length); + $this->BSIoffset += $length; + + return bindec($data); + } + + public static function sampleRateCodeLookup($fscod) { + static $sampleRateCodeLookup = array( + 0 => 48000, + 1 => 44100, + 2 => 32000, + 3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute. + ); + return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false); + } + + public static function serviceTypeLookup($bsmod, $acmod) { + static $serviceTypeLookup = array(); + if (empty($serviceTypeLookup)) { + for ($i = 0; $i <= 7; $i++) { + $serviceTypeLookup[0][$i] = 'main audio service: complete main (CM)'; + $serviceTypeLookup[1][$i] = 'main audio service: music and effects (ME)'; + $serviceTypeLookup[2][$i] = 'associated service: visually impaired (VI)'; + $serviceTypeLookup[3][$i] = 'associated service: hearing impaired (HI)'; + $serviceTypeLookup[4][$i] = 'associated service: dialogue (D)'; + $serviceTypeLookup[5][$i] = 'associated service: commentary (C)'; + $serviceTypeLookup[6][$i] = 'associated service: emergency (E)'; + } + + $serviceTypeLookup[7][1] = 'associated service: voice over (VO)'; + for ($i = 2; $i <= 7; $i++) { + $serviceTypeLookup[7][$i] = 'main audio service: karaoke'; + } + } + return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false); + } + + public static function audioCodingModeLookup($acmod) { + // array(channel configuration, # channels (not incl LFE), channel order) + static $audioCodingModeLookup = array ( + 0 => array('channel_config'=>'1+1', 'num_channels'=>2, 'channel_order'=>'Ch1,Ch2'), + 1 => array('channel_config'=>'1/0', 'num_channels'=>1, 'channel_order'=>'C'), + 2 => array('channel_config'=>'2/0', 'num_channels'=>2, 'channel_order'=>'L,R'), + 3 => array('channel_config'=>'3/0', 'num_channels'=>3, 'channel_order'=>'L,C,R'), + 4 => array('channel_config'=>'2/1', 'num_channels'=>3, 'channel_order'=>'L,R,S'), + 5 => array('channel_config'=>'3/1', 'num_channels'=>4, 'channel_order'=>'L,C,R,S'), + 6 => array('channel_config'=>'2/2', 'num_channels'=>4, 'channel_order'=>'L,R,SL,SR'), + 7 => array('channel_config'=>'3/2', 'num_channels'=>5, 'channel_order'=>'L,C,R,SL,SR'), + ); + return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false); + } + + public static function centerMixLevelLookup($cmixlev) { + static $centerMixLevelLookup; + if (empty($centerMixLevelLookup)) { + $centerMixLevelLookup = array( + 0 => pow(2, -3.0 / 6), // 0.707 (-3.0 dB) + 1 => pow(2, -4.5 / 6), // 0.595 (-4.5 dB) + 2 => pow(2, -6.0 / 6), // 0.500 (-6.0 dB) + 3 => 'reserved' + ); + } + return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false); + } + + public static function surroundMixLevelLookup($surmixlev) { + static $surroundMixLevelLookup; + if (empty($surroundMixLevelLookup)) { + $surroundMixLevelLookup = array( + 0 => pow(2, -3.0 / 6), + 1 => pow(2, -6.0 / 6), + 2 => 0, + 3 => 'reserved' + ); + } + return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false); + } + + public static function dolbySurroundModeLookup($dsurmod) { + static $dolbySurroundModeLookup = array( + 0 => 'not indicated', + 1 => 'Not Dolby Surround encoded', + 2 => 'Dolby Surround encoded', + 3 => 'reserved' + ); + return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false); + } + + public static function channelsEnabledLookup($acmod, $lfeon) { + $lookup = array( + 'ch1'=>(bool) ($acmod == 0), + 'ch2'=>(bool) ($acmod == 0), + 'left'=>(bool) ($acmod > 1), + 'right'=>(bool) ($acmod > 1), + 'center'=>(bool) ($acmod & 0x01), + 'surround_mono'=>false, + 'surround_left'=>false, + 'surround_right'=>false, + 'lfe'=>$lfeon); + switch ($acmod) { + case 4: + case 5: + $lookup['surround_mono'] = true; + break; + case 6: + case 7: + $lookup['surround_left'] = true; + $lookup['surround_right'] = true; + break; + } + return $lookup; + } + + public static function heavyCompression($compre) { + // The first four bits indicate gain changes in 6.02dB increments which can be + // implemented with an arithmetic shift operation. The following four bits + // indicate linear gain changes, and require a 5-bit multiply. + // We will represent the two 4-bit fields of compr as follows: + // X0 X1 X2 X3 . Y4 Y5 Y6 Y7 + // The meaning of the X values is most simply described by considering X to represent a 4-bit + // signed integer with values from -8 to +7. The gain indicated by X is then (X + 1) * 6.02 dB. The + // following table shows this in detail. + + // Meaning of 4 msb of compr + // 7 +48.16 dB + // 6 +42.14 dB + // 5 +36.12 dB + // 4 +30.10 dB + // 3 +24.08 dB + // 2 +18.06 dB + // 1 +12.04 dB + // 0 +6.02 dB + // -1 0 dB + // -2 -6.02 dB + // -3 -12.04 dB + // -4 -18.06 dB + // -5 -24.08 dB + // -6 -30.10 dB + // -7 -36.12 dB + // -8 -42.14 dB + + $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT); + if ($fourbit{0} == '1') { + $log_gain = -8 + bindec(substr($fourbit, 1)); + } else { + $log_gain = bindec(substr($fourbit, 1)); + } + $log_gain = ($log_gain + 1) * getid3_lib::RGADamplitude2dB(2); + + // The value of Y is a linear representation of a gain change of up to -6 dB. Y is considered to + // be an unsigned fractional integer, with a leading value of 1, or: 0.1 Y4 Y5 Y6 Y7 (base 2). Y can + // represent values between 0.111112 (or 31/32) and 0.100002 (or 1/2). Thus, Y can represent gain + // changes from -0.28 dB to -6.02 dB. + + $lin_gain = (16 + ($compre & 0x0F)) / 32; + + // The combination of X and Y values allows compr to indicate gain changes from + // 48.16 - 0.28 = +47.89 dB, to + // -42.14 - 6.02 = -48.16 dB. + + return $log_gain - $lin_gain; + } + + public static function roomTypeLookup($roomtyp) { + static $roomTypeLookup = array( + 0 => 'not indicated', + 1 => 'large room, X curve monitor', + 2 => 'small room, flat monitor', + 3 => 'reserved' + ); + return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false); + } + + public static function frameSizeLookup($frmsizecod, $fscod) { + $padding = (bool) ($frmsizecod % 2); + $framesizeid = floor($frmsizecod / 2); + + static $frameSizeLookup = array(); + if (empty($frameSizeLookup)) { + $frameSizeLookup = array ( + 0 => array(128, 138, 192), + 1 => array(40, 160, 174, 240), + 2 => array(48, 192, 208, 288), + 3 => array(56, 224, 242, 336), + 4 => array(64, 256, 278, 384), + 5 => array(80, 320, 348, 480), + 6 => array(96, 384, 416, 576), + 7 => array(112, 448, 486, 672), + 8 => array(128, 512, 556, 768), + 9 => array(160, 640, 696, 960), + 10 => array(192, 768, 834, 1152), + 11 => array(224, 896, 974, 1344), + 12 => array(256, 1024, 1114, 1536), + 13 => array(320, 1280, 1392, 1920), + 14 => array(384, 1536, 1670, 2304), + 15 => array(448, 1792, 1950, 2688), + 16 => array(512, 2048, 2228, 3072), + 17 => array(576, 2304, 2506, 3456), + 18 => array(640, 2560, 2786, 3840) + ); + } + if (($fscod == 1) && $padding) { + // frame lengths are padded by 1 word (16 bits) at 44100 + $frameSizeLookup[$frmsizecod] += 2; + } + return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false); + } + + public static function bitrateLookup($frmsizecod) { + $framesizeid = floor($frmsizecod / 2); + + static $bitrateLookup = array( + 0 => 32000, + 1 => 40000, + 2 => 48000, + 3 => 56000, + 4 => 64000, + 5 => 80000, + 6 => 96000, + 7 => 112000, + 8 => 128000, + 9 => 160000, + 10 => 192000, + 11 => 224000, + 12 => 256000, + 13 => 320000, + 14 => 384000, + 15 => 448000, + 16 => 512000, + 17 => 576000, + 18 => 640000 + ); + return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false); + } + + +} diff --git a/sources/wp-includes/ID3/module.audio.dts.php b/sources/wp-includes/ID3/module.audio.dts.php new file mode 100644 index 0000000..79982cc --- /dev/null +++ b/sources/wp-includes/ID3/module.audio.dts.php @@ -0,0 +1,290 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio.dts.php // +// module for analyzing DTS Audio files // +// dependencies: NONE // +// // +///////////////////////////////////////////////////////////////// + + +/** +* @tutorial http://wiki.multimedia.cx/index.php?title=DTS +*/ +class getid3_dts extends getid3_handler +{ + /** + * Default DTS syncword used in native .cpt or .dts formats + */ + const syncword = "\x7F\xFE\x80\x01"; + + private $readBinDataOffset = 0; + + /** + * Possible syncwords indicating bitstream encoding + */ + public static $syncwords = array( + 0 => "\x7F\xFE\x80\x01", // raw big-endian + 1 => "\xFE\x7F\x01\x80", // raw little-endian + 2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian + 3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian + + public function Analyze() { + $info = &$this->getid3->info; + $info['fileformat'] = 'dts'; + + $this->fseek($info['avdataoffset']); + $DTSheader = $this->fread(20); // we only need 2 words magic + 6 words frame header, but these words may be normal 16-bit words OR 14-bit words with 2 highest bits set to zero, so 8 words can be either 8*16/8 = 16 bytes OR 8*16*(16/14)/8 = 18.3 bytes + + // check syncword + $sync = substr($DTSheader, 0, 4); + if (($encoding = array_search($sync, self::$syncwords)) !== false) { + + $info['dts']['raw']['magic'] = $sync; + $this->readBinDataOffset = 32; + + } elseif ($this->isDependencyFor('matroska')) { + + // Matroska contains DTS without syncword encoded as raw big-endian format + $encoding = 0; + $this->readBinDataOffset = 0; + + } else { + + unset($info['fileformat']); + return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"'); + + } + + // decode header + $fhBS = ''; + for ($word_offset = 0; $word_offset <= strlen($DTSheader); $word_offset += 2) { + switch ($encoding) { + case 0: // raw big-endian + $fhBS .= getid3_lib::BigEndian2Bin( substr($DTSheader, $word_offset, 2) ); + break; + case 1: // raw little-endian + $fhBS .= getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2))); + break; + case 2: // 14-bit big-endian + $fhBS .= substr(getid3_lib::BigEndian2Bin( substr($DTSheader, $word_offset, 2) ), 2, 14); + break; + case 3: // 14-bit little-endian + $fhBS .= substr(getid3_lib::BigEndian2Bin(strrev(substr($DTSheader, $word_offset, 2))), 2, 14); + break; + } + } + + $info['dts']['raw']['frame_type'] = $this->readBinData($fhBS, 1); + $info['dts']['raw']['deficit_samples'] = $this->readBinData($fhBS, 5); + $info['dts']['flags']['crc_present'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['raw']['pcm_sample_blocks'] = $this->readBinData($fhBS, 7); + $info['dts']['raw']['frame_byte_size'] = $this->readBinData($fhBS, 14); + $info['dts']['raw']['channel_arrangement'] = $this->readBinData($fhBS, 6); + $info['dts']['raw']['sample_frequency'] = $this->readBinData($fhBS, 4); + $info['dts']['raw']['bitrate'] = $this->readBinData($fhBS, 5); + $info['dts']['flags']['embedded_downmix'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['dynamicrange'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['timestamp'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['auxdata'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['hdcd'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['raw']['extension_audio'] = $this->readBinData($fhBS, 3); + $info['dts']['flags']['extended_coding'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['audio_sync_insertion'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['raw']['lfe_effects'] = $this->readBinData($fhBS, 2); + $info['dts']['flags']['predictor_history'] = (bool) $this->readBinData($fhBS, 1); + if ($info['dts']['flags']['crc_present']) { + $info['dts']['raw']['crc16'] = $this->readBinData($fhBS, 16); + } + $info['dts']['flags']['mri_perfect_reconst'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['raw']['encoder_soft_version'] = $this->readBinData($fhBS, 4); + $info['dts']['raw']['copy_history'] = $this->readBinData($fhBS, 2); + $info['dts']['raw']['bits_per_sample'] = $this->readBinData($fhBS, 2); + $info['dts']['flags']['surround_es'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['front_sum_diff'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['flags']['surround_sum_diff'] = (bool) $this->readBinData($fhBS, 1); + $info['dts']['raw']['dialog_normalization'] = $this->readBinData($fhBS, 4); + + + $info['dts']['bitrate'] = self::bitrateLookup($info['dts']['raw']['bitrate']); + $info['dts']['bits_per_sample'] = self::bitPerSampleLookup($info['dts']['raw']['bits_per_sample']); + $info['dts']['sample_rate'] = self::sampleRateLookup($info['dts']['raw']['sample_frequency']); + $info['dts']['dialog_normalization'] = self::dialogNormalization($info['dts']['raw']['dialog_normalization'], $info['dts']['raw']['encoder_soft_version']); + $info['dts']['flags']['lossless'] = (($info['dts']['raw']['bitrate'] == 31) ? true : false); + $info['dts']['bitrate_mode'] = (($info['dts']['raw']['bitrate'] == 30) ? 'vbr' : 'cbr'); + $info['dts']['channels'] = self::numChannelsLookup($info['dts']['raw']['channel_arrangement']); + $info['dts']['channel_arrangement'] = self::channelArrangementLookup($info['dts']['raw']['channel_arrangement']); + + $info['audio']['dataformat'] = 'dts'; + $info['audio']['lossless'] = $info['dts']['flags']['lossless']; + $info['audio']['bitrate_mode'] = $info['dts']['bitrate_mode']; + $info['audio']['bits_per_sample'] = $info['dts']['bits_per_sample']; + $info['audio']['sample_rate'] = $info['dts']['sample_rate']; + $info['audio']['channels'] = $info['dts']['channels']; + $info['audio']['bitrate'] = $info['dts']['bitrate']; + if (isset($info['avdataend']) && !empty($info['dts']['bitrate']) && is_numeric($info['dts']['bitrate'])) { + $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($info['dts']['bitrate'] / 8); + if (($encoding == 2) || ($encoding == 3)) { + // 14-bit data packed into 16-bit words, so the playtime is wrong because only (14/16) of the bytes in the data portion of the file are used at the specified bitrate + $info['playtime_seconds'] *= (14 / 16); + } + } + return true; + } + + private function readBinData($bin, $length) { + $data = substr($bin, $this->readBinDataOffset, $length); + $this->readBinDataOffset += $length; + + return bindec($data); + } + + public static function bitrateLookup($index) { + static $lookup = array( + 0 => 32000, + 1 => 56000, + 2 => 64000, + 3 => 96000, + 4 => 112000, + 5 => 128000, + 6 => 192000, + 7 => 224000, + 8 => 256000, + 9 => 320000, + 10 => 384000, + 11 => 448000, + 12 => 512000, + 13 => 576000, + 14 => 640000, + 15 => 768000, + 16 => 960000, + 17 => 1024000, + 18 => 1152000, + 19 => 1280000, + 20 => 1344000, + 21 => 1408000, + 22 => 1411200, + 23 => 1472000, + 24 => 1536000, + 25 => 1920000, + 26 => 2048000, + 27 => 3072000, + 28 => 3840000, + 29 => 'open', + 30 => 'variable', + 31 => 'lossless', + ); + return (isset($lookup[$index]) ? $lookup[$index] : false); + } + + public static function sampleRateLookup($index) { + static $lookup = array( + 0 => 'invalid', + 1 => 8000, + 2 => 16000, + 3 => 32000, + 4 => 'invalid', + 5 => 'invalid', + 6 => 11025, + 7 => 22050, + 8 => 44100, + 9 => 'invalid', + 10 => 'invalid', + 11 => 12000, + 12 => 24000, + 13 => 48000, + 14 => 'invalid', + 15 => 'invalid', + ); + return (isset($lookup[$index]) ? $lookup[$index] : false); + } + + public static function bitPerSampleLookup($index) { + static $lookup = array( + 0 => 16, + 1 => 20, + 2 => 24, + 3 => 24, + ); + return (isset($lookup[$index]) ? $lookup[$index] : false); + } + + public static function numChannelsLookup($index) { + switch ($index) { + case 0: + return 1; + break; + case 1: + case 2: + case 3: + case 4: + return 2; + break; + case 5: + case 6: + return 3; + break; + case 7: + case 8: + return 4; + break; + case 9: + return 5; + break; + case 10: + case 11: + case 12: + return 6; + break; + case 13: + return 7; + break; + case 14: + case 15: + return 8; + break; + } + return false; + } + + public static function channelArrangementLookup($index) { + static $lookup = array( + 0 => 'A', + 1 => 'A + B (dual mono)', + 2 => 'L + R (stereo)', + 3 => '(L+R) + (L-R) (sum-difference)', + 4 => 'LT + RT (left and right total)', + 5 => 'C + L + R', + 6 => 'L + R + S', + 7 => 'C + L + R + S', + 8 => 'L + R + SL + SR', + 9 => 'C + L + R + SL + SR', + 10 => 'CL + CR + L + R + SL + SR', + 11 => 'C + L + R+ LR + RR + OV', + 12 => 'CF + CR + LF + RF + LR + RR', + 13 => 'CL + C + CR + L + R + SL + SR', + 14 => 'CL + CR + L + R + SL1 + SL2 + SR1 + SR2', + 15 => 'CL + C+ CR + L + R + SL + S + SR', + ); + return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined'); + } + + public static function dialogNormalization($index, $version) { + switch ($version) { + case 7: + return 0 - $index; + break; + case 6: + return 0 - 16 - $index; + break; + } + return false; + } + +} diff --git a/sources/wp-includes/ID3/module.audio.flac.php b/sources/wp-includes/ID3/module.audio.flac.php new file mode 100644 index 0000000..6b9598c --- /dev/null +++ b/sources/wp-includes/ID3/module.audio.flac.php @@ -0,0 +1,442 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio.flac.php // +// module for analyzing FLAC and OggFLAC audio files // +// dependencies: module.audio.ogg.php // +// /// +///////////////////////////////////////////////////////////////// + + +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true); + +/** +* @tutorial http://flac.sourceforge.net/format.html +*/ +class getid3_flac extends getid3_handler +{ + const syncword = 'fLaC'; + + public function Analyze() { + $info = &$this->getid3->info; + + $this->fseek($info['avdataoffset']); + $StreamMarker = $this->fread(4); + if ($StreamMarker != self::syncword) { + return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($StreamMarker).'"'); + } + $info['fileformat'] = 'flac'; + $info['audio']['dataformat'] = 'flac'; + $info['audio']['bitrate_mode'] = 'vbr'; + $info['audio']['lossless'] = true; + + // parse flac container + return $this->parseMETAdata(); + } + + public function parseMETAdata() { + $info = &$this->getid3->info; + do { + $BlockOffset = $this->ftell(); + $BlockHeader = $this->fread(4); + $LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1)); + $LastBlockFlag = (bool) ($LBFBT & 0x80); + $BlockType = ($LBFBT & 0x7F); + $BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3)); + $BlockTypeText = self::metaBlockTypeLookup($BlockType); + + if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) { + $this->error('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file'); + break; + } + if ($BlockLength < 1) { + $this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid'); + break; + } + + $info['flac'][$BlockTypeText]['raw'] = array(); + $BlockTypeText_raw = &$info['flac'][$BlockTypeText]['raw']; + + $BlockTypeText_raw['offset'] = $BlockOffset; + $BlockTypeText_raw['last_meta_block'] = $LastBlockFlag; + $BlockTypeText_raw['block_type'] = $BlockType; + $BlockTypeText_raw['block_type_text'] = $BlockTypeText; + $BlockTypeText_raw['block_length'] = $BlockLength; + if ($BlockTypeText_raw['block_type'] != 0x06) { // do not read attachment data automatically + $BlockTypeText_raw['block_data'] = $this->fread($BlockLength); + } + + switch ($BlockTypeText) { + case 'STREAMINFO': // 0x00 + if (!$this->parseSTREAMINFO($BlockTypeText_raw['block_data'])) { + return false; + } + break; + + case 'PADDING': // 0x01 + unset($info['flac']['PADDING']); // ignore + break; + + case 'APPLICATION': // 0x02 + if (!$this->parseAPPLICATION($BlockTypeText_raw['block_data'])) { + return false; + } + break; + + case 'SEEKTABLE': // 0x03 + if (!$this->parseSEEKTABLE($BlockTypeText_raw['block_data'])) { + return false; + } + break; + + case 'VORBIS_COMMENT': // 0x04 + if (!$this->parseVORBIS_COMMENT($BlockTypeText_raw['block_data'])) { + return false; + } + break; + + case 'CUESHEET': // 0x05 + if (!$this->parseCUESHEET($BlockTypeText_raw['block_data'])) { + return false; + } + break; + + case 'PICTURE': // 0x06 + if (!$this->parsePICTURE()) { + return false; + } + break; + + default: + $this->warning('Unhandled METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockType.') at offset '.$BlockOffset); + } + + unset($info['flac'][$BlockTypeText]['raw']); + $info['avdataoffset'] = $this->ftell(); + } + while ($LastBlockFlag === false); + + // handle tags + if (!empty($info['flac']['VORBIS_COMMENT']['comments'])) { + $info['flac']['comments'] = $info['flac']['VORBIS_COMMENT']['comments']; + } + if (!empty($info['flac']['VORBIS_COMMENT']['vendor'])) { + $info['audio']['encoder'] = str_replace('reference ', '', $info['flac']['VORBIS_COMMENT']['vendor']); + } + + // copy attachments to 'comments' array if nesesary + if (isset($info['flac']['PICTURE']) && ($this->getid3->option_save_attachments !== getID3::ATTACHMENTS_NONE)) { + foreach ($info['flac']['PICTURE'] as $entry) { + if (!empty($entry['data'])) { + $info['flac']['comments']['picture'][] = array('image_mime'=>$entry['image_mime'], 'data'=>$entry['data']); + } + } + } + + if (isset($info['flac']['STREAMINFO'])) { + if (!$this->isDependencyFor('matroska')) { + $info['flac']['compressed_audio_bytes'] = $info['avdataend'] - $info['avdataoffset']; + } + $info['flac']['uncompressed_audio_bytes'] = $info['flac']['STREAMINFO']['samples_stream'] * $info['flac']['STREAMINFO']['channels'] * ($info['flac']['STREAMINFO']['bits_per_sample'] / 8); + if ($info['flac']['uncompressed_audio_bytes'] == 0) { + return $this->error('Corrupt FLAC file: uncompressed_audio_bytes == zero'); + } + if (!empty($info['flac']['compressed_audio_bytes'])) { + $info['flac']['compression_ratio'] = $info['flac']['compressed_audio_bytes'] / $info['flac']['uncompressed_audio_bytes']; + } + } + + // set md5_data_source - built into flac 0.5+ + if (isset($info['flac']['STREAMINFO']['audio_signature'])) { + + if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) { + $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)'); + } + else { + $info['md5_data_source'] = ''; + $md5 = $info['flac']['STREAMINFO']['audio_signature']; + for ($i = 0; $i < strlen($md5); $i++) { + $info['md5_data_source'] .= str_pad(dechex(ord($md5[$i])), 2, '00', STR_PAD_LEFT); + } + if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) { + unset($info['md5_data_source']); + } + } + } + + if (isset($info['flac']['STREAMINFO']['bits_per_sample'])) { + $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample']; + if ($info['audio']['bits_per_sample'] == 8) { + // special case + // must invert sign bit on all data bytes before MD5'ing to match FLAC's calculated value + // MD5sum calculates on unsigned bytes, but FLAC calculated MD5 on 8-bit audio data as signed + $this->warning('FLAC calculates MD5 data strangely on 8-bit audio, so the stored md5_data_source value will not match the decoded WAV file'); + } + } + + return true; + } + + private function parseSTREAMINFO($BlockData) { + $info = &$this->getid3->info; + + $info['flac']['STREAMINFO'] = array(); + $streaminfo = &$info['flac']['STREAMINFO']; + + $streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2)); + $streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2)); + $streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3)); + $streaminfo['max_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 7, 3)); + + $SRCSBSS = getid3_lib::BigEndian2Bin(substr($BlockData, 10, 8)); + $streaminfo['sample_rate'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 0, 20)); + $streaminfo['channels'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 20, 3)) + 1; + $streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1; + $streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36)); + + $streaminfo['audio_signature'] = substr($BlockData, 18, 16); + + if (!empty($streaminfo['sample_rate'])) { + + $info['audio']['bitrate_mode'] = 'vbr'; + $info['audio']['sample_rate'] = $streaminfo['sample_rate']; + $info['audio']['channels'] = $streaminfo['channels']; + $info['audio']['bits_per_sample'] = $streaminfo['bits_per_sample']; + $info['playtime_seconds'] = $streaminfo['samples_stream'] / $streaminfo['sample_rate']; + if ($info['playtime_seconds'] > 0) { + if (!$this->isDependencyFor('matroska')) { + $info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; + } + else { + $this->warning('Cannot determine audio bitrate because total stream size is unknown'); + } + } + + } else { + return $this->error('Corrupt METAdata block: STREAMINFO'); + } + + return true; + } + + private function parseAPPLICATION($BlockData) { + $info = &$this->getid3->info; + + $ApplicationID = getid3_lib::BigEndian2Int(substr($BlockData, 0, 4)); + $info['flac']['APPLICATION'][$ApplicationID]['name'] = self::applicationIDLookup($ApplicationID); + $info['flac']['APPLICATION'][$ApplicationID]['data'] = substr($BlockData, 4); + + return true; + } + + private function parseSEEKTABLE($BlockData) { + $info = &$this->getid3->info; + + $offset = 0; + $BlockLength = strlen($BlockData); + $placeholderpattern = str_repeat("\xFF", 8); + while ($offset < $BlockLength) { + $SampleNumberString = substr($BlockData, $offset, 8); + $offset += 8; + if ($SampleNumberString == $placeholderpattern) { + + // placeholder point + getid3_lib::safe_inc($info['flac']['SEEKTABLE']['placeholders'], 1); + $offset += 10; + + } else { + + $SampleNumber = getid3_lib::BigEndian2Int($SampleNumberString); + $info['flac']['SEEKTABLE'][$SampleNumber]['offset'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8)); + $offset += 8; + $info['flac']['SEEKTABLE'][$SampleNumber]['samples'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 2)); + $offset += 2; + + } + } + + return true; + } + + private function parseVORBIS_COMMENT($BlockData) { + $info = &$this->getid3->info; + + $getid3_ogg = new getid3_ogg($this->getid3); + if ($this->isDependencyFor('matroska')) { + $getid3_ogg->setStringMode($this->data_string); + } + $getid3_ogg->ParseVorbisComments(); + if (isset($info['ogg'])) { + unset($info['ogg']['comments_raw']); + $info['flac']['VORBIS_COMMENT'] = $info['ogg']; + unset($info['ogg']); + } + + unset($getid3_ogg); + + return true; + } + + private function parseCUESHEET($BlockData) { + $info = &$this->getid3->info; + $offset = 0; + $info['flac']['CUESHEET']['media_catalog_number'] = trim(substr($BlockData, $offset, 128), "\0"); + $offset += 128; + $info['flac']['CUESHEET']['lead_in_samples'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8)); + $offset += 8; + $info['flac']['CUESHEET']['flags']['is_cd'] = (bool) (getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)) & 0x80); + $offset += 1; + + $offset += 258; // reserved + + $info['flac']['CUESHEET']['number_tracks'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)); + $offset += 1; + + for ($track = 0; $track < $info['flac']['CUESHEET']['number_tracks']; $track++) { + $TrackSampleOffset = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8)); + $offset += 8; + $TrackNumber = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)); + $offset += 1; + + $info['flac']['CUESHEET']['tracks'][$TrackNumber]['sample_offset'] = $TrackSampleOffset; + + $info['flac']['CUESHEET']['tracks'][$TrackNumber]['isrc'] = substr($BlockData, $offset, 12); + $offset += 12; + + $TrackFlagsRaw = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)); + $offset += 1; + $info['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['is_audio'] = (bool) ($TrackFlagsRaw & 0x80); + $info['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['pre_emphasis'] = (bool) ($TrackFlagsRaw & 0x40); + + $offset += 13; // reserved + + $info['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)); + $offset += 1; + + for ($index = 0; $index < $info['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points']; $index++) { + $IndexSampleOffset = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8)); + $offset += 8; + $IndexNumber = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)); + $offset += 1; + + $offset += 3; // reserved + + $info['flac']['CUESHEET']['tracks'][$TrackNumber]['indexes'][$IndexNumber] = $IndexSampleOffset; + } + } + + return true; + } + + /** + * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment + * External usage: audio.ogg + */ + public function parsePICTURE() { + $info = &$this->getid3->info; + + $picture['typeid'] = getid3_lib::BigEndian2Int($this->fread(4)); + $picture['type'] = self::pictureTypeLookup($picture['typeid']); + $picture['image_mime'] = $this->fread(getid3_lib::BigEndian2Int($this->fread(4))); + $descr_length = getid3_lib::BigEndian2Int($this->fread(4)); + if ($descr_length) { + $picture['description'] = $this->fread($descr_length); + } + $picture['width'] = getid3_lib::BigEndian2Int($this->fread(4)); + $picture['height'] = getid3_lib::BigEndian2Int($this->fread(4)); + $picture['color_depth'] = getid3_lib::BigEndian2Int($this->fread(4)); + $picture['colors_indexed'] = getid3_lib::BigEndian2Int($this->fread(4)); + $data_length = getid3_lib::BigEndian2Int($this->fread(4)); + + if ($picture['image_mime'] == '-->') { + $picture['data'] = $this->fread($data_length); + } else { + $picture['data'] = $this->saveAttachment( + str_replace('/', '_', $picture['type']).'_'.$this->ftell(), + $this->ftell(), + $data_length, + $picture['image_mime']); + } + + $info['flac']['PICTURE'][] = $picture; + + return true; + } + + public static function metaBlockTypeLookup($blocktype) { + static $lookup = array( + 0 => 'STREAMINFO', + 1 => 'PADDING', + 2 => 'APPLICATION', + 3 => 'SEEKTABLE', + 4 => 'VORBIS_COMMENT', + 5 => 'CUESHEET', + 6 => 'PICTURE', + ); + return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved'); + } + + public static function applicationIDLookup($applicationid) { + // http://flac.sourceforge.net/id.html + static $lookup = array( + 0x41544348 => 'FlacFile', // "ATCH" + 0x42534F4C => 'beSolo', // "BSOL" + 0x42554753 => 'Bugs Player', // "BUGS" + 0x43756573 => 'GoldWave cue points (specification)', // "Cues" + 0x46696361 => 'CUE Splitter', // "Fica" + 0x46746F6C => 'flac-tools', // "Ftol" + 0x4D4F5442 => 'MOTB MetaCzar', // "MOTB" + 0x4D505345 => 'MP3 Stream Editor', // "MPSE" + 0x4D754D4C => 'MusicML: Music Metadata Language', // "MuML" + 0x52494646 => 'Sound Devices RIFF chunk storage', // "RIFF" + 0x5346464C => 'Sound Font FLAC', // "SFFL" + 0x534F4E59 => 'Sony Creative Software', // "SONY" + 0x5351455A => 'flacsqueeze', // "SQEZ" + 0x54745776 => 'TwistedWave', // "TtWv" + 0x55495453 => 'UITS Embedding tools', // "UITS" + 0x61696666 => 'FLAC AIFF chunk storage', // "aiff" + 0x696D6167 => 'flac-image application for storing arbitrary files in APPLICATION metadata blocks', // "imag" + 0x7065656D => 'Parseable Embedded Extensible Metadata (specification)', // "peem" + 0x71667374 => 'QFLAC Studio', // "qfst" + 0x72696666 => 'FLAC RIFF chunk storage', // "riff" + 0x74756E65 => 'TagTuner', // "tune" + 0x78626174 => 'XBAT', // "xbat" + 0x786D6364 => 'xmcd', // "xmcd" + ); + return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved'); + } + + public static function pictureTypeLookup($type_id) { + static $lookup = array ( + 0 => 'Other', + 1 => '32x32 pixels \'file icon\' (PNG only)', + 2 => 'Other file icon', + 3 => 'Cover (front)', + 4 => 'Cover (back)', + 5 => 'Leaflet page', + 6 => 'Media (e.g. label side of CD)', + 7 => 'Lead artist/lead performer/soloist', + 8 => 'Artist/performer', + 9 => 'Conductor', + 10 => 'Band/Orchestra', + 11 => 'Composer', + 12 => 'Lyricist/text writer', + 13 => 'Recording Location', + 14 => 'During recording', + 15 => 'During performance', + 16 => 'Movie/video screen capture', + 17 => 'A bright coloured fish', + 18 => 'Illustration', + 19 => 'Band/artist logotype', + 20 => 'Publisher/Studio logotype', + ); + return (isset($lookup[$type_id]) ? $lookup[$type_id] : 'reserved'); + } + +} diff --git a/sources/wp-includes/ID3/module.audio.mp3.php b/sources/wp-includes/ID3/module.audio.mp3.php new file mode 100644 index 0000000..e6ffea9 --- /dev/null +++ b/sources/wp-includes/ID3/module.audio.mp3.php @@ -0,0 +1,2009 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio.mp3.php // +// module for analyzing MP3 files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +// number of frames to scan to determine if MPEG-audio sequence is valid +// Lower this number to 5-20 for faster scanning +// Increase this number to 50+ for most accurate detection of valid VBR/CBR +// mpeg-audio streams +define('GETID3_MP3_VALID_CHECK_FRAMES', 35); + + +class getid3_mp3 extends getid3_handler +{ + + public $allow_bruteforce = false; // forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files + + public function Analyze() { + $info = &$this->getid3->info; + + $initialOffset = $info['avdataoffset']; + + if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) { + if ($this->allow_bruteforce) { + $info['error'][] = 'Rescanning file in BruteForce mode'; + $this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info); + } + } + + + if (isset($info['mpeg']['audio']['bitrate_mode'])) { + $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); + } + + if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0) && ($info['avdataoffset'] != $initialOffset)))) { + + $synchoffsetwarning = 'Unknown data before synch '; + if (isset($info['id3v2']['headerlength'])) { + $synchoffsetwarning .= '(ID3v2 header ends at '.$info['id3v2']['headerlength'].', then '.($info['avdataoffset'] - $info['id3v2']['headerlength']).' bytes garbage, '; + } elseif ($initialOffset > 0) { + $synchoffsetwarning .= '(should be at '.$initialOffset.', '; + } else { + $synchoffsetwarning .= '(should be at beginning of file, '; + } + $synchoffsetwarning .= 'synch detected at '.$info['avdataoffset'].')'; + if (isset($info['audio']['bitrate_mode']) && ($info['audio']['bitrate_mode'] == 'cbr')) { + + if (!empty($info['id3v2']['headerlength']) && (($info['avdataoffset'] - $info['id3v2']['headerlength']) == $info['mpeg']['audio']['framelength'])) { + + $synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90-3.92) DLL in CBR mode.'; + $info['audio']['codec'] = 'LAME'; + $CurrentDataLAMEversionString = 'LAME3.'; + + } elseif (empty($info['id3v2']['headerlength']) && ($info['avdataoffset'] == $info['mpeg']['audio']['framelength'])) { + + $synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90 - 3.92) DLL in CBR mode.'; + $info['audio']['codec'] = 'LAME'; + $CurrentDataLAMEversionString = 'LAME3.'; + + } + + } + $info['warning'][] = $synchoffsetwarning; + + } + + if (isset($info['mpeg']['audio']['LAME'])) { + $info['audio']['codec'] = 'LAME'; + if (!empty($info['mpeg']['audio']['LAME']['long_version'])) { + $info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['long_version'], "\x00"); + } elseif (!empty($info['mpeg']['audio']['LAME']['short_version'])) { + $info['audio']['encoder'] = rtrim($info['mpeg']['audio']['LAME']['short_version'], "\x00"); + } + } + + $CurrentDataLAMEversionString = (!empty($CurrentDataLAMEversionString) ? $CurrentDataLAMEversionString : (isset($info['audio']['encoder']) ? $info['audio']['encoder'] : '')); + if (!empty($CurrentDataLAMEversionString) && (substr($CurrentDataLAMEversionString, 0, 6) == 'LAME3.') && !preg_match('[0-9\)]', substr($CurrentDataLAMEversionString, -1))) { + // a version number of LAME that does not end with a number like "LAME3.92" + // or with a closing parenthesis like "LAME3.88 (alpha)" + // or a version of LAME with the LAMEtag-not-filled-in-DLL-mode bug (3.90-3.92) + + // not sure what the actual last frame length will be, but will be less than or equal to 1441 + $PossiblyLongerLAMEversion_FrameLength = 1441; + + // Not sure what version of LAME this is - look in padding of last frame for longer version string + $PossibleLAMEversionStringOffset = $info['avdataend'] - $PossiblyLongerLAMEversion_FrameLength; + fseek($this->getid3->fp, $PossibleLAMEversionStringOffset); + $PossiblyLongerLAMEversion_Data = fread($this->getid3->fp, $PossiblyLongerLAMEversion_FrameLength); + switch (substr($CurrentDataLAMEversionString, -1)) { + case 'a': + case 'b': + // "LAME3.94a" will have a longer version string of "LAME3.94 (alpha)" for example + // need to trim off "a" to match longer string + $CurrentDataLAMEversionString = substr($CurrentDataLAMEversionString, 0, -1); + break; + } + if (($PossiblyLongerLAMEversion_String = strstr($PossiblyLongerLAMEversion_Data, $CurrentDataLAMEversionString)) !== false) { + if (substr($PossiblyLongerLAMEversion_String, 0, strlen($CurrentDataLAMEversionString)) == $CurrentDataLAMEversionString) { + $PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3" "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)" + if (empty($info['audio']['encoder']) || (strlen($PossiblyLongerLAMEversion_NewString) > strlen($info['audio']['encoder']))) { + $info['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString; + } + } + } + } + if (!empty($info['audio']['encoder'])) { + $info['audio']['encoder'] = rtrim($info['audio']['encoder'], "\x00 "); + } + + switch (isset($info['mpeg']['audio']['layer']) ? $info['mpeg']['audio']['layer'] : '') { + case 1: + case 2: + $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer']; + break; + } + if (isset($info['fileformat']) && ($info['fileformat'] == 'mp3')) { + switch ($info['audio']['dataformat']) { + case 'mp1': + case 'mp2': + case 'mp3': + $info['fileformat'] = $info['audio']['dataformat']; + break; + + default: + $info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"'; + break; + } + } + + if (empty($info['fileformat'])) { + unset($info['fileformat']); + unset($info['audio']['bitrate_mode']); + unset($info['avdataoffset']); + unset($info['avdataend']); + return false; + } + + $info['mime_type'] = 'audio/mpeg'; + $info['audio']['lossless'] = false; + + // Calculate playtime + if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) { + $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate']; + } + + $info['audio']['encoder_options'] = $this->GuessEncoderOptions(); + + return true; + } + + + public function GuessEncoderOptions() { + // shortcuts + $info = &$this->getid3->info; + if (!empty($info['mpeg']['audio'])) { + $thisfile_mpeg_audio = &$info['mpeg']['audio']; + if (!empty($thisfile_mpeg_audio['LAME'])) { + $thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME']; + } + } + + $encoder_options = ''; + static $NamedPresetBitrates = array(16, 24, 40, 56, 112, 128, 160, 192, 256); + + if (isset($thisfile_mpeg_audio['VBR_method']) && ($thisfile_mpeg_audio['VBR_method'] == 'Fraunhofer') && !empty($thisfile_mpeg_audio['VBR_quality'])) { + + $encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality']; + + } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) { + + $encoder_options = $thisfile_mpeg_audio_lame['preset_used']; + + } elseif (!empty($thisfile_mpeg_audio_lame['vbr_quality'])) { + + static $KnownEncoderValues = array(); + if (empty($KnownEncoderValues)) { + + //$KnownEncoderValues[abrbitrate_minbitrate][vbr_quality][raw_vbr_method][raw_noise_shaping][raw_stereo_mode][ath_type][lowpass_frequency] = 'preset name'; + $KnownEncoderValues[0xFF][58][1][1][3][2][20500] = '--alt-preset insane'; // 3.90, 3.90.1, 3.92 + $KnownEncoderValues[0xFF][58][1][1][3][2][20600] = '--alt-preset insane'; // 3.90.2, 3.90.3, 3.91 + $KnownEncoderValues[0xFF][57][1][1][3][4][20500] = '--alt-preset insane'; // 3.94, 3.95 + $KnownEncoderValues['**'][78][3][2][3][2][19500] = '--alt-preset extreme'; // 3.90, 3.90.1, 3.92 + $KnownEncoderValues['**'][78][3][2][3][2][19600] = '--alt-preset extreme'; // 3.90.2, 3.91 + $KnownEncoderValues['**'][78][3][1][3][2][19600] = '--alt-preset extreme'; // 3.90.3 + $KnownEncoderValues['**'][78][4][2][3][2][19500] = '--alt-preset fast extreme'; // 3.90, 3.90.1, 3.92 + $KnownEncoderValues['**'][78][4][2][3][2][19600] = '--alt-preset fast extreme'; // 3.90.2, 3.90.3, 3.91 + $KnownEncoderValues['**'][78][3][2][3][4][19000] = '--alt-preset standard'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues['**'][78][3][1][3][4][19000] = '--alt-preset standard'; // 3.90.3 + $KnownEncoderValues['**'][78][4][2][3][4][19000] = '--alt-preset fast standard'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues['**'][78][4][1][3][4][19000] = '--alt-preset fast standard'; // 3.90.3 + $KnownEncoderValues['**'][88][4][1][3][3][19500] = '--r3mix'; // 3.90, 3.90.1, 3.92 + $KnownEncoderValues['**'][88][4][1][3][3][19600] = '--r3mix'; // 3.90.2, 3.90.3, 3.91 + $KnownEncoderValues['**'][67][4][1][3][4][18000] = '--r3mix'; // 3.94, 3.95 + $KnownEncoderValues['**'][68][3][2][3][4][18000] = '--alt-preset medium'; // 3.90.3 + $KnownEncoderValues['**'][68][4][2][3][4][18000] = '--alt-preset fast medium'; // 3.90.3 + + $KnownEncoderValues[0xFF][99][1][1][1][2][0] = '--preset studio'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues[0xFF][58][2][1][3][2][20600] = '--preset studio'; // 3.90.3, 3.93.1 + $KnownEncoderValues[0xFF][58][2][1][3][2][20500] = '--preset studio'; // 3.93 + $KnownEncoderValues[0xFF][57][2][1][3][4][20500] = '--preset studio'; // 3.94, 3.95 + $KnownEncoderValues[0xC0][88][1][1][1][2][0] = '--preset cd'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues[0xC0][58][2][2][3][2][19600] = '--preset cd'; // 3.90.3, 3.93.1 + $KnownEncoderValues[0xC0][58][2][2][3][2][19500] = '--preset cd'; // 3.93 + $KnownEncoderValues[0xC0][57][2][1][3][4][19500] = '--preset cd'; // 3.94, 3.95 + $KnownEncoderValues[0xA0][78][1][1][3][2][18000] = '--preset hifi'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues[0xA0][58][2][2][3][2][18000] = '--preset hifi'; // 3.90.3, 3.93, 3.93.1 + $KnownEncoderValues[0xA0][57][2][1][3][4][18000] = '--preset hifi'; // 3.94, 3.95 + $KnownEncoderValues[0x80][67][1][1][3][2][18000] = '--preset tape'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues[0x80][67][1][1][3][2][15000] = '--preset radio'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues[0x70][67][1][1][3][2][15000] = '--preset fm'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92 + $KnownEncoderValues[0x70][58][2][2][3][2][16000] = '--preset tape/radio/fm'; // 3.90.3, 3.93, 3.93.1 + $KnownEncoderValues[0x70][57][2][1][3][4][16000] = '--preset tape/radio/fm'; // 3.94, 3.95 + $KnownEncoderValues[0x38][58][2][2][0][2][10000] = '--preset voice'; // 3.90.3, 3.93, 3.93.1 + $KnownEncoderValues[0x38][57][2][1][0][4][15000] = '--preset voice'; // 3.94, 3.95 + $KnownEncoderValues[0x38][57][2][1][0][4][16000] = '--preset voice'; // 3.94a14 + $KnownEncoderValues[0x28][65][1][1][0][2][7500] = '--preset mw-us'; // 3.90, 3.90.1, 3.92 + $KnownEncoderValues[0x28][65][1][1][0][2][7600] = '--preset mw-us'; // 3.90.2, 3.91 + $KnownEncoderValues[0x28][58][2][2][0][2][7000] = '--preset mw-us'; // 3.90.3, 3.93, 3.93.1 + $KnownEncoderValues[0x28][57][2][1][0][4][10500] = '--preset mw-us'; // 3.94, 3.95 + $KnownEncoderValues[0x28][57][2][1][0][4][11200] = '--preset mw-us'; // 3.94a14 + $KnownEncoderValues[0x28][57][2][1][0][4][8800] = '--preset mw-us'; // 3.94a15 + $KnownEncoderValues[0x18][58][2][2][0][2][4000] = '--preset phon+/lw/mw-eu/sw'; // 3.90.3, 3.93.1 + $KnownEncoderValues[0x18][58][2][2][0][2][3900] = '--preset phon+/lw/mw-eu/sw'; // 3.93 + $KnownEncoderValues[0x18][57][2][1][0][4][5900] = '--preset phon+/lw/mw-eu/sw'; // 3.94, 3.95 + $KnownEncoderValues[0x18][57][2][1][0][4][6200] = '--preset phon+/lw/mw-eu/sw'; // 3.94a14 + $KnownEncoderValues[0x18][57][2][1][0][4][3200] = '--preset phon+/lw/mw-eu/sw'; // 3.94a15 + $KnownEncoderValues[0x10][58][2][2][0][2][3800] = '--preset phone'; // 3.90.3, 3.93.1 + $KnownEncoderValues[0x10][58][2][2][0][2][3700] = '--preset phone'; // 3.93 + $KnownEncoderValues[0x10][57][2][1][0][4][5600] = '--preset phone'; // 3.94, 3.95 + } + + if (isset($KnownEncoderValues[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) { + + $encoder_options = $KnownEncoderValues[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']]; + + } elseif (isset($KnownEncoderValues['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) { + + $encoder_options = $KnownEncoderValues['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']]; + + } elseif ($info['audio']['bitrate_mode'] == 'vbr') { + + // http://gabriel.mp3-tech.org/mp3infotag.html + // int Quality = (100 - 10 * gfp->VBR_q - gfp->quality)h + + + $LAME_V_value = 10 - ceil($thisfile_mpeg_audio_lame['vbr_quality'] / 10); + $LAME_q_value = 100 - $thisfile_mpeg_audio_lame['vbr_quality'] - ($LAME_V_value * 10); + $encoder_options = '-V'.$LAME_V_value.' -q'.$LAME_q_value; + + } elseif ($info['audio']['bitrate_mode'] == 'cbr') { + + $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000); + + } else { + + $encoder_options = strtoupper($info['audio']['bitrate_mode']); + + } + + } elseif (!empty($thisfile_mpeg_audio_lame['bitrate_abr'])) { + + $encoder_options = 'ABR'.$thisfile_mpeg_audio_lame['bitrate_abr']; + + } elseif (!empty($info['audio']['bitrate'])) { + + if ($info['audio']['bitrate_mode'] == 'cbr') { + $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000); + } else { + $encoder_options = strtoupper($info['audio']['bitrate_mode']); + } + + } + if (!empty($thisfile_mpeg_audio_lame['bitrate_min'])) { + $encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min']; + } + + if (!empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']) || !empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'])) { + $encoder_options .= ' --nogap'; + } + + if (!empty($thisfile_mpeg_audio_lame['lowpass_frequency'])) { + $ExplodedOptions = explode(' ', $encoder_options, 4); + if ($ExplodedOptions[0] == '--r3mix') { + $ExplodedOptions[1] = 'r3mix'; + } + switch ($ExplodedOptions[0]) { + case '--preset': + case '--alt-preset': + case '--r3mix': + if ($ExplodedOptions[1] == 'fast') { + $ExplodedOptions[1] .= ' '.$ExplodedOptions[2]; + } + switch ($ExplodedOptions[1]) { + case 'portable': + case 'medium': + case 'standard': + case 'extreme': + case 'insane': + case 'fast portable': + case 'fast medium': + case 'fast standard': + case 'fast extreme': + case 'fast insane': + case 'r3mix': + static $ExpectedLowpass = array( + 'insane|20500' => 20500, + 'insane|20600' => 20600, // 3.90.2, 3.90.3, 3.91 + 'medium|18000' => 18000, + 'fast medium|18000' => 18000, + 'extreme|19500' => 19500, // 3.90, 3.90.1, 3.92, 3.95 + 'extreme|19600' => 19600, // 3.90.2, 3.90.3, 3.91, 3.93.1 + 'fast extreme|19500' => 19500, // 3.90, 3.90.1, 3.92, 3.95 + 'fast extreme|19600' => 19600, // 3.90.2, 3.90.3, 3.91, 3.93.1 + 'standard|19000' => 19000, + 'fast standard|19000' => 19000, + 'r3mix|19500' => 19500, // 3.90, 3.90.1, 3.92 + 'r3mix|19600' => 19600, // 3.90.2, 3.90.3, 3.91 + 'r3mix|18000' => 18000, // 3.94, 3.95 + ); + if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']]) && ($thisfile_mpeg_audio_lame['lowpass_frequency'] < 22050) && (round($thisfile_mpeg_audio_lame['lowpass_frequency'] / 1000) < round($thisfile_mpeg_audio['sample_rate'] / 2000))) { + $encoder_options .= ' --lowpass '.$thisfile_mpeg_audio_lame['lowpass_frequency']; + } + break; + + default: + break; + } + break; + } + } + + if (isset($thisfile_mpeg_audio_lame['raw']['source_sample_freq'])) { + if (($thisfile_mpeg_audio['sample_rate'] == 44100) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 1)) { + $encoder_options .= ' --resample 44100'; + } elseif (($thisfile_mpeg_audio['sample_rate'] == 48000) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 2)) { + $encoder_options .= ' --resample 48000'; + } elseif ($thisfile_mpeg_audio['sample_rate'] < 44100) { + switch ($thisfile_mpeg_audio_lame['raw']['source_sample_freq']) { + case 0: // <= 32000 + // may or may not be same as source frequency - ignore + break; + case 1: // 44100 + case 2: // 48000 + case 3: // 48000+ + $ExplodedOptions = explode(' ', $encoder_options, 4); + switch ($ExplodedOptions[0]) { + case '--preset': + case '--alt-preset': + switch ($ExplodedOptions[1]) { + case 'fast': + case 'portable': + case 'medium': + case 'standard': + case 'extreme': + case 'insane': + $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate']; + break; + + default: + static $ExpectedResampledRate = array( + 'phon+/lw/mw-eu/sw|16000' => 16000, + 'mw-us|24000' => 24000, // 3.95 + 'mw-us|32000' => 32000, // 3.93 + 'mw-us|16000' => 16000, // 3.92 + 'phone|16000' => 16000, + 'phone|11025' => 11025, // 3.94a15 + 'radio|32000' => 32000, // 3.94a15 + 'fm/radio|32000' => 32000, // 3.92 + 'fm|32000' => 32000, // 3.90 + 'voice|32000' => 32000); + if (!isset($ExpectedResampledRate[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio['sample_rate']])) { + $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate']; + } + break; + } + break; + + case '--r3mix': + default: + $encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate']; + break; + } + break; + } + } + } + if (empty($encoder_options) && !empty($info['audio']['bitrate']) && !empty($info['audio']['bitrate_mode'])) { + //$encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000); + $encoder_options = strtoupper($info['audio']['bitrate_mode']); + } + + return $encoder_options; + } + + + public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) { + static $MPEGaudioVersionLookup; + static $MPEGaudioLayerLookup; + static $MPEGaudioBitrateLookup; + static $MPEGaudioFrequencyLookup; + static $MPEGaudioChannelModeLookup; + static $MPEGaudioModeExtensionLookup; + static $MPEGaudioEmphasisLookup; + if (empty($MPEGaudioVersionLookup)) { + $MPEGaudioVersionLookup = self::MPEGaudioVersionArray(); + $MPEGaudioLayerLookup = self::MPEGaudioLayerArray(); + $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray(); + $MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray(); + $MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray(); + $MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray(); + $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray(); + } + + if (fseek($this->getid3->fp, $offset, SEEK_SET) != 0) { + $info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset; + return false; + } + //$headerstring = fread($this->getid3->fp, 1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame + $headerstring = fread($this->getid3->fp, 226); // LAME header at offset 36 + 190 bytes of Xing/LAME data + + // MP3 audio frame structure: + // $aa $aa $aa $aa [$bb $bb] $cc... + // where $aa..$aa is the four-byte mpeg-audio header (below) + // $bb $bb is the optional 2-byte CRC + // and $cc... is the audio data + + $head4 = substr($headerstring, 0, 4); + + static $MPEGaudioHeaderDecodeCache = array(); + if (isset($MPEGaudioHeaderDecodeCache[$head4])) { + $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4]; + } else { + $MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4); + $MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray; + } + + static $MPEGaudioHeaderValidCache = array(); + if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache + //$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1) + $MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false); + } + + // shortcut + if (!isset($info['mpeg']['audio'])) { + $info['mpeg']['audio'] = array(); + } + $thisfile_mpeg_audio = &$info['mpeg']['audio']; + + + if ($MPEGaudioHeaderValidCache[$head4]) { + $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; + } else { + $info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset; + return false; + } + + if (!$FastMPEGheaderScan) { + $thisfile_mpeg_audio['version'] = $MPEGaudioVersionLookup[$thisfile_mpeg_audio['raw']['version']]; + $thisfile_mpeg_audio['layer'] = $MPEGaudioLayerLookup[$thisfile_mpeg_audio['raw']['layer']]; + + $thisfile_mpeg_audio['channelmode'] = $MPEGaudioChannelModeLookup[$thisfile_mpeg_audio['raw']['channelmode']]; + $thisfile_mpeg_audio['channels'] = (($thisfile_mpeg_audio['channelmode'] == 'mono') ? 1 : 2); + $thisfile_mpeg_audio['sample_rate'] = $MPEGaudioFrequencyLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['raw']['sample_rate']]; + $thisfile_mpeg_audio['protection'] = !$thisfile_mpeg_audio['raw']['protection']; + $thisfile_mpeg_audio['private'] = (bool) $thisfile_mpeg_audio['raw']['private']; + $thisfile_mpeg_audio['modeextension'] = $MPEGaudioModeExtensionLookup[$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['modeextension']]; + $thisfile_mpeg_audio['copyright'] = (bool) $thisfile_mpeg_audio['raw']['copyright']; + $thisfile_mpeg_audio['original'] = (bool) $thisfile_mpeg_audio['raw']['original']; + $thisfile_mpeg_audio['emphasis'] = $MPEGaudioEmphasisLookup[$thisfile_mpeg_audio['raw']['emphasis']]; + + $info['audio']['channels'] = $thisfile_mpeg_audio['channels']; + $info['audio']['sample_rate'] = $thisfile_mpeg_audio['sample_rate']; + + if ($thisfile_mpeg_audio['protection']) { + $thisfile_mpeg_audio['crc'] = getid3_lib::BigEndian2Int(substr($headerstring, 4, 2)); + } + } + + if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) { + // http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0 + $info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1'; + $thisfile_mpeg_audio['raw']['bitrate'] = 0; + } + $thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding']; + $thisfile_mpeg_audio['bitrate'] = $MPEGaudioBitrateLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['bitrate']]; + + if (($thisfile_mpeg_audio['bitrate'] == 'free') && ($offset == $info['avdataoffset'])) { + // only skip multiple frame check if free-format bitstream found at beginning of file + // otherwise is quite possibly simply corrupted data + $recursivesearch = false; + } + + // For Layer 2 there are some combinations of bitrate and mode which are not allowed. + if (!$FastMPEGheaderScan && ($thisfile_mpeg_audio['layer'] == '2')) { + + $info['audio']['dataformat'] = 'mp2'; + switch ($thisfile_mpeg_audio['channelmode']) { + + case 'mono': + if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) { + // these are ok + } else { + $info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.'; + return false; + } + break; + + case 'stereo': + case 'joint stereo': + case 'dual channel': + if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) { + // these are ok + } else { + $info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.'; + return false; + } + break; + + } + + } + + + if ($info['audio']['sample_rate'] > 0) { + $thisfile_mpeg_audio['framelength'] = self::MPEGaudioFrameLength($thisfile_mpeg_audio['bitrate'], $thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['layer'], (int) $thisfile_mpeg_audio['padding'], $info['audio']['sample_rate']); + } + + $nextframetestoffset = $offset + 1; + if ($thisfile_mpeg_audio['bitrate'] != 'free') { + + $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; + + if (isset($thisfile_mpeg_audio['framelength'])) { + $nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength']; + } else { + $info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.'; + return false; + } + + } + + $ExpectedNumberOfAudioBytes = 0; + + //////////////////////////////////////////////////////////////////////////////////// + // Variable-bitrate headers + + if (substr($headerstring, 4 + 32, 4) == 'VBRI') { + // Fraunhofer VBR header is hardcoded 'VBRI' at offset 0x24 (36) + // specs taken from http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html + + $thisfile_mpeg_audio['bitrate_mode'] = 'vbr'; + $thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer'; + $info['audio']['codec'] = 'Fraunhofer'; + + $SideInfoData = substr($headerstring, 4 + 2, 32); + + $FraunhoferVBROffset = 36; + + $thisfile_mpeg_audio['VBR_encoder_version'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 4, 2)); // VbriVersion + $thisfile_mpeg_audio['VBR_encoder_delay'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 6, 2)); // VbriDelay + $thisfile_mpeg_audio['VBR_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 8, 2)); // VbriQuality + $thisfile_mpeg_audio['VBR_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 10, 4)); // VbriStreamBytes + $thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 14, 4)); // VbriStreamFrames + $thisfile_mpeg_audio['VBR_seek_offsets'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 18, 2)); // VbriTableSize + $thisfile_mpeg_audio['VBR_seek_scale'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 20, 2)); // VbriTableScale + $thisfile_mpeg_audio['VBR_entry_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 22, 2)); // VbriEntryBytes + $thisfile_mpeg_audio['VBR_entry_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 24, 2)); // VbriEntryFrames + + $ExpectedNumberOfAudioBytes = $thisfile_mpeg_audio['VBR_bytes']; + + $previousbyteoffset = $offset; + for ($i = 0; $i < $thisfile_mpeg_audio['VBR_seek_offsets']; $i++) { + $Fraunhofer_OffsetN = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset, $thisfile_mpeg_audio['VBR_entry_bytes'])); + $FraunhoferVBROffset += $thisfile_mpeg_audio['VBR_entry_bytes']; + $thisfile_mpeg_audio['VBR_offsets_relative'][$i] = ($Fraunhofer_OffsetN * $thisfile_mpeg_audio['VBR_seek_scale']); + $thisfile_mpeg_audio['VBR_offsets_absolute'][$i] = ($Fraunhofer_OffsetN * $thisfile_mpeg_audio['VBR_seek_scale']) + $previousbyteoffset; + $previousbyteoffset += $Fraunhofer_OffsetN; + } + + + } else { + + // Xing VBR header is hardcoded 'Xing' at a offset 0x0D (13), 0x15 (21) or 0x24 (36) + // depending on MPEG layer and number of channels + + $VBRidOffset = self::XingVBRidOffset($thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['channelmode']); + $SideInfoData = substr($headerstring, 4 + 2, $VBRidOffset - 4); + + if ((substr($headerstring, $VBRidOffset, strlen('Xing')) == 'Xing') || (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Info')) { + // 'Xing' is traditional Xing VBR frame + // 'Info' is LAME-encoded CBR (This was done to avoid CBR files to be recognized as traditional Xing VBR files by some decoders.) + // 'Info' *can* legally be used to specify a VBR file as well, however. + + // http://www.multiweb.cz/twoinches/MP3inside.htm + //00..03 = "Xing" or "Info" + //04..07 = Flags: + // 0x01 Frames Flag set if value for number of frames in file is stored + // 0x02 Bytes Flag set if value for filesize in bytes is stored + // 0x04 TOC Flag set if values for TOC are stored + // 0x08 VBR Scale Flag set if values for VBR scale is stored + //08..11 Frames: Number of frames in file (including the first Xing/Info one) + //12..15 Bytes: File length in Bytes + //16..115 TOC (Table of Contents): + // Contains of 100 indexes (one Byte length) for easier lookup in file. Approximately solves problem with moving inside file. + // Each Byte has a value according this formula: + // (TOC[i] / 256) * fileLenInBytes + // So if song lasts eg. 240 sec. and you want to jump to 60. sec. (and file is 5 000 000 Bytes length) you can use: + // TOC[(60/240)*100] = TOC[25] + // and corresponding Byte in file is then approximately at: + // (TOC[25]/256) * 5000000 + //116..119 VBR Scale + + + // should be safe to leave this at 'vbr' and let it be overriden to 'cbr' if a CBR preset/mode is used by LAME +// if (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Xing') { + $thisfile_mpeg_audio['bitrate_mode'] = 'vbr'; + $thisfile_mpeg_audio['VBR_method'] = 'Xing'; +// } else { +// $ScanAsCBR = true; +// $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; +// } + + $thisfile_mpeg_audio['xing_flags_raw'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 4, 4)); + + $thisfile_mpeg_audio['xing_flags']['frames'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000001); + $thisfile_mpeg_audio['xing_flags']['bytes'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000002); + $thisfile_mpeg_audio['xing_flags']['toc'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000004); + $thisfile_mpeg_audio['xing_flags']['vbr_scale'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000008); + + if ($thisfile_mpeg_audio['xing_flags']['frames']) { + $thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 8, 4)); + //$thisfile_mpeg_audio['VBR_frames']--; // don't count header Xing/Info frame + } + if ($thisfile_mpeg_audio['xing_flags']['bytes']) { + $thisfile_mpeg_audio['VBR_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 12, 4)); + } + + //if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) { + if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) { + + $framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']; + + if ($thisfile_mpeg_audio['layer'] == '1') { + // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12 + //$info['audio']['bitrate'] = ((($framelengthfloat / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12; + $info['audio']['bitrate'] = ($framelengthfloat / 4) * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 12; + } else { + // Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144 + //$info['audio']['bitrate'] = (($framelengthfloat - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144; + $info['audio']['bitrate'] = $framelengthfloat * $thisfile_mpeg_audio['sample_rate'] * (2 / $info['audio']['channels']) / 144; + } + $thisfile_mpeg_audio['framelength'] = floor($framelengthfloat); + } + + if ($thisfile_mpeg_audio['xing_flags']['toc']) { + $LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100); + for ($i = 0; $i < 100; $i++) { + $thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData{$i}); + } + } + if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) { + $thisfile_mpeg_audio['VBR_scale'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 116, 4)); + } + + + // http://gabriel.mp3-tech.org/mp3infotag.html + if (substr($headerstring, $VBRidOffset + 120, 4) == 'LAME') { + + // shortcut + $thisfile_mpeg_audio['LAME'] = array(); + $thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME']; + + + $thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20); + $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9); + + if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { + + // extra 11 chars are not part of version string when LAMEtag present + unset($thisfile_mpeg_audio_lame['long_version']); + + // It the LAME tag was only introduced in LAME v3.90 + // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 + + // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html + // are assuming a 'Xing' identifier offset of 0x24, which is the case for + // MPEG-1 non-mono, but not for other combinations + $LAMEtagOffsetContant = $VBRidOffset - 0x24; + + // shortcuts + $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); + $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; + $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; + $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; + $thisfile_mpeg_audio_lame['raw'] = array(); + $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; + + // byte $9B VBR Quality + // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. + // Actually overwrites original Xing bytes + unset($thisfile_mpeg_audio['VBR_scale']); + $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); + + // bytes $9C-$A4 Encoder short VersionString + $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); + + // byte $A5 Info Tag revision + VBR method + $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); + + $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; + $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; + $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); + $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' + + // byte $A6 Lowpass filter value + $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; + + // bytes $A7-$AE Replay Gain + // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html + // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" + if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { + // LAME 3.94a16 and later - 9.23 fixed point + // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 + $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); + } else { + // LAME 3.94a15 and earlier - 32-bit floating point + // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 + $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); + } + if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { + unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); + } else { + $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); + } + + $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2)); + $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2)); + + + if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) { + + $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF; + $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']); + $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']); + $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']); + + if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { + $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; + } + $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator']; + $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db']; + } else { + unset($thisfile_mpeg_audio_lame_RGAD['track']); + } + if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) { + + $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13; + $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10; + $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9; + $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF; + $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']); + $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']); + $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']); + + if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { + $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; + } + $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator']; + $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db']; + } else { + unset($thisfile_mpeg_audio_lame_RGAD['album']); + } + if (empty($thisfile_mpeg_audio_lame_RGAD)) { + unset($thisfile_mpeg_audio_lame['RGAD']); + } + + + // byte $AF Encoding flags + ATH Type + $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1)); + $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10); + $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20); + $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40); + $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80); + $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F; + + // byte $B0 if ABR {specified bitrate} else {minimal bitrate} + $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1)); + if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR) + $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; + } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR) + // ignore + } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate + $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; + } + + // bytes $B1-$B3 Encoder delays + $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3)); + $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12; + $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF; + + // byte $B4 Misc + $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1)); + $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03); + $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2; + $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5; + $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6; + $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping']; + $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']); + $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality']; + $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']); + + // byte $B5 MP3 Gain + $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true); + $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain']; + $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6)); + + // bytes $B6-$B7 Preset and surround info + $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2)); + // Reserved = ($PresetSurroundBytes & 0xC000); + $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800); + $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']); + $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF); + $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); + if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { + $info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'; + } + if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { + // this may change if 3.90.4 ever comes out + $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3'; + } + + // bytes $B8-$BB MusicLength + $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4)); + $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']); + + // bytes $BC-$BD MusicCRC + $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2)); + + // bytes $BE-$BF CRC-16 of Info Tag + $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2)); + + + // LAME CBR + if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { + + $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; + $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); + $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; + //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) { + // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min']; + //} + + } + + } + } + + } else { + + // not Fraunhofer or Xing VBR methods, most likely CBR (but could be VBR with no header) + $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; + if ($recursivesearch) { + $thisfile_mpeg_audio['bitrate_mode'] = 'vbr'; + if ($this->RecursiveFrameScanning($offset, $nextframetestoffset, true)) { + $recursivesearch = false; + $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; + } + if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') { + $info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.'; + } + } + + } + + } + + if (($ExpectedNumberOfAudioBytes > 0) && ($ExpectedNumberOfAudioBytes != ($info['avdataend'] - $info['avdataoffset']))) { + if ($ExpectedNumberOfAudioBytes > ($info['avdataend'] - $info['avdataoffset'])) { + if (isset($info['fileformat']) && ($info['fileformat'] == 'riff')) { + // ignore, audio data is broken into chunks so will always be data "missing" + } elseif (($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])) == 1) { + $info['warning'][] = 'Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)'; + } else { + $info['warning'][] = 'Probable truncated file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' (short by '.($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])).' bytes)'; + } + } else { + if ((($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes) == 1) { + // $prenullbytefileoffset = ftell($this->getid3->fp); + // fseek($this->getid3->fp, $info['avdataend'], SEEK_SET); + // $PossibleNullByte = fread($this->getid3->fp, 1); + // fseek($this->getid3->fp, $prenullbytefileoffset, SEEK_SET); + // if ($PossibleNullByte === "\x00") { + $info['avdataend']--; + // $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'; + // } else { + // $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)'; + // } + } else { + $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)'; + } + } + } + + if (($thisfile_mpeg_audio['bitrate'] == 'free') && empty($info['audio']['bitrate'])) { + if (($offset == $info['avdataoffset']) && empty($thisfile_mpeg_audio['VBR_frames'])) { + $framebytelength = $this->FreeFormatFrameLength($offset, true); + if ($framebytelength > 0) { + $thisfile_mpeg_audio['framelength'] = $framebytelength; + if ($thisfile_mpeg_audio['layer'] == '1') { + // BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12 + $info['audio']['bitrate'] = ((($framebytelength / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12; + } else { + // Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144 + $info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144; + } + } else { + $info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header'; + } + } + } + + if (isset($thisfile_mpeg_audio['VBR_frames']) ? $thisfile_mpeg_audio['VBR_frames'] : '') { + switch ($thisfile_mpeg_audio['bitrate_mode']) { + case 'vbr': + case 'abr': + $bytes_per_frame = 1152; + if (($thisfile_mpeg_audio['version'] == '1') && ($thisfile_mpeg_audio['layer'] == 1)) { + $bytes_per_frame = 384; + } elseif ((($thisfile_mpeg_audio['version'] == '2') || ($thisfile_mpeg_audio['version'] == '2.5')) && ($thisfile_mpeg_audio['layer'] == 3)) { + $bytes_per_frame = 576; + } + $thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0); + if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) { + $info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; + $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion + } + break; + } + } + + // End variable-bitrate headers + //////////////////////////////////////////////////////////////////////////////////// + + if ($recursivesearch) { + + if (!$this->RecursiveFrameScanning($offset, $nextframetestoffset, $ScanAsCBR)) { + return false; + } + + } + + + //if (false) { + // // experimental side info parsing section - not returning anything useful yet + // + // $SideInfoBitstream = getid3_lib::BigEndian2Bin($SideInfoData); + // $SideInfoOffset = 0; + // + // if ($thisfile_mpeg_audio['version'] == '1') { + // if ($thisfile_mpeg_audio['channelmode'] == 'mono') { + // // MPEG-1 (mono) + // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9); + // $SideInfoOffset += 9; + // $SideInfoOffset += 5; + // } else { + // // MPEG-1 (stereo, joint-stereo, dual-channel) + // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9); + // $SideInfoOffset += 9; + // $SideInfoOffset += 3; + // } + // } else { // 2 or 2.5 + // if ($thisfile_mpeg_audio['channelmode'] == 'mono') { + // // MPEG-2, MPEG-2.5 (mono) + // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8); + // $SideInfoOffset += 8; + // $SideInfoOffset += 1; + // } else { + // // MPEG-2, MPEG-2.5 (stereo, joint-stereo, dual-channel) + // $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8); + // $SideInfoOffset += 8; + // $SideInfoOffset += 2; + // } + // } + // + // if ($thisfile_mpeg_audio['version'] == '1') { + // for ($channel = 0; $channel < $info['audio']['channels']; $channel++) { + // for ($scfsi_band = 0; $scfsi_band < 4; $scfsi_band++) { + // $thisfile_mpeg_audio['scfsi'][$channel][$scfsi_band] = substr($SideInfoBitstream, $SideInfoOffset, 1); + // $SideInfoOffset += 2; + // } + // } + // } + // for ($granule = 0; $granule < (($thisfile_mpeg_audio['version'] == '1') ? 2 : 1); $granule++) { + // for ($channel = 0; $channel < $info['audio']['channels']; $channel++) { + // $thisfile_mpeg_audio['part2_3_length'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 12); + // $SideInfoOffset += 12; + // $thisfile_mpeg_audio['big_values'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9); + // $SideInfoOffset += 9; + // $thisfile_mpeg_audio['global_gain'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 8); + // $SideInfoOffset += 8; + // if ($thisfile_mpeg_audio['version'] == '1') { + // $thisfile_mpeg_audio['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4); + // $SideInfoOffset += 4; + // } else { + // $thisfile_mpeg_audio['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9); + // $SideInfoOffset += 9; + // } + // $thisfile_mpeg_audio['window_switching_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1); + // $SideInfoOffset += 1; + // + // if ($thisfile_mpeg_audio['window_switching_flag'][$granule][$channel] == '1') { + // + // $thisfile_mpeg_audio['block_type'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 2); + // $SideInfoOffset += 2; + // $thisfile_mpeg_audio['mixed_block_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1); + // $SideInfoOffset += 1; + // + // for ($region = 0; $region < 2; $region++) { + // $thisfile_mpeg_audio['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5); + // $SideInfoOffset += 5; + // } + // $thisfile_mpeg_audio['table_select'][$granule][$channel][2] = 0; + // + // for ($window = 0; $window < 3; $window++) { + // $thisfile_mpeg_audio['subblock_gain'][$granule][$channel][$window] = substr($SideInfoBitstream, $SideInfoOffset, 3); + // $SideInfoOffset += 3; + // } + // + // } else { + // + // for ($region = 0; $region < 3; $region++) { + // $thisfile_mpeg_audio['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5); + // $SideInfoOffset += 5; + // } + // + // $thisfile_mpeg_audio['region0_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4); + // $SideInfoOffset += 4; + // $thisfile_mpeg_audio['region1_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 3); + // $SideInfoOffset += 3; + // $thisfile_mpeg_audio['block_type'][$granule][$channel] = 0; + // } + // + // if ($thisfile_mpeg_audio['version'] == '1') { + // $thisfile_mpeg_audio['preflag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1); + // $SideInfoOffset += 1; + // } + // $thisfile_mpeg_audio['scalefac_scale'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1); + // $SideInfoOffset += 1; + // $thisfile_mpeg_audio['count1table_select'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1); + // $SideInfoOffset += 1; + // } + // } + //} + + return true; + } + + public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) { + $info = &$this->getid3->info; + $firstframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); + $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false); + + for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) { + // check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch + if (($nextframetestoffset + 4) >= $info['avdataend']) { + // end of file + return true; + } + + $nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); + if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) { + if ($ScanAsCBR) { + // force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header + if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) { + return false; + } + } + + + // next frame is OK, get ready to check the one after that + if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) { + $nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength']; + } else { + $info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.'; + return false; + } + + } elseif (!empty($firstframetestarray['mpeg']['audio']['framelength']) && (($nextframetestoffset + $firstframetestarray['mpeg']['audio']['framelength']) > $info['avdataend'])) { + + // it's not the end of the file, but there's not enough data left for another frame, so assume it's garbage/padding and return OK + return true; + + } else { + + // next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence + $info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.'; + + return false; + } + } + return true; + } + + public function FreeFormatFrameLength($offset, $deepscan=false) { + $info = &$this->getid3->info; + + fseek($this->getid3->fp, $offset, SEEK_SET); + $MPEGaudioData = fread($this->getid3->fp, 32768); + + $SyncPattern1 = substr($MPEGaudioData, 0, 4); + // may be different pattern due to padding + $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) | 0x02).$SyncPattern1{3}; + if ($SyncPattern2 === $SyncPattern1) { + $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) & 0xFD).$SyncPattern1{3}; + } + + $framelength = false; + $framelength1 = strpos($MPEGaudioData, $SyncPattern1, 4); + $framelength2 = strpos($MPEGaudioData, $SyncPattern2, 4); + if ($framelength1 > 4) { + $framelength = $framelength1; + } + if (($framelength2 > 4) && ($framelength2 < $framelength1)) { + $framelength = $framelength2; + } + if (!$framelength) { + + // LAME 3.88 has a different value for modeextension on the first frame vs the rest + $framelength1 = strpos($MPEGaudioData, substr($SyncPattern1, 0, 3), 4); + $framelength2 = strpos($MPEGaudioData, substr($SyncPattern2, 0, 3), 4); + + if ($framelength1 > 4) { + $framelength = $framelength1; + } + if (($framelength2 > 4) && ($framelength2 < $framelength1)) { + $framelength = $framelength2; + } + if (!$framelength) { + $info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset; + return false; + } else { + $info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)'; + $info['audio']['codec'] = 'LAME'; + $info['audio']['encoder'] = 'LAME3.88'; + $SyncPattern1 = substr($SyncPattern1, 0, 3); + $SyncPattern2 = substr($SyncPattern2, 0, 3); + } + } + + if ($deepscan) { + + $ActualFrameLengthValues = array(); + $nextoffset = $offset + $framelength; + while ($nextoffset < ($info['avdataend'] - 6)) { + fseek($this->getid3->fp, $nextoffset - 1, SEEK_SET); + $NextSyncPattern = fread($this->getid3->fp, 6); + if ((substr($NextSyncPattern, 1, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 1, strlen($SyncPattern2)) == $SyncPattern2)) { + // good - found where expected + $ActualFrameLengthValues[] = $framelength; + } elseif ((substr($NextSyncPattern, 0, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 0, strlen($SyncPattern2)) == $SyncPattern2)) { + // ok - found one byte earlier than expected (last frame wasn't padded, first frame was) + $ActualFrameLengthValues[] = ($framelength - 1); + $nextoffset--; + } elseif ((substr($NextSyncPattern, 2, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 2, strlen($SyncPattern2)) == $SyncPattern2)) { + // ok - found one byte later than expected (last frame was padded, first frame wasn't) + $ActualFrameLengthValues[] = ($framelength + 1); + $nextoffset++; + } else { + $info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset; + return false; + } + $nextoffset += $framelength; + } + if (count($ActualFrameLengthValues) > 0) { + $framelength = intval(round(array_sum($ActualFrameLengthValues) / count($ActualFrameLengthValues))); + } + } + return $framelength; + } + + public function getOnlyMPEGaudioInfoBruteForce() { + $MPEGaudioHeaderDecodeCache = array(); + $MPEGaudioHeaderValidCache = array(); + $MPEGaudioHeaderLengthCache = array(); + $MPEGaudioVersionLookup = self::MPEGaudioVersionArray(); + $MPEGaudioLayerLookup = self::MPEGaudioLayerArray(); + $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray(); + $MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray(); + $MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray(); + $MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray(); + $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray(); + $LongMPEGversionLookup = array(); + $LongMPEGlayerLookup = array(); + $LongMPEGbitrateLookup = array(); + $LongMPEGpaddingLookup = array(); + $LongMPEGfrequencyLookup = array(); + $Distribution['bitrate'] = array(); + $Distribution['frequency'] = array(); + $Distribution['layer'] = array(); + $Distribution['version'] = array(); + $Distribution['padding'] = array(); + + $info = &$this->getid3->info; + fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + + $max_frames_scan = 5000; + $frames_scanned = 0; + + $previousvalidframe = $info['avdataoffset']; + while (ftell($this->getid3->fp) < $info['avdataend']) { + set_time_limit(30); + $head4 = fread($this->getid3->fp, 4); + if (strlen($head4) < 4) { + break; + } + if ($head4{0} != "\xFF") { + for ($i = 1; $i < 4; $i++) { + if ($head4{$i} == "\xFF") { + fseek($this->getid3->fp, $i - 4, SEEK_CUR); + continue 2; + } + } + continue; + } + if (!isset($MPEGaudioHeaderDecodeCache[$head4])) { + $MPEGaudioHeaderDecodeCache[$head4] = self::MPEGaudioHeaderDecode($head4); + } + if (!isset($MPEGaudioHeaderValidCache[$head4])) { + $MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$head4], false, false); + } + if ($MPEGaudioHeaderValidCache[$head4]) { + + if (!isset($MPEGaudioHeaderLengthCache[$head4])) { + $LongMPEGversionLookup[$head4] = $MPEGaudioVersionLookup[$MPEGaudioHeaderDecodeCache[$head4]['version']]; + $LongMPEGlayerLookup[$head4] = $MPEGaudioLayerLookup[$MPEGaudioHeaderDecodeCache[$head4]['layer']]; + $LongMPEGbitrateLookup[$head4] = $MPEGaudioBitrateLookup[$LongMPEGversionLookup[$head4]][$LongMPEGlayerLookup[$head4]][$MPEGaudioHeaderDecodeCache[$head4]['bitrate']]; + $LongMPEGpaddingLookup[$head4] = (bool) $MPEGaudioHeaderDecodeCache[$head4]['padding']; + $LongMPEGfrequencyLookup[$head4] = $MPEGaudioFrequencyLookup[$LongMPEGversionLookup[$head4]][$MPEGaudioHeaderDecodeCache[$head4]['sample_rate']]; + $MPEGaudioHeaderLengthCache[$head4] = self::MPEGaudioFrameLength( + $LongMPEGbitrateLookup[$head4], + $LongMPEGversionLookup[$head4], + $LongMPEGlayerLookup[$head4], + $LongMPEGpaddingLookup[$head4], + $LongMPEGfrequencyLookup[$head4]); + } + if ($MPEGaudioHeaderLengthCache[$head4] > 4) { + $WhereWeWere = ftell($this->getid3->fp); + fseek($this->getid3->fp, $MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR); + $next4 = fread($this->getid3->fp, 4); + if ($next4{0} == "\xFF") { + if (!isset($MPEGaudioHeaderDecodeCache[$next4])) { + $MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4); + } + if (!isset($MPEGaudioHeaderValidCache[$next4])) { + $MPEGaudioHeaderValidCache[$next4] = self::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$next4], false, false); + } + if ($MPEGaudioHeaderValidCache[$next4]) { + fseek($this->getid3->fp, -4, SEEK_CUR); + + getid3_lib::safe_inc($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]); + getid3_lib::safe_inc($Distribution['layer'][$LongMPEGlayerLookup[$head4]]); + getid3_lib::safe_inc($Distribution['version'][$LongMPEGversionLookup[$head4]]); + getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]); + getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]); + if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) { + $pct_data_scanned = (ftell($this->getid3->fp) - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']); + $info['warning'][] = 'too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.'; + foreach ($Distribution as $key1 => $value1) { + foreach ($value1 as $key2 => $value2) { + $Distribution[$key1][$key2] = round($value2 / $pct_data_scanned); + } + } + break; + } + continue; + } + } + unset($next4); + fseek($this->getid3->fp, $WhereWeWere - 3, SEEK_SET); + } + + } + } + foreach ($Distribution as $key => $value) { + ksort($Distribution[$key], SORT_NUMERIC); + } + ksort($Distribution['version'], SORT_STRING); + $info['mpeg']['audio']['bitrate_distribution'] = $Distribution['bitrate']; + $info['mpeg']['audio']['frequency_distribution'] = $Distribution['frequency']; + $info['mpeg']['audio']['layer_distribution'] = $Distribution['layer']; + $info['mpeg']['audio']['version_distribution'] = $Distribution['version']; + $info['mpeg']['audio']['padding_distribution'] = $Distribution['padding']; + if (count($Distribution['version']) > 1) { + $info['error'][] = 'Corrupt file - more than one MPEG version detected'; + } + if (count($Distribution['layer']) > 1) { + $info['error'][] = 'Corrupt file - more than one MPEG layer detected'; + } + if (count($Distribution['frequency']) > 1) { + $info['error'][] = 'Corrupt file - more than one MPEG sample rate detected'; + } + + + $bittotal = 0; + foreach ($Distribution['bitrate'] as $bitratevalue => $bitratecount) { + if ($bitratevalue != 'free') { + $bittotal += ($bitratevalue * $bitratecount); + } + } + $info['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']); + if ($info['mpeg']['audio']['frame_count'] == 0) { + $info['error'][] = 'no MPEG audio frames found'; + return false; + } + $info['mpeg']['audio']['bitrate'] = ($bittotal / $info['mpeg']['audio']['frame_count']); + $info['mpeg']['audio']['bitrate_mode'] = ((count($Distribution['bitrate']) > 0) ? 'vbr' : 'cbr'); + $info['mpeg']['audio']['sample_rate'] = getid3_lib::array_max($Distribution['frequency'], true); + + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; + $info['audio']['bitrate_mode'] = $info['mpeg']['audio']['bitrate_mode']; + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + $info['audio']['dataformat'] = 'mp'.getid3_lib::array_max($Distribution['layer'], true); + $info['fileformat'] = $info['audio']['dataformat']; + + return true; + } + + + public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) { + // looks for synch, decodes MPEG audio header + + $info = &$this->getid3->info; + + static $MPEGaudioVersionLookup; + static $MPEGaudioLayerLookup; + static $MPEGaudioBitrateLookup; + if (empty($MPEGaudioVersionLookup)) { + $MPEGaudioVersionLookup = self::MPEGaudioVersionArray(); + $MPEGaudioLayerLookup = self::MPEGaudioLayerArray(); + $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray(); + + } + + fseek($this->getid3->fp, $avdataoffset, SEEK_SET); + $sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset); + if ($sync_seek_buffer_size <= 0) { + $info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset; + return false; + } + $header = fread($this->getid3->fp, $sync_seek_buffer_size); + $sync_seek_buffer_size = strlen($header); + $SynchSeekOffset = 0; + while ($SynchSeekOffset < $sync_seek_buffer_size) { + if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !feof($this->getid3->fp)) { + + if ($SynchSeekOffset > $sync_seek_buffer_size) { + // if a synch's not found within the first 128k bytes, then give up + $info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB'; + if (isset($info['audio']['bitrate'])) { + unset($info['audio']['bitrate']); + } + if (isset($info['mpeg']['audio'])) { + unset($info['mpeg']['audio']); + } + if (empty($info['mpeg'])) { + unset($info['mpeg']); + } + return false; + + } elseif (feof($this->getid3->fp)) { + + $info['error'][] = 'Could not find valid MPEG audio synch before end of file'; + if (isset($info['audio']['bitrate'])) { + unset($info['audio']['bitrate']); + } + if (isset($info['mpeg']['audio'])) { + unset($info['mpeg']['audio']); + } + if (isset($info['mpeg']) && (!is_array($info['mpeg']) || (count($info['mpeg']) == 0))) { + unset($info['mpeg']); + } + return false; + } + } + + if (($SynchSeekOffset + 1) >= strlen($header)) { + $info['error'][] = 'Could not find valid MPEG synch before end of file'; + return false; + } + + if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected + if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) { + $FirstFrameThisfileInfo = $info; + $FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset; + if (!$this->decodeMPEGaudioHeader($FirstFrameAVDataOffset, $FirstFrameThisfileInfo, false)) { + // if this is the first valid MPEG-audio frame, save it in case it's a VBR header frame and there's + // garbage between this frame and a valid sequence of MPEG-audio frames, to be restored below + unset($FirstFrameThisfileInfo); + } + } + + $dummy = $info; // only overwrite real data if valid header found + if ($this->decodeMPEGaudioHeader($avdataoffset + $SynchSeekOffset, $dummy, true)) { + $info = $dummy; + $info['avdataoffset'] = $avdataoffset + $SynchSeekOffset; + switch (isset($info['fileformat']) ? $info['fileformat'] : '') { + case '': + case 'id3': + case 'ape': + case 'mp3': + $info['fileformat'] = 'mp3'; + $info['audio']['dataformat'] = 'mp3'; + break; + } + if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) { + if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) { + // If there is garbage data between a valid VBR header frame and a sequence + // of valid MPEG-audio frames the VBR data is no longer discarded. + $info = $FirstFrameThisfileInfo; + $info['avdataoffset'] = $FirstFrameAVDataOffset; + $info['fileformat'] = 'mp3'; + $info['audio']['dataformat'] = 'mp3'; + $dummy = $info; + unset($dummy['mpeg']['audio']); + $GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength']; + $GarbageOffsetEnd = $avdataoffset + $SynchSeekOffset; + if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) { + $info = $dummy; + $info['avdataoffset'] = $GarbageOffsetEnd; + $info['warning'][] = 'apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd; + } else { + $info['warning'][] = 'using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')'; + } + } + } + if (isset($info['mpeg']['audio']['bitrate_mode']) && ($info['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($info['mpeg']['audio']['VBR_method'])) { + // VBR file with no VBR header + $BitrateHistogram = true; + } + + if ($BitrateHistogram) { + + $info['mpeg']['audio']['stereo_distribution'] = array('stereo'=>0, 'joint stereo'=>0, 'dual channel'=>0, 'mono'=>0); + $info['mpeg']['audio']['version_distribution'] = array('1'=>0, '2'=>0, '2.5'=>0); + + if ($info['mpeg']['audio']['version'] == '1') { + if ($info['mpeg']['audio']['layer'] == 3) { + $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0); + } elseif ($info['mpeg']['audio']['layer'] == 2) { + $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0, 384000=>0); + } elseif ($info['mpeg']['audio']['layer'] == 1) { + $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 64000=>0, 96000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 288000=>0, 320000=>0, 352000=>0, 384000=>0, 416000=>0, 448000=>0); + } + } elseif ($info['mpeg']['audio']['layer'] == 1) { + $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0, 176000=>0, 192000=>0, 224000=>0, 256000=>0); + } else { + $info['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 8000=>0, 16000=>0, 24000=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0); + } + + $dummy = array('error'=>$info['error'], 'warning'=>$info['warning'], 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); + $synchstartoffset = $info['avdataoffset']; + fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + + // you can play with these numbers: + $max_frames_scan = 50000; + $max_scan_segments = 10; + + // don't play with these numbers: + $FastMode = false; + $SynchErrorsFound = 0; + $frames_scanned = 0; + $this_scan_segment = 0; + $frames_scan_per_segment = ceil($max_frames_scan / $max_scan_segments); + $pct_data_scanned = 0; + for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) { + $frames_scanned_this_segment = 0; + if (ftell($this->getid3->fp) >= $info['avdataend']) { + break; + } + $scan_start_offset[$current_segment] = max(ftell($this->getid3->fp), $info['avdataoffset'] + round($current_segment * (($info['avdataend'] - $info['avdataoffset']) / $max_scan_segments))); + if ($current_segment > 0) { + fseek($this->getid3->fp, $scan_start_offset[$current_segment], SEEK_SET); + $buffer_4k = fread($this->getid3->fp, 4096); + for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) { + if (($buffer_4k{$j} == "\xFF") && ($buffer_4k{($j + 1)} > "\xE0")) { // synch detected + if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) { + $calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength']; + if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) { + $scan_start_offset[$current_segment] += $j; + break; + } + } + } + } + } + $synchstartoffset = $scan_start_offset[$current_segment]; + while ($this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) { + $FastMode = true; + $thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']]; + + if (empty($dummy['mpeg']['audio']['framelength'])) { + $SynchErrorsFound++; + $synchstartoffset++; + } else { + getid3_lib::safe_inc($info['mpeg']['audio']['bitrate_distribution'][$thisframebitrate]); + getid3_lib::safe_inc($info['mpeg']['audio']['stereo_distribution'][$dummy['mpeg']['audio']['channelmode']]); + getid3_lib::safe_inc($info['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]); + $synchstartoffset += $dummy['mpeg']['audio']['framelength']; + } + $frames_scanned++; + if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) { + $this_pct_scanned = (ftell($this->getid3->fp) - $scan_start_offset[$current_segment]) / ($info['avdataend'] - $info['avdataoffset']); + if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) { + // file likely contains < $max_frames_scan, just scan as one segment + $max_scan_segments = 1; + $frames_scan_per_segment = $max_frames_scan; + } else { + $pct_data_scanned += $this_pct_scanned; + break; + } + } + } + } + if ($pct_data_scanned > 0) { + $info['warning'][] = 'too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.'; + foreach ($info['mpeg']['audio'] as $key1 => $value1) { + if (!preg_match('#_distribution$#i', $key1)) { + continue; + } + foreach ($value1 as $key2 => $value2) { + $info['mpeg']['audio'][$key1][$key2] = round($value2 / $pct_data_scanned); + } + } + } + + if ($SynchErrorsFound > 0) { + $info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis'; + //return false; + } + + $bittotal = 0; + $framecounter = 0; + foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bitratevalue => $bitratecount) { + $framecounter += $bitratecount; + if ($bitratevalue != 'free') { + $bittotal += ($bitratevalue * $bitratecount); + } + } + if ($framecounter == 0) { + $info['error'][] = 'Corrupt MP3 file: framecounter == zero'; + return false; + } + $info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter); + $info['mpeg']['audio']['bitrate'] = ($bittotal / $framecounter); + + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; + + + // Definitively set VBR vs CBR, even if the Xing/LAME/VBRI header says differently + $distinct_bitrates = 0; + foreach ($info['mpeg']['audio']['bitrate_distribution'] as $bitrate_value => $bitrate_count) { + if ($bitrate_count > 0) { + $distinct_bitrates++; + } + } + if ($distinct_bitrates > 1) { + $info['mpeg']['audio']['bitrate_mode'] = 'vbr'; + } else { + $info['mpeg']['audio']['bitrate_mode'] = 'cbr'; + } + $info['audio']['bitrate_mode'] = $info['mpeg']['audio']['bitrate_mode']; + + } + + break; // exit while() + } + } + + $SynchSeekOffset++; + if (($avdataoffset + $SynchSeekOffset) >= $info['avdataend']) { + // end of file/data + + if (empty($info['mpeg']['audio'])) { + + $info['error'][] = 'could not find valid MPEG synch before end of file'; + if (isset($info['audio']['bitrate'])) { + unset($info['audio']['bitrate']); + } + if (isset($info['mpeg']['audio'])) { + unset($info['mpeg']['audio']); + } + if (isset($info['mpeg']) && (!is_array($info['mpeg']) || empty($info['mpeg']))) { + unset($info['mpeg']); + } + return false; + + } + break; + } + + } + $info['audio']['channels'] = $info['mpeg']['audio']['channels']; + $info['audio']['channelmode'] = $info['mpeg']['audio']['channelmode']; + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + return true; + } + + + public static function MPEGaudioVersionArray() { + static $MPEGaudioVersion = array('2.5', false, '2', '1'); + return $MPEGaudioVersion; + } + + public static function MPEGaudioLayerArray() { + static $MPEGaudioLayer = array(false, 3, 2, 1); + return $MPEGaudioLayer; + } + + public static function MPEGaudioBitrateArray() { + static $MPEGaudioBitrate; + if (empty($MPEGaudioBitrate)) { + $MPEGaudioBitrate = array ( + '1' => array (1 => array('free', 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000), + 2 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000), + 3 => array('free', 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000) + ), + + '2' => array (1 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000), + 2 => array('free', 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000), + ) + ); + $MPEGaudioBitrate['2'][3] = $MPEGaudioBitrate['2'][2]; + $MPEGaudioBitrate['2.5'] = $MPEGaudioBitrate['2']; + } + return $MPEGaudioBitrate; + } + + public static function MPEGaudioFrequencyArray() { + static $MPEGaudioFrequency; + if (empty($MPEGaudioFrequency)) { + $MPEGaudioFrequency = array ( + '1' => array(44100, 48000, 32000), + '2' => array(22050, 24000, 16000), + '2.5' => array(11025, 12000, 8000) + ); + } + return $MPEGaudioFrequency; + } + + public static function MPEGaudioChannelModeArray() { + static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono'); + return $MPEGaudioChannelMode; + } + + public static function MPEGaudioModeExtensionArray() { + static $MPEGaudioModeExtension; + if (empty($MPEGaudioModeExtension)) { + $MPEGaudioModeExtension = array ( + 1 => array('4-31', '8-31', '12-31', '16-31'), + 2 => array('4-31', '8-31', '12-31', '16-31'), + 3 => array('', 'IS', 'MS', 'IS+MS') + ); + } + return $MPEGaudioModeExtension; + } + + public static function MPEGaudioEmphasisArray() { + static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17'); + return $MPEGaudioEmphasis; + } + + public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) { + return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15); + } + + public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) { + if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) { + return false; + } + + static $MPEGaudioVersionLookup; + static $MPEGaudioLayerLookup; + static $MPEGaudioBitrateLookup; + static $MPEGaudioFrequencyLookup; + static $MPEGaudioChannelModeLookup; + static $MPEGaudioModeExtensionLookup; + static $MPEGaudioEmphasisLookup; + if (empty($MPEGaudioVersionLookup)) { + $MPEGaudioVersionLookup = self::MPEGaudioVersionArray(); + $MPEGaudioLayerLookup = self::MPEGaudioLayerArray(); + $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray(); + $MPEGaudioFrequencyLookup = self::MPEGaudioFrequencyArray(); + $MPEGaudioChannelModeLookup = self::MPEGaudioChannelModeArray(); + $MPEGaudioModeExtensionLookup = self::MPEGaudioModeExtensionArray(); + $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray(); + } + + if (isset($MPEGaudioVersionLookup[$rawarray['version']])) { + $decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']]; + } else { + echo ($echoerrors ? "\n".'invalid Version ('.$rawarray['version'].')' : ''); + return false; + } + if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) { + $decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']]; + } else { + echo ($echoerrors ? "\n".'invalid Layer ('.$rawarray['layer'].')' : ''); + return false; + } + if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) { + echo ($echoerrors ? "\n".'invalid Bitrate ('.$rawarray['bitrate'].')' : ''); + if ($rawarray['bitrate'] == 15) { + // known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0 + // let it go through here otherwise file will not be identified + if (!$allowBitrate15) { + return false; + } + } else { + return false; + } + } + if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) { + echo ($echoerrors ? "\n".'invalid Frequency ('.$rawarray['sample_rate'].')' : ''); + return false; + } + if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) { + echo ($echoerrors ? "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')' : ''); + return false; + } + if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) { + echo ($echoerrors ? "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')' : ''); + return false; + } + if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) { + echo ($echoerrors ? "\n".'invalid Emphasis ('.$rawarray['emphasis'].')' : ''); + return false; + } + // These are just either set or not set, you can't mess that up :) + // $rawarray['protection']; + // $rawarray['padding']; + // $rawarray['private']; + // $rawarray['copyright']; + // $rawarray['original']; + + return true; + } + + public static function MPEGaudioHeaderDecode($Header4Bytes) { + // AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM + // A - Frame sync (all bits set) + // B - MPEG Audio version ID + // C - Layer description + // D - Protection bit + // E - Bitrate index + // F - Sampling rate frequency index + // G - Padding bit + // H - Private bit + // I - Channel Mode + // J - Mode extension (Only if Joint stereo) + // K - Copyright + // L - Original + // M - Emphasis + + if (strlen($Header4Bytes) != 4) { + return false; + } + + $MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4; + $MPEGrawHeader['version'] = (ord($Header4Bytes{1}) & 0x18) >> 3; // BB + $MPEGrawHeader['layer'] = (ord($Header4Bytes{1}) & 0x06) >> 1; // CC + $MPEGrawHeader['protection'] = (ord($Header4Bytes{1}) & 0x01); // D + $MPEGrawHeader['bitrate'] = (ord($Header4Bytes{2}) & 0xF0) >> 4; // EEEE + $MPEGrawHeader['sample_rate'] = (ord($Header4Bytes{2}) & 0x0C) >> 2; // FF + $MPEGrawHeader['padding'] = (ord($Header4Bytes{2}) & 0x02) >> 1; // G + $MPEGrawHeader['private'] = (ord($Header4Bytes{2}) & 0x01); // H + $MPEGrawHeader['channelmode'] = (ord($Header4Bytes{3}) & 0xC0) >> 6; // II + $MPEGrawHeader['modeextension'] = (ord($Header4Bytes{3}) & 0x30) >> 4; // JJ + $MPEGrawHeader['copyright'] = (ord($Header4Bytes{3}) & 0x08) >> 3; // K + $MPEGrawHeader['original'] = (ord($Header4Bytes{3}) & 0x04) >> 2; // L + $MPEGrawHeader['emphasis'] = (ord($Header4Bytes{3}) & 0x03); // MM + + return $MPEGrawHeader; + } + + public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) { + static $AudioFrameLengthCache = array(); + + if (!isset($AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate])) { + $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = false; + if ($bitrate != 'free') { + + if ($version == '1') { + + if ($layer == '1') { + + // For Layer I slot is 32 bits long + $FrameLengthCoefficient = 48; + $SlotLength = 4; + + } else { // Layer 2 / 3 + + // for Layer 2 and Layer 3 slot is 8 bits long. + $FrameLengthCoefficient = 144; + $SlotLength = 1; + + } + + } else { // MPEG-2 / MPEG-2.5 + + if ($layer == '1') { + + // For Layer I slot is 32 bits long + $FrameLengthCoefficient = 24; + $SlotLength = 4; + + } elseif ($layer == '2') { + + // for Layer 2 and Layer 3 slot is 8 bits long. + $FrameLengthCoefficient = 144; + $SlotLength = 1; + + } else { // layer 3 + + // for Layer 2 and Layer 3 slot is 8 bits long. + $FrameLengthCoefficient = 72; + $SlotLength = 1; + + } + + } + + // FrameLengthInBytes = ((Coefficient * BitRate) / SampleRate) + Padding + if ($samplerate > 0) { + $NewFramelength = ($FrameLengthCoefficient * $bitrate) / $samplerate; + $NewFramelength = floor($NewFramelength / $SlotLength) * $SlotLength; // round to next-lower multiple of SlotLength (1 byte for Layer 2/3, 4 bytes for Layer I) + if ($padding) { + $NewFramelength += $SlotLength; + } + $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = (int) $NewFramelength; + } + } + } + return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate]; + } + + public static function ClosestStandardMP3Bitrate($bit_rate) { + static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000); + static $bit_rate_table = array (0=>'-'); + $round_bit_rate = intval(round($bit_rate, -3)); + if (!isset($bit_rate_table[$round_bit_rate])) { + if ($round_bit_rate > max($standard_bit_rates)) { + $bit_rate_table[$round_bit_rate] = round($bit_rate, 2 - strlen($bit_rate)); + } else { + $bit_rate_table[$round_bit_rate] = max($standard_bit_rates); + foreach ($standard_bit_rates as $standard_bit_rate) { + if ($round_bit_rate >= $standard_bit_rate + (($bit_rate_table[$round_bit_rate] - $standard_bit_rate) / 2)) { + break; + } + $bit_rate_table[$round_bit_rate] = $standard_bit_rate; + } + } + } + return $bit_rate_table[$round_bit_rate]; + } + + public static function XingVBRidOffset($version, $channelmode) { + static $XingVBRidOffsetCache = array(); + if (empty($XingVBRidOffset)) { + $XingVBRidOffset = array ( + '1' => array ('mono' => 0x15, // 4 + 17 = 21 + 'stereo' => 0x24, // 4 + 32 = 36 + 'joint stereo' => 0x24, + 'dual channel' => 0x24 + ), + + '2' => array ('mono' => 0x0D, // 4 + 9 = 13 + 'stereo' => 0x15, // 4 + 17 = 21 + 'joint stereo' => 0x15, + 'dual channel' => 0x15 + ), + + '2.5' => array ('mono' => 0x15, + 'stereo' => 0x15, + 'joint stereo' => 0x15, + 'dual channel' => 0x15 + ) + ); + } + return $XingVBRidOffset[$version][$channelmode]; + } + + public static function LAMEvbrMethodLookup($VBRmethodID) { + static $LAMEvbrMethodLookup = array( + 0x00 => 'unknown', + 0x01 => 'cbr', + 0x02 => 'abr', + 0x03 => 'vbr-old / vbr-rh', + 0x04 => 'vbr-new / vbr-mtrh', + 0x05 => 'vbr-mt', + 0x06 => 'vbr (full vbr method 4)', + 0x08 => 'cbr (constant bitrate 2 pass)', + 0x09 => 'abr (2 pass)', + 0x0F => 'reserved' + ); + return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : ''); + } + + public static function LAMEmiscStereoModeLookup($StereoModeID) { + static $LAMEmiscStereoModeLookup = array( + 0 => 'mono', + 1 => 'stereo', + 2 => 'dual mono', + 3 => 'joint stereo', + 4 => 'forced stereo', + 5 => 'auto', + 6 => 'intensity stereo', + 7 => 'other' + ); + return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : ''); + } + + public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) { + static $LAMEmiscSourceSampleFrequencyLookup = array( + 0 => '<= 32 kHz', + 1 => '44.1 kHz', + 2 => '48 kHz', + 3 => '> 48kHz' + ); + return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : ''); + } + + public static function LAMEsurroundInfoLookup($SurroundInfoID) { + static $LAMEsurroundInfoLookup = array( + 0 => 'no surround info', + 1 => 'DPL encoding', + 2 => 'DPL2 encoding', + 3 => 'Ambisonic encoding' + ); + return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved'); + } + + public static function LAMEpresetUsedLookup($LAMEtag) { + + if ($LAMEtag['preset_used_id'] == 0) { + // no preset used (LAME >=3.93) + // no preset recorded (LAME <3.93) + return ''; + } + $LAMEpresetUsedLookup = array(); + + ///// THIS PART CANNOT BE STATIC . + for ($i = 8; $i <= 320; $i++) { + switch ($LAMEtag['vbr_method']) { + case 'cbr': + $LAMEpresetUsedLookup[$i] = '--alt-preset '.$LAMEtag['vbr_method'].' '.$i; + break; + case 'abr': + default: // other VBR modes shouldn't be here(?) + $LAMEpresetUsedLookup[$i] = '--alt-preset '.$i; + break; + } + } + + // named old-style presets (studio, phone, voice, etc) are handled in GuessEncoderOptions() + + // named alt-presets + $LAMEpresetUsedLookup[1000] = '--r3mix'; + $LAMEpresetUsedLookup[1001] = '--alt-preset standard'; + $LAMEpresetUsedLookup[1002] = '--alt-preset extreme'; + $LAMEpresetUsedLookup[1003] = '--alt-preset insane'; + $LAMEpresetUsedLookup[1004] = '--alt-preset fast standard'; + $LAMEpresetUsedLookup[1005] = '--alt-preset fast extreme'; + $LAMEpresetUsedLookup[1006] = '--alt-preset medium'; + $LAMEpresetUsedLookup[1007] = '--alt-preset fast medium'; + + // LAME 3.94 additions/changes + $LAMEpresetUsedLookup[1010] = '--preset portable'; // 3.94a15 Oct 21 2003 + $LAMEpresetUsedLookup[1015] = '--preset radio'; // 3.94a15 Oct 21 2003 + + $LAMEpresetUsedLookup[320] = '--preset insane'; // 3.94a15 Nov 12 2003 + $LAMEpresetUsedLookup[410] = '-V9'; + $LAMEpresetUsedLookup[420] = '-V8'; + $LAMEpresetUsedLookup[440] = '-V6'; + $LAMEpresetUsedLookup[430] = '--preset radio'; // 3.94a15 Nov 12 2003 + $LAMEpresetUsedLookup[450] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'portable'; // 3.94a15 Nov 12 2003 + $LAMEpresetUsedLookup[460] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'medium'; // 3.94a15 Nov 12 2003 + $LAMEpresetUsedLookup[470] = '--r3mix'; // 3.94b1 Dec 18 2003 + $LAMEpresetUsedLookup[480] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'standard'; // 3.94a15 Nov 12 2003 + $LAMEpresetUsedLookup[490] = '-V1'; + $LAMEpresetUsedLookup[500] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'extreme'; // 3.94a15 Nov 12 2003 + + return (isset($LAMEpresetUsedLookup[$LAMEtag['preset_used_id']]) ? $LAMEpresetUsedLookup[$LAMEtag['preset_used_id']] : 'new/unknown preset: '.$LAMEtag['preset_used_id'].' - report to info@getid3.org'); + } + +} diff --git a/sources/wp-includes/ID3/module.audio.ogg.php b/sources/wp-includes/ID3/module.audio.ogg.php new file mode 100644 index 0000000..a2a35aa --- /dev/null +++ b/sources/wp-includes/ID3/module.audio.ogg.php @@ -0,0 +1,671 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio.ogg.php // +// module for analyzing Ogg Vorbis, OggFLAC and Speex files // +// dependencies: module.audio.flac.php // +// /// +///////////////////////////////////////////////////////////////// + +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE__, true); + +class getid3_ogg extends getid3_handler +{ + // http://xiph.org/vorbis/doc/Vorbis_I_spec.html + public function Analyze() { + $info = &$this->getid3->info; + + $info['fileformat'] = 'ogg'; + + // Warn about illegal tags - only vorbiscomments are allowed + if (isset($info['id3v2'])) { + $info['warning'][] = 'Illegal ID3v2 tag present.'; + } + if (isset($info['id3v1'])) { + $info['warning'][] = 'Illegal ID3v1 tag present.'; + } + if (isset($info['ape'])) { + $info['warning'][] = 'Illegal APE tag present.'; + } + + + // Page 1 - Stream Header + + $this->fseek($info['avdataoffset']); + + $oggpageinfo = $this->ParseOggPageHeader(); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; + + if ($this->ftell() >= $this->getid3->fread_buffer_size()) { + $info['error'][] = 'Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)'; + unset($info['fileformat']); + unset($info['ogg']); + return false; + } + + $filedata = $this->fread($oggpageinfo['page_length']); + $filedataoffset = 0; + + if (substr($filedata, 0, 4) == 'fLaC') { + + $info['audio']['dataformat'] = 'flac'; + $info['audio']['bitrate_mode'] = 'vbr'; + $info['audio']['lossless'] = true; + + } elseif (substr($filedata, 1, 6) == 'vorbis') { + + $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo); + + } elseif (substr($filedata, 0, 8) == 'Speex ') { + + // http://www.speex.org/manual/node10.html + + $info['audio']['dataformat'] = 'speex'; + $info['mime_type'] = 'audio/speex'; + $info['audio']['bitrate_mode'] = 'abr'; + $info['audio']['lossless'] = false; + + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_string'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'Speex ' + $filedataoffset += 8; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version'] = substr($filedata, $filedataoffset, 20); + $filedataoffset += 20; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version_id'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['header_size'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode_bitstream_version'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['bitrate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['framesize'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['frames_per_packet'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['extra_headers'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved1'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['reserved2'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + + $info['speex']['speex_version'] = trim($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['speex_version']); + $info['speex']['sample_rate'] = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['rate']; + $info['speex']['channels'] = $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['nb_channels']; + $info['speex']['vbr'] = (bool) $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['vbr']; + $info['speex']['band_type'] = $this->SpeexBandModeLookup($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['mode']); + + $info['audio']['sample_rate'] = $info['speex']['sample_rate']; + $info['audio']['channels'] = $info['speex']['channels']; + if ($info['speex']['vbr']) { + $info['audio']['bitrate_mode'] = 'vbr'; + } + + + } elseif (substr($filedata, 0, 8) == "fishead\x00") { + + // Ogg Skeleton version 3.0 Format Specification + // http://xiph.org/ogg/doc/skeleton.html + $filedataoffset += 8; + $info['ogg']['skeleton']['fishead']['raw']['version_major'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2)); + $filedataoffset += 2; + $info['ogg']['skeleton']['fishead']['raw']['version_minor'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2)); + $filedataoffset += 2; + $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fishead']['raw']['utc'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 20)); + $filedataoffset += 20; + + $info['ogg']['skeleton']['fishead']['version'] = $info['ogg']['skeleton']['fishead']['raw']['version_major'].'.'.$info['ogg']['skeleton']['fishead']['raw']['version_minor']; + $info['ogg']['skeleton']['fishead']['presentationtime'] = $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator']; + $info['ogg']['skeleton']['fishead']['basetime'] = $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator']; + $info['ogg']['skeleton']['fishead']['utc'] = $info['ogg']['skeleton']['fishead']['raw']['utc']; + + + $counter = 0; + do { + $oggpageinfo = $this->ParseOggPageHeader(); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno'].'.'.$counter++] = $oggpageinfo; + $filedata = $this->fread($oggpageinfo['page_length']); + $this->fseek($oggpageinfo['page_end_offset']); + + if (substr($filedata, 0, 8) == "fisbone\x00") { + + $filedataoffset = 8; + $info['ogg']['skeleton']['fisbone']['raw']['message_header_offset'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['skeleton']['fisbone']['raw']['serial_number'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['skeleton']['fisbone']['raw']['number_header_packets'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['skeleton']['fisbone']['raw']['granulerate_numerator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fisbone']['raw']['granulerate_denominator'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fisbone']['raw']['basegranule'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $info['ogg']['skeleton']['fisbone']['raw']['preroll'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['skeleton']['fisbone']['raw']['granuleshift'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['skeleton']['fisbone']['raw']['padding'] = substr($filedata, $filedataoffset, 3); + $filedataoffset += 3; + + } elseif (substr($filedata, 1, 6) == 'theora') { + + $info['video']['dataformat'] = 'theora'; + $info['error'][] = 'Ogg Theora not correctly handled in this version of getID3 ['.$this->getid3->version().']'; + //break; + + } elseif (substr($filedata, 1, 6) == 'vorbis') { + + $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo); + + } else { + $info['error'][] = 'unexpected'; + //break; + } + //} while ($oggpageinfo['page_seqno'] == 0); + } while (($oggpageinfo['page_seqno'] == 0) && (substr($filedata, 0, 8) != "fisbone\x00")); + + $this->fseek($oggpageinfo['page_start_offset']); + + $info['error'][] = 'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']'; + //return false; + + } else { + + $info['error'][] = 'Expecting either "Speex " or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"'; + unset($info['ogg']); + unset($info['mime_type']); + return false; + + } + + // Page 2 - Comment Header + $oggpageinfo = $this->ParseOggPageHeader(); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; + + switch ($info['audio']['dataformat']) { + case 'vorbis': + $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, 0, 1)); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 1, 6); // hard-coded to 'vorbis' + + $this->ParseVorbisComments(); + break; + + case 'flac': + $flac = new getid3_flac($this->getid3); + if (!$flac->parseMETAdata()) { + $info['error'][] = 'Failed to parse FLAC headers'; + return false; + } + unset($flac); + break; + + case 'speex': + $this->fseek($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length'], SEEK_CUR); + $this->ParseVorbisComments(); + break; + } + + + // Last Page - Number of Samples + if (!getid3_lib::intValueSupported($info['avdataend'])) { + + $info['warning'][] = 'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)'; + + } else { + + $this->fseek(max($info['avdataend'] - $this->getid3->fread_buffer_size(), 0)); + $LastChunkOfOgg = strrev($this->fread($this->getid3->fread_buffer_size())); + if ($LastOggSpostion = strpos($LastChunkOfOgg, 'SggO')) { + $this->fseek($info['avdataend'] - ($LastOggSpostion + strlen('SggO'))); + $info['avdataend'] = $this->ftell(); + $info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader(); + $info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position']; + if ($info['ogg']['samples'] == 0) { + $info['error'][] = 'Corrupt Ogg file: eos.number of samples == zero'; + return false; + } + if (!empty($info['audio']['sample_rate'])) { + $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']); + } + } + + } + + if (!empty($info['ogg']['bitrate_average'])) { + $info['audio']['bitrate'] = $info['ogg']['bitrate_average']; + } elseif (!empty($info['ogg']['bitrate_nominal'])) { + $info['audio']['bitrate'] = $info['ogg']['bitrate_nominal']; + } elseif (!empty($info['ogg']['bitrate_min']) && !empty($info['ogg']['bitrate_max'])) { + $info['audio']['bitrate'] = ($info['ogg']['bitrate_min'] + $info['ogg']['bitrate_max']) / 2; + } + if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) { + if ($info['audio']['bitrate'] == 0) { + $info['error'][] = 'Corrupt Ogg file: bitrate_audio == zero'; + return false; + } + $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']); + } + + if (isset($info['ogg']['vendor'])) { + $info['audio']['encoder'] = preg_replace('/^Encoded with /', '', $info['ogg']['vendor']); + + // Vorbis only + if ($info['audio']['dataformat'] == 'vorbis') { + + // Vorbis 1.0 starts with Xiph.Org + if (preg_match('/^Xiph.Org/', $info['audio']['encoder'])) { + + if ($info['audio']['bitrate_mode'] == 'abr') { + + // Set -b 128 on abr files + $info['audio']['encoder_options'] = '-b '.round($info['ogg']['bitrate_nominal'] / 1000); + + } elseif (($info['audio']['bitrate_mode'] == 'vbr') && ($info['audio']['channels'] == 2) && ($info['audio']['sample_rate'] >= 44100) && ($info['audio']['sample_rate'] <= 48000)) { + // Set -q N on vbr files + $info['audio']['encoder_options'] = '-q '.$this->get_quality_from_nominal_bitrate($info['ogg']['bitrate_nominal']); + + } + } + + if (empty($info['audio']['encoder_options']) && !empty($info['ogg']['bitrate_nominal'])) { + $info['audio']['encoder_options'] = 'Nominal bitrate: '.intval(round($info['ogg']['bitrate_nominal'] / 1000)).'kbps'; + } + } + } + + return true; + } + + public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) { + $info = &$this->getid3->info; + $info['audio']['dataformat'] = 'vorbis'; + $info['audio']['lossless'] = false; + + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['packet_type'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, $filedataoffset, 6); // hard-coded to 'vorbis' + $filedataoffset += 6; + $info['ogg']['bitstreamversion'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['numberofchannels'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['audio']['channels'] = $info['ogg']['numberofchannels']; + $info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + if ($info['ogg']['samplerate'] == 0) { + $info['error'][] = 'Corrupt Ogg file: sample rate == zero'; + return false; + } + $info['audio']['sample_rate'] = $info['ogg']['samplerate']; + $info['ogg']['samples'] = 0; // filled in later + $info['ogg']['bitrate_average'] = 0; // filled in later + $info['ogg']['bitrate_max'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['bitrate_nominal'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['bitrate_min'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['blocksize_small'] = pow(2, getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0x0F); + $info['ogg']['blocksize_large'] = pow(2, (getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)) & 0xF0) >> 4); + $info['ogg']['stop_bit'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); // must be 1, marks end of packet + + $info['audio']['bitrate_mode'] = 'vbr'; // overridden if actually abr + if ($info['ogg']['bitrate_max'] == 0xFFFFFFFF) { + unset($info['ogg']['bitrate_max']); + $info['audio']['bitrate_mode'] = 'abr'; + } + if ($info['ogg']['bitrate_nominal'] == 0xFFFFFFFF) { + unset($info['ogg']['bitrate_nominal']); + } + if ($info['ogg']['bitrate_min'] == 0xFFFFFFFF) { + unset($info['ogg']['bitrate_min']); + $info['audio']['bitrate_mode'] = 'abr'; + } + return true; + } + + public function ParseOggPageHeader() { + // http://xiph.org/ogg/vorbis/doc/framing.html + $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file + + $filedata = $this->fread($this->getid3->fread_buffer_size()); + $filedataoffset = 0; + while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) { + if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) { + // should be found before here + return false; + } + if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) { + if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) { + // get some more data, unless eof, in which case fail + return false; + } + } + } + $filedataoffset += strlen('OggS') - 1; // page, delimited by 'OggS' + + $oggheader['stream_structver'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $oggheader['flags_raw'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $oggheader['flags']['fresh'] = (bool) ($oggheader['flags_raw'] & 0x01); // fresh packet + $oggheader['flags']['bos'] = (bool) ($oggheader['flags_raw'] & 0x02); // first page of logical bitstream (bos) + $oggheader['flags']['eos'] = (bool) ($oggheader['flags_raw'] & 0x04); // last page of logical bitstream (eos) + + $oggheader['pcm_abs_position'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 8)); + $filedataoffset += 8; + $oggheader['stream_serialno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $oggheader['page_seqno'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $oggheader['page_checksum'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $oggheader['page_segments'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $oggheader['page_length'] = 0; + for ($i = 0; $i < $oggheader['page_segments']; $i++) { + $oggheader['segment_table'][$i] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $oggheader['page_length'] += $oggheader['segment_table'][$i]; + } + $oggheader['header_end_offset'] = $oggheader['page_start_offset'] + $filedataoffset; + $oggheader['page_end_offset'] = $oggheader['header_end_offset'] + $oggheader['page_length']; + $this->fseek($oggheader['header_end_offset']); + + return $oggheader; + } + + // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005 + public function ParseVorbisComments() { + $info = &$this->getid3->info; + + $OriginalOffset = $this->ftell(); + $commentdataoffset = 0; + $VorbisCommentPage = 1; + + switch ($info['audio']['dataformat']) { + case 'vorbis': + case 'speex': + $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset']; // Second Ogg page, after header block + $this->fseek($CommentStartOffset); + $commentdataoffset = 27 + $info['ogg']['pageheader'][$VorbisCommentPage]['page_segments']; + $commentdata = $this->fread(self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1) + $commentdataoffset); + + if ($info['audio']['dataformat'] == 'vorbis') { + $commentdataoffset += (strlen('vorbis') + 1); + } + break; + + case 'flac': + $CommentStartOffset = $info['flac']['VORBIS_COMMENT']['raw']['offset'] + 4; + $this->fseek($CommentStartOffset); + $commentdata = $this->fread($info['flac']['VORBIS_COMMENT']['raw']['block_length']); + break; + + default: + return false; + } + + $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4)); + $commentdataoffset += 4; + + $info['ogg']['vendor'] = substr($commentdata, $commentdataoffset, $VendorSize); + $commentdataoffset += $VendorSize; + + $CommentsCount = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4)); + $commentdataoffset += 4; + $info['avdataoffset'] = $CommentStartOffset + $commentdataoffset; + + $basicfields = array('TITLE', 'ARTIST', 'ALBUM', 'TRACKNUMBER', 'GENRE', 'DATE', 'DESCRIPTION', 'COMMENT'); + $ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw']; + for ($i = 0; $i < $CommentsCount; $i++) { + + $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset; + + if ($this->ftell() < ($ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + 4)) { + if ($oggpageinfo = $this->ParseOggPageHeader()) { + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; + + $VorbisCommentPage++; + + // First, save what we haven't read yet + $AsYetUnusedData = substr($commentdata, $commentdataoffset); + + // Then take that data off the end + $commentdata = substr($commentdata, 0, $commentdataoffset); + + // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct + $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); + $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); + + // Finally, stick the unused data back on the end + $commentdata .= $AsYetUnusedData; + + //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); + $commentdata .= $this->fread($this->OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1)); + } + + } + $ThisFileInfo_ogg_comments_raw[$i]['size'] = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4)); + + // replace avdataoffset with position just after the last vorbiscomment + $info['avdataoffset'] = $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] + $ThisFileInfo_ogg_comments_raw[$i]['size'] + 4; + + $commentdataoffset += 4; + while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) { + if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) { + $info['warning'][] = 'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments'; + break 2; + } + + $VorbisCommentPage++; + + $oggpageinfo = $this->ParseOggPageHeader(); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; + + // First, save what we haven't read yet + $AsYetUnusedData = substr($commentdata, $commentdataoffset); + + // Then take that data off the end + $commentdata = substr($commentdata, 0, $commentdataoffset); + + // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct + $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); + $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); + + // Finally, stick the unused data back on the end + $commentdata .= $AsYetUnusedData; + + //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); + if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { + $info['warning'][] = 'undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell(); + break; + } + $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); + if ($readlength <= 0) { + $info['warning'][] = 'invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell(); + break; + } + $commentdata .= $this->fread($readlength); + + //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; + } + $ThisFileInfo_ogg_comments_raw[$i]['offset'] = $commentdataoffset; + $commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo_ogg_comments_raw[$i]['size']); + $commentdataoffset += $ThisFileInfo_ogg_comments_raw[$i]['size']; + + if (!$commentstring) { + + // no comment? + $info['warning'][] = 'Blank Ogg comment ['.$i.']'; + + } elseif (strstr($commentstring, '=')) { + + $commentexploded = explode('=', $commentstring, 2); + $ThisFileInfo_ogg_comments_raw[$i]['key'] = strtoupper($commentexploded[0]); + $ThisFileInfo_ogg_comments_raw[$i]['value'] = (isset($commentexploded[1]) ? $commentexploded[1] : ''); + + if ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'METADATA_BLOCK_PICTURE') { + + // http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE + // The unencoded format is that of the FLAC picture block. The fields are stored in big endian order as in FLAC, picture data is stored according to the relevant standard. + // http://flac.sourceforge.net/format.html#metadata_block_picture + $flac = new getid3_flac($this->getid3); + $flac->setStringMode(base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value'])); + $flac->parsePICTURE(); + $info['ogg']['comments']['picture'][] = $flac->getid3->info['flac']['PICTURE'][0]; + unset($flac); + + } elseif ($ThisFileInfo_ogg_comments_raw[$i]['key'] == 'COVERART') { + + $data = base64_decode($ThisFileInfo_ogg_comments_raw[$i]['value']); + $this->notice('Found deprecated COVERART tag, it should be replaced in honor of METADATA_BLOCK_PICTURE structure'); + /** @todo use 'coverartmime' where available */ + $imageinfo = getid3_lib::GetDataImageSize($data); + if ($imageinfo === false || !isset($imageinfo['mime'])) { + $this->warning('COVERART vorbiscomment tag contains invalid image'); + continue; + } + + $ogg = new self($this->getid3); + $ogg->setStringMode($data); + $info['ogg']['comments']['picture'][] = array( + 'image_mime' => $imageinfo['mime'], + 'data' => $ogg->saveAttachment('coverart', 0, strlen($data), $imageinfo['mime']), + ); + unset($ogg); + + } else { + + $info['ogg']['comments'][strtolower($ThisFileInfo_ogg_comments_raw[$i]['key'])][] = $ThisFileInfo_ogg_comments_raw[$i]['value']; + + } + + } else { + + $info['warning'][] = '[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring; + + } + unset($ThisFileInfo_ogg_comments_raw[$i]); + } + unset($ThisFileInfo_ogg_comments_raw); + + + // Replay Gain Adjustment + // http://privatewww.essex.ac.uk/~djmrob/replaygain/ + if (isset($info['ogg']['comments']) && is_array($info['ogg']['comments'])) { + foreach ($info['ogg']['comments'] as $index => $commentvalue) { + switch ($index) { + case 'rg_audiophile': + case 'replaygain_album_gain': + $info['replay_gain']['album']['adjustment'] = (double) $commentvalue[0]; + unset($info['ogg']['comments'][$index]); + break; + + case 'rg_radio': + case 'replaygain_track_gain': + $info['replay_gain']['track']['adjustment'] = (double) $commentvalue[0]; + unset($info['ogg']['comments'][$index]); + break; + + case 'replaygain_album_peak': + $info['replay_gain']['album']['peak'] = (double) $commentvalue[0]; + unset($info['ogg']['comments'][$index]); + break; + + case 'rg_peak': + case 'replaygain_track_peak': + $info['replay_gain']['track']['peak'] = (double) $commentvalue[0]; + unset($info['ogg']['comments'][$index]); + break; + + case 'replaygain_reference_loudness': + $info['replay_gain']['reference_volume'] = (double) $commentvalue[0]; + unset($info['ogg']['comments'][$index]); + break; + + default: + // do nothing + break; + } + } + } + + $this->fseek($OriginalOffset); + + return true; + } + + public static function SpeexBandModeLookup($mode) { + static $SpeexBandModeLookup = array(); + if (empty($SpeexBandModeLookup)) { + $SpeexBandModeLookup[0] = 'narrow'; + $SpeexBandModeLookup[1] = 'wide'; + $SpeexBandModeLookup[2] = 'ultra-wide'; + } + return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null); + } + + + public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) { + for ($i = 0; $i < $SegmentNumber; $i++) { + $segmentlength = 0; + foreach ($OggInfoArray['segment_table'] as $key => $value) { + $segmentlength += $value; + if ($value < 255) { + break; + } + } + } + return $segmentlength; + } + + + public static function get_quality_from_nominal_bitrate($nominal_bitrate) { + + // decrease precision + $nominal_bitrate = $nominal_bitrate / 1000; + + if ($nominal_bitrate < 128) { + // q-1 to q4 + $qval = ($nominal_bitrate - 64) / 16; + } elseif ($nominal_bitrate < 256) { + // q4 to q8 + $qval = $nominal_bitrate / 32; + } elseif ($nominal_bitrate < 320) { + // q8 to q9 + $qval = ($nominal_bitrate + 256) / 64; + } else { + // q9 to q10 + $qval = ($nominal_bitrate + 1300) / 180; + } + //return $qval; // 5.031324 + //return intval($qval); // 5 + return round($qval, 1); // 5 or 4.9 + } + +} diff --git a/sources/wp-includes/ID3/module.tag.apetag.php b/sources/wp-includes/ID3/module.tag.apetag.php new file mode 100644 index 0000000..afeede7 --- /dev/null +++ b/sources/wp-includes/ID3/module.tag.apetag.php @@ -0,0 +1,370 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.tag.apetag.php // +// module for analyzing APE tags // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + +class getid3_apetag extends getid3_handler +{ + public $inline_attachments = true; // true: return full data for all attachments; false: return no data for all attachments; integer: return data for attachments <= than this; string: save as file to this directory + public $overrideendoffset = 0; + + public function Analyze() { + $info = &$this->getid3->info; + + if (!getid3_lib::intValueSupported($info['filesize'])) { + $info['warning'][] = 'Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; + return false; + } + + $id3v1tagsize = 128; + $apetagheadersize = 32; + $lyrics3tagsize = 10; + + if ($this->overrideendoffset == 0) { + + fseek($this->getid3->fp, 0 - $id3v1tagsize - $apetagheadersize - $lyrics3tagsize, SEEK_END); + $APEfooterID3v1 = fread($this->getid3->fp, $id3v1tagsize + $apetagheadersize + $lyrics3tagsize); + + //if (preg_match('/APETAGEX.{24}TAG.{125}$/i', $APEfooterID3v1)) { + if (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $id3v1tagsize - $apetagheadersize, 8) == 'APETAGEX') { + + // APE tag found before ID3v1 + $info['ape']['tag_offset_end'] = $info['filesize'] - $id3v1tagsize; + + //} elseif (preg_match('/APETAGEX.{24}$/i', $APEfooterID3v1)) { + } elseif (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $apetagheadersize, 8) == 'APETAGEX') { + + // APE tag found, no ID3v1 + $info['ape']['tag_offset_end'] = $info['filesize']; + + } + + } else { + + fseek($this->getid3->fp, $this->overrideendoffset - $apetagheadersize, SEEK_SET); + if (fread($this->getid3->fp, 8) == 'APETAGEX') { + $info['ape']['tag_offset_end'] = $this->overrideendoffset; + } + + } + if (!isset($info['ape']['tag_offset_end'])) { + + // APE tag not found + unset($info['ape']); + return false; + + } + + // shortcut + $thisfile_ape = &$info['ape']; + + fseek($this->getid3->fp, $thisfile_ape['tag_offset_end'] - $apetagheadersize, SEEK_SET); + $APEfooterData = fread($this->getid3->fp, 32); + if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) { + $info['error'][] = 'Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end']; + return false; + } + + if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) { + fseek($this->getid3->fp, $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'] - $apetagheadersize, SEEK_SET); + $thisfile_ape['tag_offset_start'] = ftell($this->getid3->fp); + $APEtagData = fread($this->getid3->fp, $thisfile_ape['footer']['raw']['tagsize'] + $apetagheadersize); + } else { + $thisfile_ape['tag_offset_start'] = $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize']; + fseek($this->getid3->fp, $thisfile_ape['tag_offset_start'], SEEK_SET); + $APEtagData = fread($this->getid3->fp, $thisfile_ape['footer']['raw']['tagsize']); + } + $info['avdataend'] = $thisfile_ape['tag_offset_start']; + + if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) { + $info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in APEtag data'; + unset($info['id3v1']); + foreach ($info['warning'] as $key => $value) { + if ($value == 'Some ID3v1 fields do not use NULL characters for padding') { + unset($info['warning'][$key]); + sort($info['warning']); + break; + } + } + } + + $offset = 0; + if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) { + if ($thisfile_ape['header'] = $this->parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize))) { + $offset += $apetagheadersize; + } else { + $info['error'][] = 'Error parsing APE header at offset '.$thisfile_ape['tag_offset_start']; + return false; + } + } + + // shortcut + $info['replay_gain'] = array(); + $thisfile_replaygain = &$info['replay_gain']; + + for ($i = 0; $i < $thisfile_ape['footer']['raw']['tag_items']; $i++) { + $value_size = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4)); + $offset += 4; + $item_flags = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4)); + $offset += 4; + if (strstr(substr($APEtagData, $offset), "\x00") === false) { + $info['error'][] = 'Cannot find null-byte (0x00) seperator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset); + return false; + } + $ItemKeyLength = strpos($APEtagData, "\x00", $offset) - $offset; + $item_key = strtolower(substr($APEtagData, $offset, $ItemKeyLength)); + + // shortcut + $thisfile_ape['items'][$item_key] = array(); + $thisfile_ape_items_current = &$thisfile_ape['items'][$item_key]; + + $thisfile_ape_items_current['offset'] = $thisfile_ape['tag_offset_start'] + $offset; + + $offset += ($ItemKeyLength + 1); // skip 0x00 terminator + $thisfile_ape_items_current['data'] = substr($APEtagData, $offset, $value_size); + $offset += $value_size; + + $thisfile_ape_items_current['flags'] = $this->parseAPEtagFlags($item_flags); + switch ($thisfile_ape_items_current['flags']['item_contents_raw']) { + case 0: // UTF-8 + case 3: // Locator (URL, filename, etc), UTF-8 encoded + $thisfile_ape_items_current['data'] = explode("\x00", trim($thisfile_ape_items_current['data'])); + break; + + default: // binary data + break; + } + + switch (strtolower($item_key)) { + case 'replaygain_track_gain': + $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero! + $thisfile_replaygain['track']['originator'] = 'unspecified'; + break; + + case 'replaygain_track_peak': + $thisfile_replaygain['track']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero! + $thisfile_replaygain['track']['originator'] = 'unspecified'; + if ($thisfile_replaygain['track']['peak'] <= 0) { + $info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")'; + } + break; + + case 'replaygain_album_gain': + $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero! + $thisfile_replaygain['album']['originator'] = 'unspecified'; + break; + + case 'replaygain_album_peak': + $thisfile_replaygain['album']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero! + $thisfile_replaygain['album']['originator'] = 'unspecified'; + if ($thisfile_replaygain['album']['peak'] <= 0) { + $info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")'; + } + break; + + case 'mp3gain_undo': + list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $thisfile_ape_items_current['data'][0]); + $thisfile_replaygain['mp3gain']['undo_left'] = intval($mp3gain_undo_left); + $thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right); + $thisfile_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false); + break; + + case 'mp3gain_minmax': + list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $thisfile_ape_items_current['data'][0]); + $thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min); + $thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max); + break; + + case 'mp3gain_album_minmax': + list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $thisfile_ape_items_current['data'][0]); + $thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min); + $thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max); + break; + + case 'tracknumber': + if (is_array($thisfile_ape_items_current['data'])) { + foreach ($thisfile_ape_items_current['data'] as $comment) { + $thisfile_ape['comments']['track'][] = $comment; + } + } + break; + + case 'cover art (artist)': + case 'cover art (back)': + case 'cover art (band logo)': + case 'cover art (band)': + case 'cover art (colored fish)': + case 'cover art (composer)': + case 'cover art (conductor)': + case 'cover art (front)': + case 'cover art (icon)': + case 'cover art (illustration)': + case 'cover art (lead)': + case 'cover art (leaflet)': + case 'cover art (lyricist)': + case 'cover art (media)': + case 'cover art (movie scene)': + case 'cover art (other icon)': + case 'cover art (other)': + case 'cover art (performance)': + case 'cover art (publisher logo)': + case 'cover art (recording)': + case 'cover art (studio)': + // list of possible cover arts from http://taglib-sharp.sourcearchive.com/documentation/2.0.3.0-2/Ape_2Tag_8cs-source.html + list($thisfile_ape_items_current['filename'], $thisfile_ape_items_current['data']) = explode("\x00", $thisfile_ape_items_current['data'], 2); + $thisfile_ape_items_current['data_offset'] = $thisfile_ape_items_current['offset'] + strlen($thisfile_ape_items_current['filename']."\x00"); + $thisfile_ape_items_current['data_length'] = strlen($thisfile_ape_items_current['data']); + + $thisfile_ape_items_current['image_mime'] = ''; + $imageinfo = array(); + $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo); + $thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]); + + do { + if ($this->inline_attachments === false) { + // skip entirely + unset($thisfile_ape_items_current['data']); + break; + } + if ($this->inline_attachments === true) { + // great + } elseif (is_int($this->inline_attachments)) { + if ($this->inline_attachments < $thisfile_ape_items_current['data_length']) { + // too big, skip + $info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)'; + unset($thisfile_ape_items_current['data']); + break; + } + } elseif (is_string($this->inline_attachments)) { + $this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR); + if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) { + // cannot write, skip + $info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)'; + unset($thisfile_ape_items_current['data']); + break; + } + } + // if we get this far, must be OK + if (is_string($this->inline_attachments)) { + $destination_filename = $this->inline_attachments.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$thisfile_ape_items_current['data_offset']; + if (!file_exists($destination_filename) || is_writable($destination_filename)) { + file_put_contents($destination_filename, $thisfile_ape_items_current['data']); + } else { + $info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)'; + } + $thisfile_ape_items_current['data_filename'] = $destination_filename; + unset($thisfile_ape_items_current['data']); + } else { + if (!isset($info['ape']['comments']['picture'])) { + $info['ape']['comments']['picture'] = array(); + } + $info['ape']['comments']['picture'][] = array('data'=>$thisfile_ape_items_current['data'], 'image_mime'=>$thisfile_ape_items_current['image_mime']); + } + } while (false); + break; + + default: + if (is_array($thisfile_ape_items_current['data'])) { + foreach ($thisfile_ape_items_current['data'] as $comment) { + $thisfile_ape['comments'][strtolower($item_key)][] = $comment; + } + } + break; + } + + } + if (empty($thisfile_replaygain)) { + unset($info['replay_gain']); + } + return true; + } + + public function parseAPEheaderFooter($APEheaderFooterData) { + // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html + + // shortcut + $headerfooterinfo['raw'] = array(); + $headerfooterinfo_raw = &$headerfooterinfo['raw']; + + $headerfooterinfo_raw['footer_tag'] = substr($APEheaderFooterData, 0, 8); + if ($headerfooterinfo_raw['footer_tag'] != 'APETAGEX') { + return false; + } + $headerfooterinfo_raw['version'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 8, 4)); + $headerfooterinfo_raw['tagsize'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 12, 4)); + $headerfooterinfo_raw['tag_items'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 16, 4)); + $headerfooterinfo_raw['global_flags'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 20, 4)); + $headerfooterinfo_raw['reserved'] = substr($APEheaderFooterData, 24, 8); + + $headerfooterinfo['tag_version'] = $headerfooterinfo_raw['version'] / 1000; + if ($headerfooterinfo['tag_version'] >= 2) { + $headerfooterinfo['flags'] = $this->parseAPEtagFlags($headerfooterinfo_raw['global_flags']); + } + return $headerfooterinfo; + } + + public function parseAPEtagFlags($rawflagint) { + // "Note: APE Tags 1.0 do not use any of the APE Tag flags. + // All are set to zero on creation and ignored on reading." + // http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html + $flags['header'] = (bool) ($rawflagint & 0x80000000); + $flags['footer'] = (bool) ($rawflagint & 0x40000000); + $flags['this_is_header'] = (bool) ($rawflagint & 0x20000000); + $flags['item_contents_raw'] = ($rawflagint & 0x00000006) >> 1; + $flags['read_only'] = (bool) ($rawflagint & 0x00000001); + + $flags['item_contents'] = $this->APEcontentTypeFlagLookup($flags['item_contents_raw']); + + return $flags; + } + + public function APEcontentTypeFlagLookup($contenttypeid) { + static $APEcontentTypeFlagLookup = array( + 0 => 'utf-8', + 1 => 'binary', + 2 => 'external', + 3 => 'reserved' + ); + return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid'); + } + + public function APEtagItemIsUTF8Lookup($itemkey) { + static $APEtagItemIsUTF8Lookup = array( + 'title', + 'subtitle', + 'artist', + 'album', + 'debut album', + 'publisher', + 'conductor', + 'track', + 'composer', + 'comment', + 'copyright', + 'publicationright', + 'file', + 'year', + 'record date', + 'record location', + 'genre', + 'media', + 'related', + 'isrc', + 'abstract', + 'language', + 'bibliography' + ); + return in_array(strtolower($itemkey), $APEtagItemIsUTF8Lookup); + } + +} diff --git a/sources/wp-includes/ID3/module.tag.id3v1.php b/sources/wp-includes/ID3/module.tag.id3v1.php new file mode 100644 index 0000000..fd9069e --- /dev/null +++ b/sources/wp-includes/ID3/module.tag.id3v1.php @@ -0,0 +1,359 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.tag.id3v1.php // +// module for analyzing ID3v1 tags // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_id3v1 extends getid3_handler +{ + + public function Analyze() { + $info = &$this->getid3->info; + + if (!getid3_lib::intValueSupported($info['filesize'])) { + $info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; + return false; + } + + fseek($this->getid3->fp, -256, SEEK_END); + $preid3v1 = fread($this->getid3->fp, 128); + $id3v1tag = fread($this->getid3->fp, 128); + + if (substr($id3v1tag, 0, 3) == 'TAG') { + + $info['avdataend'] = $info['filesize'] - 128; + + $ParsedID3v1['title'] = $this->cutfield(substr($id3v1tag, 3, 30)); + $ParsedID3v1['artist'] = $this->cutfield(substr($id3v1tag, 33, 30)); + $ParsedID3v1['album'] = $this->cutfield(substr($id3v1tag, 63, 30)); + $ParsedID3v1['year'] = $this->cutfield(substr($id3v1tag, 93, 4)); + $ParsedID3v1['comment'] = substr($id3v1tag, 97, 30); // can't remove nulls yet, track detection depends on them + $ParsedID3v1['genreid'] = ord(substr($id3v1tag, 127, 1)); + + // If second-last byte of comment field is null and last byte of comment field is non-null + // then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number + if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) { + $ParsedID3v1['track'] = ord(substr($ParsedID3v1['comment'], 29, 1)); + $ParsedID3v1['comment'] = substr($ParsedID3v1['comment'], 0, 28); + } + $ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']); + + $ParsedID3v1['genre'] = $this->LookupGenreName($ParsedID3v1['genreid']); + if (!empty($ParsedID3v1['genre'])) { + unset($ParsedID3v1['genreid']); + } + if (isset($ParsedID3v1['genre']) && (empty($ParsedID3v1['genre']) || ($ParsedID3v1['genre'] == 'Unknown'))) { + unset($ParsedID3v1['genre']); + } + + foreach ($ParsedID3v1 as $key => $value) { + $ParsedID3v1['comments'][$key][0] = $value; + } + + // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces + $GoodFormatID3v1tag = $this->GenerateID3v1Tag( + $ParsedID3v1['title'], + $ParsedID3v1['artist'], + $ParsedID3v1['album'], + $ParsedID3v1['year'], + (isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false), + $ParsedID3v1['comment'], + (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : '')); + $ParsedID3v1['padding_valid'] = true; + if ($id3v1tag !== $GoodFormatID3v1tag) { + $ParsedID3v1['padding_valid'] = false; + $info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding'; + } + + $ParsedID3v1['tag_offset_end'] = $info['filesize']; + $ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128; + + $info['id3v1'] = $ParsedID3v1; + } + + if (substr($preid3v1, 0, 3) == 'TAG') { + // The way iTunes handles tags is, well, brain-damaged. + // It completely ignores v1 if ID3v2 is present. + // This goes as far as adding a new v1 tag *even if there already is one* + + // A suspected double-ID3v1 tag has been detected, but it could be that + // the "TAG" identifier is a legitimate part of an APE or Lyrics3 tag + if (substr($preid3v1, 96, 8) == 'APETAGEX') { + // an APE tag footer was found before the last ID3v1, assume false "TAG" synch + } elseif (substr($preid3v1, 119, 6) == 'LYRICS') { + // a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch + } else { + // APE and Lyrics3 footers not found - assume double ID3v1 + $info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes'; + $info['avdataend'] -= 128; + } + } + + return true; + } + + public static function cutfield($str) { + return trim(substr($str, 0, strcspn($str, "\x00"))); + } + + public static function ArrayOfGenres($allowSCMPXextended=false) { + static $GenreLookup = array( + 0 => 'Blues', + 1 => 'Classic Rock', + 2 => 'Country', + 3 => 'Dance', + 4 => 'Disco', + 5 => 'Funk', + 6 => 'Grunge', + 7 => 'Hip-Hop', + 8 => 'Jazz', + 9 => 'Metal', + 10 => 'New Age', + 11 => 'Oldies', + 12 => 'Other', + 13 => 'Pop', + 14 => 'R&B', + 15 => 'Rap', + 16 => 'Reggae', + 17 => 'Rock', + 18 => 'Techno', + 19 => 'Industrial', + 20 => 'Alternative', + 21 => 'Ska', + 22 => 'Death Metal', + 23 => 'Pranks', + 24 => 'Soundtrack', + 25 => 'Euro-Techno', + 26 => 'Ambient', + 27 => 'Trip-Hop', + 28 => 'Vocal', + 29 => 'Jazz+Funk', + 30 => 'Fusion', + 31 => 'Trance', + 32 => 'Classical', + 33 => 'Instrumental', + 34 => 'Acid', + 35 => 'House', + 36 => 'Game', + 37 => 'Sound Clip', + 38 => 'Gospel', + 39 => 'Noise', + 40 => 'Alt. Rock', + 41 => 'Bass', + 42 => 'Soul', + 43 => 'Punk', + 44 => 'Space', + 45 => 'Meditative', + 46 => 'Instrumental Pop', + 47 => 'Instrumental Rock', + 48 => 'Ethnic', + 49 => 'Gothic', + 50 => 'Darkwave', + 51 => 'Techno-Industrial', + 52 => 'Electronic', + 53 => 'Pop-Folk', + 54 => 'Eurodance', + 55 => 'Dream', + 56 => 'Southern Rock', + 57 => 'Comedy', + 58 => 'Cult', + 59 => 'Gangsta Rap', + 60 => 'Top 40', + 61 => 'Christian Rap', + 62 => 'Pop/Funk', + 63 => 'Jungle', + 64 => 'Native American', + 65 => 'Cabaret', + 66 => 'New Wave', + 67 => 'Psychedelic', + 68 => 'Rave', + 69 => 'Showtunes', + 70 => 'Trailer', + 71 => 'Lo-Fi', + 72 => 'Tribal', + 73 => 'Acid Punk', + 74 => 'Acid Jazz', + 75 => 'Polka', + 76 => 'Retro', + 77 => 'Musical', + 78 => 'Rock & Roll', + 79 => 'Hard Rock', + 80 => 'Folk', + 81 => 'Folk/Rock', + 82 => 'National Folk', + 83 => 'Swing', + 84 => 'Fast-Fusion', + 85 => 'Bebob', + 86 => 'Latin', + 87 => 'Revival', + 88 => 'Celtic', + 89 => 'Bluegrass', + 90 => 'Avantgarde', + 91 => 'Gothic Rock', + 92 => 'Progressive Rock', + 93 => 'Psychedelic Rock', + 94 => 'Symphonic Rock', + 95 => 'Slow Rock', + 96 => 'Big Band', + 97 => 'Chorus', + 98 => 'Easy Listening', + 99 => 'Acoustic', + 100 => 'Humour', + 101 => 'Speech', + 102 => 'Chanson', + 103 => 'Opera', + 104 => 'Chamber Music', + 105 => 'Sonata', + 106 => 'Symphony', + 107 => 'Booty Bass', + 108 => 'Primus', + 109 => 'Porn Groove', + 110 => 'Satire', + 111 => 'Slow Jam', + 112 => 'Club', + 113 => 'Tango', + 114 => 'Samba', + 115 => 'Folklore', + 116 => 'Ballad', + 117 => 'Power Ballad', + 118 => 'Rhythmic Soul', + 119 => 'Freestyle', + 120 => 'Duet', + 121 => 'Punk Rock', + 122 => 'Drum Solo', + 123 => 'A Cappella', + 124 => 'Euro-House', + 125 => 'Dance Hall', + 126 => 'Goa', + 127 => 'Drum & Bass', + 128 => 'Club-House', + 129 => 'Hardcore', + 130 => 'Terror', + 131 => 'Indie', + 132 => 'BritPop', + 133 => 'Negerpunk', + 134 => 'Polsk Punk', + 135 => 'Beat', + 136 => 'Christian Gangsta Rap', + 137 => 'Heavy Metal', + 138 => 'Black Metal', + 139 => 'Crossover', + 140 => 'Contemporary Christian', + 141 => 'Christian Rock', + 142 => 'Merengue', + 143 => 'Salsa', + 144 => 'Thrash Metal', + 145 => 'Anime', + 146 => 'JPop', + 147 => 'Synthpop', + + 255 => 'Unknown', + + 'CR' => 'Cover', + 'RX' => 'Remix' + ); + + static $GenreLookupSCMPX = array(); + if ($allowSCMPXextended && empty($GenreLookupSCMPX)) { + $GenreLookupSCMPX = $GenreLookup; + // http://www.geocities.co.jp/SiliconValley-Oakland/3664/alittle.html#GenreExtended + // Extended ID3v1 genres invented by SCMPX + // Note that 255 "Japanese Anime" conflicts with standard "Unknown" + $GenreLookupSCMPX[240] = 'Sacred'; + $GenreLookupSCMPX[241] = 'Northern Europe'; + $GenreLookupSCMPX[242] = 'Irish & Scottish'; + $GenreLookupSCMPX[243] = 'Scotland'; + $GenreLookupSCMPX[244] = 'Ethnic Europe'; + $GenreLookupSCMPX[245] = 'Enka'; + $GenreLookupSCMPX[246] = 'Children\'s Song'; + $GenreLookupSCMPX[247] = 'Japanese Sky'; + $GenreLookupSCMPX[248] = 'Japanese Heavy Rock'; + $GenreLookupSCMPX[249] = 'Japanese Doom Rock'; + $GenreLookupSCMPX[250] = 'Japanese J-POP'; + $GenreLookupSCMPX[251] = 'Japanese Seiyu'; + $GenreLookupSCMPX[252] = 'Japanese Ambient Techno'; + $GenreLookupSCMPX[253] = 'Japanese Moemoe'; + $GenreLookupSCMPX[254] = 'Japanese Tokusatsu'; + //$GenreLookupSCMPX[255] = 'Japanese Anime'; + } + + return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup); + } + + public static function LookupGenreName($genreid, $allowSCMPXextended=true) { + switch ($genreid) { + case 'RX': + case 'CR': + break; + default: + if (!is_numeric($genreid)) { + return false; + } + $genreid = intval($genreid); // to handle 3 or '3' or '03' + break; + } + $GenreLookup = self::ArrayOfGenres($allowSCMPXextended); + return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false); + } + + public static function LookupGenreID($genre, $allowSCMPXextended=false) { + $GenreLookup = self::ArrayOfGenres($allowSCMPXextended); + $LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre)); + foreach ($GenreLookup as $key => $value) { + if (strtolower(str_replace(' ', '', $value)) == $LowerCaseNoSpaceSearchTerm) { + return $key; + } + } + return false; + } + + public static function StandardiseID3v1GenreName($OriginalGenre) { + if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) { + return self::LookupGenreName($GenreID); + } + return $OriginalGenre; + } + + public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') { + $ID3v1Tag = 'TAG'; + $ID3v1Tag .= str_pad(trim(substr($title, 0, 30)), 30, "\x00", STR_PAD_RIGHT); + $ID3v1Tag .= str_pad(trim(substr($artist, 0, 30)), 30, "\x00", STR_PAD_RIGHT); + $ID3v1Tag .= str_pad(trim(substr($album, 0, 30)), 30, "\x00", STR_PAD_RIGHT); + $ID3v1Tag .= str_pad(trim(substr($year, 0, 4)), 4, "\x00", STR_PAD_LEFT); + if (!empty($track) && ($track > 0) && ($track <= 255)) { + $ID3v1Tag .= str_pad(trim(substr($comment, 0, 28)), 28, "\x00", STR_PAD_RIGHT); + $ID3v1Tag .= "\x00"; + if (gettype($track) == 'string') { + $track = (int) $track; + } + $ID3v1Tag .= chr($track); + } else { + $ID3v1Tag .= str_pad(trim(substr($comment, 0, 30)), 30, "\x00", STR_PAD_RIGHT); + } + if (($genreid < 0) || ($genreid > 147)) { + $genreid = 255; // 'unknown' genre + } + switch (gettype($genreid)) { + case 'string': + case 'integer': + $ID3v1Tag .= chr(intval($genreid)); + break; + default: + $ID3v1Tag .= chr(255); // 'unknown' genre + break; + } + + return $ID3v1Tag; + } + +} diff --git a/sources/wp-includes/ID3/module.tag.id3v2.php b/sources/wp-includes/ID3/module.tag.id3v2.php new file mode 100644 index 0000000..b08f9f9 --- /dev/null +++ b/sources/wp-includes/ID3/module.tag.id3v2.php @@ -0,0 +1,3414 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +/// // +// module.tag.id3v2.php // +// module for analyzing ID3v2 tags // +// dependencies: module.tag.id3v1.php // +// /// +///////////////////////////////////////////////////////////////// + +getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v1.php', __FILE__, true); + +class getid3_id3v2 extends getid3_handler +{ + public $StartingOffset = 0; + + public function Analyze() { + $info = &$this->getid3->info; + + // Overall tag structure: + // +-----------------------------+ + // | Header (10 bytes) | + // +-----------------------------+ + // | Extended Header | + // | (variable length, OPTIONAL) | + // +-----------------------------+ + // | Frames (variable length) | + // +-----------------------------+ + // | Padding | + // | (variable length, OPTIONAL) | + // +-----------------------------+ + // | Footer (10 bytes, OPTIONAL) | + // +-----------------------------+ + + // Header + // ID3v2/file identifier "ID3" + // ID3v2 version $04 00 + // ID3v2 flags (%ab000000 in v2.2, %abc00000 in v2.3, %abcd0000 in v2.4.x) + // ID3v2 size 4 * %0xxxxxxx + + + // shortcuts + $info['id3v2']['header'] = true; + $thisfile_id3v2 = &$info['id3v2']; + $thisfile_id3v2['flags'] = array(); + $thisfile_id3v2_flags = &$thisfile_id3v2['flags']; + + + fseek($this->getid3->fp, $this->StartingOffset, SEEK_SET); + $header = fread($this->getid3->fp, 10); + if (substr($header, 0, 3) == 'ID3' && strlen($header) == 10) { + + $thisfile_id3v2['majorversion'] = ord($header{3}); + $thisfile_id3v2['minorversion'] = ord($header{4}); + + // shortcut + $id3v2_majorversion = &$thisfile_id3v2['majorversion']; + + } else { + + unset($info['id3v2']); + return false; + + } + + if ($id3v2_majorversion > 4) { // this script probably won't correctly parse ID3v2.5.x and above (if it ever exists) + + $info['error'][] = 'this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion']; + return false; + + } + + $id3_flags = ord($header{5}); + switch ($id3v2_majorversion) { + case 2: + // %ab000000 in v2.2 + $thisfile_id3v2_flags['unsynch'] = (bool) ($id3_flags & 0x80); // a - Unsynchronisation + $thisfile_id3v2_flags['compression'] = (bool) ($id3_flags & 0x40); // b - Compression + break; + + case 3: + // %abc00000 in v2.3 + $thisfile_id3v2_flags['unsynch'] = (bool) ($id3_flags & 0x80); // a - Unsynchronisation + $thisfile_id3v2_flags['exthead'] = (bool) ($id3_flags & 0x40); // b - Extended header + $thisfile_id3v2_flags['experim'] = (bool) ($id3_flags & 0x20); // c - Experimental indicator + break; + + case 4: + // %abcd0000 in v2.4 + $thisfile_id3v2_flags['unsynch'] = (bool) ($id3_flags & 0x80); // a - Unsynchronisation + $thisfile_id3v2_flags['exthead'] = (bool) ($id3_flags & 0x40); // b - Extended header + $thisfile_id3v2_flags['experim'] = (bool) ($id3_flags & 0x20); // c - Experimental indicator + $thisfile_id3v2_flags['isfooter'] = (bool) ($id3_flags & 0x10); // d - Footer present + break; + } + + $thisfile_id3v2['headerlength'] = getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length + + $thisfile_id3v2['tag_offset_start'] = $this->StartingOffset; + $thisfile_id3v2['tag_offset_end'] = $thisfile_id3v2['tag_offset_start'] + $thisfile_id3v2['headerlength']; + + + + // create 'encoding' key - used by getid3::HandleAllTags() + // in ID3v2 every field can have it's own encoding type + // so force everything to UTF-8 so it can be handled consistantly + $thisfile_id3v2['encoding'] = 'UTF-8'; + + + // Frames + + // All ID3v2 frames consists of one frame header followed by one or more + // fields containing the actual information. The header is always 10 + // bytes and laid out as follows: + // + // Frame ID $xx xx xx xx (four characters) + // Size 4 * %0xxxxxxx + // Flags $xx xx + + $sizeofframes = $thisfile_id3v2['headerlength'] - 10; // not including 10-byte initial header + if (!empty($thisfile_id3v2['exthead']['length'])) { + $sizeofframes -= ($thisfile_id3v2['exthead']['length'] + 4); + } + if (!empty($thisfile_id3v2_flags['isfooter'])) { + $sizeofframes -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio + } + if ($sizeofframes > 0) { + + $framedata = fread($this->getid3->fp, $sizeofframes); // read all frames from file into $framedata variable + + // if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x) + if (!empty($thisfile_id3v2_flags['unsynch']) && ($id3v2_majorversion <= 3)) { + $framedata = $this->DeUnsynchronise($framedata); + } + // [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead + // of on tag level, making it easier to skip frames, increasing the streamability + // of the tag. The unsynchronisation flag in the header [S:3.1] indicates that + // there exists an unsynchronised frame, while the new unsynchronisation flag in + // the frame header [S:4.1.2] indicates unsynchronisation. + + + //$framedataoffset = 10 + ($thisfile_id3v2['exthead']['length'] ? $thisfile_id3v2['exthead']['length'] + 4 : 0); // how many bytes into the stream - start from after the 10-byte header (and extended header length+4, if present) + $framedataoffset = 10; // how many bytes into the stream - start from after the 10-byte header + + + // Extended Header + if (!empty($thisfile_id3v2_flags['exthead'])) { + $extended_header_offset = 0; + + if ($id3v2_majorversion == 3) { + + // v2.3 definition: + //Extended header size $xx xx xx xx // 32-bit integer + //Extended Flags $xx xx + // %x0000000 %00000000 // v2.3 + // x - CRC data present + //Size of padding $xx xx xx xx + + $thisfile_id3v2['exthead']['length'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4), 0); + $extended_header_offset += 4; + + $thisfile_id3v2['exthead']['flag_bytes'] = 2; + $thisfile_id3v2['exthead']['flag_raw'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, $thisfile_id3v2['exthead']['flag_bytes'])); + $extended_header_offset += $thisfile_id3v2['exthead']['flag_bytes']; + + $thisfile_id3v2['exthead']['flags']['crc'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x8000); + + $thisfile_id3v2['exthead']['padding_size'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4)); + $extended_header_offset += 4; + + if ($thisfile_id3v2['exthead']['flags']['crc']) { + $thisfile_id3v2['exthead']['flag_data']['crc'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4)); + $extended_header_offset += 4; + } + $extended_header_offset += $thisfile_id3v2['exthead']['padding_size']; + + } elseif ($id3v2_majorversion == 4) { + + // v2.4 definition: + //Extended header size 4 * %0xxxxxxx // 28-bit synchsafe integer + //Number of flag bytes $01 + //Extended Flags $xx + // %0bcd0000 // v2.4 + // b - Tag is an update + // Flag data length $00 + // c - CRC data present + // Flag data length $05 + // Total frame CRC 5 * %0xxxxxxx + // d - Tag restrictions + // Flag data length $01 + + $thisfile_id3v2['exthead']['length'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 4), true); + $extended_header_offset += 4; + + $thisfile_id3v2['exthead']['flag_bytes'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should always be 1 + $extended_header_offset += 1; + + $thisfile_id3v2['exthead']['flag_raw'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, $thisfile_id3v2['exthead']['flag_bytes'])); + $extended_header_offset += $thisfile_id3v2['exthead']['flag_bytes']; + + $thisfile_id3v2['exthead']['flags']['update'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x40); + $thisfile_id3v2['exthead']['flags']['crc'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x20); + $thisfile_id3v2['exthead']['flags']['restrictions'] = (bool) ($thisfile_id3v2['exthead']['flag_raw'] & 0x10); + + if ($thisfile_id3v2['exthead']['flags']['update']) { + $ext_header_chunk_length = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should be 0 + $extended_header_offset += 1; + } + + if ($thisfile_id3v2['exthead']['flags']['crc']) { + $ext_header_chunk_length = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should be 5 + $extended_header_offset += 1; + $thisfile_id3v2['exthead']['flag_data']['crc'] = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, $ext_header_chunk_length), true, false); + $extended_header_offset += $ext_header_chunk_length; + } + + if ($thisfile_id3v2['exthead']['flags']['restrictions']) { + $ext_header_chunk_length = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); // should be 1 + $extended_header_offset += 1; + + // %ppqrrstt + $restrictions_raw = getid3_lib::BigEndian2Int(substr($framedata, $extended_header_offset, 1)); + $extended_header_offset += 1; + $thisfile_id3v2['exthead']['flags']['restrictions']['tagsize'] = ($restrictions_raw & 0xC0) >> 6; // p - Tag size restrictions + $thisfile_id3v2['exthead']['flags']['restrictions']['textenc'] = ($restrictions_raw & 0x20) >> 5; // q - Text encoding restrictions + $thisfile_id3v2['exthead']['flags']['restrictions']['textsize'] = ($restrictions_raw & 0x18) >> 3; // r - Text fields size restrictions + $thisfile_id3v2['exthead']['flags']['restrictions']['imgenc'] = ($restrictions_raw & 0x04) >> 2; // s - Image encoding restrictions + $thisfile_id3v2['exthead']['flags']['restrictions']['imgsize'] = ($restrictions_raw & 0x03) >> 0; // t - Image size restrictions + + $thisfile_id3v2['exthead']['flags']['restrictions_text']['tagsize'] = $this->LookupExtendedHeaderRestrictionsTagSizeLimits($thisfile_id3v2['exthead']['flags']['restrictions']['tagsize']); + $thisfile_id3v2['exthead']['flags']['restrictions_text']['textenc'] = $this->LookupExtendedHeaderRestrictionsTextEncodings($thisfile_id3v2['exthead']['flags']['restrictions']['textenc']); + $thisfile_id3v2['exthead']['flags']['restrictions_text']['textsize'] = $this->LookupExtendedHeaderRestrictionsTextFieldSize($thisfile_id3v2['exthead']['flags']['restrictions']['textsize']); + $thisfile_id3v2['exthead']['flags']['restrictions_text']['imgenc'] = $this->LookupExtendedHeaderRestrictionsImageEncoding($thisfile_id3v2['exthead']['flags']['restrictions']['imgenc']); + $thisfile_id3v2['exthead']['flags']['restrictions_text']['imgsize'] = $this->LookupExtendedHeaderRestrictionsImageSizeSize($thisfile_id3v2['exthead']['flags']['restrictions']['imgsize']); + } + + if ($thisfile_id3v2['exthead']['length'] != $extended_header_offset) { + $info['warning'][] = 'ID3v2.4 extended header length mismatch (expecting '.intval($thisfile_id3v2['exthead']['length']).', found '.intval($extended_header_offset).')'; + } + } + + $framedataoffset += $extended_header_offset; + $framedata = substr($framedata, $extended_header_offset); + } // end extended header + + + while (isset($framedata) && (strlen($framedata) > 0)) { // cycle through until no more frame data is left to parse + if (strlen($framedata) <= $this->ID3v2HeaderLength($id3v2_majorversion)) { + // insufficient room left in ID3v2 header for actual data - must be padding + $thisfile_id3v2['padding']['start'] = $framedataoffset; + $thisfile_id3v2['padding']['length'] = strlen($framedata); + $thisfile_id3v2['padding']['valid'] = true; + for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) { + if ($framedata{$i} != "\x00") { + $thisfile_id3v2['padding']['valid'] = false; + $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i; + $info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)'; + break; + } + } + break; // skip rest of ID3v2 header + } + if ($id3v2_majorversion == 2) { + // Frame ID $xx xx xx (three characters) + // Size $xx xx xx (24-bit integer) + // Flags $xx xx + + $frame_header = substr($framedata, 0, 6); // take next 6 bytes for header + $framedata = substr($framedata, 6); // and leave the rest in $framedata + $frame_name = substr($frame_header, 0, 3); + $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 3, 3), 0); + $frame_flags = 0; // not used for anything in ID3v2.2, just set to avoid E_NOTICEs + + } elseif ($id3v2_majorversion > 2) { + + // Frame ID $xx xx xx xx (four characters) + // Size $xx xx xx xx (32-bit integer in v2.3, 28-bit synchsafe in v2.4+) + // Flags $xx xx + + $frame_header = substr($framedata, 0, 10); // take next 10 bytes for header + $framedata = substr($framedata, 10); // and leave the rest in $framedata + + $frame_name = substr($frame_header, 0, 4); + if ($id3v2_majorversion == 3) { + $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer + } else { // ID3v2.4+ + $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 1); // 32-bit synchsafe integer (28-bit value) + } + + if ($frame_size < (strlen($framedata) + 4)) { + $nextFrameID = substr($framedata, $frame_size, 4); + if ($this->IsValidID3v2FrameName($nextFrameID, $id3v2_majorversion)) { + // next frame is OK + } elseif (($frame_name == "\x00".'MP3') || ($frame_name == "\x00\x00".'MP') || ($frame_name == ' MP3') || ($frame_name == 'MP3e')) { + // MP3ext known broken frames - "ok" for the purposes of this test + } elseif (($id3v2_majorversion == 4) && ($this->IsValidID3v2FrameName(substr($framedata, getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0), 4), 3))) { + $info['warning'][] = 'ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3'; + $id3v2_majorversion = 3; + $frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer + } + } + + + $frame_flags = getid3_lib::BigEndian2Int(substr($frame_header, 8, 2)); + } + + if ((($id3v2_majorversion == 2) && ($frame_name == "\x00\x00\x00")) || ($frame_name == "\x00\x00\x00\x00")) { + // padding encountered + + $thisfile_id3v2['padding']['start'] = $framedataoffset; + $thisfile_id3v2['padding']['length'] = strlen($frame_header) + strlen($framedata); + $thisfile_id3v2['padding']['valid'] = true; + + $len = strlen($framedata); + for ($i = 0; $i < $len; $i++) { + if ($framedata{$i} != "\x00") { + $thisfile_id3v2['padding']['valid'] = false; + $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i; + $info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)'; + break; + } + } + break; // skip rest of ID3v2 header + } + + if ($frame_name == 'COM ') { + $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably others too)]'; + $frame_name = 'COMM'; + } + if (($frame_size <= strlen($framedata)) && ($this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion))) { + + unset($parsedFrame); + $parsedFrame['frame_name'] = $frame_name; + $parsedFrame['frame_flags_raw'] = $frame_flags; + $parsedFrame['data'] = substr($framedata, 0, $frame_size); + $parsedFrame['datalength'] = getid3_lib::CastAsInt($frame_size); + $parsedFrame['dataoffset'] = $framedataoffset; + + $this->ParseID3v2Frame($parsedFrame); + $thisfile_id3v2[$frame_name][] = $parsedFrame; + + $framedata = substr($framedata, $frame_size); + + } else { // invalid frame length or FrameID + + if ($frame_size <= strlen($framedata)) { + + if ($this->IsValidID3v2FrameName(substr($framedata, $frame_size, 4), $id3v2_majorversion)) { + + // next frame is valid, just skip the current frame + $framedata = substr($framedata, $frame_size); + $info['warning'][] = 'Next ID3v2 frame is valid, skipping current frame.'; + + } else { + + // next frame is invalid too, abort processing + //unset($framedata); + $framedata = null; + $info['error'][] = 'Next ID3v2 frame is also invalid, aborting processing.'; + + } + + } elseif ($frame_size == strlen($framedata)) { + + // this is the last frame, just skip + $info['warning'][] = 'This was the last ID3v2 frame.'; + + } else { + + // next frame is invalid too, abort processing + //unset($framedata); + $framedata = null; + $info['warning'][] = 'Invalid ID3v2 frame size, aborting.'; + + } + if (!$this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion)) { + + switch ($frame_name) { + case "\x00\x00".'MP': + case "\x00".'MP3': + case ' MP3': + case 'MP3e': + case "\x00".'MP': + case ' MP': + case 'MP3': + $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]'; + break; + + default: + $info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))).'; + break; + } + + } elseif (!isset($framedata) || ($frame_size > strlen($framedata))) { + + $info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.(isset($framedata) ? strlen($framedata) : 'null').')).'; + + } else { + + $info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag).'; + + } + + } + $framedataoffset += ($frame_size + $this->ID3v2HeaderLength($id3v2_majorversion)); + + } + + } + + + // Footer + + // The footer is a copy of the header, but with a different identifier. + // ID3v2 identifier "3DI" + // ID3v2 version $04 00 + // ID3v2 flags %abcd0000 + // ID3v2 size 4 * %0xxxxxxx + + if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) { + $footer = fread($this->getid3->fp, 10); + if (substr($footer, 0, 3) == '3DI') { + $thisfile_id3v2['footer'] = true; + $thisfile_id3v2['majorversion_footer'] = ord($footer{3}); + $thisfile_id3v2['minorversion_footer'] = ord($footer{4}); + } + if ($thisfile_id3v2['majorversion_footer'] <= 4) { + $id3_flags = ord(substr($footer{5})); + $thisfile_id3v2_flags['unsynch_footer'] = (bool) ($id3_flags & 0x80); + $thisfile_id3v2_flags['extfoot_footer'] = (bool) ($id3_flags & 0x40); + $thisfile_id3v2_flags['experim_footer'] = (bool) ($id3_flags & 0x20); + $thisfile_id3v2_flags['isfooter_footer'] = (bool) ($id3_flags & 0x10); + + $thisfile_id3v2['footerlength'] = getid3_lib::BigEndian2Int(substr($footer, 6, 4), 1); + } + } // end footer + + if (isset($thisfile_id3v2['comments']['genre'])) { + foreach ($thisfile_id3v2['comments']['genre'] as $key => $value) { + unset($thisfile_id3v2['comments']['genre'][$key]); + $thisfile_id3v2['comments'] = getid3_lib::array_merge_noclobber($thisfile_id3v2['comments'], array('genre'=>$this->ParseID3v2GenreString($value))); + } + } + + if (isset($thisfile_id3v2['comments']['track'])) { + foreach ($thisfile_id3v2['comments']['track'] as $key => $value) { + if (strstr($value, '/')) { + list($thisfile_id3v2['comments']['tracknum'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track'][$key]); + } + } + } + + if (!isset($thisfile_id3v2['comments']['year']) && !empty($thisfile_id3v2['comments']['recording_time'][0]) && preg_match('#^([0-9]{4})#', trim($thisfile_id3v2['comments']['recording_time'][0]), $matches)) { + $thisfile_id3v2['comments']['year'] = array($matches[1]); + } + + + if (!empty($thisfile_id3v2['TXXX'])) { + // MediaMonkey does this, maybe others: write a blank RGAD frame, but put replay-gain adjustment values in TXXX frames + foreach ($thisfile_id3v2['TXXX'] as $txxx_array) { + switch ($txxx_array['description']) { + case 'replaygain_track_gain': + if (empty($info['replay_gain']['track']['adjustment']) && !empty($txxx_array['data'])) { + $info['replay_gain']['track']['adjustment'] = floatval(trim(str_replace('dB', '', $txxx_array['data']))); + } + break; + case 'replaygain_track_peak': + if (empty($info['replay_gain']['track']['peak']) && !empty($txxx_array['data'])) { + $info['replay_gain']['track']['peak'] = floatval($txxx_array['data']); + } + break; + case 'replaygain_album_gain': + if (empty($info['replay_gain']['album']['adjustment']) && !empty($txxx_array['data'])) { + $info['replay_gain']['album']['adjustment'] = floatval(trim(str_replace('dB', '', $txxx_array['data']))); + } + break; + } + } + } + + + // Set avdataoffset + $info['avdataoffset'] = $thisfile_id3v2['headerlength']; + if (isset($thisfile_id3v2['footer'])) { + $info['avdataoffset'] += 10; + } + + return true; + } + + + public function ParseID3v2GenreString($genrestring) { + // Parse genres into arrays of genreName and genreID + // ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)' + // ID3v2.4.x: '21' $00 'Eurodisco' $00 + $clean_genres = array(); + if (strpos($genrestring, "\x00") === false) { + $genrestring = preg_replace('#\(([0-9]{1,3})\)#', '$1'."\x00", $genrestring); + } + $genre_elements = explode("\x00", $genrestring); + foreach ($genre_elements as $element) { + $element = trim($element); + if ($element) { + if (preg_match('#^[0-9]{1,3}#', $element)) { + $clean_genres[] = getid3_id3v1::LookupGenreName($element); + } else { + $clean_genres[] = str_replace('((', '(', $element); + } + } + } + return $clean_genres; + } + + + public function ParseID3v2Frame(&$parsedFrame) { + + // shortcuts + $info = &$this->getid3->info; + $id3v2_majorversion = $info['id3v2']['majorversion']; + + $parsedFrame['framenamelong'] = $this->FrameNameLongLookup($parsedFrame['frame_name']); + if (empty($parsedFrame['framenamelong'])) { + unset($parsedFrame['framenamelong']); + } + $parsedFrame['framenameshort'] = $this->FrameNameShortLookup($parsedFrame['frame_name']); + if (empty($parsedFrame['framenameshort'])) { + unset($parsedFrame['framenameshort']); + } + + if ($id3v2_majorversion >= 3) { // frame flags are not part of the ID3v2.2 standard + if ($id3v2_majorversion == 3) { + // Frame Header Flags + // %abc00000 %ijk00000 + $parsedFrame['flags']['TagAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x8000); // a - Tag alter preservation + $parsedFrame['flags']['FileAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x4000); // b - File alter preservation + $parsedFrame['flags']['ReadOnly'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x2000); // c - Read only + $parsedFrame['flags']['compression'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0080); // i - Compression + $parsedFrame['flags']['Encryption'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0040); // j - Encryption + $parsedFrame['flags']['GroupingIdentity'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0020); // k - Grouping identity + + } elseif ($id3v2_majorversion == 4) { + // Frame Header Flags + // %0abc0000 %0h00kmnp + $parsedFrame['flags']['TagAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x4000); // a - Tag alter preservation + $parsedFrame['flags']['FileAlterPreservation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x2000); // b - File alter preservation + $parsedFrame['flags']['ReadOnly'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x1000); // c - Read only + $parsedFrame['flags']['GroupingIdentity'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0040); // h - Grouping identity + $parsedFrame['flags']['compression'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0008); // k - Compression + $parsedFrame['flags']['Encryption'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0004); // m - Encryption + $parsedFrame['flags']['Unsynchronisation'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0002); // n - Unsynchronisation + $parsedFrame['flags']['DataLengthIndicator'] = (bool) ($parsedFrame['frame_flags_raw'] & 0x0001); // p - Data length indicator + + // Frame-level de-unsynchronisation - ID3v2.4 + if ($parsedFrame['flags']['Unsynchronisation']) { + $parsedFrame['data'] = $this->DeUnsynchronise($parsedFrame['data']); + } + + if ($parsedFrame['flags']['DataLengthIndicator']) { + $parsedFrame['data_length_indicator'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 4), 1); + $parsedFrame['data'] = substr($parsedFrame['data'], 4); + } + } + + // Frame-level de-compression + if ($parsedFrame['flags']['compression']) { + $parsedFrame['decompressed_size'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 4)); + if (!function_exists('gzuncompress')) { + $info['warning'][] = 'gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame['frame_name'].'"'; + } else { + if ($decompresseddata = @gzuncompress(substr($parsedFrame['data'], 4))) { + //if ($decompresseddata = @gzuncompress($parsedFrame['data'])) { + $parsedFrame['data'] = $decompresseddata; + unset($decompresseddata); + } else { + $info['warning'][] = 'gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame['frame_name'].'"'; + } + } + } + } + + if (!empty($parsedFrame['flags']['DataLengthIndicator'])) { + if ($parsedFrame['data_length_indicator'] != strlen($parsedFrame['data'])) { + $info['warning'][] = 'ID3v2 frame "'.$parsedFrame['frame_name'].'" should be '.$parsedFrame['data_length_indicator'].' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame['data']).' bytes of data'; + } + } + + if (isset($parsedFrame['datalength']) && ($parsedFrame['datalength'] == 0)) { + + $warning = 'Frame "'.$parsedFrame['frame_name'].'" at offset '.$parsedFrame['dataoffset'].' has no data portion'; + switch ($parsedFrame['frame_name']) { + case 'WCOM': + $warning .= ' (this is known to happen with files tagged by RioPort)'; + break; + + default: + break; + } + $info['warning'][] = $warning; + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'UFID')) || // 4.1 UFID Unique file identifier + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'UFI'))) { // 4.1 UFI Unique file identifier + // There may be more than one 'UFID' frame in a tag, + // but only one with the same 'Owner identifier'. + //
    + // Owner identifier $00 + // Identifier + $exploded = explode("\x00", $parsedFrame['data'], 2); + $parsedFrame['ownerid'] = (isset($exploded[0]) ? $exploded[0] : ''); + $parsedFrame['data'] = (isset($exploded[1]) ? $exploded[1] : ''); + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'TXXX')) || // 4.2.2 TXXX User defined text information frame + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'TXX'))) { // 4.2.2 TXX User defined text information frame + // There may be more than one 'TXXX' frame in each tag, + // but only one with the same description. + //
    + // Text encoding $xx + // Description $00 (00) + // Value + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['description'] = $frame_description; + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data'])); + } + //unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain + + + } elseif ($parsedFrame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame + // There may only be one text information frame of its kind in an tag. + //
    + // Text encoding $xx + // Information + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + // ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with / + // This of course breaks when an artist name contains slash character, e.g. "AC/DC" + // MP3tag (maybe others) implement alternative system where multiple artists are null-separated, which makes more sense + // getID3 will split null-separated artists into multiple artists and leave slash-separated ones to the user + switch ($parsedFrame['encoding']) { + case 'UTF-16': + case 'UTF-16BE': + case 'UTF-16LE': + $wordsize = 2; + break; + case 'ISO-8859-1': + case 'UTF-8': + default: + $wordsize = 1; + break; + } + $Txxx_elements = array(); + $Txxx_elements_start_offset = 0; + for ($i = 0; $i < strlen($parsedFrame['data']); $i += $wordsize) { + if (substr($parsedFrame['data'], $i, $wordsize) == str_repeat("\x00", $wordsize)) { + $Txxx_elements[] = substr($parsedFrame['data'], $Txxx_elements_start_offset, $i - $Txxx_elements_start_offset); + $Txxx_elements_start_offset = $i + $wordsize; + } + } + $Txxx_elements[] = substr($parsedFrame['data'], $Txxx_elements_start_offset, $i - $Txxx_elements_start_offset); + foreach ($Txxx_elements as $Txxx_element) { + $string = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $Txxx_element); + if (!empty($string)) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $string; + } + } + unset($string, $wordsize, $i, $Txxx_elements, $Txxx_element, $Txxx_elements_start_offset); + } + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'WXXX')) || // 4.3.2 WXXX User defined URL link frame + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'WXX'))) { // 4.3.2 WXX User defined URL link frame + // There may be more than one 'WXXX' frame in each tag, + // but only one with the same description + //
    + // Text encoding $xx + // Description $00 (00) + // URL + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); + + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding)); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + if ($frame_terminatorpos) { + // there are null bytes after the data - this is not according to spec + // only use data up to first null byte + $frame_urldata = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos); + } else { + // no null bytes following data, just use all data + $frame_urldata = (string) $parsedFrame['data']; + } + + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['url'] = $frame_urldata; + $parsedFrame['description'] = $frame_description; + if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']); + } + unset($parsedFrame['data']); + + + } elseif ($parsedFrame['frame_name']{0} == 'W') { // 4.3. W??? URL link frames + // There may only be one URL link frame of its kind in a tag, + // except when stated otherwise in the frame description + //
    + // URL + + $parsedFrame['url'] = trim($parsedFrame['data']); + if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url']; + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'IPLS')) || // 4.4 IPLS Involved people list (ID3v2.3 only) + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'IPL'))) { // 4.4 IPL Involved people list (ID3v2.2 only) + // http://id3.org/id3v2.3.0#sec4.4 + // There may only be one 'IPL' frame in each tag + //
    + // Text encoding $xx + // People list strings + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']); + $parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset); + + // http://www.getid3.org/phpBB3/viewtopic.php?t=1369 + // "this tag typically contains null terminated strings, which are associated in pairs" + // "there are users that use the tag incorrectly" + $IPLS_parts = array(); + if (strpos($parsedFrame['data_raw'], "\x00") !== false) { + $IPLS_parts_unsorted = array(); + if (((strlen($parsedFrame['data_raw']) % 2) == 0) && ((substr($parsedFrame['data_raw'], 0, 2) == "\xFF\xFE") || (substr($parsedFrame['data_raw'], 0, 2) == "\xFE\xFF"))) { + // UTF-16, be careful looking for null bytes since most 2-byte characters may contain one; you need to find twin null bytes, and on even padding + $thisILPS = ''; + for ($i = 0; $i < strlen($parsedFrame['data_raw']); $i += 2) { + $twobytes = substr($parsedFrame['data_raw'], $i, 2); + if ($twobytes === "\x00\x00") { + $IPLS_parts_unsorted[] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $thisILPS); + $thisILPS = ''; + } else { + $thisILPS .= $twobytes; + } + } + if (strlen($thisILPS) > 2) { // 2-byte BOM + $IPLS_parts_unsorted[] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $thisILPS); + } + } else { + // ISO-8859-1 or UTF-8 or other single-byte-null character set + $IPLS_parts_unsorted = explode("\x00", $parsedFrame['data_raw']); + } + if (count($IPLS_parts_unsorted) == 1) { + // just a list of names, e.g. "Dino Baptiste, Jimmy Copley, John Gordon, Bernie Marsden, Sharon Watson" + foreach ($IPLS_parts_unsorted as $key => $value) { + $IPLS_parts_sorted = preg_split('#[;,\\r\\n\\t]#', $value); + $position = ''; + foreach ($IPLS_parts_sorted as $person) { + $IPLS_parts[] = array('position'=>$position, 'person'=>$person); + } + } + } elseif ((count($IPLS_parts_unsorted) % 2) == 0) { + $position = ''; + $person = ''; + foreach ($IPLS_parts_unsorted as $key => $value) { + if (($key % 2) == 0) { + $position = $value; + } else { + $person = $value; + $IPLS_parts[] = array('position'=>$position, 'person'=>$person); + $position = ''; + $person = ''; + } + } + } else { + foreach ($IPLS_parts_unsorted as $key => $value) { + $IPLS_parts[] = array($value); + } + } + + } else { + $IPLS_parts = preg_split('#[;,\\r\\n\\t]#', $parsedFrame['data_raw']); + } + $parsedFrame['data'] = $IPLS_parts; + + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['data']; + } + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'MCDI')) || // 4.4 MCDI Music CD identifier + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'MCI'))) { // 4.5 MCI Music CD identifier + // There may only be one 'MCDI' frame in each tag + //
    + // CD TOC + + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['data']; + } + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'ETCO')) || // 4.5 ETCO Event timing codes + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ETC'))) { // 4.6 ETC Event timing codes + // There may only be one 'ETCO' frame in each tag + //
    + // Time stamp format $xx + // Where time stamp format is: + // $01 (32-bit value) MPEG frames from beginning of file + // $02 (32-bit value) milliseconds from beginning of file + // Followed by a list of key events in the following format: + // Type of event $xx + // Time stamp $xx (xx ...) + // The 'Time stamp' is set to zero if directly at the beginning of the sound + // or after the previous event. All events MUST be sorted in chronological order. + + $frame_offset = 0; + $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + + while ($frame_offset < strlen($parsedFrame['data'])) { + $parsedFrame['typeid'] = substr($parsedFrame['data'], $frame_offset++, 1); + $parsedFrame['type'] = $this->ETCOEventLookup($parsedFrame['typeid']); + $parsedFrame['timestamp'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4)); + $frame_offset += 4; + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'MLLT')) || // 4.6 MLLT MPEG location lookup table + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'MLL'))) { // 4.7 MLL MPEG location lookup table + // There may only be one 'MLLT' frame in each tag + //
    + // MPEG frames between reference $xx xx + // Bytes between reference $xx xx xx + // Milliseconds between reference $xx xx xx + // Bits for bytes deviation $xx + // Bits for milliseconds dev. $xx + // Then for every reference the following data is included; + // Deviation in bytes %xxx.... + // Deviation in milliseconds %xxx.... + + $frame_offset = 0; + $parsedFrame['framesbetweenreferences'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 2)); + $parsedFrame['bytesbetweenreferences'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 2, 3)); + $parsedFrame['msbetweenreferences'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 5, 3)); + $parsedFrame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1)); + $parsedFrame['bitsformsdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1)); + $parsedFrame['data'] = substr($parsedFrame['data'], 10); + while ($frame_offset < strlen($parsedFrame['data'])) { + $deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1)); + } + $reference_counter = 0; + while (strlen($deviationbitstream) > 0) { + $parsedFrame[$reference_counter]['bytedeviation'] = bindec(substr($deviationbitstream, 0, $parsedFrame['bitsforbytesdeviation'])); + $parsedFrame[$reference_counter]['msdeviation'] = bindec(substr($deviationbitstream, $parsedFrame['bitsforbytesdeviation'], $parsedFrame['bitsformsdeviation'])); + $deviationbitstream = substr($deviationbitstream, $parsedFrame['bitsforbytesdeviation'] + $parsedFrame['bitsformsdeviation']); + $reference_counter++; + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'SYTC')) || // 4.7 SYTC Synchronised tempo codes + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'STC'))) { // 4.8 STC Synchronised tempo codes + // There may only be one 'SYTC' frame in each tag + //
    + // Time stamp format $xx + // Tempo data + // Where time stamp format is: + // $01 (32-bit value) MPEG frames from beginning of file + // $02 (32-bit value) milliseconds from beginning of file + + $frame_offset = 0; + $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $timestamp_counter = 0; + while ($frame_offset < strlen($parsedFrame['data'])) { + $parsedFrame[$timestamp_counter]['tempo'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ($parsedFrame[$timestamp_counter]['tempo'] == 255) { + $parsedFrame[$timestamp_counter]['tempo'] += ord(substr($parsedFrame['data'], $frame_offset++, 1)); + } + $parsedFrame[$timestamp_counter]['timestamp'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4)); + $frame_offset += 4; + $timestamp_counter++; + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USLT')) || // 4.8 USLT Unsynchronised lyric/text transcription + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription + // There may be more than one 'Unsynchronised lyrics/text transcription' frame + // in each tag, but only one with the same language and content descriptor. + //
    + // Text encoding $xx + // Language $xx xx xx + // Content descriptor $00 (00) + // Lyrics/text + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_language = substr($parsedFrame['data'], $frame_offset, 3); + $frame_offset += 3; + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); + + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['data'] = $parsedFrame['data']; + $parsedFrame['language'] = $frame_language; + $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); + $parsedFrame['description'] = $frame_description; + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'SYLT')) || // 4.9 SYLT Synchronised lyric/text + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'SLT'))) { // 4.10 SLT Synchronised lyric/text + // There may be more than one 'SYLT' frame in each tag, + // but only one with the same language and content descriptor. + //
    + // Text encoding $xx + // Language $xx xx xx + // Time stamp format $xx + // $01 (32-bit value) MPEG frames from beginning of file + // $02 (32-bit value) milliseconds from beginning of file + // Content type $xx + // Content descriptor $00 (00) + // Terminated text to be synced (typically a syllable) + // Sync identifier (terminator to above string) $00 (00) + // Time stamp $xx (xx ...) + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_language = substr($parsedFrame['data'], $frame_offset, 3); + $frame_offset += 3; + $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['contenttypeid'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['contenttype'] = $this->SYTLContentTypeLookup($parsedFrame['contenttypeid']); + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['language'] = $frame_language; + $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); + + $timestampindex = 0; + $frame_remainingdata = substr($parsedFrame['data'], $frame_offset); + while (strlen($frame_remainingdata)) { + $frame_offset = 0; + $frame_terminatorpos = strpos($frame_remainingdata, $this->TextEncodingTerminatorLookup($frame_textencoding)); + if ($frame_terminatorpos === false) { + $frame_remainingdata = ''; + } else { + if (ord(substr($frame_remainingdata, $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset); + + $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); + if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) { + // timestamp probably omitted for first data item + } else { + $parsedFrame['lyrics'][$timestampindex]['timestamp'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 4)); + $frame_remainingdata = substr($frame_remainingdata, 4); + } + $timestampindex++; + } + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'COMM')) || // 4.10 COMM Comments + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'COM'))) { // 4.11 COM Comments + // There may be more than one comment frame in each tag, + // but only one with the same language and content descriptor. + //
    + // Text encoding $xx + // Language $xx xx xx + // Short content descrip. $00 (00) + // The actual text + + if (strlen($parsedFrame['data']) < 5) { + + $info['warning'][] = 'Invalid data (too short) for "'.$parsedFrame['frame_name'].'" frame at offset '.$parsedFrame['dataoffset']; + + } else { + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_language = substr($parsedFrame['data'], $frame_offset, 3); + $frame_offset += 3; + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); + + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['language'] = $frame_language; + $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); + $parsedFrame['description'] = $frame_description; + $parsedFrame['data'] = $frame_text; + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); + } + + } + + } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'RVA2')) { // 4.11 RVA2 Relative volume adjustment (2) (ID3v2.4+ only) + // There may be more than one 'RVA2' frame in each tag, + // but only one with the same identification string + //
    + // Identification $00 + // The 'identification' string is used to identify the situation and/or + // device where this adjustment should apply. The following is then + // repeated for every channel: + // Type of channel $xx + // Volume adjustment $xx xx + // Bits representing peak $xx + // Peak volume $xx (xx ...) + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00"); + $frame_idstring = substr($parsedFrame['data'], 0, $frame_terminatorpos); + if (ord($frame_idstring) === 0) { + $frame_idstring = ''; + } + $frame_remainingdata = substr($parsedFrame['data'], $frame_terminatorpos + strlen("\x00")); + $parsedFrame['description'] = $frame_idstring; + $RVA2channelcounter = 0; + while (strlen($frame_remainingdata) >= 5) { + $frame_offset = 0; + $frame_channeltypeid = ord(substr($frame_remainingdata, $frame_offset++, 1)); + $parsedFrame[$RVA2channelcounter]['channeltypeid'] = $frame_channeltypeid; + $parsedFrame[$RVA2channelcounter]['channeltype'] = $this->RVA2ChannelTypeLookup($frame_channeltypeid); + $parsedFrame[$RVA2channelcounter]['volumeadjust'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, $frame_offset, 2), false, true); // 16-bit signed + $frame_offset += 2; + $parsedFrame[$RVA2channelcounter]['bitspeakvolume'] = ord(substr($frame_remainingdata, $frame_offset++, 1)); + if (($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] < 1) || ($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] > 4)) { + $info['warning'][] = 'ID3v2::RVA2 frame['.$RVA2channelcounter.'] contains invalid '.$parsedFrame[$RVA2channelcounter]['bitspeakvolume'].'-byte bits-representing-peak value'; + break; + } + $frame_bytespeakvolume = ceil($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] / 8); + $parsedFrame[$RVA2channelcounter]['peakvolume'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, $frame_offset, $frame_bytespeakvolume)); + $frame_remainingdata = substr($frame_remainingdata, $frame_offset + $frame_bytespeakvolume); + $RVA2channelcounter++; + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'RVAD')) || // 4.12 RVAD Relative volume adjustment (ID3v2.3 only) + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'RVA'))) { // 4.12 RVA Relative volume adjustment (ID3v2.2 only) + // There may only be one 'RVA' frame in each tag + //
    + // ID3v2.2 => Increment/decrement %000000ba + // ID3v2.3 => Increment/decrement %00fedcba + // Bits used for volume descr. $xx + // Relative volume change, right $xx xx (xx ...) // a + // Relative volume change, left $xx xx (xx ...) // b + // Peak volume right $xx xx (xx ...) + // Peak volume left $xx xx (xx ...) + // ID3v2.3 only, optional (not present in ID3v2.2): + // Relative volume change, right back $xx xx (xx ...) // c + // Relative volume change, left back $xx xx (xx ...) // d + // Peak volume right back $xx xx (xx ...) + // Peak volume left back $xx xx (xx ...) + // ID3v2.3 only, optional (not present in ID3v2.2): + // Relative volume change, center $xx xx (xx ...) // e + // Peak volume center $xx xx (xx ...) + // ID3v2.3 only, optional (not present in ID3v2.2): + // Relative volume change, bass $xx xx (xx ...) // f + // Peak volume bass $xx xx (xx ...) + + $frame_offset = 0; + $frame_incrdecrflags = getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['incdec']['right'] = (bool) substr($frame_incrdecrflags, 6, 1); + $parsedFrame['incdec']['left'] = (bool) substr($frame_incrdecrflags, 7, 1); + $parsedFrame['bitsvolume'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $frame_bytesvolume = ceil($parsedFrame['bitsvolume'] / 8); + $parsedFrame['volumechange']['right'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + if ($parsedFrame['incdec']['right'] === false) { + $parsedFrame['volumechange']['right'] *= -1; + } + $frame_offset += $frame_bytesvolume; + $parsedFrame['volumechange']['left'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + if ($parsedFrame['incdec']['left'] === false) { + $parsedFrame['volumechange']['left'] *= -1; + } + $frame_offset += $frame_bytesvolume; + $parsedFrame['peakvolume']['right'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + $frame_offset += $frame_bytesvolume; + $parsedFrame['peakvolume']['left'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + $frame_offset += $frame_bytesvolume; + if ($id3v2_majorversion == 3) { + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_offset); + if (strlen($parsedFrame['data']) > 0) { + $parsedFrame['incdec']['rightrear'] = (bool) substr($frame_incrdecrflags, 4, 1); + $parsedFrame['incdec']['leftrear'] = (bool) substr($frame_incrdecrflags, 5, 1); + $parsedFrame['volumechange']['rightrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + if ($parsedFrame['incdec']['rightrear'] === false) { + $parsedFrame['volumechange']['rightrear'] *= -1; + } + $frame_offset += $frame_bytesvolume; + $parsedFrame['volumechange']['leftrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + if ($parsedFrame['incdec']['leftrear'] === false) { + $parsedFrame['volumechange']['leftrear'] *= -1; + } + $frame_offset += $frame_bytesvolume; + $parsedFrame['peakvolume']['rightrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + $frame_offset += $frame_bytesvolume; + $parsedFrame['peakvolume']['leftrear'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + $frame_offset += $frame_bytesvolume; + } + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_offset); + if (strlen($parsedFrame['data']) > 0) { + $parsedFrame['incdec']['center'] = (bool) substr($frame_incrdecrflags, 3, 1); + $parsedFrame['volumechange']['center'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + if ($parsedFrame['incdec']['center'] === false) { + $parsedFrame['volumechange']['center'] *= -1; + } + $frame_offset += $frame_bytesvolume; + $parsedFrame['peakvolume']['center'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + $frame_offset += $frame_bytesvolume; + } + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_offset); + if (strlen($parsedFrame['data']) > 0) { + $parsedFrame['incdec']['bass'] = (bool) substr($frame_incrdecrflags, 2, 1); + $parsedFrame['volumechange']['bass'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + if ($parsedFrame['incdec']['bass'] === false) { + $parsedFrame['volumechange']['bass'] *= -1; + } + $frame_offset += $frame_bytesvolume; + $parsedFrame['peakvolume']['bass'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesvolume)); + $frame_offset += $frame_bytesvolume; + } + } + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'EQU2')) { // 4.12 EQU2 Equalisation (2) (ID3v2.4+ only) + // There may be more than one 'EQU2' frame in each tag, + // but only one with the same identification string + //
    + // Interpolation method $xx + // $00 Band + // $01 Linear + // Identification $00 + // The following is then repeated for every adjustment point + // Frequency $xx xx + // Volume adjustment $xx xx + + $frame_offset = 0; + $frame_interpolationmethod = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_idstring = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_idstring) === 0) { + $frame_idstring = ''; + } + $parsedFrame['description'] = $frame_idstring; + $frame_remainingdata = substr($parsedFrame['data'], $frame_terminatorpos + strlen("\x00")); + while (strlen($frame_remainingdata)) { + $frame_frequency = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 2)) / 2; + $parsedFrame['data'][$frame_frequency] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 2, 2), false, true); + $frame_remainingdata = substr($frame_remainingdata, 4); + } + $parsedFrame['interpolationmethod'] = $frame_interpolationmethod; + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'EQUA')) || // 4.12 EQUA Equalisation (ID3v2.3 only) + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'EQU'))) { // 4.13 EQU Equalisation (ID3v2.2 only) + // There may only be one 'EQUA' frame in each tag + //
    + // Adjustment bits $xx + // This is followed by 2 bytes + ('adjustment bits' rounded up to the + // nearest byte) for every equalisation band in the following format, + // giving a frequency range of 0 - 32767Hz: + // Increment/decrement %x (MSB of the Frequency) + // Frequency (lower 15 bits) + // Adjustment $xx (xx ...) + + $frame_offset = 0; + $parsedFrame['adjustmentbits'] = substr($parsedFrame['data'], $frame_offset++, 1); + $frame_adjustmentbytes = ceil($parsedFrame['adjustmentbits'] / 8); + + $frame_remainingdata = (string) substr($parsedFrame['data'], $frame_offset); + while (strlen($frame_remainingdata) > 0) { + $frame_frequencystr = getid3_lib::BigEndian2Bin(substr($frame_remainingdata, 0, 2)); + $frame_incdec = (bool) substr($frame_frequencystr, 0, 1); + $frame_frequency = bindec(substr($frame_frequencystr, 1, 15)); + $parsedFrame[$frame_frequency]['incdec'] = $frame_incdec; + $parsedFrame[$frame_frequency]['adjustment'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 2, $frame_adjustmentbytes)); + if ($parsedFrame[$frame_frequency]['incdec'] === false) { + $parsedFrame[$frame_frequency]['adjustment'] *= -1; + } + $frame_remainingdata = substr($frame_remainingdata, 2 + $frame_adjustmentbytes); + } + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RVRB')) || // 4.13 RVRB Reverb + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'REV'))) { // 4.14 REV Reverb + // There may only be one 'RVRB' frame in each tag. + //
    + // Reverb left (ms) $xx xx + // Reverb right (ms) $xx xx + // Reverb bounces, left $xx + // Reverb bounces, right $xx + // Reverb feedback, left to left $xx + // Reverb feedback, left to right $xx + // Reverb feedback, right to right $xx + // Reverb feedback, right to left $xx + // Premix left to right $xx + // Premix right to left $xx + + $frame_offset = 0; + $parsedFrame['left'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['right'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['bouncesL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['bouncesR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['feedbackLL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['feedbackLR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['feedbackRR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['feedbackRL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['premixLR'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['premixRL'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'APIC')) || // 4.14 APIC Attached picture + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'PIC'))) { // 4.15 PIC Attached picture + // There may be several pictures attached to one file, + // each in their individual 'APIC' frame, but only one + // with the same content descriptor + //
    + // Text encoding $xx + // ID3v2.3+ => MIME type $00 + // ID3v2.2 => Image format $xx xx xx + // Picture type $xx + // Description $00 (00) + // Picture data + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + + if ($id3v2_majorversion == 2 && strlen($parsedFrame['data']) > $frame_offset) { + $frame_imagetype = substr($parsedFrame['data'], $frame_offset, 3); + if (strtolower($frame_imagetype) == 'ima') { + // complete hack for mp3Rage (www.chaoticsoftware.com) that puts ID3v2.3-formatted + // MIME type instead of 3-char ID3v2.2-format image type (thanks xbhoffØpacbell*net) + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_mimetype) === 0) { + $frame_mimetype = ''; + } + $frame_imagetype = strtoupper(str_replace('image/', '', strtolower($frame_mimetype))); + if ($frame_imagetype == 'JPEG') { + $frame_imagetype = 'JPG'; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + } else { + $frame_offset += 3; + } + } + if ($id3v2_majorversion > 2 && strlen($parsedFrame['data']) > $frame_offset) { + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_mimetype) === 0) { + $frame_mimetype = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + } + + $frame_picturetype = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + + if ($frame_offset >= $parsedFrame['datalength']) { + $info['warning'][] = 'data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset); + } else { + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + if ($id3v2_majorversion == 2) { + $parsedFrame['imagetype'] = $frame_imagetype; + } else { + $parsedFrame['mime'] = $frame_mimetype; + } + $parsedFrame['picturetypeid'] = $frame_picturetype; + $parsedFrame['picturetype'] = $this->APICPictureTypeLookup($frame_picturetype); + $parsedFrame['description'] = $frame_description; + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); + $parsedFrame['datalength'] = strlen($parsedFrame['data']); + + $parsedFrame['image_mime'] = ''; + $imageinfo = array(); + $imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo); + if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) { + $parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]); + if ($imagechunkcheck[0]) { + $parsedFrame['image_width'] = $imagechunkcheck[0]; + } + if ($imagechunkcheck[1]) { + $parsedFrame['image_height'] = $imagechunkcheck[1]; + } + } + + do { + if ($this->getid3->option_save_attachments === false) { + // skip entirely + unset($parsedFrame['data']); + break; + } + if ($this->getid3->option_save_attachments === true) { + // great +/* + } elseif (is_int($this->getid3->option_save_attachments)) { + if ($this->getid3->option_save_attachments < $parsedFrame['data_length']) { + // too big, skip + $info['warning'][] = 'attachment at '.$frame_offset.' is too large to process inline ('.number_format($parsedFrame['data_length']).' bytes)'; + unset($parsedFrame['data']); + break; + } +*/ + } elseif (is_string($this->getid3->option_save_attachments)) { + $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); + if (!is_dir($dir) || !is_writable($dir)) { + // cannot write, skip + $info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)'; + unset($parsedFrame['data']); + break; + } + } + // if we get this far, must be OK + if (is_string($this->getid3->option_save_attachments)) { + $destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset; + if (!file_exists($destination_filename) || is_writable($destination_filename)) { + file_put_contents($destination_filename, $parsedFrame['data']); + } else { + $info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)'; + } + $parsedFrame['data_filename'] = $destination_filename; + unset($parsedFrame['data']); + } else { + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + if (!isset($info['id3v2']['comments']['picture'])) { + $info['id3v2']['comments']['picture'] = array(); + } + $info['id3v2']['comments']['picture'][] = array('data'=>$parsedFrame['data'], 'image_mime'=>$parsedFrame['image_mime']); + } + } + } while (false); + } + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GEOB')) || // 4.15 GEOB General encapsulated object + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'GEO'))) { // 4.16 GEO General encapsulated object + // There may be more than one 'GEOB' frame in each tag, + // but only one with the same content descriptor + //
    + // Text encoding $xx + // MIME type $00 + // Filename $00 (00) + // Content description $00 (00) + // Encapsulated object + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_mimetype) === 0) { + $frame_mimetype = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_filename = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_filename) === 0) { + $frame_filename = ''; + } + $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)); + + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)); + + $parsedFrame['objectdata'] = (string) substr($parsedFrame['data'], $frame_offset); + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['mime'] = $frame_mimetype; + $parsedFrame['filename'] = $frame_filename; + $parsedFrame['description'] = $frame_description; + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'PCNT')) || // 4.16 PCNT Play counter + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CNT'))) { // 4.17 CNT Play counter + // There may only be one 'PCNT' frame in each tag. + // When the counter reaches all one's, one byte is inserted in + // front of the counter thus making the counter eight bits bigger + //
    + // Counter $xx xx xx xx (xx ...) + + $parsedFrame['data'] = getid3_lib::BigEndian2Int($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'POPM')) || // 4.17 POPM Popularimeter + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'POP'))) { // 4.18 POP Popularimeter + // There may be more than one 'POPM' frame in each tag, + // but only one with the same email address + //
    + // Email to user $00 + // Rating $xx + // Counter $xx xx xx xx (xx ...) + + $frame_offset = 0; + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_emailaddress = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_emailaddress) === 0) { + $frame_emailaddress = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + $frame_rating = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['counter'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset)); + $parsedFrame['email'] = $frame_emailaddress; + $parsedFrame['rating'] = $frame_rating; + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RBUF')) || // 4.18 RBUF Recommended buffer size + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'BUF'))) { // 4.19 BUF Recommended buffer size + // There may only be one 'RBUF' frame in each tag + //
    + // Buffer size $xx xx xx + // Embedded info flag %0000000x + // Offset to next tag $xx xx xx xx + + $frame_offset = 0; + $parsedFrame['buffersize'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 3)); + $frame_offset += 3; + + $frame_embeddedinfoflags = getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['flags']['embededinfo'] = (bool) substr($frame_embeddedinfoflags, 7, 1); + $parsedFrame['nexttagoffset'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4)); + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CRM')) { // 4.20 Encrypted meta frame (ID3v2.2 only) + // There may be more than one 'CRM' frame in a tag, + // but only one with the same 'owner identifier' + //
    + // Owner identifier $00 (00) + // Content/explanation $00 (00) + // Encrypted datablock + + $frame_offset = 0; + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $parsedFrame['ownerid'] = $frame_ownerid; + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + $parsedFrame['description'] = $frame_description; + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'AENC')) || // 4.19 AENC Audio encryption + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CRA'))) { // 4.21 CRA Audio encryption + // There may be more than one 'AENC' frames in a tag, + // but only one with the same 'Owner identifier' + //
    + // Owner identifier $00 + // Preview start $xx xx + // Preview length $xx xx + // Encryption info + + $frame_offset = 0; + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_ownerid) === 0) { + $frame_ownerid == ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + $parsedFrame['ownerid'] = $frame_ownerid; + $parsedFrame['previewstart'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['previewlength'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['encryptioninfo'] = (string) substr($parsedFrame['data'], $frame_offset); + unset($parsedFrame['data']); + + + } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'LINK')) || // 4.20 LINK Linked information + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'LNK'))) { // 4.22 LNK Linked information + // There may be more than one 'LINK' frame in a tag, + // but only one with the same contents + //
    + // ID3v2.3+ => Frame identifier $xx xx xx xx + // ID3v2.2 => Frame identifier $xx xx xx + // URL $00 + // ID and additional data + + $frame_offset = 0; + if ($id3v2_majorversion == 2) { + $parsedFrame['frameid'] = substr($parsedFrame['data'], $frame_offset, 3); + $frame_offset += 3; + } else { + $parsedFrame['frameid'] = substr($parsedFrame['data'], $frame_offset, 4); + $frame_offset += 4; + } + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_url = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_url) === 0) { + $frame_url = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + $parsedFrame['url'] = $frame_url; + + $parsedFrame['additionaldata'] = (string) substr($parsedFrame['data'], $frame_offset); + if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = utf8_encode($parsedFrame['url']); + } + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'POSS')) { // 4.21 POSS Position synchronisation frame (ID3v2.3+ only) + // There may only be one 'POSS' frame in each tag + // + // Time stamp format $xx + // Position $xx (xx ...) + + $frame_offset = 0; + $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['position'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset)); + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USER')) { // 4.22 USER Terms of use (ID3v2.3+ only) + // There may be more than one 'Terms of use' frame in a tag, + // but only one with the same 'Language' + //
    + // Text encoding $xx + // Language $xx xx xx + // The actual text + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $frame_language = substr($parsedFrame['data'], $frame_offset, 3); + $frame_offset += 3; + $parsedFrame['language'] = $frame_language; + $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); + } + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'OWNE')) { // 4.23 OWNE Ownership frame (ID3v2.3+ only) + // There may only be one 'OWNE' frame in a tag + //
    + // Text encoding $xx + // Price paid $00 + // Date of purch. + // Seller + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_pricepaid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $parsedFrame['pricepaid']['currencyid'] = substr($frame_pricepaid, 0, 3); + $parsedFrame['pricepaid']['currency'] = $this->LookupCurrencyUnits($parsedFrame['pricepaid']['currencyid']); + $parsedFrame['pricepaid']['value'] = substr($frame_pricepaid, 3); + + $parsedFrame['purchasedate'] = substr($parsedFrame['data'], $frame_offset, 8); + if (!$this->IsValidDateStampString($parsedFrame['purchasedate'])) { + $parsedFrame['purchasedateunix'] = mktime (0, 0, 0, substr($parsedFrame['purchasedate'], 4, 2), substr($parsedFrame['purchasedate'], 6, 2), substr($parsedFrame['purchasedate'], 0, 4)); + } + $frame_offset += 8; + + $parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset); + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'COMR')) { // 4.24 COMR Commercial frame (ID3v2.3+ only) + // There may be more than one 'commercial frame' in a tag, + // but no two may be identical + //
    + // Text encoding $xx + // Price string $00 + // Valid until + // Contact URL $00 + // Received as $xx + // Name of seller $00 (00) + // Description $00 (00) + // Picture MIME type $00 + // Seller logo + + $frame_offset = 0; + $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) { + $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'; + } + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_pricestring = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + $frame_offset = $frame_terminatorpos + strlen("\x00"); + $frame_rawpricearray = explode('/', $frame_pricestring); + foreach ($frame_rawpricearray as $key => $val) { + $frame_currencyid = substr($val, 0, 3); + $parsedFrame['price'][$frame_currencyid]['currency'] = $this->LookupCurrencyUnits($frame_currencyid); + $parsedFrame['price'][$frame_currencyid]['value'] = substr($val, 3); + } + + $frame_datestring = substr($parsedFrame['data'], $frame_offset, 8); + $frame_offset += 8; + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_contacturl = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $frame_receivedasid = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_sellername = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_sellername) === 0) { + $frame_sellername = ''; + } + $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)); + + $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_description) === 0) { + $frame_description = ''; + } + $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)); + + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_mimetype = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $frame_sellerlogo = substr($parsedFrame['data'], $frame_offset); + + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + + $parsedFrame['pricevaliduntil'] = $frame_datestring; + $parsedFrame['contacturl'] = $frame_contacturl; + $parsedFrame['receivedasid'] = $frame_receivedasid; + $parsedFrame['receivedas'] = $this->COMRReceivedAsLookup($frame_receivedasid); + $parsedFrame['sellername'] = $frame_sellername; + $parsedFrame['description'] = $frame_description; + $parsedFrame['mime'] = $frame_mimetype; + $parsedFrame['logo'] = $frame_sellerlogo; + unset($parsedFrame['data']); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'ENCR')) { // 4.25 ENCR Encryption method registration (ID3v2.3+ only) + // There may be several 'ENCR' frames in a tag, + // but only one containing the same symbol + // and only one containing the same owner identifier + //
    + // Owner identifier $00 + // Method symbol $xx + // Encryption data + + $frame_offset = 0; + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_ownerid) === 0) { + $frame_ownerid = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $parsedFrame['ownerid'] = $frame_ownerid; + $parsedFrame['methodsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GRID')) { // 4.26 GRID Group identification registration (ID3v2.3+ only) + + // There may be several 'GRID' frames in a tag, + // but only one containing the same symbol + // and only one containing the same owner identifier + //
    + // Owner identifier $00 + // Group symbol $xx + // Group dependent data + + $frame_offset = 0; + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_ownerid) === 0) { + $frame_ownerid = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $parsedFrame['ownerid'] = $frame_ownerid; + $parsedFrame['groupsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'PRIV')) { // 4.27 PRIV Private frame (ID3v2.3+ only) + // The tag may contain more than one 'PRIV' frame + // but only with different contents + //
    + // Owner identifier $00 + // The private data + + $frame_offset = 0; + $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset); + $frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + if (ord($frame_ownerid) === 0) { + $frame_ownerid = ''; + } + $frame_offset = $frame_terminatorpos + strlen("\x00"); + + $parsedFrame['ownerid'] = $frame_ownerid; + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + + + } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'SIGN')) { // 4.28 SIGN Signature frame (ID3v2.4+ only) + // There may be more than one 'signature frame' in a tag, + // but no two may be identical + //
    + // Group symbol $xx + // Signature + + $frame_offset = 0; + $parsedFrame['groupsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset); + + + } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'SEEK')) { // 4.29 SEEK Seek frame (ID3v2.4+ only) + // There may only be one 'seek frame' in a tag + //
    + // Minimum offset to next tag $xx xx xx xx + + $frame_offset = 0; + $parsedFrame['data'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4)); + + + } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'ASPI')) { // 4.30 ASPI Audio seek point index (ID3v2.4+ only) + // There may only be one 'audio seek point index' frame in a tag + //
    + // Indexed data start (S) $xx xx xx xx + // Indexed data length (L) $xx xx xx xx + // Number of index points (N) $xx xx + // Bits per index point (b) $xx + // Then for every index point the following data is included: + // Fraction at index (Fi) $xx (xx) + + $frame_offset = 0; + $parsedFrame['datastart'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4)); + $frame_offset += 4; + $parsedFrame['indexeddatalength'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4)); + $frame_offset += 4; + $parsedFrame['indexpoints'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['bitsperpoint'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); + $frame_bytesperpoint = ceil($parsedFrame['bitsperpoint'] / 8); + for ($i = 0; $i < $frame_indexpoints; $i++) { + $parsedFrame['indexes'][$i] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesperpoint)); + $frame_offset += $frame_bytesperpoint; + } + unset($parsedFrame['data']); + + } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RGAD')) { // Replay Gain Adjustment + // http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html + // There may only be one 'RGAD' frame in a tag + //
    + // Peak Amplitude $xx $xx $xx $xx + // Radio Replay Gain Adjustment %aaabbbcd %dddddddd + // Audiophile Replay Gain Adjustment %aaabbbcd %dddddddd + // a - name code + // b - originator code + // c - sign bit + // d - replay gain adjustment + + $frame_offset = 0; + $parsedFrame['peakamplitude'] = getid3_lib::BigEndian2Float(substr($parsedFrame['data'], $frame_offset, 4)); + $frame_offset += 4; + $rg_track_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $rg_album_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['raw']['track']['name'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 0, 3)); + $parsedFrame['raw']['track']['originator'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 3, 3)); + $parsedFrame['raw']['track']['signbit'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 6, 1)); + $parsedFrame['raw']['track']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 7, 9)); + $parsedFrame['raw']['album']['name'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 0, 3)); + $parsedFrame['raw']['album']['originator'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 3, 3)); + $parsedFrame['raw']['album']['signbit'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 6, 1)); + $parsedFrame['raw']['album']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 7, 9)); + $parsedFrame['track']['name'] = getid3_lib::RGADnameLookup($parsedFrame['raw']['track']['name']); + $parsedFrame['track']['originator'] = getid3_lib::RGADoriginatorLookup($parsedFrame['raw']['track']['originator']); + $parsedFrame['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($parsedFrame['raw']['track']['adjustment'], $parsedFrame['raw']['track']['signbit']); + $parsedFrame['album']['name'] = getid3_lib::RGADnameLookup($parsedFrame['raw']['album']['name']); + $parsedFrame['album']['originator'] = getid3_lib::RGADoriginatorLookup($parsedFrame['raw']['album']['originator']); + $parsedFrame['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($parsedFrame['raw']['album']['adjustment'], $parsedFrame['raw']['album']['signbit']); + + $info['replay_gain']['track']['peak'] = $parsedFrame['peakamplitude']; + $info['replay_gain']['track']['originator'] = $parsedFrame['track']['originator']; + $info['replay_gain']['track']['adjustment'] = $parsedFrame['track']['adjustment']; + $info['replay_gain']['album']['originator'] = $parsedFrame['album']['originator']; + $info['replay_gain']['album']['adjustment'] = $parsedFrame['album']['adjustment']; + + unset($parsedFrame['data']); + + } + + return true; + } + + + public function DeUnsynchronise($data) { + return str_replace("\xFF\x00", "\xFF", $data); + } + + public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) { + static $LookupExtendedHeaderRestrictionsTagSizeLimits = array( + 0x00 => 'No more than 128 frames and 1 MB total tag size', + 0x01 => 'No more than 64 frames and 128 KB total tag size', + 0x02 => 'No more than 32 frames and 40 KB total tag size', + 0x03 => 'No more than 32 frames and 4 KB total tag size', + ); + return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : ''); + } + + public function LookupExtendedHeaderRestrictionsTextEncodings($index) { + static $LookupExtendedHeaderRestrictionsTextEncodings = array( + 0x00 => 'No restrictions', + 0x01 => 'Strings are only encoded with ISO-8859-1 or UTF-8', + ); + return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : ''); + } + + public function LookupExtendedHeaderRestrictionsTextFieldSize($index) { + static $LookupExtendedHeaderRestrictionsTextFieldSize = array( + 0x00 => 'No restrictions', + 0x01 => 'No string is longer than 1024 characters', + 0x02 => 'No string is longer than 128 characters', + 0x03 => 'No string is longer than 30 characters', + ); + return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : ''); + } + + public function LookupExtendedHeaderRestrictionsImageEncoding($index) { + static $LookupExtendedHeaderRestrictionsImageEncoding = array( + 0x00 => 'No restrictions', + 0x01 => 'Images are encoded only with PNG or JPEG', + ); + return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : ''); + } + + public function LookupExtendedHeaderRestrictionsImageSizeSize($index) { + static $LookupExtendedHeaderRestrictionsImageSizeSize = array( + 0x00 => 'No restrictions', + 0x01 => 'All images are 256x256 pixels or smaller', + 0x02 => 'All images are 64x64 pixels or smaller', + 0x03 => 'All images are exactly 64x64 pixels, unless required otherwise', + ); + return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : ''); + } + + public function LookupCurrencyUnits($currencyid) { + + $begin = __LINE__; + + /** This is not a comment! + + + AED Dirhams + AFA Afghanis + ALL Leke + AMD Drams + ANG Guilders + AOA Kwanza + ARS Pesos + ATS Schillings + AUD Dollars + AWG Guilders + AZM Manats + BAM Convertible Marka + BBD Dollars + BDT Taka + BEF Francs + BGL Leva + BHD Dinars + BIF Francs + BMD Dollars + BND Dollars + BOB Bolivianos + BRL Brazil Real + BSD Dollars + BTN Ngultrum + BWP Pulas + BYR Rubles + BZD Dollars + CAD Dollars + CDF Congolese Francs + CHF Francs + CLP Pesos + CNY Yuan Renminbi + COP Pesos + CRC Colones + CUP Pesos + CVE Escudos + CYP Pounds + CZK Koruny + DEM Deutsche Marks + DJF Francs + DKK Kroner + DOP Pesos + DZD Algeria Dinars + EEK Krooni + EGP Pounds + ERN Nakfa + ESP Pesetas + ETB Birr + EUR Euro + FIM Markkaa + FJD Dollars + FKP Pounds + FRF Francs + GBP Pounds + GEL Lari + GGP Pounds + GHC Cedis + GIP Pounds + GMD Dalasi + GNF Francs + GRD Drachmae + GTQ Quetzales + GYD Dollars + HKD Dollars + HNL Lempiras + HRK Kuna + HTG Gourdes + HUF Forints + IDR Rupiahs + IEP Pounds + ILS New Shekels + IMP Pounds + INR Rupees + IQD Dinars + IRR Rials + ISK Kronur + ITL Lire + JEP Pounds + JMD Dollars + JOD Dinars + JPY Yen + KES Shillings + KGS Soms + KHR Riels + KMF Francs + KPW Won + KWD Dinars + KYD Dollars + KZT Tenge + LAK Kips + LBP Pounds + LKR Rupees + LRD Dollars + LSL Maloti + LTL Litai + LUF Francs + LVL Lati + LYD Dinars + MAD Dirhams + MDL Lei + MGF Malagasy Francs + MKD Denars + MMK Kyats + MNT Tugriks + MOP Patacas + MRO Ouguiyas + MTL Liri + MUR Rupees + MVR Rufiyaa + MWK Kwachas + MXN Pesos + MYR Ringgits + MZM Meticais + NAD Dollars + NGN Nairas + NIO Gold Cordobas + NLG Guilders + NOK Krone + NPR Nepal Rupees + NZD Dollars + OMR Rials + PAB Balboa + PEN Nuevos Soles + PGK Kina + PHP Pesos + PKR Rupees + PLN Zlotych + PTE Escudos + PYG Guarani + QAR Rials + ROL Lei + RUR Rubles + RWF Rwanda Francs + SAR Riyals + SBD Dollars + SCR Rupees + SDD Dinars + SEK Kronor + SGD Dollars + SHP Pounds + SIT Tolars + SKK Koruny + SLL Leones + SOS Shillings + SPL Luigini + SRG Guilders + STD Dobras + SVC Colones + SYP Pounds + SZL Emalangeni + THB Baht + TJR Rubles + TMM Manats + TND Dinars + TOP Pa'anga + TRL Liras + TTD Dollars + TVD Tuvalu Dollars + TWD New Dollars + TZS Shillings + UAH Hryvnia + UGX Shillings + USD Dollars + UYU Pesos + UZS Sums + VAL Lire + VEB Bolivares + VND Dong + VUV Vatu + WST Tala + XAF Francs + XAG Ounces + XAU Ounces + XCD Dollars + XDR Special Drawing Rights + XPD Ounces + XPF Francs + XPT Ounces + YER Rials + YUM New Dinars + ZAR Rand + ZMK Kwacha + ZWD Zimbabwe Dollars + + */ + + return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units'); + } + + + public function LookupCurrencyCountry($currencyid) { + + $begin = __LINE__; + + /** This is not a comment! + + AED United Arab Emirates + AFA Afghanistan + ALL Albania + AMD Armenia + ANG Netherlands Antilles + AOA Angola + ARS Argentina + ATS Austria + AUD Australia + AWG Aruba + AZM Azerbaijan + BAM Bosnia and Herzegovina + BBD Barbados + BDT Bangladesh + BEF Belgium + BGL Bulgaria + BHD Bahrain + BIF Burundi + BMD Bermuda + BND Brunei Darussalam + BOB Bolivia + BRL Brazil + BSD Bahamas + BTN Bhutan + BWP Botswana + BYR Belarus + BZD Belize + CAD Canada + CDF Congo/Kinshasa + CHF Switzerland + CLP Chile + CNY China + COP Colombia + CRC Costa Rica + CUP Cuba + CVE Cape Verde + CYP Cyprus + CZK Czech Republic + DEM Germany + DJF Djibouti + DKK Denmark + DOP Dominican Republic + DZD Algeria + EEK Estonia + EGP Egypt + ERN Eritrea + ESP Spain + ETB Ethiopia + EUR Euro Member Countries + FIM Finland + FJD Fiji + FKP Falkland Islands (Malvinas) + FRF France + GBP United Kingdom + GEL Georgia + GGP Guernsey + GHC Ghana + GIP Gibraltar + GMD Gambia + GNF Guinea + GRD Greece + GTQ Guatemala + GYD Guyana + HKD Hong Kong + HNL Honduras + HRK Croatia + HTG Haiti + HUF Hungary + IDR Indonesia + IEP Ireland (Eire) + ILS Israel + IMP Isle of Man + INR India + IQD Iraq + IRR Iran + ISK Iceland + ITL Italy + JEP Jersey + JMD Jamaica + JOD Jordan + JPY Japan + KES Kenya + KGS Kyrgyzstan + KHR Cambodia + KMF Comoros + KPW Korea + KWD Kuwait + KYD Cayman Islands + KZT Kazakstan + LAK Laos + LBP Lebanon + LKR Sri Lanka + LRD Liberia + LSL Lesotho + LTL Lithuania + LUF Luxembourg + LVL Latvia + LYD Libya + MAD Morocco + MDL Moldova + MGF Madagascar + MKD Macedonia + MMK Myanmar (Burma) + MNT Mongolia + MOP Macau + MRO Mauritania + MTL Malta + MUR Mauritius + MVR Maldives (Maldive Islands) + MWK Malawi + MXN Mexico + MYR Malaysia + MZM Mozambique + NAD Namibia + NGN Nigeria + NIO Nicaragua + NLG Netherlands (Holland) + NOK Norway + NPR Nepal + NZD New Zealand + OMR Oman + PAB Panama + PEN Peru + PGK Papua New Guinea + PHP Philippines + PKR Pakistan + PLN Poland + PTE Portugal + PYG Paraguay + QAR Qatar + ROL Romania + RUR Russia + RWF Rwanda + SAR Saudi Arabia + SBD Solomon Islands + SCR Seychelles + SDD Sudan + SEK Sweden + SGD Singapore + SHP Saint Helena + SIT Slovenia + SKK Slovakia + SLL Sierra Leone + SOS Somalia + SPL Seborga + SRG Suriname + STD São Tome and Principe + SVC El Salvador + SYP Syria + SZL Swaziland + THB Thailand + TJR Tajikistan + TMM Turkmenistan + TND Tunisia + TOP Tonga + TRL Turkey + TTD Trinidad and Tobago + TVD Tuvalu + TWD Taiwan + TZS Tanzania + UAH Ukraine + UGX Uganda + USD United States of America + UYU Uruguay + UZS Uzbekistan + VAL Vatican City + VEB Venezuela + VND Viet Nam + VUV Vanuatu + WST Samoa + XAF Communauté Financière Africaine + XAG Silver + XAU Gold + XCD East Caribbean + XDR International Monetary Fund + XPD Palladium + XPF Comptoirs Français du Pacifique + XPT Platinum + YER Yemen + YUM Yugoslavia + ZAR South Africa + ZMK Zambia + ZWD Zimbabwe + + */ + + return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country'); + } + + + + public static function LanguageLookup($languagecode, $casesensitive=false) { + + if (!$casesensitive) { + $languagecode = strtolower($languagecode); + } + + // http://www.id3.org/id3v2.4.0-structure.txt + // [4. ID3v2 frame overview] + // The three byte language field, present in several frames, is used to + // describe the language of the frame's content, according to ISO-639-2 + // [ISO-639-2]. The language should be represented in lower case. If the + // language is not known the string "XXX" should be used. + + + // ISO 639-2 - http://www.id3.org/iso639-2.html + + $begin = __LINE__; + + /** This is not a comment! + + XXX unknown + xxx unknown + aar Afar + abk Abkhazian + ace Achinese + ach Acoli + ada Adangme + afa Afro-Asiatic (Other) + afh Afrihili + afr Afrikaans + aka Akan + akk Akkadian + alb Albanian + ale Aleut + alg Algonquian Languages + amh Amharic + ang English, Old (ca. 450-1100) + apa Apache Languages + ara Arabic + arc Aramaic + arm Armenian + arn Araucanian + arp Arapaho + art Artificial (Other) + arw Arawak + asm Assamese + ath Athapascan Languages + ava Avaric + ave Avestan + awa Awadhi + aym Aymara + aze Azerbaijani + bad Banda + bai Bamileke Languages + bak Bashkir + bal Baluchi + bam Bambara + ban Balinese + baq Basque + bas Basa + bat Baltic (Other) + bej Beja + bel Byelorussian + bem Bemba + ben Bengali + ber Berber (Other) + bho Bhojpuri + bih Bihari + bik Bikol + bin Bini + bis Bislama + bla Siksika + bnt Bantu (Other) + bod Tibetan + bra Braj + bre Breton + bua Buriat + bug Buginese + bul Bulgarian + bur Burmese + cad Caddo + cai Central American Indian (Other) + car Carib + cat Catalan + cau Caucasian (Other) + ceb Cebuano + cel Celtic (Other) + ces Czech + cha Chamorro + chb Chibcha + che Chechen + chg Chagatai + chi Chinese + chm Mari + chn Chinook jargon + cho Choctaw + chr Cherokee + chu Church Slavic + chv Chuvash + chy Cheyenne + cop Coptic + cor Cornish + cos Corsican + cpe Creoles and Pidgins, English-based (Other) + cpf Creoles and Pidgins, French-based (Other) + cpp Creoles and Pidgins, Portuguese-based (Other) + cre Cree + crp Creoles and Pidgins (Other) + cus Cushitic (Other) + cym Welsh + cze Czech + dak Dakota + dan Danish + del Delaware + deu German + din Dinka + div Divehi + doi Dogri + dra Dravidian (Other) + dua Duala + dum Dutch, Middle (ca. 1050-1350) + dut Dutch + dyu Dyula + dzo Dzongkha + efi Efik + egy Egyptian (Ancient) + eka Ekajuk + ell Greek, Modern (1453-) + elx Elamite + eng English + enm English, Middle (ca. 1100-1500) + epo Esperanto + esk Eskimo (Other) + esl Spanish + est Estonian + eus Basque + ewe Ewe + ewo Ewondo + fan Fang + fao Faroese + fas Persian + fat Fanti + fij Fijian + fin Finnish + fiu Finno-Ugrian (Other) + fon Fon + fra French + fre French + frm French, Middle (ca. 1400-1600) + fro French, Old (842- ca. 1400) + fry Frisian + ful Fulah + gaa Ga + gae Gaelic (Scots) + gai Irish + gay Gayo + gdh Gaelic (Scots) + gem Germanic (Other) + geo Georgian + ger German + gez Geez + gil Gilbertese + glg Gallegan + gmh German, Middle High (ca. 1050-1500) + goh German, Old High (ca. 750-1050) + gon Gondi + got Gothic + grb Grebo + grc Greek, Ancient (to 1453) + gre Greek, Modern (1453-) + grn Guarani + guj Gujarati + hai Haida + hau Hausa + haw Hawaiian + heb Hebrew + her Herero + hil Hiligaynon + him Himachali + hin Hindi + hmo Hiri Motu + hun Hungarian + hup Hupa + hye Armenian + iba Iban + ibo Igbo + ice Icelandic + ijo Ijo + iku Inuktitut + ilo Iloko + ina Interlingua (International Auxiliary language Association) + inc Indic (Other) + ind Indonesian + ine Indo-European (Other) + ine Interlingue + ipk Inupiak + ira Iranian (Other) + iri Irish + iro Iroquoian uages + isl Icelandic + ita Italian + jav Javanese + jaw Javanese + jpn Japanese + jpr Judeo-Persian + jrb Judeo-Arabic + kaa Kara-Kalpak + kab Kabyle + kac Kachin + kal Greenlandic + kam Kamba + kan Kannada + kar Karen + kas Kashmiri + kat Georgian + kau Kanuri + kaw Kawi + kaz Kazakh + kha Khasi + khi Khoisan (Other) + khm Khmer + kho Khotanese + kik Kikuyu + kin Kinyarwanda + kir Kirghiz + kok Konkani + kom Komi + kon Kongo + kor Korean + kpe Kpelle + kro Kru + kru Kurukh + kua Kuanyama + kum Kumyk + kur Kurdish + kus Kusaie + kut Kutenai + lad Ladino + lah Lahnda + lam Lamba + lao Lao + lat Latin + lav Latvian + lez Lezghian + lin Lingala + lit Lithuanian + lol Mongo + loz Lozi + ltz Letzeburgesch + lub Luba-Katanga + lug Ganda + lui Luiseno + lun Lunda + luo Luo (Kenya and Tanzania) + mac Macedonian + mad Madurese + mag Magahi + mah Marshall + mai Maithili + mak Macedonian + mak Makasar + mal Malayalam + man Mandingo + mao Maori + map Austronesian (Other) + mar Marathi + mas Masai + max Manx + may Malay + men Mende + mga Irish, Middle (900 - 1200) + mic Micmac + min Minangkabau + mis Miscellaneous (Other) + mkh Mon-Kmer (Other) + mlg Malagasy + mlt Maltese + mni Manipuri + mno Manobo Languages + moh Mohawk + mol Moldavian + mon Mongolian + mos Mossi + mri Maori + msa Malay + mul Multiple Languages + mun Munda Languages + mus Creek + mwr Marwari + mya Burmese + myn Mayan Languages + nah Aztec + nai North American Indian (Other) + nau Nauru + nav Navajo + nbl Ndebele, South + nde Ndebele, North + ndo Ndongo + nep Nepali + new Newari + nic Niger-Kordofanian (Other) + niu Niuean + nla Dutch + nno Norwegian (Nynorsk) + non Norse, Old + nor Norwegian + nso Sotho, Northern + nub Nubian Languages + nya Nyanja + nym Nyamwezi + nyn Nyankole + nyo Nyoro + nzi Nzima + oci Langue d'Oc (post 1500) + oji Ojibwa + ori Oriya + orm Oromo + osa Osage + oss Ossetic + ota Turkish, Ottoman (1500 - 1928) + oto Otomian Languages + paa Papuan-Australian (Other) + pag Pangasinan + pal Pahlavi + pam Pampanga + pan Panjabi + pap Papiamento + pau Palauan + peo Persian, Old (ca 600 - 400 B.C.) + per Persian + phn Phoenician + pli Pali + pol Polish + pon Ponape + por Portuguese + pra Prakrit uages + pro Provencal, Old (to 1500) + pus Pushto + que Quechua + raj Rajasthani + rar Rarotongan + roa Romance (Other) + roh Rhaeto-Romance + rom Romany + ron Romanian + rum Romanian + run Rundi + rus Russian + sad Sandawe + sag Sango + sah Yakut + sai South American Indian (Other) + sal Salishan Languages + sam Samaritan Aramaic + san Sanskrit + sco Scots + scr Serbo-Croatian + sel Selkup + sem Semitic (Other) + sga Irish, Old (to 900) + shn Shan + sid Sidamo + sin Singhalese + sio Siouan Languages + sit Sino-Tibetan (Other) + sla Slavic (Other) + slk Slovak + slo Slovak + slv Slovenian + smi Sami Languages + smo Samoan + sna Shona + snd Sindhi + sog Sogdian + som Somali + son Songhai + sot Sotho, Southern + spa Spanish + sqi Albanian + srd Sardinian + srr Serer + ssa Nilo-Saharan (Other) + ssw Siswant + ssw Swazi + suk Sukuma + sun Sudanese + sus Susu + sux Sumerian + sve Swedish + swa Swahili + swe Swedish + syr Syriac + tah Tahitian + tam Tamil + tat Tatar + tel Telugu + tem Timne + ter Tereno + tgk Tajik + tgl Tagalog + tha Thai + tib Tibetan + tig Tigre + tir Tigrinya + tiv Tivi + tli Tlingit + tmh Tamashek + tog Tonga (Nyasa) + ton Tonga (Tonga Islands) + tru Truk + tsi Tsimshian + tsn Tswana + tso Tsonga + tuk Turkmen + tum Tumbuka + tur Turkish + tut Altaic (Other) + twi Twi + tyv Tuvinian + uga Ugaritic + uig Uighur + ukr Ukrainian + umb Umbundu + und Undetermined + urd Urdu + uzb Uzbek + vai Vai + ven Venda + vie Vietnamese + vol Volapük + vot Votic + wak Wakashan Languages + wal Walamo + war Waray + was Washo + wel Welsh + wen Sorbian Languages + wol Wolof + xho Xhosa + yao Yao + yap Yap + yid Yiddish + yor Yoruba + zap Zapotec + zen Zenaga + zha Zhuang + zho Chinese + zul Zulu + zun Zuni + + */ + + return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode'); + } + + + public static function ETCOEventLookup($index) { + if (($index >= 0x17) && ($index <= 0xDF)) { + return 'reserved for future use'; + } + if (($index >= 0xE0) && ($index <= 0xEF)) { + return 'not predefined synch 0-F'; + } + if (($index >= 0xF0) && ($index <= 0xFC)) { + return 'reserved for future use'; + } + + static $EventLookup = array( + 0x00 => 'padding (has no meaning)', + 0x01 => 'end of initial silence', + 0x02 => 'intro start', + 0x03 => 'main part start', + 0x04 => 'outro start', + 0x05 => 'outro end', + 0x06 => 'verse start', + 0x07 => 'refrain start', + 0x08 => 'interlude start', + 0x09 => 'theme start', + 0x0A => 'variation start', + 0x0B => 'key change', + 0x0C => 'time change', + 0x0D => 'momentary unwanted noise (Snap, Crackle & Pop)', + 0x0E => 'sustained noise', + 0x0F => 'sustained noise end', + 0x10 => 'intro end', + 0x11 => 'main part end', + 0x12 => 'verse end', + 0x13 => 'refrain end', + 0x14 => 'theme end', + 0x15 => 'profanity', + 0x16 => 'profanity end', + 0xFD => 'audio end (start of silence)', + 0xFE => 'audio file ends', + 0xFF => 'one more byte of events follows' + ); + + return (isset($EventLookup[$index]) ? $EventLookup[$index] : ''); + } + + public static function SYTLContentTypeLookup($index) { + static $SYTLContentTypeLookup = array( + 0x00 => 'other', + 0x01 => 'lyrics', + 0x02 => 'text transcription', + 0x03 => 'movement/part name', // (e.g. 'Adagio') + 0x04 => 'events', // (e.g. 'Don Quijote enters the stage') + 0x05 => 'chord', // (e.g. 'Bb F Fsus') + 0x06 => 'trivia/\'pop up\' information', + 0x07 => 'URLs to webpages', + 0x08 => 'URLs to images' + ); + + return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : ''); + } + + public static function APICPictureTypeLookup($index, $returnarray=false) { + static $APICPictureTypeLookup = array( + 0x00 => 'Other', + 0x01 => '32x32 pixels \'file icon\' (PNG only)', + 0x02 => 'Other file icon', + 0x03 => 'Cover (front)', + 0x04 => 'Cover (back)', + 0x05 => 'Leaflet page', + 0x06 => 'Media (e.g. label side of CD)', + 0x07 => 'Lead artist/lead performer/soloist', + 0x08 => 'Artist/performer', + 0x09 => 'Conductor', + 0x0A => 'Band/Orchestra', + 0x0B => 'Composer', + 0x0C => 'Lyricist/text writer', + 0x0D => 'Recording Location', + 0x0E => 'During recording', + 0x0F => 'During performance', + 0x10 => 'Movie/video screen capture', + 0x11 => 'A bright coloured fish', + 0x12 => 'Illustration', + 0x13 => 'Band/artist logotype', + 0x14 => 'Publisher/Studio logotype' + ); + if ($returnarray) { + return $APICPictureTypeLookup; + } + return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : ''); + } + + public static function COMRReceivedAsLookup($index) { + static $COMRReceivedAsLookup = array( + 0x00 => 'Other', + 0x01 => 'Standard CD album with other songs', + 0x02 => 'Compressed audio on CD', + 0x03 => 'File over the Internet', + 0x04 => 'Stream over the Internet', + 0x05 => 'As note sheets', + 0x06 => 'As note sheets in a book with other sheets', + 0x07 => 'Music on other media', + 0x08 => 'Non-musical merchandise' + ); + + return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : ''); + } + + public static function RVA2ChannelTypeLookup($index) { + static $RVA2ChannelTypeLookup = array( + 0x00 => 'Other', + 0x01 => 'Master volume', + 0x02 => 'Front right', + 0x03 => 'Front left', + 0x04 => 'Back right', + 0x05 => 'Back left', + 0x06 => 'Front centre', + 0x07 => 'Back centre', + 0x08 => 'Subwoofer' + ); + + return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : ''); + } + + public static function FrameNameLongLookup($framename) { + + $begin = __LINE__; + + /** This is not a comment! + + AENC Audio encryption + APIC Attached picture + ASPI Audio seek point index + BUF Recommended buffer size + CNT Play counter + COM Comments + COMM Comments + COMR Commercial frame + CRA Audio encryption + CRM Encrypted meta frame + ENCR Encryption method registration + EQU Equalisation + EQU2 Equalisation (2) + EQUA Equalisation + ETC Event timing codes + ETCO Event timing codes + GEO General encapsulated object + GEOB General encapsulated object + GRID Group identification registration + IPL Involved people list + IPLS Involved people list + LINK Linked information + LNK Linked information + MCDI Music CD identifier + MCI Music CD Identifier + MLL MPEG location lookup table + MLLT MPEG location lookup table + OWNE Ownership frame + PCNT Play counter + PIC Attached picture + POP Popularimeter + POPM Popularimeter + POSS Position synchronisation frame + PRIV Private frame + RBUF Recommended buffer size + REV Reverb + RVA Relative volume adjustment + RVA2 Relative volume adjustment (2) + RVAD Relative volume adjustment + RVRB Reverb + SEEK Seek frame + SIGN Signature frame + SLT Synchronised lyric/text + STC Synced tempo codes + SYLT Synchronised lyric/text + SYTC Synchronised tempo codes + TAL Album/Movie/Show title + TALB Album/Movie/Show title + TBP BPM (Beats Per Minute) + TBPM BPM (beats per minute) + TCM Composer + TCMP Part of a compilation + TCO Content type + TCOM Composer + TCON Content type + TCOP Copyright message + TCP Part of a compilation + TCR Copyright message + TDA Date + TDAT Date + TDEN Encoding time + TDLY Playlist delay + TDOR Original release time + TDRC Recording time + TDRL Release time + TDTG Tagging time + TDY Playlist delay + TEN Encoded by + TENC Encoded by + TEXT Lyricist/Text writer + TFLT File type + TFT File type + TIM Time + TIME Time + TIPL Involved people list + TIT1 Content group description + TIT2 Title/songname/content description + TIT3 Subtitle/Description refinement + TKE Initial key + TKEY Initial key + TLA Language(s) + TLAN Language(s) + TLE Length + TLEN Length + TMCL Musician credits list + TMED Media type + TMOO Mood + TMT Media type + TOA Original artist(s)/performer(s) + TOAL Original album/movie/show title + TOF Original filename + TOFN Original filename + TOL Original Lyricist(s)/text writer(s) + TOLY Original lyricist(s)/text writer(s) + TOPE Original artist(s)/performer(s) + TOR Original release year + TORY Original release year + TOT Original album/Movie/Show title + TOWN File owner/licensee + TP1 Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group + TP2 Band/Orchestra/Accompaniment + TP3 Conductor/Performer refinement + TP4 Interpreted, remixed, or otherwise modified by + TPA Part of a set + TPB Publisher + TPE1 Lead performer(s)/Soloist(s) + TPE2 Band/orchestra/accompaniment + TPE3 Conductor/performer refinement + TPE4 Interpreted, remixed, or otherwise modified by + TPOS Part of a set + TPRO Produced notice + TPUB Publisher + TRC ISRC (International Standard Recording Code) + TRCK Track number/Position in set + TRD Recording dates + TRDA Recording dates + TRK Track number/Position in set + TRSN Internet radio station name + TRSO Internet radio station owner + TS2 Album-Artist sort order + TSA Album sort order + TSC Composer sort order + TSI Size + TSIZ Size + TSO2 Album-Artist sort order + TSOA Album sort order + TSOC Composer sort order + TSOP Performer sort order + TSOT Title sort order + TSP Performer sort order + TSRC ISRC (international standard recording code) + TSS Software/hardware and settings used for encoding + TSSE Software/Hardware and settings used for encoding + TSST Set subtitle + TST Title sort order + TT1 Content group description + TT2 Title/Songname/Content description + TT3 Subtitle/Description refinement + TXT Lyricist/text writer + TXX User defined text information frame + TXXX User defined text information frame + TYE Year + TYER Year + UFI Unique file identifier + UFID Unique file identifier + ULT Unsychronised lyric/text transcription + USER Terms of use + USLT Unsynchronised lyric/text transcription + WAF Official audio file webpage + WAR Official artist/performer webpage + WAS Official audio source webpage + WCM Commercial information + WCOM Commercial information + WCOP Copyright/Legal information + WCP Copyright/Legal information + WOAF Official audio file webpage + WOAR Official artist/performer webpage + WOAS Official audio source webpage + WORS Official Internet radio station homepage + WPAY Payment + WPB Publishers official webpage + WPUB Publishers official webpage + WXX User defined URL link frame + WXXX User defined URL link frame + TFEA Featured Artist + TSTU Recording Studio + rgad Replay Gain Adjustment + + */ + + return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_long'); + + // Last three: + // from Helium2 [www.helium2.com] + // from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html + } + + + public static function FrameNameShortLookup($framename) { + + $begin = __LINE__; + + /** This is not a comment! + + AENC audio_encryption + APIC attached_picture + ASPI audio_seek_point_index + BUF recommended_buffer_size + CNT play_counter + COM comment + COMM comment + COMR commercial_frame + CRA audio_encryption + CRM encrypted_meta_frame + ENCR encryption_method_registration + EQU equalisation + EQU2 equalisation + EQUA equalisation + ETC event_timing_codes + ETCO event_timing_codes + GEO general_encapsulated_object + GEOB general_encapsulated_object + GRID group_identification_registration + IPL involved_people_list + IPLS involved_people_list + LINK linked_information + LNK linked_information + MCDI music_cd_identifier + MCI music_cd_identifier + MLL mpeg_location_lookup_table + MLLT mpeg_location_lookup_table + OWNE ownership_frame + PCNT play_counter + PIC attached_picture + POP popularimeter + POPM popularimeter + POSS position_synchronisation_frame + PRIV private_frame + RBUF recommended_buffer_size + REV reverb + RVA relative_volume_adjustment + RVA2 relative_volume_adjustment + RVAD relative_volume_adjustment + RVRB reverb + SEEK seek_frame + SIGN signature_frame + SLT synchronised_lyric + STC synced_tempo_codes + SYLT synchronised_lyric + SYTC synchronised_tempo_codes + TAL album + TALB album + TBP bpm + TBPM bpm + TCM composer + TCMP part_of_a_compilation + TCO genre + TCOM composer + TCON genre + TCOP copyright_message + TCP part_of_a_compilation + TCR copyright_message + TDA date + TDAT date + TDEN encoding_time + TDLY playlist_delay + TDOR original_release_time + TDRC recording_time + TDRL release_time + TDTG tagging_time + TDY playlist_delay + TEN encoded_by + TENC encoded_by + TEXT lyricist + TFLT file_type + TFT file_type + TIM time + TIME time + TIPL involved_people_list + TIT1 content_group_description + TIT2 title + TIT3 subtitle + TKE initial_key + TKEY initial_key + TLA language + TLAN language + TLE length + TLEN length + TMCL musician_credits_list + TMED media_type + TMOO mood + TMT media_type + TOA original_artist + TOAL original_album + TOF original_filename + TOFN original_filename + TOL original_lyricist + TOLY original_lyricist + TOPE original_artist + TOR original_year + TORY original_year + TOT original_album + TOWN file_owner + TP1 artist + TP2 band + TP3 conductor + TP4 remixer + TPA part_of_a_set + TPB publisher + TPE1 artist + TPE2 band + TPE3 conductor + TPE4 remixer + TPOS part_of_a_set + TPRO produced_notice + TPUB publisher + TRC isrc + TRCK track_number + TRD recording_dates + TRDA recording_dates + TRK track_number + TRSN internet_radio_station_name + TRSO internet_radio_station_owner + TS2 album_artist_sort_order + TSA album_sort_order + TSC composer_sort_order + TSI size + TSIZ size + TSO2 album_artist_sort_order + TSOA album_sort_order + TSOC composer_sort_order + TSOP performer_sort_order + TSOT title_sort_order + TSP performer_sort_order + TSRC isrc + TSS encoder_settings + TSSE encoder_settings + TSST set_subtitle + TST title_sort_order + TT1 content_group_description + TT2 title + TT3 subtitle + TXT lyricist + TXX text + TXXX text + TYE year + TYER year + UFI unique_file_identifier + UFID unique_file_identifier + ULT unsychronised_lyric + USER terms_of_use + USLT unsynchronised_lyric + WAF url_file + WAR url_artist + WAS url_source + WCM commercial_information + WCOM commercial_information + WCOP copyright + WCP copyright + WOAF url_file + WOAR url_artist + WOAS url_source + WORS url_station + WPAY url_payment + WPB url_publisher + WPUB url_publisher + WXX url_user + WXXX url_user + TFEA featured_artist + TSTU recording_studio + rgad replay_gain_adjustment + + */ + + return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short'); + } + + public static function TextEncodingTerminatorLookup($encoding) { + // http://www.id3.org/id3v2.4.0-structure.txt + // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings: + static $TextEncodingTerminatorLookup = array( + 0 => "\x00", // $00 ISO-8859-1. Terminated with $00. + 1 => "\x00\x00", // $01 UTF-16 encoded Unicode with BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00. + 2 => "\x00\x00", // $02 UTF-16BE encoded Unicode without BOM. Terminated with $00 00. + 3 => "\x00", // $03 UTF-8 encoded Unicode. Terminated with $00. + 255 => "\x00\x00" + ); + return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : ''); + } + + public static function TextEncodingNameLookup($encoding) { + // http://www.id3.org/id3v2.4.0-structure.txt + // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings: + static $TextEncodingNameLookup = array( + 0 => 'ISO-8859-1', // $00 ISO-8859-1. Terminated with $00. + 1 => 'UTF-16', // $01 UTF-16 encoded Unicode with BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00. + 2 => 'UTF-16BE', // $02 UTF-16BE encoded Unicode without BOM. Terminated with $00 00. + 3 => 'UTF-8', // $03 UTF-8 encoded Unicode. Terminated with $00. + 255 => 'UTF-16BE' + ); + return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1'); + } + + public static function IsValidID3v2FrameName($framename, $id3v2majorversion) { + switch ($id3v2majorversion) { + case 2: + return preg_match('#[A-Z][A-Z0-9]{2}#', $framename); + break; + + case 3: + case 4: + return preg_match('#[A-Z][A-Z0-9]{3}#', $framename); + break; + } + return false; + } + + public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) { + for ($i = 0; $i < strlen($numberstring); $i++) { + if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) { + if (($numberstring{$i} == '.') && $allowdecimal) { + // allowed + } elseif (($numberstring{$i} == '-') && $allownegative && ($i == 0)) { + // allowed + } else { + return false; + } + } + } + return true; + } + + public static function IsValidDateStampString($datestamp) { + if (strlen($datestamp) != 8) { + return false; + } + if (!self::IsANumber($datestamp, false)) { + return false; + } + $year = substr($datestamp, 0, 4); + $month = substr($datestamp, 4, 2); + $day = substr($datestamp, 6, 2); + if (($year == 0) || ($month == 0) || ($day == 0)) { + return false; + } + if ($month > 12) { + return false; + } + if ($day > 31) { + return false; + } + if (($day > 30) && (($month == 4) || ($month == 6) || ($month == 9) || ($month == 11))) { + return false; + } + if (($day > 29) && ($month == 2)) { + return false; + } + return true; + } + + public static function ID3v2HeaderLength($majorversion) { + return (($majorversion == 2) ? 6 : 10); + } + +} + diff --git a/sources/wp-includes/ID3/module.tag.lyrics3.php b/sources/wp-includes/ID3/module.tag.lyrics3.php new file mode 100644 index 0000000..108d7ae --- /dev/null +++ b/sources/wp-includes/ID3/module.tag.lyrics3.php @@ -0,0 +1,294 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +/// // +// module.tag.lyrics3.php // +// module for analyzing Lyrics3 tags // +// dependencies: module.tag.apetag.php (optional) // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_lyrics3 extends getid3_handler +{ + + public function Analyze() { + $info = &$this->getid3->info; + + // http://www.volweb.cz/str/tags.htm + + if (!getid3_lib::intValueSupported($info['filesize'])) { + $info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; + return false; + } + + fseek($this->getid3->fp, (0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] + $lyrics3_id3v1 = fread($this->getid3->fp, 128 + 9 + 6); + $lyrics3lsz = substr($lyrics3_id3v1, 0, 6); // Lyrics3size + $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 + $id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1 + + if ($lyrics3end == 'LYRICSEND') { + // Lyrics3v1, ID3v1, no APE + + $lyrics3size = 5100; + $lyrics3offset = $info['filesize'] - 128 - $lyrics3size; + $lyrics3version = 1; + + } elseif ($lyrics3end == 'LYRICS200') { + // Lyrics3v2, ID3v1, no APE + + // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' + $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); + $lyrics3offset = $info['filesize'] - 128 - $lyrics3size; + $lyrics3version = 2; + + } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICSEND')) { + // Lyrics3v1, no ID3v1, no APE + + $lyrics3size = 5100; + $lyrics3offset = $info['filesize'] - $lyrics3size; + $lyrics3version = 1; + $lyrics3offset = $info['filesize'] - $lyrics3size; + + } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICS200')) { + + // Lyrics3v2, no ID3v1, no APE + + $lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' + $lyrics3offset = $info['filesize'] - $lyrics3size; + $lyrics3version = 2; + + } else { + + if (isset($info['ape']['tag_offset_start']) && ($info['ape']['tag_offset_start'] > 15)) { + + fseek($this->getid3->fp, $info['ape']['tag_offset_start'] - 15, SEEK_SET); + $lyrics3lsz = fread($this->getid3->fp, 6); + $lyrics3end = fread($this->getid3->fp, 9); + + if ($lyrics3end == 'LYRICSEND') { + // Lyrics3v1, APE, maybe ID3v1 + + $lyrics3size = 5100; + $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size; + $info['avdataend'] = $lyrics3offset; + $lyrics3version = 1; + $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability'; + + } elseif ($lyrics3end == 'LYRICS200') { + // Lyrics3v2, APE, maybe ID3v1 + + $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' + $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size; + $lyrics3version = 2; + $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability'; + + } + + } + + } + + if (isset($lyrics3offset)) { + $info['avdataend'] = $lyrics3offset; + $this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size); + + if (!isset($info['ape'])) { + $GETID3_ERRORARRAY = &$info['warning']; + if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, false)) { + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_apetag = new getid3_apetag($getid3_temp); + $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start']; + $getid3_apetag->Analyze(); + if (!empty($getid3_temp->info['ape'])) { + $info['ape'] = $getid3_temp->info['ape']; + } + if (!empty($getid3_temp->info['replay_gain'])) { + $info['replay_gain'] = $getid3_temp->info['replay_gain']; + } + unset($getid3_temp, $getid3_apetag); + } + } + + } + + return true; + } + + public function getLyrics3Data($endoffset, $version, $length) { + // http://www.volweb.cz/str/tags.htm + + $info = &$this->getid3->info; + + if (!getid3_lib::intValueSupported($endoffset)) { + $info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; + return false; + } + + fseek($this->getid3->fp, $endoffset, SEEK_SET); + if ($length <= 0) { + return false; + } + $rawdata = fread($this->getid3->fp, $length); + + $ParsedLyrics3['raw']['lyrics3version'] = $version; + $ParsedLyrics3['raw']['lyrics3tagsize'] = $length; + $ParsedLyrics3['tag_offset_start'] = $endoffset; + $ParsedLyrics3['tag_offset_end'] = $endoffset + $length - 1; + + if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') { + if (strpos($rawdata, 'LYRICSBEGIN') !== false) { + + $info['warning'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version; + $info['avdataend'] = $endoffset + strpos($rawdata, 'LYRICSBEGIN'); + $rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN')); + $length = strlen($rawdata); + $ParsedLyrics3['tag_offset_start'] = $info['avdataend']; + $ParsedLyrics3['raw']['lyrics3tagsize'] = $length; + + } else { + + $info['error'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead'; + return false; + + } + + } + + switch ($version) { + + case 1: + if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICSEND') { + $ParsedLyrics3['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9)); + $this->Lyrics3LyricsTimestampParse($ParsedLyrics3); + } else { + $info['error'][] = '"LYRICSEND" expected at '.(ftell($this->getid3->fp) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead'; + return false; + } + break; + + case 2: + if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICS200') { + $ParsedLyrics3['raw']['unparsed'] = substr($rawdata, 11, strlen($rawdata) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ + $rawdata = $ParsedLyrics3['raw']['unparsed']; + while (strlen($rawdata) > 0) { + $fieldname = substr($rawdata, 0, 3); + $fieldsize = (int) substr($rawdata, 3, 5); + $ParsedLyrics3['raw'][$fieldname] = substr($rawdata, 8, $fieldsize); + $rawdata = substr($rawdata, 3 + 5 + $fieldsize); + } + + if (isset($ParsedLyrics3['raw']['IND'])) { + $i = 0; + $flagnames = array('lyrics', 'timestamps', 'inhibitrandom'); + foreach ($flagnames as $flagname) { + if (strlen($ParsedLyrics3['raw']['IND']) > $i++) { + $ParsedLyrics3['flags'][$flagname] = $this->IntString2Bool(substr($ParsedLyrics3['raw']['IND'], $i, 1 - 1)); + } + } + } + + $fieldnametranslation = array('ETT'=>'title', 'EAR'=>'artist', 'EAL'=>'album', 'INF'=>'comment', 'AUT'=>'author'); + foreach ($fieldnametranslation as $key => $value) { + if (isset($ParsedLyrics3['raw'][$key])) { + $ParsedLyrics3['comments'][$value][] = trim($ParsedLyrics3['raw'][$key]); + } + } + + if (isset($ParsedLyrics3['raw']['IMG'])) { + $imagestrings = explode("\r\n", $ParsedLyrics3['raw']['IMG']); + foreach ($imagestrings as $key => $imagestring) { + if (strpos($imagestring, '||') !== false) { + $imagearray = explode('||', $imagestring); + $ParsedLyrics3['images'][$key]['filename'] = (isset($imagearray[0]) ? $imagearray[0] : ''); + $ParsedLyrics3['images'][$key]['description'] = (isset($imagearray[1]) ? $imagearray[1] : ''); + $ParsedLyrics3['images'][$key]['timestamp'] = $this->Lyrics3Timestamp2Seconds(isset($imagearray[2]) ? $imagearray[2] : ''); + } + } + } + if (isset($ParsedLyrics3['raw']['LYR'])) { + $this->Lyrics3LyricsTimestampParse($ParsedLyrics3); + } + } else { + $info['error'][] = '"LYRICS200" expected at '.(ftell($this->getid3->fp) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead'; + return false; + } + break; + + default: + $info['error'][] = 'Cannot process Lyrics3 version '.$version.' (only v1 and v2)'; + return false; + break; + } + + + if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] <= $ParsedLyrics3['tag_offset_end'])) { + $info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data'; + unset($info['id3v1']); + foreach ($info['warning'] as $key => $value) { + if ($value == 'Some ID3v1 fields do not use NULL characters for padding') { + unset($info['warning'][$key]); + sort($info['warning']); + break; + } + } + } + + $info['lyrics3'] = $ParsedLyrics3; + + return true; + } + + public function Lyrics3Timestamp2Seconds($rawtimestamp) { + if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) { + return (int) (($regs[1] * 60) + $regs[2]); + } + return false; + } + + public function Lyrics3LyricsTimestampParse(&$Lyrics3data) { + $lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']); + foreach ($lyricsarray as $key => $lyricline) { + $regs = array(); + unset($thislinetimestamps); + while (preg_match('#^(\\[[0-9]{2}:[0-9]{2}\\])#', $lyricline, $regs)) { + $thislinetimestamps[] = $this->Lyrics3Timestamp2Seconds($regs[0]); + $lyricline = str_replace($regs[0], '', $lyricline); + } + $notimestamplyricsarray[$key] = $lyricline; + if (isset($thislinetimestamps) && is_array($thislinetimestamps)) { + sort($thislinetimestamps); + foreach ($thislinetimestamps as $timestampkey => $timestamp) { + if (isset($Lyrics3data['synchedlyrics'][$timestamp])) { + // timestamps only have a 1-second resolution, it's possible that multiple lines + // could have the same timestamp, if so, append + $Lyrics3data['synchedlyrics'][$timestamp] .= "\r\n".$lyricline; + } else { + $Lyrics3data['synchedlyrics'][$timestamp] = $lyricline; + } + } + } + } + $Lyrics3data['unsynchedlyrics'] = implode("\r\n", $notimestamplyricsarray); + if (isset($Lyrics3data['synchedlyrics']) && is_array($Lyrics3data['synchedlyrics'])) { + ksort($Lyrics3data['synchedlyrics']); + } + return true; + } + + public function IntString2Bool($char) { + if ($char == '1') { + return true; + } elseif ($char == '0') { + return false; + } + return null; + } +} diff --git a/sources/wp-includes/ID3/readme.txt b/sources/wp-includes/ID3/readme.txt new file mode 100644 index 0000000..337e84f --- /dev/null +++ b/sources/wp-includes/ID3/readme.txt @@ -0,0 +1,603 @@ +///////////////////////////////////////////////////////////////// +/// getID3() by James Heinrich // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// + +***************************************************************** +***************************************************************** + + getID3() is released under multiple licenses. You may choose + from the following licenses, and use getID3 according to the + terms of the license most suitable to your project. + +GNU GPL: https://gnu.org/licenses/gpl.html (v3) + https://gnu.org/licenses/old-licenses/gpl-2.0.html (v2) + https://gnu.org/licenses/old-licenses/gpl-1.0.html (v1) + +GNU LGPL: https://gnu.org/licenses/lgpl.html (v3) + +Mozilla MPL: http://www.mozilla.org/MPL/2.0/ (v2) + +getID3 Commercial License: http://getid3.org/#gCL (payment required) + +***************************************************************** +***************************************************************** +Copies of each of the above licenses are included in the 'licenses' +directory of the getID3 distribution. + + + +---------------------------------------------+ + | If you want to donate, there is a link on | + | http://www.getid3.org for PayPal donations. | + +---------------------------------------------+ + + +Quick Start +=========================================================================== + +Q: How can I check that getID3() works on my server/files? +A: Unzip getID3() to a directory, then access /demos/demo.browse.php + + + +Support +=========================================================================== + +Q: I have a question, or I found a bug. What do I do? +A: The preferred method of support requests and/or bug reports is the + forum at http://support.getid3.org/ + + + +Sourceforge Notification +=========================================================================== + +It's highly recommended that you sign up for notification from +Sourceforge for when new versions are released. Please visit: +http://sourceforge.net/project/showfiles.php?group_id=55859 +and click the little "monitor package" icon/link. If you're +previously signed up for the mailing list, be aware that it has +been discontinued, only the automated Sourceforge notification +will be used from now on. + + + +What does getID3() do? +=========================================================================== + +Reads & parses (to varying degrees): +# tags: + * APE (v1 and v2) + * ID3v1 (& ID3v1.1) + * ID3v2 (v2.4, v2.3, v2.2) + * Lyrics3 (v1 & v2) + +# audio-lossy: + * MP3/MP2/MP1 + * MPC / Musepack + * Ogg (Vorbis, OggFLAC, Speex) + * AAC / MP4 + * AC3 + * DTS + * RealAudio + * Speex + * DSS + * VQF + +# audio-lossless: + * AIFF + * AU + * Bonk + * CD-audio (*.cda) + * FLAC + * LA (Lossless Audio) + * LiteWave + * LPAC + * MIDI + * Monkey's Audio + * OptimFROG + * RKAU + * Shorten + * TTA + * VOC + * WAV (RIFF) + * WavPack + +# audio-video: + * ASF: ASF, Windows Media Audio (WMA), Windows Media Video (WMV) + * AVI (RIFF) + * Flash + * Matroska (MKV) + * MPEG-1 / MPEG-2 + * NSV (Nullsoft Streaming Video) + * Quicktime (including MP4) + * RealVideo + +# still image: + * BMP + * GIF + * JPEG + * PNG + * TIFF + * SWF (Flash) + * PhotoCD + +# data: + * ISO-9660 CD-ROM image (directory structure) + * SZIP (limited support) + * ZIP (directory structure) + * TAR + * CUE + + +Writes: + * ID3v1 (& ID3v1.1) + * ID3v2 (v2.3 & v2.4) + * VorbisComment on OggVorbis + * VorbisComment on FLAC (not OggFLAC) + * APE v2 + * Lyrics3 (delete only) + + + +Requirements +=========================================================================== + +* PHP 4.2.0 up to 5.2.x for getID3() 1.7.x (and earlier) +* PHP 5.0.5 (or higher) for getID3() 1.8.x (and up) +* PHP 5.0.5 (or higher) for getID3() 2.0.x (and up) +* at least 4MB memory for PHP. 8MB or more is highly recommended. + 12MB is required with all modules loaded. + + + +Usage +=========================================================================== + +See /demos/demo.basic.php for a very basic use of getID3() with no +fancy output, just scanning one file. + +See structure.txt for the returned data structure. + +*> For an example of a complete directory-browsing, <* +*> file-scanning implementation of getID3(), please run <* +*> /demos/demo.browse.php <* + +See /demos/demo.mysql.php for a sample recursive scanning code that +scans every file in a given directory, and all sub-directories, stores +the results in a database and allows various analysis / maintenance +operations + +To analyze remote files over HTTP or FTP you need to copy the file +locally first before running getID3(). Your code would look something +like this: + +// Copy remote file locally to scan with getID3() +$remotefilename = 'http://www.example.com/filename.mp3'; +if ($fp_remote = fopen($remotefilename, 'rb')) { + $localtempfilename = tempnam('/tmp', 'getID3'); + if ($fp_local = fopen($localtempfilename, 'wb')) { + while ($buffer = fread($fp_remote, 8192)) { + fwrite($fp_local, $buffer); + } + fclose($fp_local); + + // Initialize getID3 engine + $getID3 = new getID3; + + $ThisFileInfo = $getID3->analyze($filename); + + // Delete temporary file + unlink($localtempfilename); + } + fclose($fp_remote); +} + + +See /demos/demo.write.php for how to write tags. + + + +What does the returned data structure look like? +=========================================================================== + +See structure.txt + +It is recommended that you look at the output of +/demos/demo.browse.php scanning the file(s) you're interested in to +confirm what data is actually returned for any particular filetype in +general, and your files in particular, as the actual data returned +may vary considerably depending on what information is available in +the file itself. + + + +Notes +=========================================================================== + +getID3() 1.x: +If the format parser encounters a critical problem, it will return +something in $fileinfo['error'], describing the encountered error. If +a less critical error or notice is generated it will appear in +$fileinfo['warning']. Both keys may contain more than one warning or +error. If something is returned in ['error'] then the file was not +correctly parsed and returned data may or may not be correct and/or +complete. If something is returned in ['warning'] (and not ['error']) +then the data that is returned is OK - usually getID3() is reporting +errors in the file that have been worked around due to known bugs in +other programs. Some warnings may indicate that the data that is +returned is OK but that some data could not be extracted due to +errors in the file. + +getID3() 2.x: +See above except errors are thrown (so you will only get one error). + + + +Disclaimer +=========================================================================== + +getID3() has been tested on many systems, on many types of files, +under many operating systems, and is generally believe to be stable +and safe. That being said, there is still the chance there is an +undiscovered and/or unfixed bug that may potentially corrupt your +file, especially within the writing functions. By using getID3() you +agree that it's not my fault if any of your files are corrupted. +In fact, I'm not liable for anything :) + + + +License +=========================================================================== + +GNU General Public License - see license.txt + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to: +Free Software Foundation, Inc. +59 Temple Place - Suite 330 +Boston, MA 02111-1307, USA. + +FAQ: +Q: Can I use getID3() in my program? Do I need a commercial license? +A: You're generally free to use getID3 however you see fit. The only + case in which you would require a commercial license is if you're + selling your closed-source program that integrates getID3. If you + sell your program including a copy of getID3, that's fine as long + as you include a copy of the sourcecode when you sell it. Or you + can distribute your code without getID3 and say "download it from + getid3.sourceforge.net" + + + +Why is it called "getID3()" if it does so much more than just that? +=========================================================================== + +v0.1 did in fact just do that. I don't have a copy of code that old, but I +could essentially write it today with a one-line function: + function getID3($filename) { return unpack('a3TAG/a30title/a30artist/a30album/a4year/a28comment/c1track/c1genreid', substr(file_get_contents($filename), -128)); } + + +Future Plans +=========================================================================== +http://www.getid3.org/phpBB3/viewforum.php?f=7 + +* Better support for MP4 container format +* Scan for appended ID3v2 tag at end of file per ID3v2.4 specs (Section 5.0) +* Support for JPEG-2000 (http://www.morgan-multimedia.com/jpeg2000_overview.htm) +* Support for MOD (mod/stm/s3m/it/xm/mtm/ult/669) +* Support for ACE (thanks Vince) +* Support for Ogg other than Vorbis, Speex and OggFlac (ie. Ogg+Xvid) +* Ability to create Xing/LAME VBR header for VBR MP3s that are missing VBR header +* Ability to "clean" ID3v2 padding (replace invalid padding with valid padding) +* Warn if MP3s change version mid-stream (in full-scan mode) +* check for corrupt/broken mid-file MP3 streams in histogram scan +* Support for lossless-compression formats + (http://www.firstpr.com.au/audiocomp/lossless/#Links) + (http://compression.ca/act-sound.html) + (http://web.inter.nl.net/users/hvdh/lossless/lossless.htm) +* Support for RIFF-INFO chunks + * http://lotto.st-andrews.ac.uk/~njh/tag_interchange.html + (thanks Nick Humfrey ) + * http://abcavi.narod.ru/sof/abcavi/infotags.htm + (thanks Kibi) +* Better support for Bink video +* http://www.hr/josip/DSP/AudioFile2.html +* http://www.pcisys.net/~melanson/codecs/ +* Detect mp3PRO +* Support for PSD +* Support for JPC +* Support for JP2 +* Support for JPX +* Support for JB2 +* Support for IFF +* Support for ICO +* Support for ANI +* Support for EXE (comments, author, etc) (thanks p*quaedackers@planet*nl) +* Support for DVD-IFO (region, subtitles, aspect ratio, etc) + (thanks p*quaedackers@planet*nl) +* More complete support for SWF - parsing encapsulated MP3 and/or JPEG content + (thanks n8n8@yahoo*com) +* Support for a2b +* Optional scan-through-frames for AVI verification + (thanks rockcohen@massive-interactive*nl) +* Support for TTF (thanks info@butterflyx*com) +* Support for DSS (http://www.getid3.org/phpBB3/viewtopic.php?t=171) +* Support for SMAF (http://smaf-yamaha.com/what/demo.html) + http://www.getid3.org/phpBB3/viewtopic.php?t=182 +* Support for AMR (http://www.getid3.org/phpBB3/viewtopic.php?t=195) +* Support for 3gpp (http://www.getid3.org/phpBB3/viewtopic.php?t=195) +* Support for ID4 (http://www.wackysoft.cjb.net grizlyY2K@hotmail*com) +* Parse XML data returned in Ogg comments +* Parse XML data from Quicktime SMIL metafiles (klausrath@mac*com) +* ID3v2 genre string creator function +* More complete parsing of JPG +* Support for all old-style ASF packets +* ASF/WMA/WMV tag writing +* Parse declared T??? ID3v2 text information frames, where appropriate + (thanks Christian Fritz for the idea) +* Recognize encoder: + http://www.guerillasoft.com/EncSpot2/index.html + http://ff123.net/identify.html + http://www.hydrogenaudio.org/?act=ST&f=16&t=9414 + http://www.hydrogenaudio.org/?showtopic=11785 +* Support for other OS/2 bitmap structures: Bitmap Array('BA'), + Color Icon('CI'), Color Pointer('CP'), Icon('IC'), Pointer ('PT') + http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm +* Support for WavPack RAW mode +* ASF/WMA/WMV data packet parsing +* ID3v2FrameFlagsLookupTagAlter() +* ID3v2FrameFlagsLookupFileAlter() +* obey ID3v2 tag alter/preserve/discard rules +* http://www.geocities.com/SiliconValley/Sector/9654/Softdoc/Illyrium/Aolyr.htm +* proper checking for LINK/LNK frame validity in ID3v2 writing +* proper checking for ASPI-TLEN frame validity in ID3v2 writing +* proper checking for COMR frame validity in ID3v2 writing +* http://www.geocities.co.jp/SiliconValley-Oakland/3664/index.html +* decode GEOB ID3v2 structure as encoded by RealJukebox, + decode NCON ID3v2 structure as encoded by MusicMatch + (probably won't happen - the formats are proprietary) + + + +Known Bugs/Issues in getID3() that may be fixed eventually +=========================================================================== +http://www.getid3.org/phpBB3/viewtopic.php?t=25 + +* Cannot determine bitrate for MPEG video with VBR video data + (need documentation) +* Interlace/progressive cannot be determined for MPEG video + (need documentation) +* MIDI playtime is sometimes inaccurate +* AAC-RAW mode files cannot be identified +* WavPack-RAW mode files cannot be identified +* mp4 files report lots of "Unknown QuickTime atom type" + (need documentation) +* Encrypted ASF/WMA/WMV files warn about "unhandled GUID + ASF_Content_Encryption_Object" +* Bitrate split between audio and video cannot be calculated for + NSV, only the total bitrate. (need documentation) +* All Ogg formats (Vorbis, OggFLAC, Speex) are affected by the + problem of large VorbisComments spanning multiple Ogg pages, but + but only OggVorbis files can be processed with vorbiscomment. +* The version of "head" supplied with Mac OS 10.2.8 (maybe other + versions too) does only understands a single option (-n) and + therefore fails. getID3 ignores this and returns wrong md5_data. + + + +Known Bugs/Issues in getID3() that cannot be fixed +-------------------------------------------------- +http://www.getid3.org/phpBB3/viewtopic.php?t=25 + +* 32-bit PHP installations only: + Files larger than 2GB cannot always be parsed fully by getID3() + due to limitations in the 32-bit PHP filesystem functions. + NOTE: Since v1.7.8b3 there is partial support for larger-than- + 2GB files, most of which will parse OK, as long as no critical + data is located beyond the 2GB offset. + Known will-work: + * all file formats on 64-bit PHP + * ZIP (format doesn't support files >2GB) + * FLAC (current encoders don't support files >2GB) + Known will-not-work: + * ID3v1 tags (always located at end-of-file) + * Lyrics3 tags (always located at end-of-file) + * APE tags (always located at end-of-file) + Maybe-will-work: + * Quicktime (will work if needed metadata is before 2GB offset, + that is if the file has been hinted/optimized for streaming) + * RIFF.WAV (should work fine, but gives warnings about not being + able to parse all chunks) + * RIFF.AVI (playtime will probably be wrong, is only based on + "movi" chunk that fits in the first 2GB, should issue error + to show that playtime is incorrect. Other data should be mostly + correct, assuming that data is constant throughout the file) + + + +Known Bugs/Issues in other programs +----------------------------------- +http://www.getid3.org/phpBB3/viewtopic.php?t=25 + +* Windows Media Player (up to v11) and iTunes (up to v10+) do + not correctly handle ID3v2.3 tags with UTF-16BE+BOM + encoding (they assume the data is UTF-16LE+BOM and either + crash (WMP) or output Asian character set (iTunes) +* Winamp (up to v2.80 at least) does not support ID3v2.4 tags, + only ID3v2.3 + see: http://forums.winamp.com/showthread.php?postid=387524 +* Some versions of Helium2 (www.helium2.com) do not write + ID3v2.4-compliant Frame Sizes, even though the tag is marked + as ID3v2.4) (detected by getID3()) +* MP3ext V3.3.17 places a non-compliant padding string at the end + of the ID3v2 header. This is supposedly fixed in v3.4b21 but + only if you manually add a registry key. This fix is not yet + confirmed. (detected by getID3()) +* CDex v1.40 (fixed by v1.50b7) writes non-compliant Ogg comment + strings, supposed to be in the format "NAME=value" but actually + written just "value" (detected by getID3()) +* Oggenc 0.9-rc3 flags the encoded file as ABR whether it's + actually ABR or VBR. +* iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably + other versions are too) writes ID3v2.3 comment tags using a + frame name 'COM ' which is not valid for ID3v2.3+ (it's an + ID3v2.2-style frame name) (detected by getID3()) +* MP2enc does not encode mono CBR MP2 files properly (half speed + sound and double playtime) +* MP2enc does not encode mono VBR MP2 files properly (actually + encoded as stereo) +* tooLAME does not encode mono VBR MP2 files properly (actually + encoded as stereo) +* AACenc encodes files in VBR mode (actually ABR) even if CBR is + specified +* AAC/ADIF - bitrate_mode = cbr for vbr files +* LAME 3.90-3.92 prepends one frame of null data (space for the + LAME/VBR header, but it never gets written) when encoding in CBR + mode with the DLL +* Ahead Nero encodes TwinVQF with a DSIZ value (which is supposed + to be the filesize in bytes) of "0" for TwinVQF v1.0 and "1" for + TwinVQF v2.0 (detected by getID3()) +* Ahead Nero encodes TwinVQF files 1 second shorter than they + should be +* AAC-ADTS files are always actually encoded VBR, even if CBR mode + is specified (the CBR-mode switches on the encoder enable ABR + mode, not CBR as such, but it's not possible to tell the + difference between such ABR files and true VBR) +* STREAMINFO.audio_signature in OggFLAC is always null. "The reason + it's like that is because there is no seeking support in + libOggFLAC yet, so it has no way to go back and write the + computed sum after encoding. Seeking support in Ogg FLAC is the + #1 item for the next release." - Josh Coalson (FLAC developer) + NOTE: getID3() will calculate md5_data in a method similar to + other file formats, but that value cannot be compared to the + md5_data value from FLAC data in a FLAC file format. +* STREAMINFO.audio_signature is not calculated in FLAC v0.3.0 & + v0.4.0 - getID3() will calculate md5_data in a method similar to + other file formats, but that value cannot be compared to the + md5_data value from FLAC v0.5.0+ +* RioPort (various versions including 2.0 and 3.11) tags ID3v2 with + a WCOM frame that has no data portion +* Earlier versions of Coolplayer adds illegal ID3 tags to Ogg Vorbis + files, thus making them corrupt. +* Meracl ID3 Tag Writer v1.3.4 (and older) incorrectly truncates the + last byte of data from an MP3 file when appending a new ID3v1 tag. + (detected by getID3()) +* Lossless-Audio files encoded with and without the -noseek switch + do actually differ internally and therefore cannot match md5_data +* iTunes has been known to append a new ID3v1 tag on the end of an + existing ID3v1 tag when ID3v2 tag is also present + (detected by getID3()) +* MediaMonkey may write a blank RGAD ID3v2 frame but put actual + replay gain adjustments in a series of user-defined TXXX frames + (detected and handled by getID3() since v1.9.2) + + + + +Reference material: +=========================================================================== + +[www.id3.org material now mirrored at http://id3lib.sourceforge.net/id3/] +* http://www.id3.org/id3v2.4.0-structure.txt +* http://www.id3.org/id3v2.4.0-frames.txt +* http://www.id3.org/id3v2.4.0-changes.txt +* http://www.id3.org/id3v2.3.0.txt +* http://www.id3.org/id3v2-00.txt +* http://www.id3.org/mp3frame.html +* http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html +* http://www.dv.co.yu/mpgscript/mpeghdr.htm +* http://www.mp3-tech.org/programmer/frame_header.html +* http://users.belgacom.net/gc247244/extra/tag.html +* http://gabriel.mp3-tech.org/mp3infotag.html +* http://www.id3.org/iso4217.html +* http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT +* http://www.xiph.org/ogg/vorbis/doc/framing.html +* http://www.xiph.org/ogg/vorbis/doc/v-comment.html +* http://leknor.com/code/php/class.ogg.php.txt +* http://www.id3.org/iso639-2.html +* http://www.id3.org/lyrics3.html +* http://www.id3.org/lyrics3200.html +* http://www.psc.edu/general/software/packages/ieee/ieee.html +* http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html +* http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html +* http://www.jmcgowan.com/avi.html +* http://www.wotsit.org/ +* http://www.herdsoft.com/ti/davincie/davp3xo2.htm +* http://www.mathdogs.com/vorbis-illuminated/bitstream-appendix.html +* "Standard MIDI File Format" by Dustin Caldwell (from www.wotsit.org) +* http://midistudio.com/Help/GMSpecs_Patches.htm +* http://www.xiph.org/archives/vorbis/200109/0459.html +* http://www.replaygain.org/ +* http://www.lossless-audio.com/ +* http://download.microsoft.com/download/winmediatech40/Doc/1.0/WIN98MeXP/EN-US/ASF_Specification_v.1.0.exe +* http://mediaxw.sourceforge.net/files/doc/Active%20Streaming%20Format%20(ASF)%201.0%20Specification.pdf +* http://www.uni-jena.de/~pfk/mpp/sv8/ (archived at http://www.hydrogenaudio.org/musepack/klemm/www.personal.uni-jena.de/~pfk/mpp/sv8/) +* http://jfaul.de/atl/ +* http://www.uni-jena.de/~pfk/mpp/ (archived at http://www.hydrogenaudio.org/musepack/klemm/www.personal.uni-jena.de/~pfk/mpp/) +* http://www.libpng.org/pub/png/spec/png-1.2-pdg.html +* http://www.real.com/devzone/library/creating/rmsdk/doc/rmff.htm +* http://www.fastgraph.com/help/bmp_os2_header_format.html +* http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm +* http://flac.sourceforge.net/format.html +* http://www.research.att.com/projects/mpegaudio/mpeg2.html +* http://www.audiocoding.com/wiki/index.php?page=AAC +* http://libmpeg.org/mpeg4/doc/w2203tfs.pdf +* http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt +* http://developer.apple.com/techpubs/quicktime/qtdevdocs/RM/frameset.htm +* http://www.nullsoft.com/nsv/ +* http://www.wotsit.org/download.asp?f=iso9660 +* http://sandbox.mc.edu/~bennet/cs110/tc/tctod.html +* http://www.cdroller.com/htm/readdata.html +* http://www.speex.org/manual/node10.html +* http://www.harmony-central.com/Computer/Programming/aiff-file-format.doc +* http://www.faqs.org/rfcs/rfc2361.html +* http://ghido.shelter.ro/ +* http://www.ebu.ch/tech_t3285.pdf +* http://www.sr.se/utveckling/tu/bwf +* http://ftp.aessc.org/pub/aes46-2002.pdf +* http://cartchunk.org:8080/ +* http://www.broadcastpapers.com/radio/cartchunk01.htm +* http://www.hr/josip/DSP/AudioFile2.html +* http://home.attbi.com/~chris.bagwell/AudioFormats-11.html +* http://www.pure-mac.com/extkey.html +* http://cesnet.dl.sourceforge.net/sourceforge/bonkenc/bonk-binary-format-0.9.txt +* http://www.headbands.com/gspot/ +* http://www.openswf.org/spec/SWFfileformat.html +* http://j-faul.virtualave.net/ +* http://www.btinternet.com/~AnthonyJ/Atari/programming/avr_format.html +* http://cui.unige.ch/OSG/info/AudioFormats/ap11.html +* http://sswf.sourceforge.net/SWFalexref.html +* http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt +* http://www-lehre.informatik.uni-osnabrueck.de/~fbstark/diplom/docs/swf/Flash_Uncovered.htm +* http://developer.apple.com/quicktime/icefloe/dispatch012.html +* http://www.csdn.net/Dev/Format/graphics/PCD.htm +* http://tta.iszf.irk.ru/ +* http://www.atsc.org/standards/a_52a.pdf +* http://www.alanwood.net/unicode/ +* http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html +* http://www.its.msstate.edu/net/real/reports/config/tags.stats +* http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt +* http://brennan.young.net/Comp/LiveStage/things.html +* http://www.multiweb.cz/twoinches/MP3inside.htm +* http://www.geocities.co.jp/SiliconValley-Oakland/3664/alittle.html#GenreExtended +* http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/ +* http://www.unicode.org/unicode/faq/utf_bom.html +* http://tta.corecodec.org/?menu=format +* http://www.scvi.net/nsvformat.htm +* http://pda.etsi.org/pda/queryform.asp +* http://cpansearch.perl.org/src/RGIBSON/Audio-DSS-0.02/lib/Audio/DSS.pm +* http://trac.musepack.net/trac/wiki/SV8Specification +* http://wyday.com/cuesharp/specification.php +* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html diff --git a/sources/wp-includes/SimplePie/Author.php b/sources/wp-includes/SimplePie/Author.php new file mode 100644 index 0000000..bbf3812 --- /dev/null +++ b/sources/wp-includes/SimplePie/Author.php @@ -0,0 +1,157 @@ +name = $name; + $this->link = $link; + $this->email = $email; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Author's name + * + * @return string|null + */ + public function get_name() + { + if ($this->name !== null) + { + return $this->name; + } + else + { + return null; + } + } + + /** + * Author's link + * + * @return string|null + */ + public function get_link() + { + if ($this->link !== null) + { + return $this->link; + } + else + { + return null; + } + } + + /** + * Author's email address + * + * @return string|null + */ + public function get_email() + { + if ($this->email !== null) + { + return $this->email; + } + else + { + return null; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Cache.php b/sources/wp-includes/SimplePie/Cache.php new file mode 100644 index 0000000..75586d7 --- /dev/null +++ b/sources/wp-includes/SimplePie/Cache.php @@ -0,0 +1,133 @@ + 'SimplePie_Cache_MySQL', + 'memcache' => 'SimplePie_Cache_Memcache', + ); + + /** + * Don't call the constructor. Please. + */ + private function __construct() { } + + /** + * Create a new SimplePie_Cache object + * + * @param string $location URL location (scheme is used to determine handler) + * @param string $filename Unique identifier for cache object + * @param string $extension 'spi' or 'spc' + * @return SimplePie_Cache_Base Type of object depends on scheme of `$location` + */ + public static function get_handler($location, $filename, $extension) + { + $type = explode(':', $location, 2); + $type = $type[0]; + if (!empty(self::$handlers[$type])) + { + $class = self::$handlers[$type]; + return new $class($location, $filename, $extension); + } + + return new SimplePie_Cache_File($location, $filename, $extension); + } + + /** + * Create a new SimplePie_Cache object + * + * @deprecated Use {@see get_handler} instead + */ + public function create($location, $filename, $extension) + { + trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED); + return self::get_handler($location, $filename, $extension); + } + + /** + * Register a handler + * + * @param string $type DSN type to register for + * @param string $class Name of handler class. Must implement SimplePie_Cache_Base + */ + public static function register($type, $class) + { + self::$handlers[$type] = $class; + } + + /** + * Parse a URL into an array + * + * @param string $url + * @return array + */ + public static function parse_URL($url) + { + $params = parse_url($url); + $params['extras'] = array(); + if (isset($params['query'])) + { + parse_str($params['query'], $params['extras']); + } + return $params; + } +} diff --git a/sources/wp-includes/SimplePie/Cache/Base.php b/sources/wp-includes/SimplePie/Cache/Base.php new file mode 100644 index 0000000..937e346 --- /dev/null +++ b/sources/wp-includes/SimplePie/Cache/Base.php @@ -0,0 +1,114 @@ +get_items(); + $items_by_id = array(); + + if (!empty($items)) + { + foreach ($items as $item) + { + $items_by_id[$item->get_id()] = $item; + } + + if (count($items_by_id) !== count($items)) + { + $items_by_id = array(); + foreach ($items as $item) + { + $items_by_id[$item->get_id(true)] = $item; + } + } + + if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; + } + elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; + } + elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; + } + elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0])) + { + $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]; + } + else + { + $channel = null; + } + + if ($channel !== null) + { + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']); + } + if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item'])) + { + unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']); + } + } + if (isset($data->data['items'])) + { + unset($data->data['items']); + } + if (isset($data->data['ordered_items'])) + { + unset($data->data['ordered_items']); + } + } + return array(serialize($data->data), $items_by_id); + } +} diff --git a/sources/wp-includes/SimplePie/Cache/File.php b/sources/wp-includes/SimplePie/Cache/File.php new file mode 100644 index 0000000..5797b3a --- /dev/null +++ b/sources/wp-includes/SimplePie/Cache/File.php @@ -0,0 +1,173 @@ +location = $location; + $this->filename = $name; + $this->extension = $type; + $this->name = "$this->location/$this->filename.$this->extension"; + } + + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location)) + { + if ($data instanceof SimplePie) + { + $data = $data->data; + } + + $data = serialize($data); + return (bool) file_put_contents($this->name, $data); + } + return false; + } + + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + if (file_exists($this->name) && is_readable($this->name)) + { + return unserialize(file_get_contents($this->name)); + } + return false; + } + + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + if (file_exists($this->name)) + { + return filemtime($this->name); + } + return false; + } + + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + if (file_exists($this->name)) + { + return touch($this->name); + } + return false; + } + + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + if (file_exists($this->name)) + { + return unlink($this->name); + } + return false; + } +} diff --git a/sources/wp-includes/SimplePie/Cache/Memcache.php b/sources/wp-includes/SimplePie/Cache/Memcache.php new file mode 100644 index 0000000..fd44780 --- /dev/null +++ b/sources/wp-includes/SimplePie/Cache/Memcache.php @@ -0,0 +1,183 @@ +options = array( + 'host' => '127.0.0.1', + 'port' => 11211, + 'extras' => array( + 'timeout' => 3600, // one hour + 'prefix' => 'simplepie_', + ), + ); + $parsed = SimplePie_Cache::parse_URL($location); + $this->options['host'] = empty($parsed['host']) ? $this->options['host'] : $parsed['host']; + $this->options['port'] = empty($parsed['port']) ? $this->options['port'] : $parsed['port']; + $this->options['extras'] = array_merge($this->options['extras'], $parsed['extras']); + $this->name = $this->options['extras']['prefix'] . md5("$name:$type"); + + $this->cache = new Memcache(); + $this->cache->addServer($this->options['host'], (int) $this->options['port']); + } + + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + if ($data instanceof SimplePie) + { + $data = $data->data; + } + return $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']); + } + + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + $data = $this->cache->get($this->name); + + if ($data !== false) + { + return unserialize($data); + } + return false; + } + + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + $data = $this->cache->get($this->name); + + if ($data !== false) + { + // essentially ignore the mtime because Memcache expires on it's own + return time(); + } + + return false; + } + + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + $data = $this->cache->get($this->name); + + if ($data !== false) + { + return $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->duration); + } + + return false; + } + + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + return $this->cache->delete($this->name, 0); + } +} diff --git a/sources/wp-includes/SimplePie/Cache/MySQL.php b/sources/wp-includes/SimplePie/Cache/MySQL.php new file mode 100644 index 0000000..d53ebc1 --- /dev/null +++ b/sources/wp-includes/SimplePie/Cache/MySQL.php @@ -0,0 +1,438 @@ +options = array( + 'user' => null, + 'pass' => null, + 'host' => '127.0.0.1', + 'port' => '3306', + 'path' => '', + 'extras' => array( + 'prefix' => '', + ), + ); + $this->options = array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location)); + + // Path is prefixed with a "/" + $this->options['dbname'] = substr($this->options['path'], 1); + + try + { + $this->mysql = new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')); + } + catch (PDOException $e) + { + $this->mysql = null; + return; + } + + $this->id = $name . $type; + + if (!$query = $this->mysql->query('SHOW TABLES')) + { + $this->mysql = null; + return; + } + + $db = array(); + while ($row = $query->fetchColumn()) + { + $db[] = $row; + } + + if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db)) + { + $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'); + if ($query === false) + { + $this->mysql = null; + } + } + + if (!in_array($this->options['extras']['prefix'] . 'items', $db)) + { + $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'); + if ($query === false) + { + $this->mysql = null; + } + } + } + + /** + * Save data to the cache + * + * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property + * @return bool Successfulness + */ + public function save($data) + { + if ($this->mysql === null) + { + return false; + } + + if ($data instanceof SimplePie) + { + $data = clone $data; + + $prepared = self::prepare_simplepie_object_for_cache($data); + + $query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed'); + $query->bindValue(':feed', $this->id); + if ($query->execute()) + { + if ($query->fetchColumn() > 0) + { + $items = count($prepared[1]); + if ($items) + { + $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed'; + $query = $this->mysql->prepare($sql); + $query->bindValue(':items', $items); + } + else + { + $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed'; + $query = $this->mysql->prepare($sql); + } + + $query->bindValue(':data', $prepared[0]); + $query->bindValue(':time', time()); + $query->bindValue(':feed', $this->id); + if (!$query->execute()) + { + return false; + } + } + else + { + $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)'); + $query->bindValue(':feed', $this->id); + $query->bindValue(':count', count($prepared[1])); + $query->bindValue(':data', $prepared[0]); + $query->bindValue(':time', time()); + if (!$query->execute()) + { + return false; + } + } + + $ids = array_keys($prepared[1]); + if (!empty($ids)) + { + foreach ($ids as $id) + { + $database_ids[] = $this->mysql->quote($id); + } + + $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed'); + $query->bindValue(':feed', $this->id); + + if ($query->execute()) + { + $existing_ids = array(); + while ($row = $query->fetchColumn()) + { + $existing_ids[] = $row; + } + + $new_ids = array_diff($ids, $existing_ids); + + foreach ($new_ids as $new_id) + { + if (!($date = $prepared[1][$new_id]->get_date('U'))) + { + $date = time(); + } + + $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)'); + $query->bindValue(':feed', $this->id); + $query->bindValue(':id', $new_id); + $query->bindValue(':data', serialize($prepared[1][$new_id]->data)); + $query->bindValue(':date', $date); + if (!$query->execute()) + { + return false; + } + } + return true; + } + } + else + { + return true; + } + } + } + else + { + $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed'); + $query->bindValue(':feed', $this->id); + if ($query->execute()) + { + if ($query->rowCount() > 0) + { + $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed'); + $query->bindValue(':data', serialize($data)); + $query->bindValue(':time', time()); + $query->bindValue(':feed', $this->id); + if ($this->execute()) + { + return true; + } + } + else + { + $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)'); + $query->bindValue(':id', $this->id); + $query->bindValue(':data', serialize($data)); + $query->bindValue(':time', time()); + if ($query->execute()) + { + return true; + } + } + } + } + return false; + } + + /** + * Retrieve the data saved to the cache + * + * @return array Data for SimplePie::$data + */ + public function load() + { + if ($this->mysql === null) + { + return false; + } + + $query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id'); + $query->bindValue(':id', $this->id); + if ($query->execute() && ($row = $query->fetch())) + { + $data = unserialize($row[1]); + + if (isset($this->options['items'][0])) + { + $items = (int) $this->options['items'][0]; + } + else + { + $items = (int) $row[0]; + } + + if ($items !== 0) + { + if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]; + } + elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]; + } + elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]; + } + elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0])) + { + $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]; + } + else + { + $feed = null; + } + + if ($feed !== null) + { + $sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC'; + if ($items > 0) + { + $sql .= ' LIMIT ' . $items; + } + + $query = $this->mysql->prepare($sql); + $query->bindValue(':feed', $this->id); + if ($query->execute()) + { + while ($row = $query->fetchColumn()) + { + $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row); + } + } + else + { + return false; + } + } + } + return $data; + } + return false; + } + + /** + * Retrieve the last modified time for the cache + * + * @return int Timestamp + */ + public function mtime() + { + if ($this->mysql === null) + { + return false; + } + + $query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id'); + $query->bindValue(':id', $this->id); + if ($query->execute() && ($time = $query->fetchColumn())) + { + return $time; + } + else + { + return false; + } + } + + /** + * Set the last modified time to the current time + * + * @return bool Success status + */ + public function touch() + { + if ($this->mysql === null) + { + return false; + } + + $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id'); + $query->bindValue(':time', time()); + $query->bindValue(':id', $this->id); + if ($query->execute() && $query->rowCount() > 0) + { + return true; + } + else + { + return false; + } + } + + /** + * Remove the cache + * + * @return bool Success status + */ + public function unlink() + { + if ($this->mysql === null) + { + return false; + } + + $query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id'); + $query->bindValue(':id', $this->id); + $query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id'); + $query2->bindValue(':id', $this->id); + if ($query->execute() && $query2->execute()) + { + return true; + } + else + { + return false; + } + } +} diff --git a/sources/wp-includes/SimplePie/Caption.php b/sources/wp-includes/SimplePie/Caption.php new file mode 100644 index 0000000..52922c5 --- /dev/null +++ b/sources/wp-includes/SimplePie/Caption.php @@ -0,0 +1,210 @@ +` captions as defined in Media RSS. + * + * Used by {@see SimplePie_Enclosure::get_caption()} and {@see SimplePie_Enclosure::get_captions()} + * + * This class can be overloaded with {@see SimplePie::set_caption_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Caption +{ + /** + * Content type + * + * @var string + * @see get_type() + */ + var $type; + + /** + * Language + * + * @var string + * @see get_language() + */ + var $lang; + + /** + * Start time + * + * @var string + * @see get_starttime() + */ + var $startTime; + + /** + * End time + * + * @var string + * @see get_endtime() + */ + var $endTime; + + /** + * Caption text + * + * @var string + * @see get_text() + */ + var $text; + + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null) + { + $this->type = $type; + $this->lang = $lang; + $this->startTime = $startTime; + $this->endTime = $endTime; + $this->text = $text; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the end time + * + * @return string|null Time in the format 'hh:mm:ss.SSS' + */ + public function get_endtime() + { + if ($this->endTime !== null) + { + return $this->endTime; + } + else + { + return null; + } + } + + /** + * Get the language + * + * @link http://tools.ietf.org/html/rfc3066 + * @return string|null Language code as per RFC 3066 + */ + public function get_language() + { + if ($this->lang !== null) + { + return $this->lang; + } + else + { + return null; + } + } + + /** + * Get the start time + * + * @return string|null Time in the format 'hh:mm:ss.SSS' + */ + public function get_starttime() + { + if ($this->startTime !== null) + { + return $this->startTime; + } + else + { + return null; + } + } + + /** + * Get the text of the caption + * + * @return string|null + */ + public function get_text() + { + if ($this->text !== null) + { + return $this->text; + } + else + { + return null; + } + } + + /** + * Get the content type (not MIME type) + * + * @return string|null Either 'text' or 'html' + */ + public function get_type() + { + if ($this->type !== null) + { + return $this->type; + } + else + { + return null; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Category.php b/sources/wp-includes/SimplePie/Category.php new file mode 100644 index 0000000..ad0407b --- /dev/null +++ b/sources/wp-includes/SimplePie/Category.php @@ -0,0 +1,157 @@ +term = $term; + $this->scheme = $scheme; + $this->label = $label; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the category identifier + * + * @return string|null + */ + public function get_term() + { + if ($this->term !== null) + { + return $this->term; + } + else + { + return null; + } + } + + /** + * Get the categorization scheme identifier + * + * @return string|null + */ + public function get_scheme() + { + if ($this->scheme !== null) + { + return $this->scheme; + } + else + { + return null; + } + } + + /** + * Get the human readable label + * + * @return string|null + */ + public function get_label() + { + if ($this->label !== null) + { + return $this->label; + } + else + { + return $this->get_term(); + } + } +} + diff --git a/sources/wp-includes/SimplePie/Content/Type/Sniffer.php b/sources/wp-includes/SimplePie/Content/Type/Sniffer.php new file mode 100644 index 0000000..20d053d --- /dev/null +++ b/sources/wp-includes/SimplePie/Content/Type/Sniffer.php @@ -0,0 +1,332 @@ +file = $file; + } + + /** + * Get the Content-Type of the specified file + * + * @return string Actual Content-Type + */ + public function get_type() + { + if (isset($this->file->headers['content-type'])) + { + if (!isset($this->file->headers['content-encoding']) + && ($this->file->headers['content-type'] === 'text/plain' + || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' + || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1' + || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8')) + { + return $this->text_or_binary(); + } + + if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) + { + $official = substr($this->file->headers['content-type'], 0, $pos); + } + else + { + $official = $this->file->headers['content-type']; + } + $official = trim(strtolower($official)); + + if ($official === 'unknown/unknown' + || $official === 'application/unknown') + { + return $this->unknown(); + } + elseif (substr($official, -4) === '+xml' + || $official === 'text/xml' + || $official === 'application/xml') + { + return $official; + } + elseif (substr($official, 0, 6) === 'image/') + { + if ($return = $this->image()) + { + return $return; + } + else + { + return $official; + } + } + elseif ($official === 'text/html') + { + return $this->feed_or_html(); + } + else + { + return $official; + } + } + else + { + return $this->unknown(); + } + } + + /** + * Sniff text or binary + * + * @return string Actual Content-Type + */ + public function text_or_binary() + { + if (substr($this->file->body, 0, 2) === "\xFE\xFF" + || substr($this->file->body, 0, 2) === "\xFF\xFE" + || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" + || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") + { + return 'text/plain'; + } + elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) + { + return 'application/octect-stream'; + } + else + { + return 'text/plain'; + } + } + + /** + * Sniff unknown + * + * @return string Actual Content-Type + */ + public function unknown() + { + $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); + if (strtolower(substr($this->file->body, $ws, 14)) === 'file->body, $ws, 5)) === 'file->body, $ws, 7)) === 'file->body, 0, 5) === '%PDF-') + { + return 'application/pdf'; + } + elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') + { + return 'application/postscript'; + } + elseif (substr($this->file->body, 0, 6) === 'GIF87a' + || substr($this->file->body, 0, 6) === 'GIF89a') + { + return 'image/gif'; + } + elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") + { + return 'image/png'; + } + elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") + { + return 'image/jpeg'; + } + elseif (substr($this->file->body, 0, 2) === "\x42\x4D") + { + return 'image/bmp'; + } + elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") + { + return 'image/vnd.microsoft.icon'; + } + else + { + return $this->text_or_binary(); + } + } + + /** + * Sniff images + * + * @return string Actual Content-Type + */ + public function image() + { + if (substr($this->file->body, 0, 6) === 'GIF87a' + || substr($this->file->body, 0, 6) === 'GIF89a') + { + return 'image/gif'; + } + elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") + { + return 'image/png'; + } + elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") + { + return 'image/jpeg'; + } + elseif (substr($this->file->body, 0, 2) === "\x42\x4D") + { + return 'image/bmp'; + } + elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") + { + return 'image/vnd.microsoft.icon'; + } + else + { + return false; + } + } + + /** + * Sniff HTML + * + * @return string Actual Content-Type + */ + public function feed_or_html() + { + $len = strlen($this->file->body); + $pos = strspn($this->file->body, "\x09\x0A\x0D\x20"); + + while ($pos < $len) + { + switch ($this->file->body[$pos]) + { + case "\x09": + case "\x0A": + case "\x0D": + case "\x20": + $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); + continue 2; + + case '<': + $pos++; + break; + + default: + return 'text/html'; + } + + if (substr($this->file->body, $pos, 3) === '!--') + { + $pos += 3; + if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) + { + $pos += 3; + } + else + { + return 'text/html'; + } + } + elseif (substr($this->file->body, $pos, 1) === '!') + { + if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) + { + $pos++; + } + else + { + return 'text/html'; + } + } + elseif (substr($this->file->body, $pos, 1) === '?') + { + if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) + { + $pos += 2; + } + else + { + return 'text/html'; + } + } + elseif (substr($this->file->body, $pos, 3) === 'rss' + || substr($this->file->body, $pos, 7) === 'rdf:RDF') + { + return 'application/rss+xml'; + } + elseif (substr($this->file->body, $pos, 4) === 'feed') + { + return 'application/atom+xml'; + } + else + { + return 'text/html'; + } + } + + return 'text/html'; + } +} + diff --git a/sources/wp-includes/SimplePie/Copyright.php b/sources/wp-includes/SimplePie/Copyright.php new file mode 100644 index 0000000..57c535a --- /dev/null +++ b/sources/wp-includes/SimplePie/Copyright.php @@ -0,0 +1,130 @@ +` copyright tags as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_copyright()} + * + * This class can be overloaded with {@see SimplePie::set_copyright_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Copyright +{ + /** + * Copyright URL + * + * @var string + * @see get_url() + */ + var $url; + + /** + * Attribution + * + * @var string + * @see get_attribution() + */ + var $label; + + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($url = null, $label = null) + { + $this->url = $url; + $this->label = $label; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the copyright URL + * + * @return string|null URL to copyright information + */ + public function get_url() + { + if ($this->url !== null) + { + return $this->url; + } + else + { + return null; + } + } + + /** + * Get the attribution text + * + * @return string|null + */ + public function get_attribution() + { + if ($this->label !== null) + { + return $this->label; + } + else + { + return null; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Core.php b/sources/wp-includes/SimplePie/Core.php new file mode 100644 index 0000000..46d9966 --- /dev/null +++ b/sources/wp-includes/SimplePie/Core.php @@ -0,0 +1,57 @@ +` as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_credit()} and {@see SimplePie_Enclosure::get_credits()} + * + * This class can be overloaded with {@see SimplePie::set_credit_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Credit +{ + /** + * Credited role + * + * @var string + * @see get_role() + */ + var $role; + + /** + * Organizational scheme + * + * @var string + * @see get_scheme() + */ + var $scheme; + + /** + * Credited name + * + * @var string + * @see get_name() + */ + var $name; + + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($role = null, $scheme = null, $name = null) + { + $this->role = $role; + $this->scheme = $scheme; + $this->name = $name; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the role of the person receiving credit + * + * @return string|null + */ + public function get_role() + { + if ($this->role !== null) + { + return $this->role; + } + else + { + return null; + } + } + + /** + * Get the organizational scheme + * + * @return string|null + */ + public function get_scheme() + { + if ($this->scheme !== null) + { + return $this->scheme; + } + else + { + return null; + } + } + + /** + * Get the credited person/entity's name + * + * @return string|null + */ + public function get_name() + { + if ($this->name !== null) + { + return $this->name; + } + else + { + return null; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Decode/HTML/Entities.php b/sources/wp-includes/SimplePie/Decode/HTML/Entities.php new file mode 100644 index 0000000..069e8d8 --- /dev/null +++ b/sources/wp-includes/SimplePie/Decode/HTML/Entities.php @@ -0,0 +1,617 @@ +data = $data; + } + + /** + * Parse the input data + * + * @access public + * @return string Output data + */ + public function parse() + { + while (($this->position = strpos($this->data, '&', $this->position)) !== false) + { + $this->consume(); + $this->entity(); + $this->consumed = ''; + } + return $this->data; + } + + /** + * Consume the next byte + * + * @access private + * @return mixed The next byte, or false, if there is no more data + */ + public function consume() + { + if (isset($this->data[$this->position])) + { + $this->consumed .= $this->data[$this->position]; + return $this->data[$this->position++]; + } + else + { + return false; + } + } + + /** + * Consume a range of characters + * + * @access private + * @param string $chars Characters to consume + * @return mixed A series of characters that match the range, or false + */ + public function consume_range($chars) + { + if ($len = strspn($this->data, $chars, $this->position)) + { + $data = substr($this->data, $this->position, $len); + $this->consumed .= $data; + $this->position += $len; + return $data; + } + else + { + return false; + } + } + + /** + * Unconsume one byte + * + * @access private + */ + public function unconsume() + { + $this->consumed = substr($this->consumed, 0, -1); + $this->position--; + } + + /** + * Decode an entity + * + * @access private + */ + public function entity() + { + switch ($this->consume()) + { + case "\x09": + case "\x0A": + case "\x0B": + case "\x0B": + case "\x0C": + case "\x20": + case "\x3C": + case "\x26": + case false: + break; + + case "\x23": + switch ($this->consume()) + { + case "\x78": + case "\x58": + $range = '0123456789ABCDEFabcdef'; + $hex = true; + break; + + default: + $range = '0123456789'; + $hex = false; + $this->unconsume(); + break; + } + + if ($codepoint = $this->consume_range($range)) + { + static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8"); + + if ($hex) + { + $codepoint = hexdec($codepoint); + } + else + { + $codepoint = intval($codepoint); + } + + if (isset($windows_1252_specials[$codepoint])) + { + $replacement = $windows_1252_specials[$codepoint]; + } + else + { + $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint); + } + + if (!in_array($this->consume(), array(';', false), true)) + { + $this->unconsume(); + } + + $consumed_length = strlen($this->consumed); + $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length); + $this->position += strlen($replacement) - $consumed_length; + } + break; + + default: + static $entities = array( + 'Aacute' => "\xC3\x81", + 'aacute' => "\xC3\xA1", + 'Aacute;' => "\xC3\x81", + 'aacute;' => "\xC3\xA1", + 'Acirc' => "\xC3\x82", + 'acirc' => "\xC3\xA2", + 'Acirc;' => "\xC3\x82", + 'acirc;' => "\xC3\xA2", + 'acute' => "\xC2\xB4", + 'acute;' => "\xC2\xB4", + 'AElig' => "\xC3\x86", + 'aelig' => "\xC3\xA6", + 'AElig;' => "\xC3\x86", + 'aelig;' => "\xC3\xA6", + 'Agrave' => "\xC3\x80", + 'agrave' => "\xC3\xA0", + 'Agrave;' => "\xC3\x80", + 'agrave;' => "\xC3\xA0", + 'alefsym;' => "\xE2\x84\xB5", + 'Alpha;' => "\xCE\x91", + 'alpha;' => "\xCE\xB1", + 'AMP' => "\x26", + 'amp' => "\x26", + 'AMP;' => "\x26", + 'amp;' => "\x26", + 'and;' => "\xE2\x88\xA7", + 'ang;' => "\xE2\x88\xA0", + 'apos;' => "\x27", + 'Aring' => "\xC3\x85", + 'aring' => "\xC3\xA5", + 'Aring;' => "\xC3\x85", + 'aring;' => "\xC3\xA5", + 'asymp;' => "\xE2\x89\x88", + 'Atilde' => "\xC3\x83", + 'atilde' => "\xC3\xA3", + 'Atilde;' => "\xC3\x83", + 'atilde;' => "\xC3\xA3", + 'Auml' => "\xC3\x84", + 'auml' => "\xC3\xA4", + 'Auml;' => "\xC3\x84", + 'auml;' => "\xC3\xA4", + 'bdquo;' => "\xE2\x80\x9E", + 'Beta;' => "\xCE\x92", + 'beta;' => "\xCE\xB2", + 'brvbar' => "\xC2\xA6", + 'brvbar;' => "\xC2\xA6", + 'bull;' => "\xE2\x80\xA2", + 'cap;' => "\xE2\x88\xA9", + 'Ccedil' => "\xC3\x87", + 'ccedil' => "\xC3\xA7", + 'Ccedil;' => "\xC3\x87", + 'ccedil;' => "\xC3\xA7", + 'cedil' => "\xC2\xB8", + 'cedil;' => "\xC2\xB8", + 'cent' => "\xC2\xA2", + 'cent;' => "\xC2\xA2", + 'Chi;' => "\xCE\xA7", + 'chi;' => "\xCF\x87", + 'circ;' => "\xCB\x86", + 'clubs;' => "\xE2\x99\xA3", + 'cong;' => "\xE2\x89\x85", + 'COPY' => "\xC2\xA9", + 'copy' => "\xC2\xA9", + 'COPY;' => "\xC2\xA9", + 'copy;' => "\xC2\xA9", + 'crarr;' => "\xE2\x86\xB5", + 'cup;' => "\xE2\x88\xAA", + 'curren' => "\xC2\xA4", + 'curren;' => "\xC2\xA4", + 'Dagger;' => "\xE2\x80\xA1", + 'dagger;' => "\xE2\x80\xA0", + 'dArr;' => "\xE2\x87\x93", + 'darr;' => "\xE2\x86\x93", + 'deg' => "\xC2\xB0", + 'deg;' => "\xC2\xB0", + 'Delta;' => "\xCE\x94", + 'delta;' => "\xCE\xB4", + 'diams;' => "\xE2\x99\xA6", + 'divide' => "\xC3\xB7", + 'divide;' => "\xC3\xB7", + 'Eacute' => "\xC3\x89", + 'eacute' => "\xC3\xA9", + 'Eacute;' => "\xC3\x89", + 'eacute;' => "\xC3\xA9", + 'Ecirc' => "\xC3\x8A", + 'ecirc' => "\xC3\xAA", + 'Ecirc;' => "\xC3\x8A", + 'ecirc;' => "\xC3\xAA", + 'Egrave' => "\xC3\x88", + 'egrave' => "\xC3\xA8", + 'Egrave;' => "\xC3\x88", + 'egrave;' => "\xC3\xA8", + 'empty;' => "\xE2\x88\x85", + 'emsp;' => "\xE2\x80\x83", + 'ensp;' => "\xE2\x80\x82", + 'Epsilon;' => "\xCE\x95", + 'epsilon;' => "\xCE\xB5", + 'equiv;' => "\xE2\x89\xA1", + 'Eta;' => "\xCE\x97", + 'eta;' => "\xCE\xB7", + 'ETH' => "\xC3\x90", + 'eth' => "\xC3\xB0", + 'ETH;' => "\xC3\x90", + 'eth;' => "\xC3\xB0", + 'Euml' => "\xC3\x8B", + 'euml' => "\xC3\xAB", + 'Euml;' => "\xC3\x8B", + 'euml;' => "\xC3\xAB", + 'euro;' => "\xE2\x82\xAC", + 'exist;' => "\xE2\x88\x83", + 'fnof;' => "\xC6\x92", + 'forall;' => "\xE2\x88\x80", + 'frac12' => "\xC2\xBD", + 'frac12;' => "\xC2\xBD", + 'frac14' => "\xC2\xBC", + 'frac14;' => "\xC2\xBC", + 'frac34' => "\xC2\xBE", + 'frac34;' => "\xC2\xBE", + 'frasl;' => "\xE2\x81\x84", + 'Gamma;' => "\xCE\x93", + 'gamma;' => "\xCE\xB3", + 'ge;' => "\xE2\x89\xA5", + 'GT' => "\x3E", + 'gt' => "\x3E", + 'GT;' => "\x3E", + 'gt;' => "\x3E", + 'hArr;' => "\xE2\x87\x94", + 'harr;' => "\xE2\x86\x94", + 'hearts;' => "\xE2\x99\xA5", + 'hellip;' => "\xE2\x80\xA6", + 'Iacute' => "\xC3\x8D", + 'iacute' => "\xC3\xAD", + 'Iacute;' => "\xC3\x8D", + 'iacute;' => "\xC3\xAD", + 'Icirc' => "\xC3\x8E", + 'icirc' => "\xC3\xAE", + 'Icirc;' => "\xC3\x8E", + 'icirc;' => "\xC3\xAE", + 'iexcl' => "\xC2\xA1", + 'iexcl;' => "\xC2\xA1", + 'Igrave' => "\xC3\x8C", + 'igrave' => "\xC3\xAC", + 'Igrave;' => "\xC3\x8C", + 'igrave;' => "\xC3\xAC", + 'image;' => "\xE2\x84\x91", + 'infin;' => "\xE2\x88\x9E", + 'int;' => "\xE2\x88\xAB", + 'Iota;' => "\xCE\x99", + 'iota;' => "\xCE\xB9", + 'iquest' => "\xC2\xBF", + 'iquest;' => "\xC2\xBF", + 'isin;' => "\xE2\x88\x88", + 'Iuml' => "\xC3\x8F", + 'iuml' => "\xC3\xAF", + 'Iuml;' => "\xC3\x8F", + 'iuml;' => "\xC3\xAF", + 'Kappa;' => "\xCE\x9A", + 'kappa;' => "\xCE\xBA", + 'Lambda;' => "\xCE\x9B", + 'lambda;' => "\xCE\xBB", + 'lang;' => "\xE3\x80\x88", + 'laquo' => "\xC2\xAB", + 'laquo;' => "\xC2\xAB", + 'lArr;' => "\xE2\x87\x90", + 'larr;' => "\xE2\x86\x90", + 'lceil;' => "\xE2\x8C\x88", + 'ldquo;' => "\xE2\x80\x9C", + 'le;' => "\xE2\x89\xA4", + 'lfloor;' => "\xE2\x8C\x8A", + 'lowast;' => "\xE2\x88\x97", + 'loz;' => "\xE2\x97\x8A", + 'lrm;' => "\xE2\x80\x8E", + 'lsaquo;' => "\xE2\x80\xB9", + 'lsquo;' => "\xE2\x80\x98", + 'LT' => "\x3C", + 'lt' => "\x3C", + 'LT;' => "\x3C", + 'lt;' => "\x3C", + 'macr' => "\xC2\xAF", + 'macr;' => "\xC2\xAF", + 'mdash;' => "\xE2\x80\x94", + 'micro' => "\xC2\xB5", + 'micro;' => "\xC2\xB5", + 'middot' => "\xC2\xB7", + 'middot;' => "\xC2\xB7", + 'minus;' => "\xE2\x88\x92", + 'Mu;' => "\xCE\x9C", + 'mu;' => "\xCE\xBC", + 'nabla;' => "\xE2\x88\x87", + 'nbsp' => "\xC2\xA0", + 'nbsp;' => "\xC2\xA0", + 'ndash;' => "\xE2\x80\x93", + 'ne;' => "\xE2\x89\xA0", + 'ni;' => "\xE2\x88\x8B", + 'not' => "\xC2\xAC", + 'not;' => "\xC2\xAC", + 'notin;' => "\xE2\x88\x89", + 'nsub;' => "\xE2\x8A\x84", + 'Ntilde' => "\xC3\x91", + 'ntilde' => "\xC3\xB1", + 'Ntilde;' => "\xC3\x91", + 'ntilde;' => "\xC3\xB1", + 'Nu;' => "\xCE\x9D", + 'nu;' => "\xCE\xBD", + 'Oacute' => "\xC3\x93", + 'oacute' => "\xC3\xB3", + 'Oacute;' => "\xC3\x93", + 'oacute;' => "\xC3\xB3", + 'Ocirc' => "\xC3\x94", + 'ocirc' => "\xC3\xB4", + 'Ocirc;' => "\xC3\x94", + 'ocirc;' => "\xC3\xB4", + 'OElig;' => "\xC5\x92", + 'oelig;' => "\xC5\x93", + 'Ograve' => "\xC3\x92", + 'ograve' => "\xC3\xB2", + 'Ograve;' => "\xC3\x92", + 'ograve;' => "\xC3\xB2", + 'oline;' => "\xE2\x80\xBE", + 'Omega;' => "\xCE\xA9", + 'omega;' => "\xCF\x89", + 'Omicron;' => "\xCE\x9F", + 'omicron;' => "\xCE\xBF", + 'oplus;' => "\xE2\x8A\x95", + 'or;' => "\xE2\x88\xA8", + 'ordf' => "\xC2\xAA", + 'ordf;' => "\xC2\xAA", + 'ordm' => "\xC2\xBA", + 'ordm;' => "\xC2\xBA", + 'Oslash' => "\xC3\x98", + 'oslash' => "\xC3\xB8", + 'Oslash;' => "\xC3\x98", + 'oslash;' => "\xC3\xB8", + 'Otilde' => "\xC3\x95", + 'otilde' => "\xC3\xB5", + 'Otilde;' => "\xC3\x95", + 'otilde;' => "\xC3\xB5", + 'otimes;' => "\xE2\x8A\x97", + 'Ouml' => "\xC3\x96", + 'ouml' => "\xC3\xB6", + 'Ouml;' => "\xC3\x96", + 'ouml;' => "\xC3\xB6", + 'para' => "\xC2\xB6", + 'para;' => "\xC2\xB6", + 'part;' => "\xE2\x88\x82", + 'permil;' => "\xE2\x80\xB0", + 'perp;' => "\xE2\x8A\xA5", + 'Phi;' => "\xCE\xA6", + 'phi;' => "\xCF\x86", + 'Pi;' => "\xCE\xA0", + 'pi;' => "\xCF\x80", + 'piv;' => "\xCF\x96", + 'plusmn' => "\xC2\xB1", + 'plusmn;' => "\xC2\xB1", + 'pound' => "\xC2\xA3", + 'pound;' => "\xC2\xA3", + 'Prime;' => "\xE2\x80\xB3", + 'prime;' => "\xE2\x80\xB2", + 'prod;' => "\xE2\x88\x8F", + 'prop;' => "\xE2\x88\x9D", + 'Psi;' => "\xCE\xA8", + 'psi;' => "\xCF\x88", + 'QUOT' => "\x22", + 'quot' => "\x22", + 'QUOT;' => "\x22", + 'quot;' => "\x22", + 'radic;' => "\xE2\x88\x9A", + 'rang;' => "\xE3\x80\x89", + 'raquo' => "\xC2\xBB", + 'raquo;' => "\xC2\xBB", + 'rArr;' => "\xE2\x87\x92", + 'rarr;' => "\xE2\x86\x92", + 'rceil;' => "\xE2\x8C\x89", + 'rdquo;' => "\xE2\x80\x9D", + 'real;' => "\xE2\x84\x9C", + 'REG' => "\xC2\xAE", + 'reg' => "\xC2\xAE", + 'REG;' => "\xC2\xAE", + 'reg;' => "\xC2\xAE", + 'rfloor;' => "\xE2\x8C\x8B", + 'Rho;' => "\xCE\xA1", + 'rho;' => "\xCF\x81", + 'rlm;' => "\xE2\x80\x8F", + 'rsaquo;' => "\xE2\x80\xBA", + 'rsquo;' => "\xE2\x80\x99", + 'sbquo;' => "\xE2\x80\x9A", + 'Scaron;' => "\xC5\xA0", + 'scaron;' => "\xC5\xA1", + 'sdot;' => "\xE2\x8B\x85", + 'sect' => "\xC2\xA7", + 'sect;' => "\xC2\xA7", + 'shy' => "\xC2\xAD", + 'shy;' => "\xC2\xAD", + 'Sigma;' => "\xCE\xA3", + 'sigma;' => "\xCF\x83", + 'sigmaf;' => "\xCF\x82", + 'sim;' => "\xE2\x88\xBC", + 'spades;' => "\xE2\x99\xA0", + 'sub;' => "\xE2\x8A\x82", + 'sube;' => "\xE2\x8A\x86", + 'sum;' => "\xE2\x88\x91", + 'sup;' => "\xE2\x8A\x83", + 'sup1' => "\xC2\xB9", + 'sup1;' => "\xC2\xB9", + 'sup2' => "\xC2\xB2", + 'sup2;' => "\xC2\xB2", + 'sup3' => "\xC2\xB3", + 'sup3;' => "\xC2\xB3", + 'supe;' => "\xE2\x8A\x87", + 'szlig' => "\xC3\x9F", + 'szlig;' => "\xC3\x9F", + 'Tau;' => "\xCE\xA4", + 'tau;' => "\xCF\x84", + 'there4;' => "\xE2\x88\xB4", + 'Theta;' => "\xCE\x98", + 'theta;' => "\xCE\xB8", + 'thetasym;' => "\xCF\x91", + 'thinsp;' => "\xE2\x80\x89", + 'THORN' => "\xC3\x9E", + 'thorn' => "\xC3\xBE", + 'THORN;' => "\xC3\x9E", + 'thorn;' => "\xC3\xBE", + 'tilde;' => "\xCB\x9C", + 'times' => "\xC3\x97", + 'times;' => "\xC3\x97", + 'TRADE;' => "\xE2\x84\xA2", + 'trade;' => "\xE2\x84\xA2", + 'Uacute' => "\xC3\x9A", + 'uacute' => "\xC3\xBA", + 'Uacute;' => "\xC3\x9A", + 'uacute;' => "\xC3\xBA", + 'uArr;' => "\xE2\x87\x91", + 'uarr;' => "\xE2\x86\x91", + 'Ucirc' => "\xC3\x9B", + 'ucirc' => "\xC3\xBB", + 'Ucirc;' => "\xC3\x9B", + 'ucirc;' => "\xC3\xBB", + 'Ugrave' => "\xC3\x99", + 'ugrave' => "\xC3\xB9", + 'Ugrave;' => "\xC3\x99", + 'ugrave;' => "\xC3\xB9", + 'uml' => "\xC2\xA8", + 'uml;' => "\xC2\xA8", + 'upsih;' => "\xCF\x92", + 'Upsilon;' => "\xCE\xA5", + 'upsilon;' => "\xCF\x85", + 'Uuml' => "\xC3\x9C", + 'uuml' => "\xC3\xBC", + 'Uuml;' => "\xC3\x9C", + 'uuml;' => "\xC3\xBC", + 'weierp;' => "\xE2\x84\x98", + 'Xi;' => "\xCE\x9E", + 'xi;' => "\xCE\xBE", + 'Yacute' => "\xC3\x9D", + 'yacute' => "\xC3\xBD", + 'Yacute;' => "\xC3\x9D", + 'yacute;' => "\xC3\xBD", + 'yen' => "\xC2\xA5", + 'yen;' => "\xC2\xA5", + 'yuml' => "\xC3\xBF", + 'Yuml;' => "\xC5\xB8", + 'yuml;' => "\xC3\xBF", + 'Zeta;' => "\xCE\x96", + 'zeta;' => "\xCE\xB6", + 'zwj;' => "\xE2\x80\x8D", + 'zwnj;' => "\xE2\x80\x8C" + ); + + for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++) + { + $consumed = substr($this->consumed, 1); + if (isset($entities[$consumed])) + { + $match = $consumed; + } + } + + if ($match !== null) + { + $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1); + $this->position += strlen($entities[$match]) - strlen($consumed) - 1; + } + break; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Enclosure.php b/sources/wp-includes/SimplePie/Enclosure.php new file mode 100644 index 0000000..5567437 --- /dev/null +++ b/sources/wp-includes/SimplePie/Enclosure.php @@ -0,0 +1,1380 @@ +bitrate = $bitrate; + $this->captions = $captions; + $this->categories = $categories; + $this->channels = $channels; + $this->copyright = $copyright; + $this->credits = $credits; + $this->description = $description; + $this->duration = $duration; + $this->expression = $expression; + $this->framerate = $framerate; + $this->hashes = $hashes; + $this->height = $height; + $this->keywords = $keywords; + $this->lang = $lang; + $this->length = $length; + $this->link = $link; + $this->medium = $medium; + $this->player = $player; + $this->ratings = $ratings; + $this->restrictions = $restrictions; + $this->samplingrate = $samplingrate; + $this->thumbnails = $thumbnails; + $this->title = $title; + $this->type = $type; + $this->width = $width; + + if (class_exists('idna_convert')) + { + $idn = new idna_convert(); + $parsed = SimplePie_Misc::parse_url($link); + $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); + } + $this->handler = $this->get_handler(); // Needs to load last + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the bitrate + * + * @return string|null + */ + public function get_bitrate() + { + if ($this->bitrate !== null) + { + return $this->bitrate; + } + else + { + return null; + } + } + + /** + * Get a single caption + * + * @param int $key + * @return SimplePie_Caption|null + */ + public function get_caption($key = 0) + { + $captions = $this->get_captions(); + if (isset($captions[$key])) + { + return $captions[$key]; + } + else + { + return null; + } + } + + /** + * Get all captions + * + * @return array|null Array of {@see SimplePie_Caption} objects + */ + public function get_captions() + { + if ($this->captions !== null) + { + return $this->captions; + } + else + { + return null; + } + } + + /** + * Get a single category + * + * @param int $key + * @return SimplePie_Category|null + */ + public function get_category($key = 0) + { + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } + } + + /** + * Get all categories + * + * @return array|null Array of {@see SimplePie_Category} objects + */ + public function get_categories() + { + if ($this->categories !== null) + { + return $this->categories; + } + else + { + return null; + } + } + + /** + * Get the number of audio channels + * + * @return int|null + */ + public function get_channels() + { + if ($this->channels !== null) + { + return $this->channels; + } + else + { + return null; + } + } + + /** + * Get the copyright information + * + * @return SimplePie_Copyright|null + */ + public function get_copyright() + { + if ($this->copyright !== null) + { + return $this->copyright; + } + else + { + return null; + } + } + + /** + * Get a single credit + * + * @param int $key + * @return SimplePie_Credit|null + */ + public function get_credit($key = 0) + { + $credits = $this->get_credits(); + if (isset($credits[$key])) + { + return $credits[$key]; + } + else + { + return null; + } + } + + /** + * Get all credits + * + * @return array|null Array of {@see SimplePie_Credit} objects + */ + public function get_credits() + { + if ($this->credits !== null) + { + return $this->credits; + } + else + { + return null; + } + } + + /** + * Get the description of the enclosure + * + * @return string|null + */ + public function get_description() + { + if ($this->description !== null) + { + return $this->description; + } + else + { + return null; + } + } + + /** + * Get the duration of the enclosure + * + * @param string $convert Convert seconds into hh:mm:ss + * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found) + */ + public function get_duration($convert = false) + { + if ($this->duration !== null) + { + if ($convert) + { + $time = SimplePie_Misc::time_hms($this->duration); + return $time; + } + else + { + return $this->duration; + } + } + else + { + return null; + } + } + + /** + * Get the expression + * + * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full' + */ + public function get_expression() + { + if ($this->expression !== null) + { + return $this->expression; + } + else + { + return 'full'; + } + } + + /** + * Get the file extension + * + * @return string|null + */ + public function get_extension() + { + if ($this->link !== null) + { + $url = SimplePie_Misc::parse_url($this->link); + if ($url['path'] !== '') + { + return pathinfo($url['path'], PATHINFO_EXTENSION); + } + } + return null; + } + + /** + * Get the framerate (in frames-per-second) + * + * @return string|null + */ + public function get_framerate() + { + if ($this->framerate !== null) + { + return $this->framerate; + } + else + { + return null; + } + } + + /** + * Get the preferred handler + * + * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3' + */ + public function get_handler() + { + return $this->get_real_type(true); + } + + /** + * Get a single hash + * + * @link http://www.rssboard.org/media-rss#media-hash + * @param int $key + * @return string|null Hash as per `media:hash`, prefixed with "$algo:" + */ + public function get_hash($key = 0) + { + $hashes = $this->get_hashes(); + if (isset($hashes[$key])) + { + return $hashes[$key]; + } + else + { + return null; + } + } + + /** + * Get all credits + * + * @return array|null Array of strings, see {@see get_hash()} + */ + public function get_hashes() + { + if ($this->hashes !== null) + { + return $this->hashes; + } + else + { + return null; + } + } + + /** + * Get the height + * + * @return string|null + */ + public function get_height() + { + if ($this->height !== null) + { + return $this->height; + } + else + { + return null; + } + } + + /** + * Get the language + * + * @link http://tools.ietf.org/html/rfc3066 + * @return string|null Language code as per RFC 3066 + */ + public function get_language() + { + if ($this->lang !== null) + { + return $this->lang; + } + else + { + return null; + } + } + + /** + * Get a single keyword + * + * @param int $key + * @return string|null + */ + public function get_keyword($key = 0) + { + $keywords = $this->get_keywords(); + if (isset($keywords[$key])) + { + return $keywords[$key]; + } + else + { + return null; + } + } + + /** + * Get all keywords + * + * @return array|null Array of strings + */ + public function get_keywords() + { + if ($this->keywords !== null) + { + return $this->keywords; + } + else + { + return null; + } + } + + /** + * Get length + * + * @return float Length in bytes + */ + public function get_length() + { + if ($this->length !== null) + { + return $this->length; + } + else + { + return null; + } + } + + /** + * Get the URL + * + * @return string|null + */ + public function get_link() + { + if ($this->link !== null) + { + return urldecode($this->link); + } + else + { + return null; + } + } + + /** + * Get the medium + * + * @link http://www.rssboard.org/media-rss#media-content + * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable' + */ + public function get_medium() + { + if ($this->medium !== null) + { + return $this->medium; + } + else + { + return null; + } + } + + /** + * Get the player URL + * + * Typically the same as {@see get_permalink()} + * @return string|null Player URL + */ + public function get_player() + { + if ($this->player !== null) + { + return $this->player; + } + else + { + return null; + } + } + + /** + * Get a single rating + * + * @param int $key + * @return SimplePie_Rating|null + */ + public function get_rating($key = 0) + { + $ratings = $this->get_ratings(); + if (isset($ratings[$key])) + { + return $ratings[$key]; + } + else + { + return null; + } + } + + /** + * Get all ratings + * + * @return array|null Array of {@see SimplePie_Rating} objects + */ + public function get_ratings() + { + if ($this->ratings !== null) + { + return $this->ratings; + } + else + { + return null; + } + } + + /** + * Get a single restriction + * + * @param int $key + * @return SimplePie_Restriction|null + */ + public function get_restriction($key = 0) + { + $restrictions = $this->get_restrictions(); + if (isset($restrictions[$key])) + { + return $restrictions[$key]; + } + else + { + return null; + } + } + + /** + * Get all restrictions + * + * @return array|null Array of {@see SimplePie_Restriction} objects + */ + public function get_restrictions() + { + if ($this->restrictions !== null) + { + return $this->restrictions; + } + else + { + return null; + } + } + + /** + * Get the sampling rate (in kHz) + * + * @return string|null + */ + public function get_sampling_rate() + { + if ($this->samplingrate !== null) + { + return $this->samplingrate; + } + else + { + return null; + } + } + + /** + * Get the file size (in MiB) + * + * @return float|null File size in mebibytes (1048 bytes) + */ + public function get_size() + { + $length = $this->get_length(); + if ($length !== null) + { + return round($length/1048576, 2); + } + else + { + return null; + } + } + + /** + * Get a single thumbnail + * + * @param int $key + * @return string|null Thumbnail URL + */ + public function get_thumbnail($key = 0) + { + $thumbnails = $this->get_thumbnails(); + if (isset($thumbnails[$key])) + { + return $thumbnails[$key]; + } + else + { + return null; + } + } + + /** + * Get all thumbnails + * + * @return array|null Array of thumbnail URLs + */ + public function get_thumbnails() + { + if ($this->thumbnails !== null) + { + return $this->thumbnails; + } + else + { + return null; + } + } + + /** + * Get the title + * + * @return string|null + */ + public function get_title() + { + if ($this->title !== null) + { + return $this->title; + } + else + { + return null; + } + } + + /** + * Get mimetype of the enclosure + * + * @see get_real_type() + * @return string|null MIME type + */ + public function get_type() + { + if ($this->type !== null) + { + return $this->type; + } + else + { + return null; + } + } + + /** + * Get the width + * + * @return string|null + */ + public function get_width() + { + if ($this->width !== null) + { + return $this->width; + } + else + { + return null; + } + } + + /** + * Embed the enclosure using `` + * + * @deprecated Use the second parameter to {@see embed} instead + * + * @param array|string $options See first paramter to {@see embed} + * @return string HTML string to output + */ + public function native_embed($options='') + { + return $this->embed($options, true); + } + + /** + * Embed the enclosure using Javascript + * + * `$options` is an array or comma-separated key:value string, with the + * following properties: + * + * - `alt` (string): Alternate content for when an end-user does not have + * the appropriate handler installed or when a file type is + * unsupported. Can be any text or HTML. Defaults to blank. + * - `altclass` (string): If a file type is unsupported, the end-user will + * see the alt text (above) linked directly to the content. That link + * will have this value as its class name. Defaults to blank. + * - `audio` (string): This is an image that should be used as a + * placeholder for audio files before they're loaded (QuickTime-only). + * Can be any relative or absolute URL. Defaults to blank. + * - `bgcolor` (string): The background color for the media, if not + * already transparent. Defaults to `#ffffff`. + * - `height` (integer): The height of the embedded media. Accepts any + * numeric pixel value (such as `360`) or `auto`. Defaults to `auto`, + * and it is recommended that you use this default. + * - `loop` (boolean): Do you want the media to loop when its done? + * Defaults to `false`. + * - `mediaplayer` (string): The location of the included + * `mediaplayer.swf` file. This allows for the playback of Flash Video + * (`.flv`) files, and is the default handler for non-Odeo MP3's. + * Defaults to blank. + * - `video` (string): This is an image that should be used as a + * placeholder for video files before they're loaded (QuickTime-only). + * Can be any relative or absolute URL. Defaults to blank. + * - `width` (integer): The width of the embedded media. Accepts any + * numeric pixel value (such as `480`) or `auto`. Defaults to `auto`, + * and it is recommended that you use this default. + * - `widescreen` (boolean): Is the enclosure widescreen or standard? + * This applies only to video enclosures, and will automatically resize + * the content appropriately. Defaults to `false`, implying 4:3 mode. + * + * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto` + * will default to 480x360 video resolution. Widescreen (16:9) mode with + * `width` and `height` set to `auto` will default to 480x270 video resolution. + * + * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'. + * @param array|string $options Comma-separated key:value list, or array + * @param bool $native Use `` + * @return string HTML string to output + */ + public function embed($options = '', $native = false) + { + // Set up defaults + $audio = ''; + $video = ''; + $alt = ''; + $altclass = ''; + $loop = 'false'; + $width = 'auto'; + $height = 'auto'; + $bgcolor = '#ffffff'; + $mediaplayer = ''; + $widescreen = false; + $handler = $this->get_handler(); + $type = $this->get_real_type(); + + // Process options and reassign values as necessary + if (is_array($options)) + { + extract($options); + } + else + { + $options = explode(',', $options); + foreach($options as $option) + { + $opt = explode(':', $option, 2); + if (isset($opt[0], $opt[1])) + { + $opt[0] = trim($opt[0]); + $opt[1] = trim($opt[1]); + switch ($opt[0]) + { + case 'audio': + $audio = $opt[1]; + break; + + case 'video': + $video = $opt[1]; + break; + + case 'alt': + $alt = $opt[1]; + break; + + case 'altclass': + $altclass = $opt[1]; + break; + + case 'loop': + $loop = $opt[1]; + break; + + case 'width': + $width = $opt[1]; + break; + + case 'height': + $height = $opt[1]; + break; + + case 'bgcolor': + $bgcolor = $opt[1]; + break; + + case 'mediaplayer': + $mediaplayer = $opt[1]; + break; + + case 'widescreen': + $widescreen = $opt[1]; + break; + } + } + } + } + + $mime = explode('/', $type, 2); + $mime = $mime[0]; + + // Process values for 'auto' + if ($width === 'auto') + { + if ($mime === 'video') + { + if ($height === 'auto') + { + $width = 480; + } + elseif ($widescreen) + { + $width = round((intval($height)/9)*16); + } + else + { + $width = round((intval($height)/3)*4); + } + } + else + { + $width = '100%'; + } + } + + if ($height === 'auto') + { + if ($mime === 'audio') + { + $height = 0; + } + elseif ($mime === 'video') + { + if ($width === 'auto') + { + if ($widescreen) + { + $height = 270; + } + else + { + $height = 360; + } + } + elseif ($widescreen) + { + $height = round((intval($width)/16)*9); + } + else + { + $height = round((intval($width)/4)*3); + } + } + else + { + $height = 376; + } + } + elseif ($mime === 'audio') + { + $height = 0; + } + + // Set proper placeholder value + if ($mime === 'audio') + { + $placeholder = $audio; + } + elseif ($mime === 'video') + { + $placeholder = $video; + } + + $embed = ''; + + // Flash + if ($handler === 'flash') + { + if ($native) + { + $embed .= "get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\">"; + } + else + { + $embed .= ""; + } + } + + // Flash Media Player file types. + // Preferred handler for MP3 file types. + elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== '')) + { + $height += 20; + if ($native) + { + $embed .= "get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\">"; + } + else + { + $embed .= ""; + } + } + + // QuickTime 7 file types. Need to test with QuickTime 6. + // Only handle MP3's if the Flash Media Player is not present. + elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === '')) + { + $height += 16; + if ($native) + { + if ($placeholder !== '') + { + $embed .= "get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\">"; + } + else + { + $embed .= "get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\">"; + } + } + else + { + $embed .= ""; + } + } + + // Windows Media + elseif ($handler === 'wmedia') + { + $height += 45; + if ($native) + { + $embed .= "get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\">"; + } + else + { + $embed .= ""; + } + } + + // Everything else + else $embed .= '' . $alt . ''; + + return $embed; + } + + /** + * Get the real media type + * + * Often, feeds lie to us, necessitating a bit of deeper inspection. This + * converts types to their canonical representations based on the file + * extension + * + * @see get_type() + * @param bool $find_handler Internal use only, use {@see get_handler()} instead + * @return string MIME type + */ + public function get_real_type($find_handler = false) + { + // Mime-types by handler. + $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash + $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player + $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime + $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media + $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3 + + if ($this->get_type() !== null) + { + $type = strtolower($this->type); + } + else + { + $type = null; + } + + // If we encounter an unsupported mime-type, check the file extension and guess intelligently. + if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3))) + { + switch (strtolower($this->get_extension())) + { + // Audio mime-types + case 'aac': + case 'adts': + $type = 'audio/acc'; + break; + + case 'aif': + case 'aifc': + case 'aiff': + case 'cdda': + $type = 'audio/aiff'; + break; + + case 'bwf': + $type = 'audio/wav'; + break; + + case 'kar': + case 'mid': + case 'midi': + case 'smf': + $type = 'audio/midi'; + break; + + case 'm4a': + $type = 'audio/x-m4a'; + break; + + case 'mp3': + case 'swa': + $type = 'audio/mp3'; + break; + + case 'wav': + $type = 'audio/wav'; + break; + + case 'wax': + $type = 'audio/x-ms-wax'; + break; + + case 'wma': + $type = 'audio/x-ms-wma'; + break; + + // Video mime-types + case '3gp': + case '3gpp': + $type = 'video/3gpp'; + break; + + case '3g2': + case '3gp2': + $type = 'video/3gpp2'; + break; + + case 'asf': + $type = 'video/x-ms-asf'; + break; + + case 'flv': + $type = 'video/x-flv'; + break; + + case 'm1a': + case 'm1s': + case 'm1v': + case 'm15': + case 'm75': + case 'mp2': + case 'mpa': + case 'mpeg': + case 'mpg': + case 'mpm': + case 'mpv': + $type = 'video/mpeg'; + break; + + case 'm4v': + $type = 'video/x-m4v'; + break; + + case 'mov': + case 'qt': + $type = 'video/quicktime'; + break; + + case 'mp4': + case 'mpg4': + $type = 'video/mp4'; + break; + + case 'sdv': + $type = 'video/sd-video'; + break; + + case 'wm': + $type = 'video/x-ms-wm'; + break; + + case 'wmv': + $type = 'video/x-ms-wmv'; + break; + + case 'wvx': + $type = 'video/x-ms-wvx'; + break; + + // Flash mime-types + case 'spl': + $type = 'application/futuresplash'; + break; + + case 'swf': + $type = 'application/x-shockwave-flash'; + break; + } + } + + if ($find_handler) + { + if (in_array($type, $types_flash)) + { + return 'flash'; + } + elseif (in_array($type, $types_fmedia)) + { + return 'fmedia'; + } + elseif (in_array($type, $types_quicktime)) + { + return 'quicktime'; + } + elseif (in_array($type, $types_wmedia)) + { + return 'wmedia'; + } + elseif (in_array($type, $types_mp3)) + { + return 'mp3'; + } + else + { + return null; + } + } + else + { + return $type; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Exception.php b/sources/wp-includes/SimplePie/Exception.php new file mode 100644 index 0000000..73e104d --- /dev/null +++ b/sources/wp-includes/SimplePie/Exception.php @@ -0,0 +1,52 @@ +encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']); + } + $this->url = $url; + $this->useragent = $useragent; + if (preg_match('/^http(s)?:\/\//i', $url)) + { + if ($useragent === null) + { + $useragent = ini_get('user_agent'); + $this->useragent = $useragent; + } + if (!is_array($headers)) + { + $headers = array(); + } + if (!$force_fsockopen && function_exists('curl_exec')) + { + $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL; + $fp = curl_init(); + $headers2 = array(); + foreach ($headers as $key => $value) + { + $headers2[] = "$key: $value"; + } + if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>=')) + { + curl_setopt($fp, CURLOPT_ENCODING, ''); + } + curl_setopt($fp, CURLOPT_URL, $url); + curl_setopt($fp, CURLOPT_HEADER, 1); + curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($fp, CURLOPT_TIMEOUT, $timeout); + curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout); + curl_setopt($fp, CURLOPT_REFERER, $url); + curl_setopt($fp, CURLOPT_USERAGENT, $useragent); + curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2); + if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>=')) + { + curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects); + } + + $this->headers = curl_exec($fp); + if (curl_errno($fp) === 23 || curl_errno($fp) === 61) + { + curl_setopt($fp, CURLOPT_ENCODING, 'none'); + $this->headers = curl_exec($fp); + } + if (curl_errno($fp)) + { + $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp); + $this->success = false; + } + else + { + $info = curl_getinfo($fp); + curl_close($fp); + $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1); + $this->headers = array_pop($this->headers); + $parser = new SimplePie_HTTP_Parser($this->headers); + if ($parser->parse()) + { + $this->headers = $parser->headers; + $this->body = $parser->body; + $this->status_code = $parser->status_code; + if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) + { + $this->redirects++; + $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); + return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); + } + } + } + } + else + { + $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN; + $url_parts = parse_url($url); + $socket_host = $url_parts['host']; + if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') + { + $socket_host = "ssl://$url_parts[host]"; + $url_parts['port'] = 443; + } + if (!isset($url_parts['port'])) + { + $url_parts['port'] = 80; + } + $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout); + if (!$fp) + { + $this->error = 'fsockopen error: ' . $errstr; + $this->success = false; + } + else + { + stream_set_timeout($fp, $timeout); + if (isset($url_parts['path'])) + { + if (isset($url_parts['query'])) + { + $get = "$url_parts[path]?$url_parts[query]"; + } + else + { + $get = $url_parts['path']; + } + } + else + { + $get = '/'; + } + $out = "GET $get HTTP/1.1\r\n"; + $out .= "Host: $url_parts[host]\r\n"; + $out .= "User-Agent: $useragent\r\n"; + if (extension_loaded('zlib')) + { + $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n"; + } + + if (isset($url_parts['user']) && isset($url_parts['pass'])) + { + $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n"; + } + foreach ($headers as $key => $value) + { + $out .= "$key: $value\r\n"; + } + $out .= "Connection: Close\r\n\r\n"; + fwrite($fp, $out); + + $info = stream_get_meta_data($fp); + + $this->headers = ''; + while (!$info['eof'] && !$info['timed_out']) + { + $this->headers .= fread($fp, 1160); + $info = stream_get_meta_data($fp); + } + if (!$info['timed_out']) + { + $parser = new SimplePie_HTTP_Parser($this->headers); + if ($parser->parse()) + { + $this->headers = $parser->headers; + $this->body = $parser->body; + $this->status_code = $parser->status_code; + if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects) + { + $this->redirects++; + $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url); + return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen); + } + if (isset($this->headers['content-encoding'])) + { + // Hey, we act dumb elsewhere, so let's do that here too + switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20"))) + { + case 'gzip': + case 'x-gzip': + $decoder = new SimplePie_gzdecode($this->body); + if (!$decoder->parse()) + { + $this->error = 'Unable to decode HTTP "gzip" stream'; + $this->success = false; + } + else + { + $this->body = $decoder->data; + } + break; + + case 'deflate': + if (($decompressed = gzinflate($this->body)) !== false) + { + $this->body = $decompressed; + } + else if (($decompressed = gzuncompress($this->body)) !== false) + { + $this->body = $decompressed; + } + else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false) + { + $this->body = $decompressed; + } + else + { + $this->error = 'Unable to decode HTTP "deflate" stream'; + $this->success = false; + } + break; + + default: + $this->error = 'Unknown content coding'; + $this->success = false; + } + } + } + } + else + { + $this->error = 'fsocket timed out'; + $this->success = false; + } + fclose($fp); + } + } + } + else + { + $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS; + if (!$this->body = file_get_contents($url)) + { + $this->error = 'file_get_contents could not read the file'; + $this->success = false; + } + } + } +} diff --git a/sources/wp-includes/SimplePie/HTTP/Parser.php b/sources/wp-includes/SimplePie/HTTP/Parser.php new file mode 100644 index 0000000..bff2222 --- /dev/null +++ b/sources/wp-includes/SimplePie/HTTP/Parser.php @@ -0,0 +1,500 @@ +data = $data; + $this->data_length = strlen($this->data); + } + + /** + * Parse the input data + * + * @return bool true on success, false on failure + */ + public function parse() + { + while ($this->state && $this->state !== 'emit' && $this->has_data()) + { + $state = $this->state; + $this->$state(); + } + $this->data = ''; + if ($this->state === 'emit' || $this->state === 'body') + { + return true; + } + else + { + $this->http_version = ''; + $this->status_code = ''; + $this->reason = ''; + $this->headers = array(); + $this->body = ''; + return false; + } + } + + /** + * Check whether there is data beyond the pointer + * + * @return bool true if there is further data, false if not + */ + protected function has_data() + { + return (bool) ($this->position < $this->data_length); + } + + /** + * See if the next character is LWS + * + * @return bool true if the next character is LWS, false if not + */ + protected function is_linear_whitespace() + { + return (bool) ($this->data[$this->position] === "\x09" + || $this->data[$this->position] === "\x20" + || ($this->data[$this->position] === "\x0A" + && isset($this->data[$this->position + 1]) + && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20"))); + } + + /** + * Parse the HTTP version + */ + protected function http_version() + { + if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/') + { + $len = strspn($this->data, '0123456789.', 5); + $this->http_version = substr($this->data, 5, $len); + $this->position += 5 + $len; + if (substr_count($this->http_version, '.') <= 1) + { + $this->http_version = (float) $this->http_version; + $this->position += strspn($this->data, "\x09\x20", $this->position); + $this->state = 'status'; + } + else + { + $this->state = false; + } + } + else + { + $this->state = false; + } + } + + /** + * Parse the status code + */ + protected function status() + { + if ($len = strspn($this->data, '0123456789', $this->position)) + { + $this->status_code = (int) substr($this->data, $this->position, $len); + $this->position += $len; + $this->state = 'reason'; + } + else + { + $this->state = false; + } + } + + /** + * Parse the reason phrase + */ + protected function reason() + { + $len = strcspn($this->data, "\x0A", $this->position); + $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20"); + $this->position += $len + 1; + $this->state = 'new_line'; + } + + /** + * Deal with a new line, shifting data around as needed + */ + protected function new_line() + { + $this->value = trim($this->value, "\x0D\x20"); + if ($this->name !== '' && $this->value !== '') + { + $this->name = strtolower($this->name); + // We should only use the last Content-Type header. c.f. issue #1 + if (isset($this->headers[$this->name]) && $this->name !== 'content-type') + { + $this->headers[$this->name] .= ', ' . $this->value; + } + else + { + $this->headers[$this->name] = $this->value; + } + } + $this->name = ''; + $this->value = ''; + if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A") + { + $this->position += 2; + $this->state = 'body'; + } + elseif ($this->data[$this->position] === "\x0A") + { + $this->position++; + $this->state = 'body'; + } + else + { + $this->state = 'name'; + } + } + + /** + * Parse a header name + */ + protected function name() + { + $len = strcspn($this->data, "\x0A:", $this->position); + if (isset($this->data[$this->position + $len])) + { + if ($this->data[$this->position + $len] === "\x0A") + { + $this->position += $len; + $this->state = 'new_line'; + } + else + { + $this->name = substr($this->data, $this->position, $len); + $this->position += $len + 1; + $this->state = 'value'; + } + } + else + { + $this->state = false; + } + } + + /** + * Parse LWS, replacing consecutive LWS characters with a single space + */ + protected function linear_whitespace() + { + do + { + if (substr($this->data, $this->position, 2) === "\x0D\x0A") + { + $this->position += 2; + } + elseif ($this->data[$this->position] === "\x0A") + { + $this->position++; + } + $this->position += strspn($this->data, "\x09\x20", $this->position); + } while ($this->has_data() && $this->is_linear_whitespace()); + $this->value .= "\x20"; + } + + /** + * See what state to move to while within non-quoted header values + */ + protected function value() + { + if ($this->is_linear_whitespace()) + { + $this->linear_whitespace(); + } + else + { + switch ($this->data[$this->position]) + { + case '"': + // Workaround for ETags: we have to include the quotes as + // part of the tag. + if (strtolower($this->name) === 'etag') + { + $this->value .= '"'; + $this->position++; + $this->state = 'value_char'; + break; + } + $this->position++; + $this->state = 'quote'; + break; + + case "\x0A": + $this->position++; + $this->state = 'new_line'; + break; + + default: + $this->state = 'value_char'; + break; + } + } + } + + /** + * Parse a header value while outside quotes + */ + protected function value_char() + { + $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position); + $this->value .= substr($this->data, $this->position, $len); + $this->position += $len; + $this->state = 'value'; + } + + /** + * See what state to move to while within quoted header values + */ + protected function quote() + { + if ($this->is_linear_whitespace()) + { + $this->linear_whitespace(); + } + else + { + switch ($this->data[$this->position]) + { + case '"': + $this->position++; + $this->state = 'value'; + break; + + case "\x0A": + $this->position++; + $this->state = 'new_line'; + break; + + case '\\': + $this->position++; + $this->state = 'quote_escaped'; + break; + + default: + $this->state = 'quote_char'; + break; + } + } + } + + /** + * Parse a header value while within quotes + */ + protected function quote_char() + { + $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position); + $this->value .= substr($this->data, $this->position, $len); + $this->position += $len; + $this->state = 'value'; + } + + /** + * Parse an escaped character within quotes + */ + protected function quote_escaped() + { + $this->value .= $this->data[$this->position]; + $this->position++; + $this->state = 'quote'; + } + + /** + * Parse the body + */ + protected function body() + { + $this->body = substr($this->data, $this->position); + if (!empty($this->headers['transfer-encoding'])) + { + unset($this->headers['transfer-encoding']); + $this->state = 'chunked'; + } + else + { + $this->state = 'emit'; + } + } + + /** + * Parsed a "Transfer-Encoding: chunked" body + */ + protected function chunked() + { + if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body))) + { + $this->state = 'emit'; + return; + } + + $decoded = ''; + $encoded = $this->body; + + while (true) + { + $is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches ); + if (!$is_chunked) + { + // Looks like it's not chunked after all + $this->state = 'emit'; + return; + } + + $length = hexdec(trim($matches[1])); + if ($length === 0) + { + // Ignore trailer headers + $this->state = 'emit'; + $this->body = $decoded; + return; + } + + $chunk_length = strlen($matches[0]); + $decoded .= $part = substr($encoded, $chunk_length, $length); + $encoded = substr($encoded, $chunk_length + $length + 2); + + if (trim($encoded) === '0' || empty($encoded)) + { + $this->state = 'emit'; + $this->body = $decoded; + return; + } + } + } +} diff --git a/sources/wp-includes/SimplePie/IRI.php b/sources/wp-includes/SimplePie/IRI.php new file mode 100644 index 0000000..d3198c0 --- /dev/null +++ b/sources/wp-includes/SimplePie/IRI.php @@ -0,0 +1,1238 @@ + array( + 'port' => 674 + ), + 'dict' => array( + 'port' => 2628 + ), + 'file' => array( + 'ihost' => 'localhost' + ), + 'http' => array( + 'port' => 80, + 'ipath' => '/' + ), + 'https' => array( + 'port' => 443, + 'ipath' => '/' + ), + ); + + /** + * Return the entire IRI when you try and read the object as a string + * + * @return string + */ + public function __toString() + { + return $this->get_iri(); + } + + /** + * Overload __set() to provide access via properties + * + * @param string $name Property name + * @param mixed $value Property value + */ + public function __set($name, $value) + { + if (method_exists($this, 'set_' . $name)) + { + call_user_func(array($this, 'set_' . $name), $value); + } + elseif ( + $name === 'iauthority' + || $name === 'iuserinfo' + || $name === 'ihost' + || $name === 'ipath' + || $name === 'iquery' + || $name === 'ifragment' + ) + { + call_user_func(array($this, 'set_' . substr($name, 1)), $value); + } + } + + /** + * Overload __get() to provide access via properties + * + * @param string $name Property name + * @return mixed + */ + public function __get($name) + { + // isset() returns false for null, we don't want to do that + // Also why we use array_key_exists below instead of isset() + $props = get_object_vars($this); + + if ( + $name === 'iri' || + $name === 'uri' || + $name === 'iauthority' || + $name === 'authority' + ) + { + $return = $this->{"get_$name"}(); + } + elseif (array_key_exists($name, $props)) + { + $return = $this->$name; + } + // host -> ihost + elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) + { + $name = $prop; + $return = $this->$prop; + } + // ischeme -> scheme + elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) + { + $name = $prop; + $return = $this->$prop; + } + else + { + trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE); + $return = null; + } + + if ($return === null && isset($this->normalization[$this->scheme][$name])) + { + return $this->normalization[$this->scheme][$name]; + } + else + { + return $return; + } + } + + /** + * Overload __isset() to provide access via properties + * + * @param string $name Property name + * @return bool + */ + public function __isset($name) + { + if (method_exists($this, 'get_' . $name) || isset($this->$name)) + { + return true; + } + else + { + return false; + } + } + + /** + * Overload __unset() to provide access via properties + * + * @param string $name Property name + */ + public function __unset($name) + { + if (method_exists($this, 'set_' . $name)) + { + call_user_func(array($this, 'set_' . $name), ''); + } + } + + /** + * Create a new IRI object, from a specified string + * + * @param string $iri + */ + public function __construct($iri = null) + { + $this->set_iri($iri); + } + + /** + * Create a new IRI object by resolving a relative IRI + * + * Returns false if $base is not absolute, otherwise an IRI. + * + * @param IRI|string $base (Absolute) Base IRI + * @param IRI|string $relative Relative IRI + * @return IRI|false + */ + public static function absolutize($base, $relative) + { + if (!($relative instanceof SimplePie_IRI)) + { + $relative = new SimplePie_IRI($relative); + } + if (!$relative->is_valid()) + { + return false; + } + elseif ($relative->scheme !== null) + { + return clone $relative; + } + else + { + if (!($base instanceof SimplePie_IRI)) + { + $base = new SimplePie_IRI($base); + } + if ($base->scheme !== null && $base->is_valid()) + { + if ($relative->get_iri() !== '') + { + if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) + { + $target = clone $relative; + $target->scheme = $base->scheme; + } + else + { + $target = new SimplePie_IRI; + $target->scheme = $base->scheme; + $target->iuserinfo = $base->iuserinfo; + $target->ihost = $base->ihost; + $target->port = $base->port; + if ($relative->ipath !== '') + { + if ($relative->ipath[0] === '/') + { + $target->ipath = $relative->ipath; + } + elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') + { + $target->ipath = '/' . $relative->ipath; + } + elseif (($last_segment = strrpos($base->ipath, '/')) !== false) + { + $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; + } + else + { + $target->ipath = $relative->ipath; + } + $target->ipath = $target->remove_dot_segments($target->ipath); + $target->iquery = $relative->iquery; + } + else + { + $target->ipath = $base->ipath; + if ($relative->iquery !== null) + { + $target->iquery = $relative->iquery; + } + elseif ($base->iquery !== null) + { + $target->iquery = $base->iquery; + } + } + $target->ifragment = $relative->ifragment; + } + } + else + { + $target = clone $base; + $target->ifragment = null; + } + $target->scheme_normalization(); + return $target; + } + else + { + return false; + } + } + } + + /** + * Parse an IRI into scheme/authority/path/query/fragment segments + * + * @param string $iri + * @return array + */ + protected function parse_iri($iri) + { + $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); + if (preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match)) + { + if ($match[1] === '') + { + $match['scheme'] = null; + } + if (!isset($match[3]) || $match[3] === '') + { + $match['authority'] = null; + } + if (!isset($match[5])) + { + $match['path'] = ''; + } + if (!isset($match[6]) || $match[6] === '') + { + $match['query'] = null; + } + if (!isset($match[8]) || $match[8] === '') + { + $match['fragment'] = null; + } + return $match; + } + else + { + // This can occur when a paragraph is accidentally parsed as a URI + return false; + } + } + + /** + * Remove dot segments from a path + * + * @param string $input + * @return string + */ + protected function remove_dot_segments($input) + { + $output = ''; + while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') + { + // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise, + if (strpos($input, '../') === 0) + { + $input = substr($input, 3); + } + elseif (strpos($input, './') === 0) + { + $input = substr($input, 2); + } + // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise, + elseif (strpos($input, '/./') === 0) + { + $input = substr($input, 2); + } + elseif ($input === '/.') + { + $input = '/'; + } + // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise, + elseif (strpos($input, '/../') === 0) + { + $input = substr($input, 3); + $output = substr_replace($output, '', strrpos($output, '/')); + } + elseif ($input === '/..') + { + $input = '/'; + $output = substr_replace($output, '', strrpos($output, '/')); + } + // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise, + elseif ($input === '.' || $input === '..') + { + $input = ''; + } + // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer + elseif (($pos = strpos($input, '/', 1)) !== false) + { + $output .= substr($input, 0, $pos); + $input = substr_replace($input, '', 0, $pos); + } + else + { + $output .= $input; + $input = ''; + } + } + return $output . $input; + } + + /** + * Replace invalid character with percent encoding + * + * @param string $string Input string + * @param string $extra_chars Valid characters not in iunreserved or + * iprivate (this is ASCII-only) + * @param bool $iprivate Allow iprivate + * @return string + */ + protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) + { + // Normalize as many pct-encoded sections as possible + $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string); + + // Replace invalid percent characters + $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string); + + // Add unreserved and % to $extra_chars (the latter is safe because all + // pct-encoded sections are now valid). + $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; + + // Now replace any bytes that aren't allowed with their pct-encoded versions + $position = 0; + $strlen = strlen($string); + while (($position += strspn($string, $extra_chars, $position)) < $strlen) + { + $value = ord($string[$position]); + + // Start position + $start = $position; + + // By default we are valid + $valid = true; + + // No one byte sequences are valid due to the while. + // Two byte sequence: + if (($value & 0xE0) === 0xC0) + { + $character = ($value & 0x1F) << 6; + $length = 2; + $remaining = 1; + } + // Three byte sequence: + elseif (($value & 0xF0) === 0xE0) + { + $character = ($value & 0x0F) << 12; + $length = 3; + $remaining = 2; + } + // Four byte sequence: + elseif (($value & 0xF8) === 0xF0) + { + $character = ($value & 0x07) << 18; + $length = 4; + $remaining = 3; + } + // Invalid byte: + else + { + $valid = false; + $length = 1; + $remaining = 0; + } + + if ($remaining) + { + if ($position + $length <= $strlen) + { + for ($position++; $remaining; $position++) + { + $value = ord($string[$position]); + + // Check that the byte is valid, then add it to the character: + if (($value & 0xC0) === 0x80) + { + $character |= ($value & 0x3F) << (--$remaining * 6); + } + // If it is invalid, count the sequence as invalid and reprocess the current byte: + else + { + $valid = false; + $position--; + break; + } + } + } + else + { + $position = $strlen - 1; + $valid = false; + } + } + + // Percent encode anything invalid or not in ucschar + if ( + // Invalid sequences + !$valid + // Non-shortest form sequences are invalid + || $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of ucschar codepoints + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + || ( + // Everything else not in ucschar + $character > 0xD7FF && $character < 0xF900 + || $character < 0xA0 + || $character > 0xEFFFD + ) + && ( + // Everything not in iprivate, if it applies + !$iprivate + || $character < 0xE000 + || $character > 0x10FFFD + ) + ) + { + // If we were a character, pretend we weren't, but rather an error. + if ($valid) + $position--; + + for ($j = $start; $j <= $position; $j++) + { + $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1); + $j += 2; + $position += 2; + $strlen += 2; + } + } + } + + return $string; + } + + /** + * Callback function for preg_replace_callback. + * + * Removes sequences of percent encoded bytes that represent UTF-8 + * encoded characters in iunreserved + * + * @param array $match PCRE match + * @return string Replacement + */ + protected function remove_iunreserved_percent_encoded($match) + { + // As we just have valid percent encoded sequences we can just explode + // and ignore the first member of the returned array (an empty string). + $bytes = explode('%', $match[0]); + + // Initialize the new string (this is what will be returned) and that + // there are no bytes remaining in the current sequence (unsurprising + // at the first byte!). + $string = ''; + $remaining = 0; + + // Loop over each and every byte, and set $value to its value + for ($i = 1, $len = count($bytes); $i < $len; $i++) + { + $value = hexdec($bytes[$i]); + + // If we're the first byte of sequence: + if (!$remaining) + { + // Start position + $start = $i; + + // By default we are valid + $valid = true; + + // One byte sequence: + if ($value <= 0x7F) + { + $character = $value; + $length = 1; + } + // Two byte sequence: + elseif (($value & 0xE0) === 0xC0) + { + $character = ($value & 0x1F) << 6; + $length = 2; + $remaining = 1; + } + // Three byte sequence: + elseif (($value & 0xF0) === 0xE0) + { + $character = ($value & 0x0F) << 12; + $length = 3; + $remaining = 2; + } + // Four byte sequence: + elseif (($value & 0xF8) === 0xF0) + { + $character = ($value & 0x07) << 18; + $length = 4; + $remaining = 3; + } + // Invalid byte: + else + { + $valid = false; + $remaining = 0; + } + } + // Continuation byte: + else + { + // Check that the byte is valid, then add it to the character: + if (($value & 0xC0) === 0x80) + { + $remaining--; + $character |= ($value & 0x3F) << ($remaining * 6); + } + // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: + else + { + $valid = false; + $remaining = 0; + $i--; + } + } + + // If we've reached the end of the current byte sequence, append it to Unicode::$data + if (!$remaining) + { + // Percent encode anything invalid or not in iunreserved + if ( + // Invalid sequences + !$valid + // Non-shortest form sequences are invalid + || $length > 1 && $character <= 0x7F + || $length > 2 && $character <= 0x7FF + || $length > 3 && $character <= 0xFFFF + // Outside of range of iunreserved codepoints + || $character < 0x2D + || $character > 0xEFFFD + // Noncharacters + || ($character & 0xFFFE) === 0xFFFE + || $character >= 0xFDD0 && $character <= 0xFDEF + // Everything else not in iunreserved (this is all BMP) + || $character === 0x2F + || $character > 0x39 && $character < 0x41 + || $character > 0x5A && $character < 0x61 + || $character > 0x7A && $character < 0x7E + || $character > 0x7E && $character < 0xA0 + || $character > 0xD7FF && $character < 0xF900 + ) + { + for ($j = $start; $j <= $i; $j++) + { + $string .= '%' . strtoupper($bytes[$j]); + } + } + else + { + for ($j = $start; $j <= $i; $j++) + { + $string .= chr(hexdec($bytes[$j])); + } + } + } + } + + // If we have any bytes left over they are invalid (i.e., we are + // mid-way through a multi-byte sequence) + if ($remaining) + { + for ($j = $start; $j < $len; $j++) + { + $string .= '%' . strtoupper($bytes[$j]); + } + } + + return $string; + } + + protected function scheme_normalization() + { + if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) + { + $this->iuserinfo = null; + } + if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) + { + $this->ihost = null; + } + if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) + { + $this->port = null; + } + if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) + { + $this->ipath = ''; + } + if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) + { + $this->iquery = null; + } + if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) + { + $this->ifragment = null; + } + } + + /** + * Check if the object represents a valid IRI. This needs to be done on each + * call as some things change depending on another part of the IRI. + * + * @return bool + */ + public function is_valid() + { + $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; + if ($this->ipath !== '' && + ( + $isauthority && ( + $this->ipath[0] !== '/' || + substr($this->ipath, 0, 2) === '//' + ) || + ( + $this->scheme === null && + !$isauthority && + strpos($this->ipath, ':') !== false && + (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) + ) + ) + ) + { + return false; + } + + return true; + } + + /** + * Set the entire IRI. Returns true on success, false on failure (if there + * are any invalid characters). + * + * @param string $iri + * @return bool + */ + public function set_iri($iri) + { + static $cache; + if (!$cache) + { + $cache = array(); + } + + if ($iri === null) + { + return true; + } + elseif (isset($cache[$iri])) + { + list($this->scheme, + $this->iuserinfo, + $this->ihost, + $this->port, + $this->ipath, + $this->iquery, + $this->ifragment, + $return) = $cache[$iri]; + return $return; + } + else + { + $parsed = $this->parse_iri((string) $iri); + if (!$parsed) + { + return false; + } + + $return = $this->set_scheme($parsed['scheme']) + && $this->set_authority($parsed['authority']) + && $this->set_path($parsed['path']) + && $this->set_query($parsed['query']) + && $this->set_fragment($parsed['fragment']); + + $cache[$iri] = array($this->scheme, + $this->iuserinfo, + $this->ihost, + $this->port, + $this->ipath, + $this->iquery, + $this->ifragment, + $return); + return $return; + } + } + + /** + * Set the scheme. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $scheme + * @return bool + */ + public function set_scheme($scheme) + { + if ($scheme === null) + { + $this->scheme = null; + } + elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) + { + $this->scheme = null; + return false; + } + else + { + $this->scheme = strtolower($scheme); + } + return true; + } + + /** + * Set the authority. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $authority + * @return bool + */ + public function set_authority($authority) + { + static $cache; + if (!$cache) + $cache = array(); + + if ($authority === null) + { + $this->iuserinfo = null; + $this->ihost = null; + $this->port = null; + return true; + } + elseif (isset($cache[$authority])) + { + list($this->iuserinfo, + $this->ihost, + $this->port, + $return) = $cache[$authority]; + + return $return; + } + else + { + $remaining = $authority; + if (($iuserinfo_end = strrpos($remaining, '@')) !== false) + { + $iuserinfo = substr($remaining, 0, $iuserinfo_end); + $remaining = substr($remaining, $iuserinfo_end + 1); + } + else + { + $iuserinfo = null; + } + if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) + { + if (($port = substr($remaining, $port_start + 1)) === false) + { + $port = null; + } + $remaining = substr($remaining, 0, $port_start); + } + else + { + $port = null; + } + + $return = $this->set_userinfo($iuserinfo) && + $this->set_host($remaining) && + $this->set_port($port); + + $cache[$authority] = array($this->iuserinfo, + $this->ihost, + $this->port, + $return); + + return $return; + } + } + + /** + * Set the iuserinfo. + * + * @param string $iuserinfo + * @return bool + */ + public function set_userinfo($iuserinfo) + { + if ($iuserinfo === null) + { + $this->iuserinfo = null; + } + else + { + $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:'); + $this->scheme_normalization(); + } + + return true; + } + + /** + * Set the ihost. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $ihost + * @return bool + */ + public function set_host($ihost) + { + if ($ihost === null) + { + $this->ihost = null; + return true; + } + elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') + { + if (SimplePie_Net_IPv6::check_ipv6(substr($ihost, 1, -1))) + { + $this->ihost = '[' . SimplePie_Net_IPv6::compress(substr($ihost, 1, -1)) . ']'; + } + else + { + $this->ihost = null; + return false; + } + } + else + { + $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;='); + + // Lowercase, but ignore pct-encoded sections (as they should + // remain uppercase). This must be done after the previous step + // as that can add unescaped characters. + $position = 0; + $strlen = strlen($ihost); + while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) + { + if ($ihost[$position] === '%') + { + $position += 3; + } + else + { + $ihost[$position] = strtolower($ihost[$position]); + $position++; + } + } + + $this->ihost = $ihost; + } + + $this->scheme_normalization(); + + return true; + } + + /** + * Set the port. Returns true on success, false on failure (if there are + * any invalid characters). + * + * @param string $port + * @return bool + */ + public function set_port($port) + { + if ($port === null) + { + $this->port = null; + return true; + } + elseif (strspn($port, '0123456789') === strlen($port)) + { + $this->port = (int) $port; + $this->scheme_normalization(); + return true; + } + else + { + $this->port = null; + return false; + } + } + + /** + * Set the ipath. + * + * @param string $ipath + * @return bool + */ + public function set_path($ipath) + { + static $cache; + if (!$cache) + { + $cache = array(); + } + + $ipath = (string) $ipath; + + if (isset($cache[$ipath])) + { + $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)]; + } + else + { + $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); + $removed = $this->remove_dot_segments($valid); + + $cache[$ipath] = array($valid, $removed); + $this->ipath = ($this->scheme !== null) ? $removed : $valid; + } + + $this->scheme_normalization(); + return true; + } + + /** + * Set the iquery. + * + * @param string $iquery + * @return bool + */ + public function set_query($iquery) + { + if ($iquery === null) + { + $this->iquery = null; + } + else + { + $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true); + $this->scheme_normalization(); + } + return true; + } + + /** + * Set the ifragment. + * + * @param string $ifragment + * @return bool + */ + public function set_fragment($ifragment) + { + if ($ifragment === null) + { + $this->ifragment = null; + } + else + { + $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?'); + $this->scheme_normalization(); + } + return true; + } + + /** + * Convert an IRI to a URI (or parts thereof) + * + * @return string + */ + public function to_uri($string) + { + static $non_ascii; + if (!$non_ascii) + { + $non_ascii = implode('', range("\x80", "\xFF")); + } + + $position = 0; + $strlen = strlen($string); + while (($position += strcspn($string, $non_ascii, $position)) < $strlen) + { + $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1); + $position += 3; + $strlen += 2; + } + + return $string; + } + + /** + * Get the complete IRI + * + * @return string + */ + public function get_iri() + { + if (!$this->is_valid()) + { + return false; + } + + $iri = ''; + if ($this->scheme !== null) + { + $iri .= $this->scheme . ':'; + } + if (($iauthority = $this->get_iauthority()) !== null) + { + $iri .= '//' . $iauthority; + } + if ($this->ipath !== '') + { + $iri .= $this->ipath; + } + elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '') + { + $iri .= $this->normalization[$this->scheme]['ipath']; + } + if ($this->iquery !== null) + { + $iri .= '?' . $this->iquery; + } + if ($this->ifragment !== null) + { + $iri .= '#' . $this->ifragment; + } + + return $iri; + } + + /** + * Get the complete URI + * + * @return string + */ + public function get_uri() + { + return $this->to_uri($this->get_iri()); + } + + /** + * Get the complete iauthority + * + * @return string + */ + protected function get_iauthority() + { + if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null) + { + $iauthority = ''; + if ($this->iuserinfo !== null) + { + $iauthority .= $this->iuserinfo . '@'; + } + if ($this->ihost !== null) + { + $iauthority .= $this->ihost; + } + if ($this->port !== null) + { + $iauthority .= ':' . $this->port; + } + return $iauthority; + } + else + { + return null; + } + } + + /** + * Get the complete authority + * + * @return string + */ + protected function get_authority() + { + $iauthority = $this->get_iauthority(); + if (is_string($iauthority)) + return $this->to_uri($iauthority); + else + return $iauthority; + } +} diff --git a/sources/wp-includes/SimplePie/Item.php b/sources/wp-includes/SimplePie/Item.php new file mode 100644 index 0000000..a77574b --- /dev/null +++ b/sources/wp-includes/SimplePie/Item.php @@ -0,0 +1,2964 @@ +feed = $feed; + $this->data = $data; + } + + /** + * Set the registry handler + * + * This is usually used by {@see SimplePie_Registry::create} + * + * @since 1.3 + * @param SimplePie_Registry $registry + */ + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } + + /** + * Get a string representation of the item + * + * @return string + */ + public function __toString() + { + return md5(serialize($this->data)); + } + + /** + * Remove items that link back to this before destroying this object + */ + public function __destruct() + { + if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) + { + unset($this->feed); + } + } + + /** + * Get data for an item-level element + * + * This method allows you to get access to ANY element/attribute that is a + * sub-element of the item/entry tag. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_item_tags($namespace, $tag) + { + if (isset($this->data['child'][$namespace][$tag])) + { + return $this->data['child'][$namespace][$tag]; + } + else + { + return null; + } + } + + /** + * Get the base URL value from the parent feed + * + * Uses `` + * + * @param array $element + * @return string + */ + public function get_base($element = array()) + { + return $this->feed->get_base($element); + } + + /** + * Sanitize feed data + * + * @access private + * @see SimplePie::sanitize() + * @param string $data Data to sanitize + * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants + * @param string $base Base URL to resolve URLs against + * @return string Sanitized data + */ + public function sanitize($data, $type, $base = '') + { + return $this->feed->sanitize($data, $type, $base); + } + + /** + * Get the parent feed + * + * Note: this may not work as you think for multifeeds! + * + * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed + * @since 1.0 + * @return SimplePie + */ + public function get_feed() + { + return $this->feed; + } + + /** + * Get the unique identifier for the item + * + * This is usually used when writing code to check for new items in a feed. + * + * Uses ``, ``, `` or the `about` attribute + * for RDF. If none of these are supplied (or `$hash` is true), creates an + * MD5 hash based on the permalink and title. If either of those are not + * supplied, creates a hash based on the full feed data. + * + * @since Beta 2 + * @param boolean $hash Should we force using a hash instead of the supplied ID? + * @return string + */ + public function get_id($hash = false) + { + if (!$hash) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'])) + { + return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (($return = $this->get_permalink()) !== null) + { + return $return; + } + elseif (($return = $this->get_title()) !== null) + { + return $return; + } + } + if ($this->get_permalink() !== null || $this->get_title() !== null) + { + return md5($this->get_permalink() . $this->get_title()); + } + else + { + return md5(serialize($this->data)); + } + } + + /** + * Get the title of the item + * + * Uses ``, `` or `<dc:title>` + * + * @since Beta 2 (previously called `get_item_title` since 0.8) + * @return string|null + */ + public function get_title() + { + if (!isset($this->data['title'])) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $this->data['title'] = null; + } + } + return $this->data['title']; + } + + /** + * Get the content for the item + * + * Prefers summaries over full content , but will return full content if a + * summary does not exist. + * + * To prefer full content instead, use {@see get_content} + * + * Uses `<atom:summary>`, `<description>`, `<dc:description>` or + * `<itunes:subtitle>` + * + * @since 0.8 + * @param boolean $description_only Should we avoid falling back to the content? + * @return string|null + */ + public function get_description($description_only = false) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML); + } + + elseif (!$description_only) + { + return $this->get_content(true); + } + else + { + return null; + } + } + + /** + * Get the content for the item + * + * Prefers full content over summaries, but will return a summary if full + * content does not exist. + * + * To prefer summaries instead, use {@see get_description} + * + * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module) + * + * @since 1.0 + * @param boolean $content_only Should we avoid falling back to the description? + * @return string|null + */ + public function get_content($content_only = false) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif (!$content_only) + { + return $this->get_description(true); + } + else + { + return null; + } + } + + /** + * Get a category for the item + * + * @since Beta 3 (previously called `get_categories()` since Beta 2) + * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Category|null + */ + public function get_category($key = 0) + { + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } + } + + /** + * Get all categories for the item + * + * Uses `<atom:category>`, `<category>` or `<dc:subject>` + * + * @since Beta 3 + * @return array|null List of {@see SimplePie_Category} objects + */ + public function get_categories() + { + $categories = array(); + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) + { + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + { + // This is really the label, but keep this as the term also for BC. + // Label will also work on retrieving because that falls back to term. + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = null; + } + $categories[] = $this->registry->create('Category', array($term, $scheme, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($categories)) + { + return array_unique($categories); + } + else + { + return null; + } + } + + /** + * Get an author for the item + * + * @since Beta 2 + * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_author($key = 0) + { + $authors = $this->get_authors(); + if (isset($authors[$key])) + { + return $authors[$key]; + } + else + { + return null; + } + } + + /** + * Get a contributor for the item + * + * @since 1.1 + * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_contributor($key = 0) + { + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) + { + return $contributors[$key]; + } + else + { + return null; + } + } + + /** + * Get all contributors for the item + * + * Uses `<atom:contributor>` + * + * @since 1.1 + * @return array|null List of {@see SimplePie_Author} objects + */ + public function get_contributors() + { + $contributors = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) + { + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) + { + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $url, $email)); + } + } + + if (!empty($contributors)) + { + return array_unique($contributors); + } + else + { + return null; + } + } + + /** + * Get all authors for the item + * + * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` + * + * @since Beta 2 + * @return array|null List of {@see SimplePie_Author} objects + */ + public function get_authors() + { + $authors = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) + { + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $authors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) + { + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = $this->registry->create('Author', array($name, $url, $email)); + } + } + if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author')) + { + $authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT))); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($authors)) + { + return array_unique($authors); + } + elseif (($source = $this->get_source()) && ($authors = $source->get_authors())) + { + return $authors; + } + elseif ($authors = $this->feed->get_authors()) + { + return $authors; + } + else + { + return null; + } + } + + /** + * Get the copyright info for the item + * + * Uses `<atom:rights>` or `<dc:rights>` + * + * @since 1.1 + * @return string + */ + public function get_copyright() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + /** + * Get the posting date/time for the item + * + * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`, + * `<atom:modified>`, `<pubDate>` or `<dc:date>` + * + * Note: obeys PHP's timezone setting. To get a UTC date/time, use + * {@see get_gmdate} + * + * @since Beta 2 (previously called `get_item_date` since 0.8) + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) + * @return int|string|null + */ + public function get_date($date_format = 'j F Y, g:i a') + { + if (!isset($this->data['date'])) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date')) + { + $this->data['date']['raw'] = $return[0]['data']; + } + + if (!empty($this->data['date']['raw'])) + { + $parser = $this->registry->call('Parse_Date', 'get'); + $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']); + } + else + { + $this->data['date'] = null; + } + } + if ($this->data['date']) + { + $date_format = (string) $date_format; + switch ($date_format) + { + case '': + return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT); + + case 'U': + return $this->data['date']['parsed']; + + default: + return date($date_format, $this->data['date']['parsed']); + } + } + else + { + return null; + } + } + + /** + * Get the update date/time for the item + * + * Uses `<atom:updated>` + * + * Note: obeys PHP's timezone setting. To get a UTC date/time, use + * {@see get_gmdate} + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data) + * @return int|string|null + */ + public function get_updated_date($date_format = 'j F Y, g:i a') + { + if (!isset($this->data['updated'])) + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated')) + { + $this->data['updated']['raw'] = $return[0]['data']; + } + + if (!empty($this->data['updated']['raw'])) + { + $parser = $this->registry->call('Parse_Date', 'get'); + $this->data['updated']['parsed'] = $parser->parse($this->data['date']['raw']); + } + else + { + $this->data['updated'] = null; + } + } + if ($this->data['updated']) + { + $date_format = (string) $date_format; + switch ($date_format) + { + case '': + return $this->sanitize($this->data['updated']['raw'], SIMPLEPIE_CONSTRUCT_TEXT); + + case 'U': + return $this->data['updated']['parsed']; + + default: + return date($date_format, $this->data['updated']['parsed']); + } + } + else + { + return null; + } + } + + /** + * Get the localized posting date/time for the item + * + * Returns the date formatted in the localized language. To display in + * languages other than the server's default, you need to change the locale + * with {@link http://php.net/setlocale setlocale()}. The available + * localizations depend on which ones are installed on your web server. + * + * @since 1.0 + * + * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data) + * @return int|string|null + */ + public function get_local_date($date_format = '%c') + { + if (!$date_format) + { + return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (($date = $this->get_date('U')) !== null && $date !== false) + { + return strftime($date_format, $date); + } + else + { + return null; + } + } + + /** + * Get the posting date/time for the item (UTC time) + * + * @see get_date + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} + * @return int|string|null + */ + public function get_gmdate($date_format = 'j F Y, g:i a') + { + $date = $this->get_date('U'); + if ($date === null) + { + return null; + } + + return gmdate($date_format, $date); + } + + /** + * Get the update date/time for the item (UTC time) + * + * @see get_updated_date + * @param string $date_format Supports any PHP date format from {@see http://php.net/date} + * @return int|string|null + */ + public function get_updated_gmdate($date_format = 'j F Y, g:i a') + { + $date = $this->get_updated_date('U'); + if ($date === null) + { + return null; + } + + return gmdate($date_format, $date); + } + + /** + * Get the permalink for the item + * + * Returns the first link available with a relationship of "alternate". + * Identical to {@see get_link()} with key 0 + * + * @see get_link + * @since 0.8 + * @return string|null Permalink URL + */ + public function get_permalink() + { + $link = $this->get_link(); + $enclosure = $this->get_enclosure(0); + if ($link !== null) + { + return $link; + } + elseif ($enclosure !== null) + { + return $enclosure->get_link(); + } + else + { + return null; + } + } + + /** + * Get a single link for the item + * + * @since Beta 3 + * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 + * @param string $rel The relationship of the link to return + * @return string|null Link URL + */ + public function get_link($key = 0, $rel = 'alternate') + { + $links = $this->get_links($rel); + if ($links[$key] !== null) + { + return $links[$key]; + } + else + { + return null; + } + } + + /** + * Get all links for the item + * + * Uses `<atom:link>`, `<link>` or `<guid>` + * + * @since Beta 2 + * @param string $rel The relationship of links to return + * @return array|null Links found for the item (strings) + */ + public function get_links($rel = 'alternate') + { + if (!isset($this->data['links'])) + { + $this->data['links'] = array(); + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + + } + } + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid')) + { + if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true') + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + } + + $keys = array_keys($this->data['links']); + foreach ($keys as $key) + { + if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key))) + { + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; + } + else + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } + } + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) + { + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; + } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); + } + } + if (isset($this->data['links'][$rel])) + { + return $this->data['links'][$rel]; + } + else + { + return null; + } + } + + /** + * Get an enclosure from the item + * + * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. + * + * @since Beta 2 + * @todo Add ability to prefer one type of content over another (in a media group). + * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Enclosure|null + */ + public function get_enclosure($key = 0, $prefer = null) + { + $enclosures = $this->get_enclosures(); + if (isset($enclosures[$key])) + { + return $enclosures[$key]; + } + else + { + return null; + } + } + + /** + * Get all available enclosures (podcasts, etc.) + * + * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS. + * + * At this point, we're pretty much assuming that all enclosures for an item + * are the same content. Anything else is too complicated to + * properly support. + * + * @since Beta 2 + * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4). + * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists). + * @return array|null List of SimplePie_Enclosure items + */ + public function get_enclosures() + { + if (!isset($this->data['enclosures'])) + { + $this->data['enclosures'] = array(); + + // Elements + $captions_parent = null; + $categories_parent = null; + $copyrights_parent = null; + $credits_parent = null; + $description_parent = null; + $duration_parent = null; + $hashes_parent = null; + $keywords_parent = null; + $player_parent = null; + $ratings_parent = null; + $restrictions_parent = null; + $thumbnails_parent = null; + $title_parent = null; + + // Let's do the channel and item-level ones first, and just re-use them if we need to. + $parent = $this->get_feed(); + + // CAPTIONS + if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) + { + foreach ($captions as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + } + elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text')) + { + foreach ($captions as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + } + if (is_array($captions_parent)) + { + $captions_parent = array_values(array_unique($captions_parent)); + } + + // CATEGORIES + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category) + { + $term = null; + $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd'; + $label = null; + if (isset($category['attribs']['']['text'])) + { + $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); + + if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'])) + { + foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory) + { + if (isset($subcategory['attribs']['']['text'])) + { + $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + } + if (is_array($categories_parent)) + { + $categories_parent = array_values(array_unique($categories_parent)); + } + + // COPYRIGHT + if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) + { + $copyright_url = null; + $copyright_label = null; + if (isset($copyright[0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($copyright[0]['data'])) + { + $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright')) + { + $copyright_url = null; + $copyright_label = null; + if (isset($copyright[0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($copyright[0]['data'])) + { + $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + + // CREDITS + if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) + { + foreach ($credits as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + } + elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit')) + { + foreach ($credits as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + } + if (is_array($credits_parent)) + { + $credits_parent = array_values(array_unique($credits_parent)); + } + + // DESCRIPTION + if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) + { + if (isset($description_parent[0]['data'])) + { + $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description')) + { + if (isset($description_parent[0]['data'])) + { + $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + + // DURATION + if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration')) + { + $seconds = null; + $minutes = null; + $hours = null; + if (isset($duration_parent[0]['data'])) + { + $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + if (sizeof($temp) > 0) + { + $seconds = (int) array_pop($temp); + } + if (sizeof($temp) > 0) + { + $minutes = (int) array_pop($temp); + $seconds += $minutes * 60; + } + if (sizeof($temp) > 0) + { + $hours = (int) array_pop($temp); + $seconds += $hours * 3600; + } + unset($temp); + $duration_parent = $seconds; + } + } + + // HASHES + if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) + { + foreach ($hashes_iterator as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes_parent[] = $algo.':'.$value; + } + } + elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash')) + { + foreach ($hashes_iterator as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes_parent[] = $algo.':'.$value; + } + } + if (is_array($hashes_parent)) + { + $hashes_parent = array_values(array_unique($hashes_parent)); + } + + // KEYWORDS + if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords')) + { + if (isset($keywords[0]['data'])) + { + $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords_parent[] = trim($word); + } + } + unset($temp); + } + if (is_array($keywords_parent)) + { + $keywords_parent = array_values(array_unique($keywords_parent)); + } + + // PLAYER + if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) + { + if (isset($player_parent[0]['attribs']['']['url'])) + { + $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player')) + { + if (isset($player_parent[0]['attribs']['']['url'])) + { + $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + + // RATINGS + if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) + { + foreach ($ratings as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + } + elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) + { + foreach ($ratings as $rating) + { + $rating_scheme = 'urn:itunes'; + $rating_value = null; + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + } + elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating')) + { + foreach ($ratings as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + } + elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit')) + { + foreach ($ratings as $rating) + { + $rating_scheme = 'urn:itunes'; + $rating_value = null; + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + } + if (is_array($ratings_parent)) + { + $ratings_parent = array_values(array_unique($ratings_parent)); + } + + // RESTRICTIONS + if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = 'allow'; + $restriction_type = null; + $restriction_value = 'itunes'; + if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') + { + $restriction_relationship = 'deny'; + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block')) + { + foreach ($restrictions as $restriction) + { + $restriction_relationship = 'allow'; + $restriction_type = null; + $restriction_value = 'itunes'; + if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') + { + $restriction_relationship = 'deny'; + } + $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + } + if (is_array($restrictions_parent)) + { + $restrictions_parent = array_values(array_unique($restrictions_parent)); + } + else + { + $restrictions_parent = array(new SimplePie_Restriction('allow', null, 'default')); + } + + // THUMBNAILS + if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + foreach ($thumbnails as $thumbnail) + { + if (isset($thumbnail['attribs']['']['url'])) + { + $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + } + elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) + { + foreach ($thumbnails as $thumbnail) + { + if (isset($thumbnail['attribs']['']['url'])) + { + $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + } + } + + // TITLES + if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) + { + if (isset($title_parent[0]['data'])) + { + $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title')) + { + if (isset($title_parent[0]['data'])) + { + $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + } + + // Clear the memory + unset($parent); + + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + // Elements + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; + + // If we have media:group tags, loop through them. + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group) + { + if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) + { + // If we have media:content tags, loop through them. + foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) + { + if (isset($content['attribs']['']['url'])) + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + // Elements + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; + + // Start checking the attributes of media:content + if (isset($content['attribs']['']['bitrate'])) + { + $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['channels'])) + { + $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['duration'])) + { + $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $duration = $duration_parent; + } + if (isset($content['attribs']['']['expression'])) + { + $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['framerate'])) + { + $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['height'])) + { + $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['lang'])) + { + $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['fileSize'])) + { + $length = ceil($content['attribs']['']['fileSize']); + } + if (isset($content['attribs']['']['medium'])) + { + $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['samplingrate'])) + { + $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['type'])) + { + $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['width'])) + { + $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + + // Checking the other optional media: elements. Priority: media:content, media:group, item, channel + + // CAPTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + if (is_array($captions)) + { + $captions = array_values(array_unique($captions)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + if (is_array($captions)) + { + $captions = array_values(array_unique($captions)); + } + } + else + { + $captions = $captions_parent; + } + + // CATEGORIES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + if (is_array($categories) && is_array($categories_parent)) + { + $categories = array_values(array_unique(array_merge($categories, $categories_parent))); + } + elseif (is_array($categories)) + { + $categories = array_values(array_unique($categories)); + } + elseif (is_array($categories_parent)) + { + $categories = array_values(array_unique($categories_parent)); + } + + // COPYRIGHTS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + else + { + $copyrights = $copyrights_parent; + } + + // CREDITS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + if (is_array($credits)) + { + $credits = array_values(array_unique($credits)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + if (is_array($credits)) + { + $credits = array_values(array_unique($credits)); + } + } + else + { + $credits = $credits_parent; + } + + // DESCRIPTION + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $description = $description_parent; + } + + // HASHES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(array_unique($hashes)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(array_unique($hashes)); + } + } + else + { + $hashes = $hashes_parent; + } + + // KEYWORDS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(array_unique($keywords)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(array_unique($keywords)); + } + } + else + { + $keywords = $keywords_parent; + } + + // PLAYER + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + $player = $player_parent; + } + + // RATINGS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + if (is_array($ratings)) + { + $ratings = array_values(array_unique($ratings)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + if (is_array($ratings)) + { + $ratings = array_values(array_unique($ratings)); + } + } + else + { + $ratings = $ratings_parent; + } + + // RESTRICTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + if (is_array($restrictions)) + { + $restrictions = array_values(array_unique($restrictions)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + if (is_array($restrictions)) + { + $restrictions = array_values(array_unique($restrictions)); + } + } + else + { + $restrictions = $restrictions_parent; + } + + // THUMBNAILS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(array_unique($thumbnails)); + } + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(array_unique($thumbnails)); + } + } + else + { + $thumbnails = $thumbnails_parent; + } + + // TITLES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } + + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width)); + } + } + } + } + + // If we have standalone media:content tags, loop through them. + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'])) + { + foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content) + { + if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + // Elements + $captions = null; + $categories = null; + $copyrights = null; + $credits = null; + $description = null; + $hashes = null; + $keywords = null; + $player = null; + $ratings = null; + $restrictions = null; + $thumbnails = null; + $title = null; + + // Start checking the attributes of media:content + if (isset($content['attribs']['']['bitrate'])) + { + $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['channels'])) + { + $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['duration'])) + { + $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $duration = $duration_parent; + } + if (isset($content['attribs']['']['expression'])) + { + $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['framerate'])) + { + $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['height'])) + { + $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['lang'])) + { + $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['fileSize'])) + { + $length = ceil($content['attribs']['']['fileSize']); + } + if (isset($content['attribs']['']['medium'])) + { + $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['samplingrate'])) + { + $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['type'])) + { + $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['width'])) + { + $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['attribs']['']['url'])) + { + $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + // Checking the other optional media: elements. Priority: media:content, media:group, item, channel + + // CAPTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption) + { + $caption_type = null; + $caption_lang = null; + $caption_startTime = null; + $caption_endTime = null; + $caption_text = null; + if (isset($caption['attribs']['']['type'])) + { + $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['lang'])) + { + $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['start'])) + { + $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['attribs']['']['end'])) + { + $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($caption['data'])) + { + $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text)); + } + if (is_array($captions)) + { + $captions = array_values(array_unique($captions)); + } + } + else + { + $captions = $captions_parent; + } + + // CATEGORIES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'])) + { + foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['data'])) + { + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = 'http://search.yahoo.com/mrss/category_schema'; + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + } + if (is_array($categories) && is_array($categories_parent)) + { + $categories = array_values(array_unique(array_merge($categories, $categories_parent))); + } + elseif (is_array($categories)) + { + $categories = array_values(array_unique($categories)); + } + elseif (is_array($categories_parent)) + { + $categories = array_values(array_unique($categories_parent)); + } + else + { + $categories = null; + } + + // COPYRIGHTS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'])) + { + $copyright_url = null; + $copyright_label = null; + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) + { + $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'])) + { + $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label)); + } + else + { + $copyrights = $copyrights_parent; + } + + // CREDITS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit) + { + $credit_role = null; + $credit_scheme = null; + $credit_name = null; + if (isset($credit['attribs']['']['role'])) + { + $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($credit['attribs']['']['scheme'])) + { + $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $credit_scheme = 'urn:ebu'; + } + if (isset($credit['data'])) + { + $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name)); + } + if (is_array($credits)) + { + $credits = array_values(array_unique($credits)); + } + } + else + { + $credits = $credits_parent; + } + + // DESCRIPTION + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'])) + { + $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $description = $description_parent; + } + + // HASHES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash) + { + $value = null; + $algo = null; + if (isset($hash['data'])) + { + $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($hash['attribs']['']['algo'])) + { + $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $algo = 'md5'; + } + $hashes[] = $algo.':'.$value; + } + if (is_array($hashes)) + { + $hashes = array_values(array_unique($hashes)); + } + } + else + { + $hashes = $hashes_parent; + } + + // KEYWORDS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'])) + { + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'])) + { + $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)); + foreach ($temp as $word) + { + $keywords[] = trim($word); + } + unset($temp); + } + if (is_array($keywords)) + { + $keywords = array_values(array_unique($keywords)); + } + } + else + { + $keywords = $keywords_parent; + } + + // PLAYER + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'])) + { + $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + $player = $player_parent; + } + + // RATINGS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating) + { + $rating_scheme = null; + $rating_value = null; + if (isset($rating['attribs']['']['scheme'])) + { + $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $rating_scheme = 'urn:simple'; + } + if (isset($rating['data'])) + { + $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value)); + } + if (is_array($ratings)) + { + $ratings = array_values(array_unique($ratings)); + } + } + else + { + $ratings = $ratings_parent; + } + + // RESTRICTIONS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction) + { + $restriction_relationship = null; + $restriction_type = null; + $restriction_value = null; + if (isset($restriction['attribs']['']['relationship'])) + { + $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['attribs']['']['type'])) + { + $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($restriction['data'])) + { + $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value)); + } + if (is_array($restrictions)) + { + $restrictions = array_values(array_unique($restrictions)); + } + } + else + { + $restrictions = $restrictions_parent; + } + + // THUMBNAILS + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'])) + { + foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) + { + $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI); + } + if (is_array($thumbnails)) + { + $thumbnails = array_values(array_unique($thumbnails)); + } + } + else + { + $thumbnails = $thumbnails_parent; + } + + // TITLES + if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'])) + { + $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $title = $title_parent; + } + + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width)); + } + } + } + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link) + { + if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + if (isset($link['attribs']['']['type'])) + { + $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($link['attribs']['']['length'])) + { + $length = ceil($link['attribs']['']['length']); + } + + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + } + + foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link) + { + if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + if (isset($link['attribs']['']['type'])) + { + $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($link['attribs']['']['length'])) + { + $length = ceil($link['attribs']['']['length']); + } + + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + } + + if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure')) + { + if (isset($enclosure[0]['attribs']['']['url'])) + { + // Attributes + $bitrate = null; + $channels = null; + $duration = null; + $expression = null; + $framerate = null; + $height = null; + $javascript = null; + $lang = null; + $length = null; + $medium = null; + $samplingrate = null; + $type = null; + $url = null; + $width = null; + + $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0])); + if (isset($enclosure[0]['attribs']['']['type'])) + { + $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($enclosure[0]['attribs']['']['length'])) + { + $length = ceil($enclosure[0]['attribs']['']['length']); + } + + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + } + + if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width)) + { + // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor + $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width)); + } + + $this->data['enclosures'] = array_values(array_unique($this->data['enclosures'])); + } + if (!empty($this->data['enclosures'])) + { + return $this->data['enclosures']; + } + else + { + return null; + } + } + + /** + * Get the latitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:lat>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_latitude() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[1]; + } + else + { + return null; + } + } + + /** + * Get the longitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_longitude() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) + { + return (float) $return[0]['data']; + } + elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[2]; + } + else + { + return null; + } + } + + /** + * Get the `<atom:source>` for the item + * + * @since 1.1 + * @return SimplePie_Source|null + */ + public function get_source() + { + if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source')) + { + return $this->registry->create('Source', array($this, $return[0])); + } + else + { + return null; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Locator.php b/sources/wp-includes/SimplePie/Locator.php new file mode 100644 index 0000000..da89514 --- /dev/null +++ b/sources/wp-includes/SimplePie/Locator.php @@ -0,0 +1,372 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Used for feed auto-discovery + * + * + * This class can be overloaded with {@see SimplePie::set_locator_class()} + * + * @package SimplePie + */ +class SimplePie_Locator +{ + var $useragent; + var $timeout; + var $file; + var $local = array(); + var $elsewhere = array(); + var $cached_entities = array(); + var $http_base; + var $base; + var $base_location = 0; + var $checked_feeds = 0; + var $max_checked_feeds = 10; + protected $registry; + + public function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10) + { + $this->file = $file; + $this->useragent = $useragent; + $this->timeout = $timeout; + $this->max_checked_feeds = $max_checked_feeds; + + if (class_exists('DOMDocument')) + { + $this->dom = new DOMDocument(); + + set_error_handler(array('SimplePie_Misc', 'silence_errors')); + $this->dom->loadHTML($this->file->body); + restore_error_handler(); + } + else + { + $this->dom = null; + } + } + + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } + + public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working) + { + if ($this->is_feed($this->file)) + { + return $this->file; + } + + if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + { + $sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file)); + if ($sniffer->get_type() !== 'text/html') + { + return null; + } + } + + if ($type & ~SIMPLEPIE_LOCATOR_NONE) + { + $this->get_base(); + } + + if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery()) + { + return $working[0]; + } + + if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links()) + { + if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local)) + { + return $working; + } + + if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local)) + { + return $working; + } + + if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere)) + { + return $working; + } + + if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere)) + { + return $working; + } + } + return null; + } + + public function is_feed($file) + { + if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE) + { + $sniffer = $this->registry->create('Content_Type_Sniffer', array($file)); + $sniffed = $sniffer->get_type(); + if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml'))) + { + return true; + } + else + { + return false; + } + } + elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL) + { + return true; + } + else + { + return false; + } + } + + public function get_base() + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use locator'); + } + $this->http_base = $this->file->url; + $this->base = $this->http_base; + $elements = $this->dom->getElementsByTagName('base'); + foreach ($elements as $element) + { + if ($element->hasAttribute('href')) + { + $base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base)); + if ($base === false) + { + continue; + } + $this->base = $base; + $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0; + break; + } + } + } + + public function autodiscovery() + { + $done = array(); + $feeds = array(); + $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds)); + $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds)); + $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds)); + + if (!empty($feeds)) + { + return array_values($feeds); + } + else + { + return null; + } + } + + protected function search_elements_by_tag($name, &$done, $feeds) + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use locator'); + } + + $links = $this->dom->getElementsByTagName($name); + foreach ($links as $link) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if ($link->hasAttribute('href') && $link->hasAttribute('rel')) + { + $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel'))))); + $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1; + + if ($this->base_location < $line) + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); + } + else + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base)); + } + if ($href === false) + { + continue; + } + + if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href])) + { + $this->checked_feeds++; + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent)); + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + { + $feeds[$href] = $feed; + } + } + $done[] = $href; + } + } + + return $feeds; + } + + public function get_links() + { + if ($this->dom === null) + { + throw new SimplePie_Exception('DOMDocument not found, unable to use locator'); + } + + $links = $this->dom->getElementsByTagName('a'); + foreach ($links as $link) + { + if ($link->hasAttribute('href')) + { + $href = trim($link->getAttribute('href')); + $parsed = $this->registry->call('Misc', 'parse_url', array($href)); + if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme'])) + { + if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo()) + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base)); + } + else + { + $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base)); + } + if ($href === false) + { + continue; + } + + $current = $this->registry->call('Misc', 'parse_url', array($this->file->url)); + + if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority']) + { + $this->local[] = $href; + } + else + { + $this->elsewhere[] = $href; + } + } + } + } + $this->local = array_unique($this->local); + $this->elsewhere = array_unique($this->elsewhere); + if (!empty($this->local) || !empty($this->elsewhere)) + { + return true; + } + return null; + } + + public function extension(&$array) + { + foreach ($array as $key => $value) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml'))) + { + $this->checked_feeds++; + + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent)); + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + { + return $feed; + } + else + { + unset($array[$key]); + } + } + } + return null; + } + + public function body(&$array) + { + foreach ($array as $key => $value) + { + if ($this->checked_feeds === $this->max_checked_feeds) + { + break; + } + if (preg_match('/(rss|rdf|atom|xml)/i', $value)) + { + $this->checked_feeds++; + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent)); + if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed)) + { + return $feed; + } + else + { + unset($array[$key]); + } + } + } + return null; + } +} + diff --git a/sources/wp-includes/SimplePie/Misc.php b/sources/wp-includes/SimplePie/Misc.php new file mode 100644 index 0000000..1c1b618 --- /dev/null +++ b/sources/wp-includes/SimplePie/Misc.php @@ -0,0 +1,2247 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Miscellanous utilities + * + * @package SimplePie + */ +class SimplePie_Misc +{ + public static function time_hms($seconds) + { + $time = ''; + + $hours = floor($seconds / 3600); + $remainder = $seconds % 3600; + if ($hours > 0) + { + $time .= $hours.':'; + } + + $minutes = floor($remainder / 60); + $seconds = $remainder % 60; + if ($minutes < 10 && $hours > 0) + { + $minutes = '0' . $minutes; + } + if ($seconds < 10) + { + $seconds = '0' . $seconds; + } + + $time .= $minutes.':'; + $time .= $seconds; + + return $time; + } + + public static function absolutize_url($relative, $base) + { + $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative); + if ($iri === false) + { + return false; + } + return $iri->get_uri(); + } + + /** + * Get a HTML/XML element from a HTML string + * + * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!) + * @param string $realname Element name (including namespace prefix if applicable) + * @param string $string HTML document + * @return array + */ + public static function get_element($realname, $string) + { + $return = array(); + $name = preg_quote($realname, '/'); + if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) + { + for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++) + { + $return[$i]['tag'] = $realname; + $return[$i]['full'] = $matches[$i][0][0]; + $return[$i]['offset'] = $matches[$i][0][1]; + if (strlen($matches[$i][3][0]) <= 2) + { + $return[$i]['self_closing'] = true; + } + else + { + $return[$i]['self_closing'] = false; + $return[$i]['content'] = $matches[$i][4][0]; + } + $return[$i]['attribs'] = array(); + if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER)) + { + for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++) + { + if (count($attribs[$j]) === 2) + { + $attribs[$j][2] = $attribs[$j][1]; + } + $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j])); + } + } + } + } + return $return; + } + + public static function element_implode($element) + { + $full = "<$element[tag]"; + foreach ($element['attribs'] as $key => $value) + { + $key = strtolower($key); + $full .= " $key=\"" . htmlspecialchars($value['data']) . '"'; + } + if ($element['self_closing']) + { + $full .= ' />'; + } + else + { + $full .= ">$element[content]</$element[tag]>"; + } + return $full; + } + + public static function error($message, $level, $file, $line) + { + if ((ini_get('error_reporting') & $level) > 0) + { + switch ($level) + { + case E_USER_ERROR: + $note = 'PHP Error'; + break; + case E_USER_WARNING: + $note = 'PHP Warning'; + break; + case E_USER_NOTICE: + $note = 'PHP Notice'; + break; + default: + $note = 'Unknown Error'; + break; + } + + $log_error = true; + if (!function_exists('error_log')) + { + $log_error = false; + } + + $log_file = @ini_get('error_log'); + if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file)) + { + $log_error = false; + } + + if ($log_error) + { + @error_log("$note: $message in $file on line $line", 0); + } + } + + return $message; + } + + public static function fix_protocol($url, $http = 1) + { + $url = SimplePie_Misc::normalize_url($url); + $parsed = SimplePie_Misc::parse_url($url); + if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https') + { + return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http); + } + + if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url)) + { + return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http); + } + + if ($http === 2 && $parsed['scheme'] !== '') + { + return "feed:$url"; + } + elseif ($http === 3 && strtolower($parsed['scheme']) === 'http') + { + return substr_replace($url, 'podcast', 0, 4); + } + elseif ($http === 4 && strtolower($parsed['scheme']) === 'http') + { + return substr_replace($url, 'itpc', 0, 4); + } + else + { + return $url; + } + } + + public static function parse_url($url) + { + $iri = new SimplePie_IRI($url); + return array( + 'scheme' => (string) $iri->scheme, + 'authority' => (string) $iri->authority, + 'path' => (string) $iri->path, + 'query' => (string) $iri->query, + 'fragment' => (string) $iri->fragment + ); + } + + public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '') + { + $iri = new SimplePie_IRI(''); + $iri->scheme = $scheme; + $iri->authority = $authority; + $iri->path = $path; + $iri->query = $query; + $iri->fragment = $fragment; + return $iri->get_uri(); + } + + public static function normalize_url($url) + { + $iri = new SimplePie_IRI($url); + return $iri->get_uri(); + } + + public static function percent_encoding_normalization($match) + { + $integer = hexdec($match[1]); + if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E) + { + return chr($integer); + } + else + { + return strtoupper($match[0]); + } + } + + /** + * Converts a Windows-1252 encoded string to a UTF-8 encoded string + * + * @static + * @param string $string Windows-1252 encoded string + * @return string UTF-8 encoded string + */ + public static function windows_1252_to_utf8($string) + { + static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF"); + + return strtr($string, $convert_table); + } + + /** + * Change a string from one encoding to another + * + * @param string $data Raw data in $input encoding + * @param string $input Encoding of $data + * @param string $output Encoding you want + * @return string|boolean False if we can't convert it + */ + public static function change_encoding($data, $input, $output) + { + $input = SimplePie_Misc::encoding($input); + $output = SimplePie_Misc::encoding($output); + + // We fail to fail on non US-ASCII bytes + if ($input === 'US-ASCII') + { + static $non_ascii_octects = ''; + if (!$non_ascii_octects) + { + for ($i = 0x80; $i <= 0xFF; $i++) + { + $non_ascii_octects .= chr($i); + } + } + $data = substr($data, 0, strcspn($data, $non_ascii_octects)); + } + + // This is first, as behaviour of this is completely predictable + if ($input === 'windows-1252' && $output === 'UTF-8') + { + return SimplePie_Misc::windows_1252_to_utf8($data); + } + // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported). + elseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc::change_encoding_mbstring($data, $input, $output))) + { + return $return; + } + // This is last, as behaviour of this varies with OS userland and PHP version + elseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output))) + { + return $return; + } + // If we can't do anything, just fail + else + { + return false; + } + } + + protected static function change_encoding_mbstring($data, $input, $output) + { + if ($input === 'windows-949') + { + $input = 'EUC-KR'; + } + if ($output === 'windows-949') + { + $output = 'EUC-KR'; + } + if ($input === 'Windows-31J') + { + $input = 'SJIS'; + } + if ($output === 'Windows-31J') + { + $output = 'SJIS'; + } + + // Check that the encoding is supported + if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80") + { + return false; + } + if (!in_array($input, mb_list_encodings())) + { + return false; + } + + // Let's do some conversion + if ($return = @mb_convert_encoding($data, $output, $input)) + { + return $return; + } + + return false; + } + + protected static function change_encoding_iconv($data, $input, $output) + { + return @iconv($input, $output, $data); + } + + /** + * Normalize an encoding name + * + * This is automatically generated by create.php + * + * To generate it, run `php create.php` on the command line, and copy the + * output to replace this function. + * + * @param string $charset Character set to standardise + * @return string Standardised name + */ + public static function encoding($charset) + { + // Normalization from UTS #22 + switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset))) + { + case 'adobestandardencoding': + case 'csadobestandardencoding': + return 'Adobe-Standard-Encoding'; + + case 'adobesymbolencoding': + case 'cshppsmath': + return 'Adobe-Symbol-Encoding'; + + case 'ami1251': + case 'amiga1251': + return 'Amiga-1251'; + + case 'ansix31101983': + case 'csat5001983': + case 'csiso99naplps': + case 'isoir99': + case 'naplps': + return 'ANSI_X3.110-1983'; + + case 'arabic7': + case 'asmo449': + case 'csiso89asmo449': + case 'iso9036': + case 'isoir89': + return 'ASMO_449'; + + case 'big5': + case 'csbig5': + return 'Big5'; + + case 'big5hkscs': + return 'Big5-HKSCS'; + + case 'bocu1': + case 'csbocu1': + return 'BOCU-1'; + + case 'brf': + case 'csbrf': + return 'BRF'; + + case 'bs4730': + case 'csiso4unitedkingdom': + case 'gb': + case 'iso646gb': + case 'isoir4': + case 'uk': + return 'BS_4730'; + + case 'bsviewdata': + case 'csiso47bsviewdata': + case 'isoir47': + return 'BS_viewdata'; + + case 'cesu8': + case 'cscesu8': + return 'CESU-8'; + + case 'ca': + case 'csa71': + case 'csaz243419851': + case 'csiso121canadian1': + case 'iso646ca': + case 'isoir121': + return 'CSA_Z243.4-1985-1'; + + case 'csa72': + case 'csaz243419852': + case 'csiso122canadian2': + case 'iso646ca2': + case 'isoir122': + return 'CSA_Z243.4-1985-2'; + + case 'csaz24341985gr': + case 'csiso123csaz24341985gr': + case 'isoir123': + return 'CSA_Z243.4-1985-gr'; + + case 'csiso139csn369103': + case 'csn369103': + case 'isoir139': + return 'CSN_369103'; + + case 'csdecmcs': + case 'dec': + case 'decmcs': + return 'DEC-MCS'; + + case 'csiso21german': + case 'de': + case 'din66003': + case 'iso646de': + case 'isoir21': + return 'DIN_66003'; + + case 'csdkus': + case 'dkus': + return 'dk-us'; + + case 'csiso646danish': + case 'dk': + case 'ds2089': + case 'iso646dk': + return 'DS_2089'; + + case 'csibmebcdicatde': + case 'ebcdicatde': + return 'EBCDIC-AT-DE'; + + case 'csebcdicatdea': + case 'ebcdicatdea': + return 'EBCDIC-AT-DE-A'; + + case 'csebcdiccafr': + case 'ebcdiccafr': + return 'EBCDIC-CA-FR'; + + case 'csebcdicdkno': + case 'ebcdicdkno': + return 'EBCDIC-DK-NO'; + + case 'csebcdicdknoa': + case 'ebcdicdknoa': + return 'EBCDIC-DK-NO-A'; + + case 'csebcdices': + case 'ebcdices': + return 'EBCDIC-ES'; + + case 'csebcdicesa': + case 'ebcdicesa': + return 'EBCDIC-ES-A'; + + case 'csebcdicess': + case 'ebcdicess': + return 'EBCDIC-ES-S'; + + case 'csebcdicfise': + case 'ebcdicfise': + return 'EBCDIC-FI-SE'; + + case 'csebcdicfisea': + case 'ebcdicfisea': + return 'EBCDIC-FI-SE-A'; + + case 'csebcdicfr': + case 'ebcdicfr': + return 'EBCDIC-FR'; + + case 'csebcdicit': + case 'ebcdicit': + return 'EBCDIC-IT'; + + case 'csebcdicpt': + case 'ebcdicpt': + return 'EBCDIC-PT'; + + case 'csebcdicuk': + case 'ebcdicuk': + return 'EBCDIC-UK'; + + case 'csebcdicus': + case 'ebcdicus': + return 'EBCDIC-US'; + + case 'csiso111ecmacyrillic': + case 'ecmacyrillic': + case 'isoir111': + case 'koi8e': + return 'ECMA-cyrillic'; + + case 'csiso17spanish': + case 'es': + case 'iso646es': + case 'isoir17': + return 'ES'; + + case 'csiso85spanish2': + case 'es2': + case 'iso646es2': + case 'isoir85': + return 'ES2'; + + case 'cseucpkdfmtjapanese': + case 'eucjp': + case 'extendedunixcodepackedformatforjapanese': + return 'EUC-JP'; + + case 'cseucfixwidjapanese': + case 'extendedunixcodefixedwidthforjapanese': + return 'Extended_UNIX_Code_Fixed_Width_for_Japanese'; + + case 'gb18030': + return 'GB18030'; + + case 'chinese': + case 'cp936': + case 'csgb2312': + case 'csiso58gb231280': + case 'gb2312': + case 'gb231280': + case 'gbk': + case 'isoir58': + case 'ms936': + case 'windows936': + return 'GBK'; + + case 'cn': + case 'csiso57gb1988': + case 'gb198880': + case 'iso646cn': + case 'isoir57': + return 'GB_1988-80'; + + case 'csiso153gost1976874': + case 'gost1976874': + case 'isoir153': + case 'stsev35888': + return 'GOST_19768-74'; + + case 'csiso150': + case 'csiso150greekccitt': + case 'greekccitt': + case 'isoir150': + return 'greek-ccitt'; + + case 'csiso88greek7': + case 'greek7': + case 'isoir88': + return 'greek7'; + + case 'csiso18greek7old': + case 'greek7old': + case 'isoir18': + return 'greek7-old'; + + case 'cshpdesktop': + case 'hpdesktop': + return 'HP-DeskTop'; + + case 'cshplegal': + case 'hplegal': + return 'HP-Legal'; + + case 'cshpmath8': + case 'hpmath8': + return 'HP-Math8'; + + case 'cshppifont': + case 'hppifont': + return 'HP-Pi-font'; + + case 'cshproman8': + case 'hproman8': + case 'r8': + case 'roman8': + return 'hp-roman8'; + + case 'hzgb2312': + return 'HZ-GB-2312'; + + case 'csibmsymbols': + case 'ibmsymbols': + return 'IBM-Symbols'; + + case 'csibmthai': + case 'ibmthai': + return 'IBM-Thai'; + + case 'cp37': + case 'csibm37': + case 'ebcdiccpca': + case 'ebcdiccpnl': + case 'ebcdiccpus': + case 'ebcdiccpwt': + case 'ibm37': + return 'IBM037'; + + case 'cp38': + case 'csibm38': + case 'ebcdicint': + case 'ibm38': + return 'IBM038'; + + case 'cp273': + case 'csibm273': + case 'ibm273': + return 'IBM273'; + + case 'cp274': + case 'csibm274': + case 'ebcdicbe': + case 'ibm274': + return 'IBM274'; + + case 'cp275': + case 'csibm275': + case 'ebcdicbr': + case 'ibm275': + return 'IBM275'; + + case 'csibm277': + case 'ebcdiccpdk': + case 'ebcdiccpno': + case 'ibm277': + return 'IBM277'; + + case 'cp278': + case 'csibm278': + case 'ebcdiccpfi': + case 'ebcdiccpse': + case 'ibm278': + return 'IBM278'; + + case 'cp280': + case 'csibm280': + case 'ebcdiccpit': + case 'ibm280': + return 'IBM280'; + + case 'cp281': + case 'csibm281': + case 'ebcdicjpe': + case 'ibm281': + return 'IBM281'; + + case 'cp284': + case 'csibm284': + case 'ebcdiccpes': + case 'ibm284': + return 'IBM284'; + + case 'cp285': + case 'csibm285': + case 'ebcdiccpgb': + case 'ibm285': + return 'IBM285'; + + case 'cp290': + case 'csibm290': + case 'ebcdicjpkana': + case 'ibm290': + return 'IBM290'; + + case 'cp297': + case 'csibm297': + case 'ebcdiccpfr': + case 'ibm297': + return 'IBM297'; + + case 'cp420': + case 'csibm420': + case 'ebcdiccpar1': + case 'ibm420': + return 'IBM420'; + + case 'cp423': + case 'csibm423': + case 'ebcdiccpgr': + case 'ibm423': + return 'IBM423'; + + case 'cp424': + case 'csibm424': + case 'ebcdiccphe': + case 'ibm424': + return 'IBM424'; + + case '437': + case 'cp437': + case 'cspc8codepage437': + case 'ibm437': + return 'IBM437'; + + case 'cp500': + case 'csibm500': + case 'ebcdiccpbe': + case 'ebcdiccpch': + case 'ibm500': + return 'IBM500'; + + case 'cp775': + case 'cspc775baltic': + case 'ibm775': + return 'IBM775'; + + case '850': + case 'cp850': + case 'cspc850multilingual': + case 'ibm850': + return 'IBM850'; + + case '851': + case 'cp851': + case 'csibm851': + case 'ibm851': + return 'IBM851'; + + case '852': + case 'cp852': + case 'cspcp852': + case 'ibm852': + return 'IBM852'; + + case '855': + case 'cp855': + case 'csibm855': + case 'ibm855': + return 'IBM855'; + + case '857': + case 'cp857': + case 'csibm857': + case 'ibm857': + return 'IBM857'; + + case 'ccsid858': + case 'cp858': + case 'ibm858': + case 'pcmultilingual850euro': + return 'IBM00858'; + + case '860': + case 'cp860': + case 'csibm860': + case 'ibm860': + return 'IBM860'; + + case '861': + case 'cp861': + case 'cpis': + case 'csibm861': + case 'ibm861': + return 'IBM861'; + + case '862': + case 'cp862': + case 'cspc862latinhebrew': + case 'ibm862': + return 'IBM862'; + + case '863': + case 'cp863': + case 'csibm863': + case 'ibm863': + return 'IBM863'; + + case 'cp864': + case 'csibm864': + case 'ibm864': + return 'IBM864'; + + case '865': + case 'cp865': + case 'csibm865': + case 'ibm865': + return 'IBM865'; + + case '866': + case 'cp866': + case 'csibm866': + case 'ibm866': + return 'IBM866'; + + case 'cp868': + case 'cpar': + case 'csibm868': + case 'ibm868': + return 'IBM868'; + + case '869': + case 'cp869': + case 'cpgr': + case 'csibm869': + case 'ibm869': + return 'IBM869'; + + case 'cp870': + case 'csibm870': + case 'ebcdiccproece': + case 'ebcdiccpyu': + case 'ibm870': + return 'IBM870'; + + case 'cp871': + case 'csibm871': + case 'ebcdiccpis': + case 'ibm871': + return 'IBM871'; + + case 'cp880': + case 'csibm880': + case 'ebcdiccyrillic': + case 'ibm880': + return 'IBM880'; + + case 'cp891': + case 'csibm891': + case 'ibm891': + return 'IBM891'; + + case 'cp903': + case 'csibm903': + case 'ibm903': + return 'IBM903'; + + case '904': + case 'cp904': + case 'csibbm904': + case 'ibm904': + return 'IBM904'; + + case 'cp905': + case 'csibm905': + case 'ebcdiccptr': + case 'ibm905': + return 'IBM905'; + + case 'cp918': + case 'csibm918': + case 'ebcdiccpar2': + case 'ibm918': + return 'IBM918'; + + case 'ccsid924': + case 'cp924': + case 'ebcdiclatin9euro': + case 'ibm924': + return 'IBM00924'; + + case 'cp1026': + case 'csibm1026': + case 'ibm1026': + return 'IBM1026'; + + case 'ibm1047': + return 'IBM1047'; + + case 'ccsid1140': + case 'cp1140': + case 'ebcdicus37euro': + case 'ibm1140': + return 'IBM01140'; + + case 'ccsid1141': + case 'cp1141': + case 'ebcdicde273euro': + case 'ibm1141': + return 'IBM01141'; + + case 'ccsid1142': + case 'cp1142': + case 'ebcdicdk277euro': + case 'ebcdicno277euro': + case 'ibm1142': + return 'IBM01142'; + + case 'ccsid1143': + case 'cp1143': + case 'ebcdicfi278euro': + case 'ebcdicse278euro': + case 'ibm1143': + return 'IBM01143'; + + case 'ccsid1144': + case 'cp1144': + case 'ebcdicit280euro': + case 'ibm1144': + return 'IBM01144'; + + case 'ccsid1145': + case 'cp1145': + case 'ebcdices284euro': + case 'ibm1145': + return 'IBM01145'; + + case 'ccsid1146': + case 'cp1146': + case 'ebcdicgb285euro': + case 'ibm1146': + return 'IBM01146'; + + case 'ccsid1147': + case 'cp1147': + case 'ebcdicfr297euro': + case 'ibm1147': + return 'IBM01147'; + + case 'ccsid1148': + case 'cp1148': + case 'ebcdicinternational500euro': + case 'ibm1148': + return 'IBM01148'; + + case 'ccsid1149': + case 'cp1149': + case 'ebcdicis871euro': + case 'ibm1149': + return 'IBM01149'; + + case 'csiso143iecp271': + case 'iecp271': + case 'isoir143': + return 'IEC_P27-1'; + + case 'csiso49inis': + case 'inis': + case 'isoir49': + return 'INIS'; + + case 'csiso50inis8': + case 'inis8': + case 'isoir50': + return 'INIS-8'; + + case 'csiso51iniscyrillic': + case 'iniscyrillic': + case 'isoir51': + return 'INIS-cyrillic'; + + case 'csinvariant': + case 'invariant': + return 'INVARIANT'; + + case 'iso2022cn': + return 'ISO-2022-CN'; + + case 'iso2022cnext': + return 'ISO-2022-CN-EXT'; + + case 'csiso2022jp': + case 'iso2022jp': + return 'ISO-2022-JP'; + + case 'csiso2022jp2': + case 'iso2022jp2': + return 'ISO-2022-JP-2'; + + case 'csiso2022kr': + case 'iso2022kr': + return 'ISO-2022-KR'; + + case 'cswindows30latin1': + case 'iso88591windows30latin1': + return 'ISO-8859-1-Windows-3.0-Latin-1'; + + case 'cswindows31latin1': + case 'iso88591windows31latin1': + return 'ISO-8859-1-Windows-3.1-Latin-1'; + + case 'csisolatin2': + case 'iso88592': + case 'iso885921987': + case 'isoir101': + case 'l2': + case 'latin2': + return 'ISO-8859-2'; + + case 'cswindows31latin2': + case 'iso88592windowslatin2': + return 'ISO-8859-2-Windows-Latin-2'; + + case 'csisolatin3': + case 'iso88593': + case 'iso885931988': + case 'isoir109': + case 'l3': + case 'latin3': + return 'ISO-8859-3'; + + case 'csisolatin4': + case 'iso88594': + case 'iso885941988': + case 'isoir110': + case 'l4': + case 'latin4': + return 'ISO-8859-4'; + + case 'csisolatincyrillic': + case 'cyrillic': + case 'iso88595': + case 'iso885951988': + case 'isoir144': + return 'ISO-8859-5'; + + case 'arabic': + case 'asmo708': + case 'csisolatinarabic': + case 'ecma114': + case 'iso88596': + case 'iso885961987': + case 'isoir127': + return 'ISO-8859-6'; + + case 'csiso88596e': + case 'iso88596e': + return 'ISO-8859-6-E'; + + case 'csiso88596i': + case 'iso88596i': + return 'ISO-8859-6-I'; + + case 'csisolatingreek': + case 'ecma118': + case 'elot928': + case 'greek': + case 'greek8': + case 'iso88597': + case 'iso885971987': + case 'isoir126': + return 'ISO-8859-7'; + + case 'csisolatinhebrew': + case 'hebrew': + case 'iso88598': + case 'iso885981988': + case 'isoir138': + return 'ISO-8859-8'; + + case 'csiso88598e': + case 'iso88598e': + return 'ISO-8859-8-E'; + + case 'csiso88598i': + case 'iso88598i': + return 'ISO-8859-8-I'; + + case 'cswindows31latin5': + case 'iso88599windowslatin5': + return 'ISO-8859-9-Windows-Latin-5'; + + case 'csisolatin6': + case 'iso885910': + case 'iso8859101992': + case 'isoir157': + case 'l6': + case 'latin6': + return 'ISO-8859-10'; + + case 'iso885913': + return 'ISO-8859-13'; + + case 'iso885914': + case 'iso8859141998': + case 'isoceltic': + case 'isoir199': + case 'l8': + case 'latin8': + return 'ISO-8859-14'; + + case 'iso885915': + case 'latin9': + return 'ISO-8859-15'; + + case 'iso885916': + case 'iso8859162001': + case 'isoir226': + case 'l10': + case 'latin10': + return 'ISO-8859-16'; + + case 'iso10646j1': + return 'ISO-10646-J-1'; + + case 'csunicode': + case 'iso10646ucs2': + return 'ISO-10646-UCS-2'; + + case 'csucs4': + case 'iso10646ucs4': + return 'ISO-10646-UCS-4'; + + case 'csunicodeascii': + case 'iso10646ucsbasic': + return 'ISO-10646-UCS-Basic'; + + case 'csunicodelatin1': + case 'iso10646': + case 'iso10646unicodelatin1': + return 'ISO-10646-Unicode-Latin1'; + + case 'csiso10646utf1': + case 'iso10646utf1': + return 'ISO-10646-UTF-1'; + + case 'csiso115481': + case 'iso115481': + case 'isotr115481': + return 'ISO-11548-1'; + + case 'csiso90': + case 'isoir90': + return 'iso-ir-90'; + + case 'csunicodeibm1261': + case 'isounicodeibm1261': + return 'ISO-Unicode-IBM-1261'; + + case 'csunicodeibm1264': + case 'isounicodeibm1264': + return 'ISO-Unicode-IBM-1264'; + + case 'csunicodeibm1265': + case 'isounicodeibm1265': + return 'ISO-Unicode-IBM-1265'; + + case 'csunicodeibm1268': + case 'isounicodeibm1268': + return 'ISO-Unicode-IBM-1268'; + + case 'csunicodeibm1276': + case 'isounicodeibm1276': + return 'ISO-Unicode-IBM-1276'; + + case 'csiso646basic1983': + case 'iso646basic1983': + case 'ref': + return 'ISO_646.basic:1983'; + + case 'csiso2intlrefversion': + case 'irv': + case 'iso646irv1983': + case 'isoir2': + return 'ISO_646.irv:1983'; + + case 'csiso2033': + case 'e13b': + case 'iso20331983': + case 'isoir98': + return 'ISO_2033-1983'; + + case 'csiso5427cyrillic': + case 'iso5427': + case 'isoir37': + return 'ISO_5427'; + + case 'iso5427cyrillic1981': + case 'iso54271981': + case 'isoir54': + return 'ISO_5427:1981'; + + case 'csiso5428greek': + case 'iso54281980': + case 'isoir55': + return 'ISO_5428:1980'; + + case 'csiso6937add': + case 'iso6937225': + case 'isoir152': + return 'ISO_6937-2-25'; + + case 'csisotextcomm': + case 'iso69372add': + case 'isoir142': + return 'ISO_6937-2-add'; + + case 'csiso8859supp': + case 'iso8859supp': + case 'isoir154': + case 'latin125': + return 'ISO_8859-supp'; + + case 'csiso10367box': + case 'iso10367box': + case 'isoir155': + return 'ISO_10367-box'; + + case 'csiso15italian': + case 'iso646it': + case 'isoir15': + case 'it': + return 'IT'; + + case 'csiso13jisc6220jp': + case 'isoir13': + case 'jisc62201969': + case 'jisc62201969jp': + case 'katakana': + case 'x2017': + return 'JIS_C6220-1969-jp'; + + case 'csiso14jisc6220ro': + case 'iso646jp': + case 'isoir14': + case 'jisc62201969ro': + case 'jp': + return 'JIS_C6220-1969-ro'; + + case 'csiso42jisc62261978': + case 'isoir42': + case 'jisc62261978': + return 'JIS_C6226-1978'; + + case 'csiso87jisx208': + case 'isoir87': + case 'jisc62261983': + case 'jisx2081983': + case 'x208': + return 'JIS_C6226-1983'; + + case 'csiso91jisc62291984a': + case 'isoir91': + case 'jisc62291984a': + case 'jpocra': + return 'JIS_C6229-1984-a'; + + case 'csiso92jisc62991984b': + case 'iso646jpocrb': + case 'isoir92': + case 'jisc62291984b': + case 'jpocrb': + return 'JIS_C6229-1984-b'; + + case 'csiso93jis62291984badd': + case 'isoir93': + case 'jisc62291984badd': + case 'jpocrbadd': + return 'JIS_C6229-1984-b-add'; + + case 'csiso94jis62291984hand': + case 'isoir94': + case 'jisc62291984hand': + case 'jpocrhand': + return 'JIS_C6229-1984-hand'; + + case 'csiso95jis62291984handadd': + case 'isoir95': + case 'jisc62291984handadd': + case 'jpocrhandadd': + return 'JIS_C6229-1984-hand-add'; + + case 'csiso96jisc62291984kana': + case 'isoir96': + case 'jisc62291984kana': + return 'JIS_C6229-1984-kana'; + + case 'csjisencoding': + case 'jisencoding': + return 'JIS_Encoding'; + + case 'cshalfwidthkatakana': + case 'jisx201': + case 'x201': + return 'JIS_X0201'; + + case 'csiso159jisx2121990': + case 'isoir159': + case 'jisx2121990': + case 'x212': + return 'JIS_X0212-1990'; + + case 'csiso141jusib1002': + case 'iso646yu': + case 'isoir141': + case 'js': + case 'jusib1002': + case 'yu': + return 'JUS_I.B1.002'; + + case 'csiso147macedonian': + case 'isoir147': + case 'jusib1003mac': + case 'macedonian': + return 'JUS_I.B1.003-mac'; + + case 'csiso146serbian': + case 'isoir146': + case 'jusib1003serb': + case 'serbian': + return 'JUS_I.B1.003-serb'; + + case 'koi7switched': + return 'KOI7-switched'; + + case 'cskoi8r': + case 'koi8r': + return 'KOI8-R'; + + case 'koi8u': + return 'KOI8-U'; + + case 'csksc5636': + case 'iso646kr': + case 'ksc5636': + return 'KSC5636'; + + case 'cskz1048': + case 'kz1048': + case 'rk1048': + case 'strk10482002': + return 'KZ-1048'; + + case 'csiso19latingreek': + case 'isoir19': + case 'latingreek': + return 'latin-greek'; + + case 'csiso27latingreek1': + case 'isoir27': + case 'latingreek1': + return 'Latin-greek-1'; + + case 'csiso158lap': + case 'isoir158': + case 'lap': + case 'latinlap': + return 'latin-lap'; + + case 'csmacintosh': + case 'mac': + case 'macintosh': + return 'macintosh'; + + case 'csmicrosoftpublishing': + case 'microsoftpublishing': + return 'Microsoft-Publishing'; + + case 'csmnem': + case 'mnem': + return 'MNEM'; + + case 'csmnemonic': + case 'mnemonic': + return 'MNEMONIC'; + + case 'csiso86hungarian': + case 'hu': + case 'iso646hu': + case 'isoir86': + case 'msz77953': + return 'MSZ_7795.3'; + + case 'csnatsdano': + case 'isoir91': + case 'natsdano': + return 'NATS-DANO'; + + case 'csnatsdanoadd': + case 'isoir92': + case 'natsdanoadd': + return 'NATS-DANO-ADD'; + + case 'csnatssefi': + case 'isoir81': + case 'natssefi': + return 'NATS-SEFI'; + + case 'csnatssefiadd': + case 'isoir82': + case 'natssefiadd': + return 'NATS-SEFI-ADD'; + + case 'csiso151cuba': + case 'cuba': + case 'iso646cu': + case 'isoir151': + case 'ncnc1081': + return 'NC_NC00-10:81'; + + case 'csiso69french': + case 'fr': + case 'iso646fr': + case 'isoir69': + case 'nfz62010': + return 'NF_Z_62-010'; + + case 'csiso25french': + case 'iso646fr1': + case 'isoir25': + case 'nfz620101973': + return 'NF_Z_62-010_(1973)'; + + case 'csiso60danishnorwegian': + case 'csiso60norwegian1': + case 'iso646no': + case 'isoir60': + case 'no': + case 'ns45511': + return 'NS_4551-1'; + + case 'csiso61norwegian2': + case 'iso646no2': + case 'isoir61': + case 'no2': + case 'ns45512': + return 'NS_4551-2'; + + case 'osdebcdicdf3irv': + return 'OSD_EBCDIC_DF03_IRV'; + + case 'osdebcdicdf41': + return 'OSD_EBCDIC_DF04_1'; + + case 'osdebcdicdf415': + return 'OSD_EBCDIC_DF04_15'; + + case 'cspc8danishnorwegian': + case 'pc8danishnorwegian': + return 'PC8-Danish-Norwegian'; + + case 'cspc8turkish': + case 'pc8turkish': + return 'PC8-Turkish'; + + case 'csiso16portuguese': + case 'iso646pt': + case 'isoir16': + case 'pt': + return 'PT'; + + case 'csiso84portuguese2': + case 'iso646pt2': + case 'isoir84': + case 'pt2': + return 'PT2'; + + case 'cp154': + case 'csptcp154': + case 'cyrillicasian': + case 'pt154': + case 'ptcp154': + return 'PTCP154'; + + case 'scsu': + return 'SCSU'; + + case 'csiso10swedish': + case 'fi': + case 'iso646fi': + case 'iso646se': + case 'isoir10': + case 'se': + case 'sen850200b': + return 'SEN_850200_B'; + + case 'csiso11swedishfornames': + case 'iso646se2': + case 'isoir11': + case 'se2': + case 'sen850200c': + return 'SEN_850200_C'; + + case 'csiso102t617bit': + case 'isoir102': + case 't617bit': + return 'T.61-7bit'; + + case 'csiso103t618bit': + case 'isoir103': + case 't61': + case 't618bit': + return 'T.61-8bit'; + + case 'csiso128t101g2': + case 'isoir128': + case 't101g2': + return 'T.101-G2'; + + case 'cstscii': + case 'tscii': + return 'TSCII'; + + case 'csunicode11': + case 'unicode11': + return 'UNICODE-1-1'; + + case 'csunicode11utf7': + case 'unicode11utf7': + return 'UNICODE-1-1-UTF-7'; + + case 'csunknown8bit': + case 'unknown8bit': + return 'UNKNOWN-8BIT'; + + case 'ansix341968': + case 'ansix341986': + case 'ascii': + case 'cp367': + case 'csascii': + case 'ibm367': + case 'iso646irv1991': + case 'iso646us': + case 'isoir6': + case 'us': + case 'usascii': + return 'US-ASCII'; + + case 'csusdk': + case 'usdk': + return 'us-dk'; + + case 'utf7': + return 'UTF-7'; + + case 'utf8': + return 'UTF-8'; + + case 'utf16': + return 'UTF-16'; + + case 'utf16be': + return 'UTF-16BE'; + + case 'utf16le': + return 'UTF-16LE'; + + case 'utf32': + return 'UTF-32'; + + case 'utf32be': + return 'UTF-32BE'; + + case 'utf32le': + return 'UTF-32LE'; + + case 'csventurainternational': + case 'venturainternational': + return 'Ventura-International'; + + case 'csventuramath': + case 'venturamath': + return 'Ventura-Math'; + + case 'csventuraus': + case 'venturaus': + return 'Ventura-US'; + + case 'csiso70videotexsupp1': + case 'isoir70': + case 'videotexsuppl': + return 'videotex-suppl'; + + case 'csviqr': + case 'viqr': + return 'VIQR'; + + case 'csviscii': + case 'viscii': + return 'VISCII'; + + case 'csshiftjis': + case 'cswindows31j': + case 'mskanji': + case 'shiftjis': + case 'windows31j': + return 'Windows-31J'; + + case 'iso885911': + case 'tis620': + return 'windows-874'; + + case 'cseuckr': + case 'csksc56011987': + case 'euckr': + case 'isoir149': + case 'korean': + case 'ksc5601': + case 'ksc56011987': + case 'ksc56011989': + case 'windows949': + return 'windows-949'; + + case 'windows1250': + return 'windows-1250'; + + case 'windows1251': + return 'windows-1251'; + + case 'cp819': + case 'csisolatin1': + case 'ibm819': + case 'iso88591': + case 'iso885911987': + case 'isoir100': + case 'l1': + case 'latin1': + case 'windows1252': + return 'windows-1252'; + + case 'windows1253': + return 'windows-1253'; + + case 'csisolatin5': + case 'iso88599': + case 'iso885991989': + case 'isoir148': + case 'l5': + case 'latin5': + case 'windows1254': + return 'windows-1254'; + + case 'windows1255': + return 'windows-1255'; + + case 'windows1256': + return 'windows-1256'; + + case 'windows1257': + return 'windows-1257'; + + case 'windows1258': + return 'windows-1258'; + + default: + return $charset; + } + } + + public static function get_curl_version() + { + if (is_array($curl = curl_version())) + { + $curl = $curl['version']; + } + elseif (substr($curl, 0, 5) === 'curl/') + { + $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5)); + } + elseif (substr($curl, 0, 8) === 'libcurl/') + { + $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8)); + } + else + { + $curl = 0; + } + return $curl; + } + + /** + * Strip HTML comments + * + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public static function strip_comments($data) + { + $output = ''; + while (($start = strpos($data, '<!--')) !== false) + { + $output .= substr($data, 0, $start); + if (($end = strpos($data, '-->', $start)) !== false) + { + $data = substr_replace($data, '', 0, $end + 3); + } + else + { + $data = ''; + } + } + return $output . $data; + } + + public static function parse_date($dt) + { + $parser = SimplePie_Parse_Date::get(); + return $parser->parse($dt); + } + + /** + * Decode HTML entities + * + * @deprecated Use DOMDocument instead + * @param string $data Input data + * @return string Output data + */ + public static function entities_decode($data) + { + $decoder = new SimplePie_Decode_HTML_Entities($data); + return $decoder->parse(); + } + + /** + * Remove RFC822 comments + * + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public static function uncomment_rfc822($string) + { + $string = (string) $string; + $position = 0; + $length = strlen($string); + $depth = 0; + + $output = ''; + + while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) + { + $output .= substr($string, $position, $pos - $position); + $position = $pos + 1; + if ($string[$pos - 1] !== '\\') + { + $depth++; + while ($depth && $position < $length) + { + $position += strcspn($string, '()', $position); + if ($string[$position - 1] === '\\') + { + $position++; + continue; + } + elseif (isset($string[$position])) + { + switch ($string[$position]) + { + case '(': + $depth++; + break; + + case ')': + $depth--; + break; + } + $position++; + } + else + { + break; + } + } + } + else + { + $output .= '('; + } + } + $output .= substr($string, $position); + + return $output; + } + + public static function parse_mime($mime) + { + if (($pos = strpos($mime, ';')) === false) + { + return trim($mime); + } + else + { + return trim(substr($mime, 0, $pos)); + } + } + + public static function atom_03_construct_type($attribs) + { + if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64')) + { + $mode = SIMPLEPIE_CONSTRUCT_BASE64; + } + else + { + $mode = SIMPLEPIE_CONSTRUCT_NONE; + } + if (isset($attribs['']['type'])) + { + switch (strtolower(trim($attribs['']['type']))) + { + case 'text': + case 'text/plain': + return SIMPLEPIE_CONSTRUCT_TEXT | $mode; + + case 'html': + case 'text/html': + return SIMPLEPIE_CONSTRUCT_HTML | $mode; + + case 'xhtml': + case 'application/xhtml+xml': + return SIMPLEPIE_CONSTRUCT_XHTML | $mode; + + default: + return SIMPLEPIE_CONSTRUCT_NONE | $mode; + } + } + else + { + return SIMPLEPIE_CONSTRUCT_TEXT | $mode; + } + } + + public static function atom_10_construct_type($attribs) + { + if (isset($attribs['']['type'])) + { + switch (strtolower(trim($attribs['']['type']))) + { + case 'text': + return SIMPLEPIE_CONSTRUCT_TEXT; + + case 'html': + return SIMPLEPIE_CONSTRUCT_HTML; + + case 'xhtml': + return SIMPLEPIE_CONSTRUCT_XHTML; + + default: + return SIMPLEPIE_CONSTRUCT_NONE; + } + } + return SIMPLEPIE_CONSTRUCT_TEXT; + } + + public static function atom_10_content_construct_type($attribs) + { + if (isset($attribs['']['type'])) + { + $type = strtolower(trim($attribs['']['type'])); + switch ($type) + { + case 'text': + return SIMPLEPIE_CONSTRUCT_TEXT; + + case 'html': + return SIMPLEPIE_CONSTRUCT_HTML; + + case 'xhtml': + return SIMPLEPIE_CONSTRUCT_XHTML; + } + if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/') + { + return SIMPLEPIE_CONSTRUCT_NONE; + } + else + { + return SIMPLEPIE_CONSTRUCT_BASE64; + } + } + else + { + return SIMPLEPIE_CONSTRUCT_TEXT; + } + } + + public static function is_isegment_nz_nc($string) + { + return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string); + } + + public static function space_seperated_tokens($string) + { + $space_characters = "\x20\x09\x0A\x0B\x0C\x0D"; + $string_length = strlen($string); + + $position = strspn($string, $space_characters); + $tokens = array(); + + while ($position < $string_length) + { + $len = strcspn($string, $space_characters, $position); + $tokens[] = substr($string, $position, $len); + $position += $len; + $position += strspn($string, $space_characters, $position); + } + + return $tokens; + } + + /** + * Converts a unicode codepoint to a UTF-8 character + * + * @static + * @param int $codepoint Unicode codepoint + * @return string UTF-8 character + */ + public static function codepoint_to_utf8($codepoint) + { + $codepoint = (int) $codepoint; + if ($codepoint < 0) + { + return false; + } + else if ($codepoint <= 0x7f) + { + return chr($codepoint); + } + else if ($codepoint <= 0x7ff) + { + return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f)); + } + else if ($codepoint <= 0xffff) + { + return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); + } + else if ($codepoint <= 0x10ffff) + { + return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f)); + } + else + { + // U+FFFD REPLACEMENT CHARACTER + return "\xEF\xBF\xBD"; + } + } + + /** + * Similar to parse_str() + * + * Returns an associative array of name/value pairs, where the value is an + * array of values that have used the same name + * + * @static + * @param string $str The input string. + * @return array + */ + public static function parse_str($str) + { + $return = array(); + $str = explode('&', $str); + + foreach ($str as $section) + { + if (strpos($section, '=') !== false) + { + list($name, $value) = explode('=', $section, 2); + $return[urldecode($name)][] = urldecode($value); + } + else + { + $return[urldecode($section)][] = null; + } + } + + return $return; + } + + /** + * Detect XML encoding, as per XML 1.0 Appendix F.1 + * + * @todo Add support for EBCDIC + * @param string $data XML data + * @param SimplePie_Registry $registry Class registry + * @return array Possible encodings + */ + public static function xml_encoding($data, $registry) + { + // UTF-32 Big Endian BOM + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") + { + $encoding[] = 'UTF-32BE'; + } + // UTF-32 Little Endian BOM + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + { + $encoding[] = 'UTF-32LE'; + } + // UTF-16 Big Endian BOM + elseif (substr($data, 0, 2) === "\xFE\xFF") + { + $encoding[] = 'UTF-16BE'; + } + // UTF-16 Little Endian BOM + elseif (substr($data, 0, 2) === "\xFF\xFE") + { + $encoding[] = 'UTF-16LE'; + } + // UTF-8 BOM + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + { + $encoding[] = 'UTF-8'; + } + // UTF-32 Big Endian Without BOM + elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C") + { + if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-32BE'; + } + // UTF-32 Little Endian Without BOM + elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00") + { + if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-32LE'; + } + // UTF-16 Big Endian Without BOM + elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C") + { + if ($pos = strpos($data, "\x00\x3F\x00\x3E")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-16BE'; + } + // UTF-16 Little Endian Without BOM + elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00") + { + if ($pos = strpos($data, "\x3F\x00\x3E\x00")) + { + $parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-16LE'; + } + // US-ASCII (or superset) + elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C") + { + if ($pos = strpos($data, "\x3F\x3E")) + { + $parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5))); + if ($parser->parse()) + { + $encoding[] = $parser->encoding; + } + } + $encoding[] = 'UTF-8'; + } + // Fallback to UTF-8 + else + { + $encoding[] = 'UTF-8'; + } + return $encoding; + } + + public static function output_javascript() + { + if (function_exists('ob_gzhandler')) + { + ob_start('ob_gzhandler'); + } + header('Content-type: text/javascript; charset: UTF-8'); + header('Cache-Control: must-revalidate'); + header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days + ?> +function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) { + if (placeholder != '') { + document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); + } + else { + document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>'); + } +} + +function embed_flash(bgcolor, width, height, link, loop, type) { + document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>'); +} + +function embed_flv(width, height, link, placeholder, loop, player) { + document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>'); +} + +function embed_wmedia(width, height, link) { + document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>'); +} + <?php + } + + /** + * Get the SimplePie build timestamp + * + * Uses the git index if it exists, otherwise uses the modification time + * of the newest file. + */ + public static function get_build() + { + $root = dirname(dirname(__FILE__)); + if (file_exists($root . '/.git/index')) + { + return filemtime($root . '/.git/index'); + } + elseif (file_exists($root . '/SimplePie')) + { + $time = 0; + foreach (glob($root . '/SimplePie/*.php') as $file) + { + if (($mtime = filemtime($file)) > $time) + { + $time = $mtime; + } + } + return $time; + } + elseif (file_exists(dirname(__FILE__) . '/Core.php')) + { + return filemtime(dirname(__FILE__) . '/Core.php'); + } + else + { + return filemtime(__FILE__); + } + } + + /** + * Format debugging information + */ + public static function debug(&$sp) + { + $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n"; + $info .= 'PHP ' . PHP_VERSION . "\n"; + if ($sp->error() !== null) + { + $info .= 'Error occurred: ' . $sp->error() . "\n"; + } + else + { + $info .= "No error found.\n"; + } + $info .= "Extensions:\n"; + $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml'); + foreach ($extensions as $ext) + { + if (extension_loaded($ext)) + { + $info .= " $ext loaded\n"; + switch ($ext) + { + case 'pcre': + $info .= ' Version ' . PCRE_VERSION . "\n"; + break; + case 'curl': + $version = curl_version(); + $info .= ' Version ' . $version['version'] . "\n"; + break; + case 'mbstring': + $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n"; + break; + case 'iconv': + $info .= ' Version ' . ICONV_VERSION . "\n"; + break; + case 'xml': + $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n"; + break; + } + } + else + { + $info .= " $ext not loaded\n"; + } + } + return $info; + } + + public static function silence_errors($num, $str) + { + // No-op + } +} + diff --git a/sources/wp-includes/SimplePie/Net/IPv6.php b/sources/wp-includes/SimplePie/Net/IPv6.php new file mode 100644 index 0000000..da80d8a --- /dev/null +++ b/sources/wp-includes/SimplePie/Net/IPv6.php @@ -0,0 +1,276 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + + +/** + * Class to validate and to work with IPv6 addresses. + * + * @package SimplePie + * @subpackage HTTP + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/package/Net_IPv6 + * @author Alexander Merz <alexander.merz@web.de> + * @author elfrink at introweb dot nl + * @author Josh Peck <jmp at joshpeck dot org> + * @author Geoffrey Sneddon <geoffers@gmail.com> + */ +class SimplePie_Net_IPv6 +{ + /** + * Uncompresses an IPv6 address + * + * RFC 4291 allows you to compress concecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and expands the '::' to + * the required number of zero pieces. + * + * Example: FF01::101 -> FF01:0:0:0:0:0:0:101 + * ::1 -> 0:0:0:0:0:0:0:1 + * + * @author Alexander Merz <alexander.merz@web.de> + * @author elfrink at introweb dot nl + * @author Josh Peck <jmp at joshpeck dot org> + * @copyright 2003-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php + * @param string $ip An IPv6 address + * @return string The uncompressed IPv6 address + */ + public static function uncompress($ip) + { + $c1 = -1; + $c2 = -1; + if (substr_count($ip, '::') === 1) + { + list($ip1, $ip2) = explode('::', $ip); + if ($ip1 === '') + { + $c1 = -1; + } + else + { + $c1 = substr_count($ip1, ':'); + } + if ($ip2 === '') + { + $c2 = -1; + } + else + { + $c2 = substr_count($ip2, ':'); + } + if (strpos($ip2, '.') !== false) + { + $c2++; + } + // :: + if ($c1 === -1 && $c2 === -1) + { + $ip = '0:0:0:0:0:0:0:0'; + } + // ::xxx + else if ($c1 === -1) + { + $fill = str_repeat('0:', 7 - $c2); + $ip = str_replace('::', $fill, $ip); + } + // xxx:: + else if ($c2 === -1) + { + $fill = str_repeat(':0', 7 - $c1); + $ip = str_replace('::', $fill, $ip); + } + // xxx::xxx + else + { + $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); + $ip = str_replace('::', $fill, $ip); + } + } + return $ip; + } + + /** + * Compresses an IPv6 address + * + * RFC 4291 allows you to compress concecutive zero pieces in an address to + * '::'. This method expects a valid IPv6 address and compresses consecutive + * zero pieces to '::'. + * + * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 + * 0:0:0:0:0:0:0:1 -> ::1 + * + * @see uncompress() + * @param string $ip An IPv6 address + * @return string The compressed IPv6 address + */ + public static function compress($ip) + { + // Prepare the IP to be compressed + $ip = self::uncompress($ip); + $ip_parts = self::split_v6_v4($ip); + + // Replace all leading zeros + $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]); + + // Find bunches of zeros + if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) + { + $max = 0; + $pos = null; + foreach ($matches[0] as $match) + { + if (strlen($match[0]) > $max) + { + $max = strlen($match[0]); + $pos = $match[1]; + } + } + + $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max); + } + + if ($ip_parts[1] !== '') + { + return implode(':', $ip_parts); + } + else + { + return $ip_parts[0]; + } + } + + /** + * Splits an IPv6 address into the IPv6 and IPv4 representation parts + * + * RFC 4291 allows you to represent the last two parts of an IPv6 address + * using the standard IPv4 representation + * + * Example: 0:0:0:0:0:0:13.1.68.3 + * 0:0:0:0:0:FFFF:129.144.52.38 + * + * @param string $ip An IPv6 address + * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part + */ + private static function split_v6_v4($ip) + { + if (strpos($ip, '.') !== false) + { + $pos = strrpos($ip, ':'); + $ipv6_part = substr($ip, 0, $pos); + $ipv4_part = substr($ip, $pos + 1); + return array($ipv6_part, $ipv4_part); + } + else + { + return array($ip, ''); + } + } + + /** + * Checks an IPv6 address + * + * Checks if the given IP is a valid IPv6 address + * + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function check_ipv6($ip) + { + $ip = self::uncompress($ip); + list($ipv6, $ipv4) = self::split_v6_v4($ip); + $ipv6 = explode(':', $ipv6); + $ipv4 = explode('.', $ipv4); + if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) + { + foreach ($ipv6 as $ipv6_part) + { + // The section can't be empty + if ($ipv6_part === '') + return false; + + // Nor can it be over four characters + if (strlen($ipv6_part) > 4) + return false; + + // Remove leading zeros (this is safe because of the above) + $ipv6_part = ltrim($ipv6_part, '0'); + if ($ipv6_part === '') + $ipv6_part = '0'; + + // Check the value is valid + $value = hexdec($ipv6_part); + if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) + return false; + } + if (count($ipv4) === 4) + { + foreach ($ipv4 as $ipv4_part) + { + $value = (int) $ipv4_part; + if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) + return false; + } + } + return true; + } + else + { + return false; + } + } + + /** + * Checks if the given IP is a valid IPv6 address + * + * @codeCoverageIgnore + * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead + * @see check_ipv6 + * @param string $ip An IPv6 address + * @return bool true if $ip is a valid IPv6 address + */ + public static function checkIPv6($ip) + { + return self::check_ipv6($ip); + } +} diff --git a/sources/wp-includes/SimplePie/Parse/Date.php b/sources/wp-includes/SimplePie/Parse/Date.php new file mode 100644 index 0000000..d51f500 --- /dev/null +++ b/sources/wp-includes/SimplePie/Parse/Date.php @@ -0,0 +1,983 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + + +/** + * Date Parser + * + * @package SimplePie + * @subpackage Parsing + */ +class SimplePie_Parse_Date +{ + /** + * Input data + * + * @access protected + * @var string + */ + var $date; + + /** + * List of days, calendar day name => ordinal day number in the week + * + * @access protected + * @var array + */ + var $day = array( + // English + 'mon' => 1, + 'monday' => 1, + 'tue' => 2, + 'tuesday' => 2, + 'wed' => 3, + 'wednesday' => 3, + 'thu' => 4, + 'thursday' => 4, + 'fri' => 5, + 'friday' => 5, + 'sat' => 6, + 'saturday' => 6, + 'sun' => 7, + 'sunday' => 7, + // Dutch + 'maandag' => 1, + 'dinsdag' => 2, + 'woensdag' => 3, + 'donderdag' => 4, + 'vrijdag' => 5, + 'zaterdag' => 6, + 'zondag' => 7, + // French + 'lundi' => 1, + 'mardi' => 2, + 'mercredi' => 3, + 'jeudi' => 4, + 'vendredi' => 5, + 'samedi' => 6, + 'dimanche' => 7, + // German + 'montag' => 1, + 'dienstag' => 2, + 'mittwoch' => 3, + 'donnerstag' => 4, + 'freitag' => 5, + 'samstag' => 6, + 'sonnabend' => 6, + 'sonntag' => 7, + // Italian + 'lunedì' => 1, + 'martedì' => 2, + 'mercoledì' => 3, + 'giovedì' => 4, + 'venerdì' => 5, + 'sabato' => 6, + 'domenica' => 7, + // Spanish + 'lunes' => 1, + 'martes' => 2, + 'miércoles' => 3, + 'jueves' => 4, + 'viernes' => 5, + 'sábado' => 6, + 'domingo' => 7, + // Finnish + 'maanantai' => 1, + 'tiistai' => 2, + 'keskiviikko' => 3, + 'torstai' => 4, + 'perjantai' => 5, + 'lauantai' => 6, + 'sunnuntai' => 7, + // Hungarian + 'hétfÅ‘' => 1, + 'kedd' => 2, + 'szerda' => 3, + 'csütörtok' => 4, + 'péntek' => 5, + 'szombat' => 6, + 'vasárnap' => 7, + // Greek + 'Δευ' => 1, + 'ΤÏι' => 2, + 'Τετ' => 3, + 'Πεμ' => 4, + 'ΠαÏ' => 5, + 'Σαβ' => 6, + 'ΚυÏ' => 7, + ); + + /** + * List of months, calendar month name => calendar month number + * + * @access protected + * @var array + */ + var $month = array( + // English + 'jan' => 1, + 'january' => 1, + 'feb' => 2, + 'february' => 2, + 'mar' => 3, + 'march' => 3, + 'apr' => 4, + 'april' => 4, + 'may' => 5, + // No long form of May + 'jun' => 6, + 'june' => 6, + 'jul' => 7, + 'july' => 7, + 'aug' => 8, + 'august' => 8, + 'sep' => 9, + 'september' => 8, + 'oct' => 10, + 'october' => 10, + 'nov' => 11, + 'november' => 11, + 'dec' => 12, + 'december' => 12, + // Dutch + 'januari' => 1, + 'februari' => 2, + 'maart' => 3, + 'april' => 4, + 'mei' => 5, + 'juni' => 6, + 'juli' => 7, + 'augustus' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'december' => 12, + // French + 'janvier' => 1, + 'février' => 2, + 'mars' => 3, + 'avril' => 4, + 'mai' => 5, + 'juin' => 6, + 'juillet' => 7, + 'août' => 8, + 'septembre' => 9, + 'octobre' => 10, + 'novembre' => 11, + 'décembre' => 12, + // German + 'januar' => 1, + 'februar' => 2, + 'märz' => 3, + 'april' => 4, + 'mai' => 5, + 'juni' => 6, + 'juli' => 7, + 'august' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'dezember' => 12, + // Italian + 'gennaio' => 1, + 'febbraio' => 2, + 'marzo' => 3, + 'aprile' => 4, + 'maggio' => 5, + 'giugno' => 6, + 'luglio' => 7, + 'agosto' => 8, + 'settembre' => 9, + 'ottobre' => 10, + 'novembre' => 11, + 'dicembre' => 12, + // Spanish + 'enero' => 1, + 'febrero' => 2, + 'marzo' => 3, + 'abril' => 4, + 'mayo' => 5, + 'junio' => 6, + 'julio' => 7, + 'agosto' => 8, + 'septiembre' => 9, + 'setiembre' => 9, + 'octubre' => 10, + 'noviembre' => 11, + 'diciembre' => 12, + // Finnish + 'tammikuu' => 1, + 'helmikuu' => 2, + 'maaliskuu' => 3, + 'huhtikuu' => 4, + 'toukokuu' => 5, + 'kesäkuu' => 6, + 'heinäkuu' => 7, + 'elokuu' => 8, + 'suuskuu' => 9, + 'lokakuu' => 10, + 'marras' => 11, + 'joulukuu' => 12, + // Hungarian + 'január' => 1, + 'február' => 2, + 'március' => 3, + 'április' => 4, + 'május' => 5, + 'június' => 6, + 'július' => 7, + 'augusztus' => 8, + 'szeptember' => 9, + 'október' => 10, + 'november' => 11, + 'december' => 12, + // Greek + 'Ιαν' => 1, + 'Φεβ' => 2, + 'Μάώ' => 3, + 'Μαώ' => 3, + 'ΑπÏ' => 4, + 'Μάι' => 5, + 'Μαϊ' => 5, + 'Μαι' => 5, + 'ΙοÏν' => 6, + 'Ιον' => 6, + 'ΙοÏλ' => 7, + 'Ιολ' => 7, + 'ΑÏγ' => 8, + 'Αυγ' => 8, + 'Σεπ' => 9, + 'Οκτ' => 10, + 'Îοέ' => 11, + 'Δεκ' => 12, + ); + + /** + * List of timezones, abbreviation => offset from UTC + * + * @access protected + * @var array + */ + var $timezone = array( + 'ACDT' => 37800, + 'ACIT' => 28800, + 'ACST' => 34200, + 'ACT' => -18000, + 'ACWDT' => 35100, + 'ACWST' => 31500, + 'AEDT' => 39600, + 'AEST' => 36000, + 'AFT' => 16200, + 'AKDT' => -28800, + 'AKST' => -32400, + 'AMDT' => 18000, + 'AMT' => -14400, + 'ANAST' => 46800, + 'ANAT' => 43200, + 'ART' => -10800, + 'AZOST' => -3600, + 'AZST' => 18000, + 'AZT' => 14400, + 'BIOT' => 21600, + 'BIT' => -43200, + 'BOT' => -14400, + 'BRST' => -7200, + 'BRT' => -10800, + 'BST' => 3600, + 'BTT' => 21600, + 'CAST' => 18000, + 'CAT' => 7200, + 'CCT' => 23400, + 'CDT' => -18000, + 'CEDT' => 7200, + 'CET' => 3600, + 'CGST' => -7200, + 'CGT' => -10800, + 'CHADT' => 49500, + 'CHAST' => 45900, + 'CIST' => -28800, + 'CKT' => -36000, + 'CLDT' => -10800, + 'CLST' => -14400, + 'COT' => -18000, + 'CST' => -21600, + 'CVT' => -3600, + 'CXT' => 25200, + 'DAVT' => 25200, + 'DTAT' => 36000, + 'EADT' => -18000, + 'EAST' => -21600, + 'EAT' => 10800, + 'ECT' => -18000, + 'EDT' => -14400, + 'EEST' => 10800, + 'EET' => 7200, + 'EGT' => -3600, + 'EKST' => 21600, + 'EST' => -18000, + 'FJT' => 43200, + 'FKDT' => -10800, + 'FKST' => -14400, + 'FNT' => -7200, + 'GALT' => -21600, + 'GEDT' => 14400, + 'GEST' => 10800, + 'GFT' => -10800, + 'GILT' => 43200, + 'GIT' => -32400, + 'GST' => 14400, + 'GST' => -7200, + 'GYT' => -14400, + 'HAA' => -10800, + 'HAC' => -18000, + 'HADT' => -32400, + 'HAE' => -14400, + 'HAP' => -25200, + 'HAR' => -21600, + 'HAST' => -36000, + 'HAT' => -9000, + 'HAY' => -28800, + 'HKST' => 28800, + 'HMT' => 18000, + 'HNA' => -14400, + 'HNC' => -21600, + 'HNE' => -18000, + 'HNP' => -28800, + 'HNR' => -25200, + 'HNT' => -12600, + 'HNY' => -32400, + 'IRDT' => 16200, + 'IRKST' => 32400, + 'IRKT' => 28800, + 'IRST' => 12600, + 'JFDT' => -10800, + 'JFST' => -14400, + 'JST' => 32400, + 'KGST' => 21600, + 'KGT' => 18000, + 'KOST' => 39600, + 'KOVST' => 28800, + 'KOVT' => 25200, + 'KRAST' => 28800, + 'KRAT' => 25200, + 'KST' => 32400, + 'LHDT' => 39600, + 'LHST' => 37800, + 'LINT' => 50400, + 'LKT' => 21600, + 'MAGST' => 43200, + 'MAGT' => 39600, + 'MAWT' => 21600, + 'MDT' => -21600, + 'MESZ' => 7200, + 'MEZ' => 3600, + 'MHT' => 43200, + 'MIT' => -34200, + 'MNST' => 32400, + 'MSDT' => 14400, + 'MSST' => 10800, + 'MST' => -25200, + 'MUT' => 14400, + 'MVT' => 18000, + 'MYT' => 28800, + 'NCT' => 39600, + 'NDT' => -9000, + 'NFT' => 41400, + 'NMIT' => 36000, + 'NOVST' => 25200, + 'NOVT' => 21600, + 'NPT' => 20700, + 'NRT' => 43200, + 'NST' => -12600, + 'NUT' => -39600, + 'NZDT' => 46800, + 'NZST' => 43200, + 'OMSST' => 25200, + 'OMST' => 21600, + 'PDT' => -25200, + 'PET' => -18000, + 'PETST' => 46800, + 'PETT' => 43200, + 'PGT' => 36000, + 'PHOT' => 46800, + 'PHT' => 28800, + 'PKT' => 18000, + 'PMDT' => -7200, + 'PMST' => -10800, + 'PONT' => 39600, + 'PST' => -28800, + 'PWT' => 32400, + 'PYST' => -10800, + 'PYT' => -14400, + 'RET' => 14400, + 'ROTT' => -10800, + 'SAMST' => 18000, + 'SAMT' => 14400, + 'SAST' => 7200, + 'SBT' => 39600, + 'SCDT' => 46800, + 'SCST' => 43200, + 'SCT' => 14400, + 'SEST' => 3600, + 'SGT' => 28800, + 'SIT' => 28800, + 'SRT' => -10800, + 'SST' => -39600, + 'SYST' => 10800, + 'SYT' => 7200, + 'TFT' => 18000, + 'THAT' => -36000, + 'TJT' => 18000, + 'TKT' => -36000, + 'TMT' => 18000, + 'TOT' => 46800, + 'TPT' => 32400, + 'TRUT' => 36000, + 'TVT' => 43200, + 'TWT' => 28800, + 'UYST' => -7200, + 'UYT' => -10800, + 'UZT' => 18000, + 'VET' => -14400, + 'VLAST' => 39600, + 'VLAT' => 36000, + 'VOST' => 21600, + 'VUT' => 39600, + 'WAST' => 7200, + 'WAT' => 3600, + 'WDT' => 32400, + 'WEST' => 3600, + 'WFT' => 43200, + 'WIB' => 25200, + 'WIT' => 32400, + 'WITA' => 28800, + 'WKST' => 18000, + 'WST' => 28800, + 'YAKST' => 36000, + 'YAKT' => 32400, + 'YAPT' => 36000, + 'YEKST' => 21600, + 'YEKT' => 18000, + ); + + /** + * Cached PCRE for SimplePie_Parse_Date::$day + * + * @access protected + * @var string + */ + var $day_pcre; + + /** + * Cached PCRE for SimplePie_Parse_Date::$month + * + * @access protected + * @var string + */ + var $month_pcre; + + /** + * Array of user-added callback methods + * + * @access private + * @var array + */ + var $built_in = array(); + + /** + * Array of user-added callback methods + * + * @access private + * @var array + */ + var $user = array(); + + /** + * Create new SimplePie_Parse_Date object, and set self::day_pcre, + * self::month_pcre, and self::built_in + * + * @access private + */ + public function __construct() + { + $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')'; + $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')'; + + static $cache; + if (!isset($cache[get_class($this)])) + { + $all_methods = get_class_methods($this); + + foreach ($all_methods as $method) + { + if (strtolower(substr($method, 0, 5)) === 'date_') + { + $cache[get_class($this)][] = $method; + } + } + } + + foreach ($cache[get_class($this)] as $method) + { + $this->built_in[] = $method; + } + } + + /** + * Get the object + * + * @access public + */ + public static function get() + { + static $object; + if (!$object) + { + $object = new SimplePie_Parse_Date; + } + return $object; + } + + /** + * Parse a date + * + * @final + * @access public + * @param string $date Date to parse + * @return int Timestamp corresponding to date string, or false on failure + */ + public function parse($date) + { + foreach ($this->user as $method) + { + if (($returned = call_user_func($method, $date)) !== false) + { + return $returned; + } + } + + foreach ($this->built_in as $method) + { + if (($returned = call_user_func(array($this, $method), $date)) !== false) + { + return $returned; + } + } + + return false; + } + + /** + * Add a callback method to parse a date + * + * @final + * @access public + * @param callback $callback + */ + public function add_callback($callback) + { + if (is_callable($callback)) + { + $this->user[] = $callback; + } + else + { + trigger_error('User-supplied function must be a valid callback', E_USER_WARNING); + } + } + + /** + * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as + * well as allowing any of upper or lower case "T", horizontal tabs, or + * spaces to be used as the time seperator (including more than one)) + * + * @access protected + * @return int Timestamp + */ + public function date_w3cdtf($date) + { + static $pcre; + if (!$pcre) + { + $year = '([0-9]{4})'; + $month = $day = $hour = $minute = $second = '([0-9]{2})'; + $decimal = '([0-9]*)'; + $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))'; + $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Year + 2: Month + 3: Day + 4: Hour + 5: Minute + 6: Second + 7: Decimal fraction of a second + 8: Zulu + 9: Timezone ± + 10: Timezone hours + 11: Timezone minutes + */ + + // Fill in empty matches + for ($i = count($match); $i <= 3; $i++) + { + $match[$i] = '1'; + } + + for ($i = count($match); $i <= 7; $i++) + { + $match[$i] = '0'; + } + + // Numeric timezone + if (isset($match[9]) && $match[9] !== '') + { + $timezone = $match[10] * 3600; + $timezone += $match[11] * 60; + if ($match[9] === '-') + { + $timezone = 0 - $timezone; + } + } + else + { + $timezone = 0; + } + + // Convert the number of seconds to an integer, taking decimals into account + $second = round($match[6] + $match[7] / pow(10, strlen($match[7]))); + + return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone; + } + else + { + return false; + } + } + + /** + * Remove RFC822 comments + * + * @access protected + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public function remove_rfc2822_comments($string) + { + $string = (string) $string; + $position = 0; + $length = strlen($string); + $depth = 0; + + $output = ''; + + while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) + { + $output .= substr($string, $position, $pos - $position); + $position = $pos + 1; + if ($string[$pos - 1] !== '\\') + { + $depth++; + while ($depth && $position < $length) + { + $position += strcspn($string, '()', $position); + if ($string[$position - 1] === '\\') + { + $position++; + continue; + } + elseif (isset($string[$position])) + { + switch ($string[$position]) + { + case '(': + $depth++; + break; + + case ')': + $depth--; + break; + } + $position++; + } + else + { + break; + } + } + } + else + { + $output .= '('; + } + } + $output .= substr($string, $position); + + return $output; + } + + /** + * Parse RFC2822's date format + * + * @access protected + * @return int Timestamp + */ + public function date_rfc2822($date) + { + static $pcre; + if (!$pcre) + { + $wsp = '[\x09\x20]'; + $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)'; + $optional_fws = $fws . '?'; + $day_name = $this->day_pcre; + $month = $this->month_pcre; + $day = '([0-9]{1,2})'; + $hour = $minute = $second = '([0-9]{2})'; + $year = '([0-9]{2,4})'; + $num_zone = '([+\-])([0-9]{2})([0-9]{2})'; + $character_zone = '([A-Z]{1,5})'; + $zone = '(?:' . $num_zone . '|' . $character_zone . ')'; + $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i'; + } + if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Day + 3: Month + 4: Year + 5: Hour + 6: Minute + 7: Second + 8: Timezone ± + 9: Timezone hours + 10: Timezone minutes + 11: Alphabetic timezone + */ + + // Find the month number + $month = $this->month[strtolower($match[3])]; + + // Numeric timezone + if ($match[8] !== '') + { + $timezone = $match[9] * 3600; + $timezone += $match[10] * 60; + if ($match[8] === '-') + { + $timezone = 0 - $timezone; + } + } + // Character timezone + elseif (isset($this->timezone[strtoupper($match[11])])) + { + $timezone = $this->timezone[strtoupper($match[11])]; + } + // Assume everything else to be -0000 + else + { + $timezone = 0; + } + + // Deal with 2/3 digit years + if ($match[4] < 50) + { + $match[4] += 2000; + } + elseif ($match[4] < 1000) + { + $match[4] += 1900; + } + + // Second is optional, if it is empty set it to zero + if ($match[7] !== '') + { + $second = $match[7]; + } + else + { + $second = 0; + } + + return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone; + } + else + { + return false; + } + } + + /** + * Parse RFC850's date format + * + * @access protected + * @return int Timestamp + */ + public function date_rfc850($date) + { + static $pcre; + if (!$pcre) + { + $space = '[\x09\x20]+'; + $day_name = $this->day_pcre; + $month = $this->month_pcre; + $day = '([0-9]{1,2})'; + $year = $hour = $minute = $second = '([0-9]{2})'; + $zone = '([A-Z]{1,5})'; + $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Day + 3: Month + 4: Year + 5: Hour + 6: Minute + 7: Second + 8: Timezone + */ + + // Month + $month = $this->month[strtolower($match[3])]; + + // Character timezone + if (isset($this->timezone[strtoupper($match[8])])) + { + $timezone = $this->timezone[strtoupper($match[8])]; + } + // Assume everything else to be -0000 + else + { + $timezone = 0; + } + + // Deal with 2 digit year + if ($match[4] < 50) + { + $match[4] += 2000; + } + else + { + $match[4] += 1900; + } + + return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone; + } + else + { + return false; + } + } + + /** + * Parse C99's asctime()'s date format + * + * @access protected + * @return int Timestamp + */ + public function date_asctime($date) + { + static $pcre; + if (!$pcre) + { + $space = '[\x09\x20]+'; + $wday_name = $this->day_pcre; + $mon_name = $this->month_pcre; + $day = '([0-9]{1,2})'; + $hour = $sec = $min = '([0-9]{2})'; + $year = '([0-9]{4})'; + $terminator = '\x0A?\x00?'; + $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Month + 3: Day + 4: Hour + 5: Minute + 6: Second + 7: Year + */ + + $month = $this->month[strtolower($match[2])]; + return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]); + } + else + { + return false; + } + } + + /** + * Parse dates using strtotime() + * + * @access protected + * @return int Timestamp + */ + public function date_strtotime($date) + { + $strtotime = strtotime($date); + if ($strtotime === -1 || $strtotime === false) + { + return false; + } + else + { + return $strtotime; + } + } +} + diff --git a/sources/wp-includes/SimplePie/Parser.php b/sources/wp-includes/SimplePie/Parser.php new file mode 100644 index 0000000..d698552 --- /dev/null +++ b/sources/wp-includes/SimplePie/Parser.php @@ -0,0 +1,407 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Parses XML into something sane + * + * + * This class can be overloaded with {@see SimplePie::set_parser_class()} + * + * @package SimplePie + * @subpackage Parsing + */ +class SimplePie_Parser +{ + var $error_code; + var $error_string; + var $current_line; + var $current_column; + var $current_byte; + var $separator = ' '; + var $namespace = array(''); + var $element = array(''); + var $xml_base = array(''); + var $xml_base_explicit = array(false); + var $xml_lang = array(''); + var $data = array(); + var $datas = array(array()); + var $current_xhtml_construct = -1; + var $encoding; + protected $registry; + + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } + + public function parse(&$data, $encoding) + { + // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character + if (strtoupper($encoding) === 'US-ASCII') + { + $this->encoding = 'UTF-8'; + } + else + { + $this->encoding = $encoding; + } + + // Strip BOM: + // UTF-32 Big Endian BOM + if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") + { + $data = substr($data, 4); + } + // UTF-32 Little Endian BOM + elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") + { + $data = substr($data, 4); + } + // UTF-16 Big Endian BOM + elseif (substr($data, 0, 2) === "\xFE\xFF") + { + $data = substr($data, 2); + } + // UTF-16 Little Endian BOM + elseif (substr($data, 0, 2) === "\xFF\xFE") + { + $data = substr($data, 2); + } + // UTF-8 BOM + elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") + { + $data = substr($data, 3); + } + + if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false) + { + $declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5))); + if ($declaration->parse()) + { + $data = substr($data, $pos + 2); + $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data; + } + else + { + $this->error_string = 'SimplePie bug! Please report this!'; + return false; + } + } + + $return = true; + + static $xml_is_sane = null; + if ($xml_is_sane === null) + { + $parser_check = xml_parser_create(); + xml_parse_into_struct($parser_check, '<foo>&</foo>', $values); + xml_parser_free($parser_check); + $xml_is_sane = isset($values[0]['value']); + } + + // Create the parser + if ($xml_is_sane) + { + $xml = xml_parser_create_ns($this->encoding, $this->separator); + xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1); + xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0); + xml_set_object($xml, $this); + xml_set_character_data_handler($xml, 'cdata'); + xml_set_element_handler($xml, 'tag_open', 'tag_close'); + + // Parse! + if (!xml_parse($xml, $data, true)) + { + $this->error_code = xml_get_error_code($xml); + $this->error_string = xml_error_string($this->error_code); + $return = false; + } + $this->current_line = xml_get_current_line_number($xml); + $this->current_column = xml_get_current_column_number($xml); + $this->current_byte = xml_get_current_byte_index($xml); + xml_parser_free($xml); + return $return; + } + else + { + libxml_clear_errors(); + $xml = new XMLReader(); + $xml->xml($data); + while (@$xml->read()) + { + switch ($xml->nodeType) + { + + case constant('XMLReader::END_ELEMENT'): + if ($xml->namespaceURI !== '') + { + $tagName = $xml->namespaceURI . $this->separator . $xml->localName; + } + else + { + $tagName = $xml->localName; + } + $this->tag_close(null, $tagName); + break; + case constant('XMLReader::ELEMENT'): + $empty = $xml->isEmptyElement; + if ($xml->namespaceURI !== '') + { + $tagName = $xml->namespaceURI . $this->separator . $xml->localName; + } + else + { + $tagName = $xml->localName; + } + $attributes = array(); + while ($xml->moveToNextAttribute()) + { + if ($xml->namespaceURI !== '') + { + $attrName = $xml->namespaceURI . $this->separator . $xml->localName; + } + else + { + $attrName = $xml->localName; + } + $attributes[$attrName] = $xml->value; + } + $this->tag_open(null, $tagName, $attributes); + if ($empty) + { + $this->tag_close(null, $tagName); + } + break; + case constant('XMLReader::TEXT'): + + case constant('XMLReader::CDATA'): + $this->cdata(null, $xml->value); + break; + } + } + if ($error = libxml_get_last_error()) + { + $this->error_code = $error->code; + $this->error_string = $error->message; + $this->current_line = $error->line; + $this->current_column = $error->column; + return false; + } + else + { + return true; + } + } + } + + public function get_error_code() + { + return $this->error_code; + } + + public function get_error_string() + { + return $this->error_string; + } + + public function get_current_line() + { + return $this->current_line; + } + + public function get_current_column() + { + return $this->current_column; + } + + public function get_current_byte() + { + return $this->current_byte; + } + + public function get_data() + { + return $this->data; + } + + public function tag_open($parser, $tag, $attributes) + { + list($this->namespace[], $this->element[]) = $this->split_ns($tag); + + $attribs = array(); + foreach ($attributes as $name => $value) + { + list($attrib_namespace, $attribute) = $this->split_ns($name); + $attribs[$attrib_namespace][$attribute] = $value; + } + + if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base'])) + { + $base = $this->registry->call('Misc', 'absolutize_url', array($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base))); + if ($base !== false) + { + $this->xml_base[] = $base; + $this->xml_base_explicit[] = true; + } + } + else + { + $this->xml_base[] = end($this->xml_base); + $this->xml_base_explicit[] = end($this->xml_base_explicit); + } + + if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang'])) + { + $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang']; + } + else + { + $this->xml_lang[] = end($this->xml_lang); + } + + if ($this->current_xhtml_construct >= 0) + { + $this->current_xhtml_construct++; + if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML) + { + $this->data['data'] .= '<' . end($this->element); + if (isset($attribs[''])) + { + foreach ($attribs[''] as $name => $value) + { + $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"'; + } + } + $this->data['data'] .= '>'; + } + } + else + { + $this->datas[] =& $this->data; + $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][]; + $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang)); + if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml') + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml') + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_20 && in_array(end($this->element), array('title'))) + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_090 && in_array(end($this->element), array('title'))) + || (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_10 && in_array(end($this->element), array('title')))) + { + $this->current_xhtml_construct = 0; + } + } + } + + public function cdata($parser, $cdata) + { + if ($this->current_xhtml_construct >= 0) + { + $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding); + } + else + { + $this->data['data'] .= $cdata; + } + } + + public function tag_close($parser, $tag) + { + if ($this->current_xhtml_construct >= 0) + { + $this->current_xhtml_construct--; + if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'))) + { + $this->data['data'] .= '</' . end($this->element) . '>'; + } + } + if ($this->current_xhtml_construct === -1) + { + $this->data =& $this->datas[count($this->datas) - 1]; + array_pop($this->datas); + } + + array_pop($this->element); + array_pop($this->namespace); + array_pop($this->xml_base); + array_pop($this->xml_base_explicit); + array_pop($this->xml_lang); + } + + public function split_ns($string) + { + static $cache = array(); + if (!isset($cache[$string])) + { + if ($pos = strpos($string, $this->separator)) + { + static $separator_length; + if (!$separator_length) + { + $separator_length = strlen($this->separator); + } + $namespace = substr($string, 0, $pos); + $local_name = substr($string, $pos + $separator_length); + if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES) + { + $namespace = SIMPLEPIE_NAMESPACE_ITUNES; + } + + // Normalize the Media RSS namespaces + if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 || + $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 ) + { + $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS; + } + $cache[$string] = array($namespace, $local_name); + } + else + { + $cache[$string] = array('', $string); + } + } + return $cache[$string]; + } +} diff --git a/sources/wp-includes/SimplePie/Rating.php b/sources/wp-includes/SimplePie/Rating.php new file mode 100644 index 0000000..8689e5d --- /dev/null +++ b/sources/wp-includes/SimplePie/Rating.php @@ -0,0 +1,129 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively + * + * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()} + * + * This class can be overloaded with {@see SimplePie::set_rating_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Rating +{ + /** + * Rating scheme + * + * @var string + * @see get_scheme() + */ + var $scheme; + + /** + * Rating value + * + * @var string + * @see get_value() + */ + var $value; + + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($scheme = null, $value = null) + { + $this->scheme = $scheme; + $this->value = $value; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the organizational scheme for the rating + * + * @return string|null + */ + public function get_scheme() + { + if ($this->scheme !== null) + { + return $this->scheme; + } + else + { + return null; + } + } + + /** + * Get the value of the rating + * + * @return string|null + */ + public function get_value() + { + if ($this->value !== null) + { + return $this->value; + } + else + { + return null; + } + } +} diff --git a/sources/wp-includes/SimplePie/Registry.php b/sources/wp-includes/SimplePie/Registry.php new file mode 100644 index 0000000..1072cde --- /dev/null +++ b/sources/wp-includes/SimplePie/Registry.php @@ -0,0 +1,225 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Handles creating objects and calling methods + * + * Access this via {@see SimplePie::get_registry()} + * + * @package SimplePie + */ +class SimplePie_Registry +{ + /** + * Default class mapping + * + * Overriding classes *must* subclass these. + * + * @var array + */ + protected $default = array( + 'Cache' => 'SimplePie_Cache', + 'Locator' => 'SimplePie_Locator', + 'Parser' => 'SimplePie_Parser', + 'File' => 'SimplePie_File', + 'Sanitize' => 'SimplePie_Sanitize', + 'Item' => 'SimplePie_Item', + 'Author' => 'SimplePie_Author', + 'Category' => 'SimplePie_Category', + 'Enclosure' => 'SimplePie_Enclosure', + 'Caption' => 'SimplePie_Caption', + 'Copyright' => 'SimplePie_Copyright', + 'Credit' => 'SimplePie_Credit', + 'Rating' => 'SimplePie_Rating', + 'Restriction' => 'SimplePie_Restriction', + 'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer', + 'Source' => 'SimplePie_Source', + 'Misc' => 'SimplePie_Misc', + 'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser', + 'Parse_Date' => 'SimplePie_Parse_Date', + ); + + /** + * Class mapping + * + * @see register() + * @var array + */ + protected $classes = array(); + + /** + * Legacy classes + * + * @see register() + * @var array + */ + protected $legacy = array(); + + /** + * Constructor + * + * No-op + */ + public function __construct() { } + + /** + * Register a class + * + * @param string $type See {@see $default} for names + * @param string $class Class name, must subclass the corresponding default + * @param bool $legacy Whether to enable legacy support for this class + * @return bool Successfulness + */ + public function register($type, $class, $legacy = false) + { + if (!is_subclass_of($class, $this->default[$type])) + { + return false; + } + + $this->classes[$type] = $class; + + if ($legacy) + { + $this->legacy[] = $class; + } + + return true; + } + + /** + * Get the class registered for a type + * + * Where possible, use {@see create()} or {@see call()} instead + * + * @param string $type + * @return string|null + */ + public function get_class($type) + { + if (!empty($this->classes[$type])) + { + return $this->classes[$type]; + } + if (!empty($this->default[$type])) + { + return $this->default[$type]; + } + + return null; + } + + /** + * Create a new instance of a given type + * + * @param string $type + * @param array $parameters Parameters to pass to the constructor + * @return object Instance of class + */ + public function &create($type, $parameters = array()) + { + $class = $this->get_class($type); + + if (in_array($class, $this->legacy)) + { + switch ($type) + { + case 'locator': + // Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class + // Specified: file, timeout, useragent, max_checked_feeds + $replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer')); + array_splice($parameters, 3, 1, $replacement); + break; + } + } + + if (!method_exists($class, '__construct')) + { + $instance = new $class; + } + else + { + $reflector = new ReflectionClass($class); + $instance = $reflector->newInstanceArgs($parameters); + } + + if (method_exists($instance, 'set_registry')) + { + $instance->set_registry($this); + } + return $instance; + } + + /** + * Call a static method for a type + * + * @param string $type + * @param string $method + * @param array $parameters + * @return mixed + */ + public function &call($type, $method, $parameters = array()) + { + $class = $this->get_class($type); + + if (in_array($class, $this->legacy)) + { + switch ($type) + { + case 'Cache': + // For backwards compatibility with old non-static + // Cache::create() methods + if ($method === 'get_handler') + { + $result = @call_user_func_array(array($class, 'create'), $parameters); + return $result; + } + break; + } + } + + $result = call_user_func_array(array($class, $method), $parameters); + return $result; + } +} \ No newline at end of file diff --git a/sources/wp-includes/SimplePie/Restriction.php b/sources/wp-includes/SimplePie/Restriction.php new file mode 100644 index 0000000..4ba371b --- /dev/null +++ b/sources/wp-includes/SimplePie/Restriction.php @@ -0,0 +1,155 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Handles `<media:restriction>` as defined in Media RSS + * + * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()} + * + * This class can be overloaded with {@see SimplePie::set_restriction_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Restriction +{ + /** + * Relationship ('allow'/'deny') + * + * @var string + * @see get_relationship() + */ + var $relationship; + + /** + * Type of restriction + * + * @var string + * @see get_type() + */ + var $type; + + /** + * Restricted values + * + * @var string + * @see get_value() + */ + var $value; + + /** + * Constructor, used to input the data + * + * For documentation on all the parameters, see the corresponding + * properties and their accessors + */ + public function __construct($relationship = null, $type = null, $value = null) + { + $this->relationship = $relationship; + $this->type = $type; + $this->value = $value; + } + + /** + * String-ified version + * + * @return string + */ + public function __toString() + { + // There is no $this->data here + return md5(serialize($this)); + } + + /** + * Get the relationship + * + * @return string|null Either 'allow' or 'deny' + */ + public function get_relationship() + { + if ($this->relationship !== null) + { + return $this->relationship; + } + else + { + return null; + } + } + + /** + * Get the type + * + * @return string|null + */ + public function get_type() + { + if ($this->type !== null) + { + return $this->type; + } + else + { + return null; + } + } + + /** + * Get the list of restricted things + * + * @return string|null + */ + public function get_value() + { + if ($this->value !== null) + { + return $this->value; + } + else + { + return null; + } + } +} diff --git a/sources/wp-includes/SimplePie/Sanitize.php b/sources/wp-includes/SimplePie/Sanitize.php new file mode 100644 index 0000000..1ce047a --- /dev/null +++ b/sources/wp-includes/SimplePie/Sanitize.php @@ -0,0 +1,554 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Used for data cleanup and post-processing + * + * + * This class can be overloaded with {@see SimplePie::set_sanitize_class()} + * + * @package SimplePie + * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags + */ +class SimplePie_Sanitize +{ + // Private vars + var $base; + + // Options + var $remove_div = true; + var $image_handler = ''; + var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); + var $encode_instead_of_strip = false; + var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + var $strip_comments = false; + var $output_encoding = 'UTF-8'; + var $enable_cache = true; + var $cache_location = './cache'; + var $cache_name_function = 'md5'; + var $timeout = 10; + var $useragent = ''; + var $force_fsockopen = false; + var $replace_url_attributes = null; + + public function __construct() + { + // Set defaults + $this->set_url_replacements(null); + } + + public function remove_div($enable = true) + { + $this->remove_div = (bool) $enable; + } + + public function set_image_handler($page = false) + { + if ($page) + { + $this->image_handler = (string) $page; + } + else + { + $this->image_handler = false; + } + } + + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } + + public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache') + { + if (isset($enable_cache)) + { + $this->enable_cache = (bool) $enable_cache; + } + + if ($cache_location) + { + $this->cache_location = (string) $cache_location; + } + + if ($cache_name_function) + { + $this->cache_name_function = (string) $cache_name_function; + } + } + + public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false) + { + if ($timeout) + { + $this->timeout = (string) $timeout; + } + + if ($useragent) + { + $this->useragent = (string) $useragent; + } + + if ($force_fsockopen) + { + $this->force_fsockopen = (string) $force_fsockopen; + } + } + + public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style')) + { + if ($tags) + { + if (is_array($tags)) + { + $this->strip_htmltags = $tags; + } + else + { + $this->strip_htmltags = explode(',', $tags); + } + } + else + { + $this->strip_htmltags = false; + } + } + + public function encode_instead_of_strip($encode = false) + { + $this->encode_instead_of_strip = (bool) $encode; + } + + public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc')) + { + if ($attribs) + { + if (is_array($attribs)) + { + $this->strip_attributes = $attribs; + } + else + { + $this->strip_attributes = explode(',', $attribs); + } + } + else + { + $this->strip_attributes = false; + } + } + + public function strip_comments($strip = false) + { + $this->strip_comments = (bool) $strip; + } + + public function set_output_encoding($encoding = 'UTF-8') + { + $this->output_encoding = (string) $encoding; + } + + /** + * Set element/attribute key/value pairs of HTML attributes + * containing URLs that need to be resolved relative to the feed + * + * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite, + * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite, + * |q|@cite + * + * @since 1.0 + * @param array|null $element_attribute Element/attribute key/value pairs, null for default + */ + public function set_url_replacements($element_attribute = null) + { + if ($element_attribute === null) + { + $element_attribute = array( + 'a' => 'href', + 'area' => 'href', + 'blockquote' => 'cite', + 'del' => 'cite', + 'form' => 'action', + 'img' => array( + 'longdesc', + 'src' + ), + 'input' => 'src', + 'ins' => 'cite', + 'q' => 'cite' + ); + } + $this->replace_url_attributes = (array) $element_attribute; + } + + public function sanitize($data, $type, $base = '') + { + $data = trim($data); + if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI) + { + if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML) + { + if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) + { + $type |= SIMPLEPIE_CONSTRUCT_HTML; + } + else + { + $type |= SIMPLEPIE_CONSTRUCT_TEXT; + } + } + + if ($type & SIMPLEPIE_CONSTRUCT_BASE64) + { + $data = base64_decode($data); + } + + if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML)) + { + + if (!class_exists('DOMDocument')) + { + $this->registry->call('Misc', 'error', array('DOMDocument not found, unable to use sanitizer', E_USER_WARNING, __FILE__, __LINE__)); + return ''; + } + $document = new DOMDocument(); + $document->encoding = 'UTF-8'; + $data = $this->preprocess($data, $type); + + set_error_handler(array('SimplePie_Misc', 'silence_errors')); + $document->loadHTML($data); + restore_error_handler(); + + // Strip comments + if ($this->strip_comments) + { + $xpath = new DOMXPath($document); + $comments = $xpath->query('//comment()'); + + foreach ($comments as $comment) + { + $comment->parentNode->removeChild($comment); + } + } + + // Strip out HTML tags and attributes that might cause various security problems. + // Based on recommendations by Mark Pilgrim at: + // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely + if ($this->strip_htmltags) + { + foreach ($this->strip_htmltags as $tag) + { + $this->strip_tag($tag, $document, $type); + } + } + + if ($this->strip_attributes) + { + foreach ($this->strip_attributes as $attrib) + { + $this->strip_attr($attrib, $document); + } + } + + // Replace relative URLs + $this->base = $base; + foreach ($this->replace_url_attributes as $element => $attributes) + { + $this->replace_urls($document, $element, $attributes); + } + + // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags. + if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache) + { + $images = $document->getElementsByTagName('img'); + foreach ($images as $img) + { + if ($img->hasAttribute('src')) + { + $image_url = call_user_func($this->cache_name_function, $img->getAttribute('src')); + $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $image_url, 'spi')); + + if ($cache->load()) + { + $img->setAttribute('src', $this->image_handler . $image_url); + } + else + { + $file = $this->registry->create('File', array($img->getAttribute('src'), $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen)); + $headers = $file->headers; + + if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) + { + if ($cache->save(array('headers' => $file->headers, 'body' => $file->body))) + { + $img->setAttribute('src', $this->image_handler . $image_url); + } + else + { + trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); + } + } + } + } + } + } + + // Remove the DOCTYPE + // Seems to cause segfaulting if we don't do this + if ($document->firstChild instanceof DOMDocumentType) + { + $document->removeChild($document->firstChild); + } + + // Move everything from the body to the root + $real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0); + $document->replaceChild($real_body, $document->firstChild); + + // Finally, convert to a HTML string + $data = trim($document->saveHTML()); + + if ($this->remove_div) + { + $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data); + $data = preg_replace('/<\/div>$/', '', $data); + } + else + { + $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data); + } + } + + if ($type & SIMPLEPIE_CONSTRUCT_IRI) + { + $absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base)); + if ($absolute !== false) + { + $data = $absolute; + } + } + + if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI)) + { + $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8'); + } + + if ($this->output_encoding !== 'UTF-8') + { + $data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding)); + } + } + return $data; + } + + protected function preprocess($html, $type) + { + $ret = ''; + if ($type & ~SIMPLEPIE_CONSTRUCT_XHTML) + { + // Atom XHTML constructs are wrapped with a div by default + // Note: No protection if $html contains a stray </div>! + $html = '<div>' . $html . '</div>'; + $ret .= '<!DOCTYPE html>'; + $content_type = 'text/html'; + } + else + { + $ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; + $content_type = 'application/xhtml+xml'; + } + + $ret .= '<html><head>'; + $ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />'; + $ret .= '</head><body>' . $html . '</body></html>'; + return $ret; + } + + public function replace_urls($document, $tag, $attributes) + { + if (!is_array($attributes)) + { + $attributes = array($attributes); + } + + if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags)) + { + $elements = $document->getElementsByTagName($tag); + foreach ($elements as $element) + { + foreach ($attributes as $attribute) + { + if ($element->hasAttribute($attribute)) + { + $value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base)); + if ($value !== false) + { + $element->setAttribute($attribute, $value); + } + } + } + } + } + } + + public function do_strip_htmltags($match) + { + if ($this->encode_instead_of_strip) + { + if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style'))) + { + $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8'); + $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8'); + return "<$match[1]$match[2]>$match[3]</$match[1]>"; + } + else + { + return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8'); + } + } + elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style'))) + { + return $match[4]; + } + else + { + return ''; + } + } + + protected function strip_tag($tag, $document, $type) + { + $xpath = new DOMXPath($document); + $elements = $xpath->query('body//' . $tag); + if ($this->encode_instead_of_strip) + { + foreach ($elements as $element) + { + $fragment = $document->createDocumentFragment(); + + // For elements which aren't script or style, include the tag itself + if (!in_array($tag, array('script', 'style'))) + { + $text = '<' . $tag; + if ($element->hasAttributes()) + { + $attrs = array(); + foreach ($element->attributes as $name => $attr) + { + $value = $attr->value; + + // In XHTML, empty values should never exist, so we repeat the value + if (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML)) + { + $value = $name; + } + // For HTML, empty is fine + elseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML)) + { + $attrs[] = $name; + continue; + } + + // Standard attribute text + $attrs[] = $name . '="' . $attr->value . '"'; + } + $text .= ' ' . implode(' ', $attrs); + } + $text .= '>'; + $fragment->appendChild(new DOMText($text)); + } + + $number = $element->childNodes->length; + for ($i = $number; $i > 0; $i--) + { + $child = $element->childNodes->item(0); + $fragment->appendChild($child); + } + + if (!in_array($tag, array('script', 'style'))) + { + $fragment->appendChild(new DOMText('</' . $tag . '>')); + } + + $element->parentNode->replaceChild($fragment, $element); + } + + return; + } + elseif (in_array($tag, array('script', 'style'))) + { + foreach ($elements as $element) + { + $element->parentNode->removeChild($element); + } + + return; + } + else + { + foreach ($elements as $element) + { + $fragment = $document->createDocumentFragment(); + $number = $element->childNodes->length; + for ($i = $number; $i > 0; $i--) + { + $child = $element->childNodes->item(0); + $fragment->appendChild($child); + } + + $element->parentNode->replaceChild($fragment, $element); + } + } + } + + protected function strip_attr($attrib, $document) + { + $xpath = new DOMXPath($document); + $elements = $xpath->query('//*[@' . $attrib . ']'); + + foreach ($elements as $element) + { + $element->removeAttribute($attrib); + } + } +} diff --git a/sources/wp-includes/SimplePie/Source.php b/sources/wp-includes/SimplePie/Source.php new file mode 100644 index 0000000..51d8e6c --- /dev/null +++ b/sources/wp-includes/SimplePie/Source.php @@ -0,0 +1,611 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * Handles `<atom:source>` + * + * Used by {@see SimplePie_Item::get_source()} + * + * This class can be overloaded with {@see SimplePie::set_source_class()} + * + * @package SimplePie + * @subpackage API + */ +class SimplePie_Source +{ + var $item; + var $data = array(); + protected $registry; + + public function __construct($item, $data) + { + $this->item = $item; + $this->data = $data; + } + + public function set_registry(SimplePie_Registry $registry) + { + $this->registry = $registry; + } + + public function __toString() + { + return md5(serialize($this->data)); + } + + public function get_source_tags($namespace, $tag) + { + if (isset($this->data['child'][$namespace][$tag])) + { + return $this->data['child'][$namespace][$tag]; + } + else + { + return null; + } + } + + public function get_base($element = array()) + { + return $this->item->get_base($element); + } + + public function sanitize($data, $type, $base = '') + { + return $this->item->sanitize($data, $type, $base); + } + + public function get_item() + { + return $this->item; + } + + public function get_title() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_category($key = 0) + { + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } + } + + public function get_categories() + { + $categories = array(); + + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) + { + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + { + // This is really the label, but keep this as the term also for BC. + // Label will also work on retrieving because that falls back to term. + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = null; + } + $categories[] = $this->registry->create('Category', array($term, $scheme, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($categories)) + { + return array_unique($categories); + } + else + { + return null; + } + } + + public function get_author($key = 0) + { + $authors = $this->get_authors(); + if (isset($authors[$key])) + { + return $authors[$key]; + } + else + { + return null; + } + } + + public function get_authors() + { + $authors = array(); + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) + { + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $authors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) + { + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = $this->registry->create('Author', array($name, $url, $email)); + } + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($authors)) + { + return array_unique($authors); + } + else + { + return null; + } + } + + public function get_contributor($key = 0) + { + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) + { + return $contributors[$key]; + } + else + { + return null; + } + } + + public function get_contributors() + { + $contributors = array(); + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) + { + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) + { + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $url, $email)); + } + } + + if (!empty($contributors)) + { + return array_unique($contributors); + } + else + { + return null; + } + } + + public function get_link($key = 0, $rel = 'alternate') + { + $links = $this->get_links($rel); + if (isset($links[$key])) + { + return $links[$key]; + } + else + { + return null; + } + } + + /** + * Added for parity between the parent-level and the item/entry-level. + */ + public function get_permalink() + { + return $this->get_link(0); + } + + public function get_links($rel = 'alternate') + { + if (!isset($this->data['links'])) + { + $this->data['links'] = array(); + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link')) + { + foreach ($links as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } + } + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link')) + { + foreach ($links as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + + } + } + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + + $keys = array_keys($this->data['links']); + foreach ($keys as $key) + { + if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key))) + { + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; + } + else + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } + } + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) + { + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; + } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); + } + } + + if (isset($this->data['links'][$rel])) + { + return $this->data['links'][$rel]; + } + else + { + return null; + } + } + + public function get_description() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + else + { + return null; + } + } + + public function get_copyright() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_language() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['xml_lang'])) + { + return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + public function get_latitude() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[1]; + } + else + { + return null; + } + } + + public function get_longitude() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) + { + return (float) $return[0]['data']; + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[2]; + } + else + { + return null; + } + } + + public function get_image_url() + { + if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image')) + { + return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + else + { + return null; + } + } +} + diff --git a/sources/wp-includes/SimplePie/XML/Declaration/Parser.php b/sources/wp-includes/SimplePie/XML/Declaration/Parser.php new file mode 100644 index 0000000..aec19f1 --- /dev/null +++ b/sources/wp-includes/SimplePie/XML/Declaration/Parser.php @@ -0,0 +1,362 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + + +/** + * Parses the XML Declaration + * + * @package SimplePie + * @subpackage Parsing + */ +class SimplePie_XML_Declaration_Parser +{ + /** + * XML Version + * + * @access public + * @var string + */ + var $version = '1.0'; + + /** + * Encoding + * + * @access public + * @var string + */ + var $encoding = 'UTF-8'; + + /** + * Standalone + * + * @access public + * @var bool + */ + var $standalone = false; + + /** + * Current state of the state machine + * + * @access private + * @var string + */ + var $state = 'before_version_name'; + + /** + * Input data + * + * @access private + * @var string + */ + var $data = ''; + + /** + * Input data length (to avoid calling strlen() everytime this is needed) + * + * @access private + * @var int + */ + var $data_length = 0; + + /** + * Current position of the pointer + * + * @var int + * @access private + */ + var $position = 0; + + /** + * Create an instance of the class with the input data + * + * @access public + * @param string $data Input data + */ + public function __construct($data) + { + $this->data = $data; + $this->data_length = strlen($this->data); + } + + /** + * Parse the input data + * + * @access public + * @return bool true on success, false on failure + */ + public function parse() + { + while ($this->state && $this->state !== 'emit' && $this->has_data()) + { + $state = $this->state; + $this->$state(); + } + $this->data = ''; + if ($this->state === 'emit') + { + return true; + } + else + { + $this->version = ''; + $this->encoding = ''; + $this->standalone = ''; + return false; + } + } + + /** + * Check whether there is data beyond the pointer + * + * @access private + * @return bool true if there is further data, false if not + */ + public function has_data() + { + return (bool) ($this->position < $this->data_length); + } + + /** + * Advance past any whitespace + * + * @return int Number of whitespace characters passed + */ + public function skip_whitespace() + { + $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position); + $this->position += $whitespace; + return $whitespace; + } + + /** + * Read value + */ + public function get_value() + { + $quote = substr($this->data, $this->position, 1); + if ($quote === '"' || $quote === "'") + { + $this->position++; + $len = strcspn($this->data, $quote, $this->position); + if ($this->has_data()) + { + $value = substr($this->data, $this->position, $len); + $this->position += $len + 1; + return $value; + } + } + return false; + } + + public function before_version_name() + { + if ($this->skip_whitespace()) + { + $this->state = 'version_name'; + } + else + { + $this->state = false; + } + } + + public function version_name() + { + if (substr($this->data, $this->position, 7) === 'version') + { + $this->position += 7; + $this->skip_whitespace(); + $this->state = 'version_equals'; + } + else + { + $this->state = false; + } + } + + public function version_equals() + { + if (substr($this->data, $this->position, 1) === '=') + { + $this->position++; + $this->skip_whitespace(); + $this->state = 'version_value'; + } + else + { + $this->state = false; + } + } + + public function version_value() + { + if ($this->version = $this->get_value()) + { + $this->skip_whitespace(); + if ($this->has_data()) + { + $this->state = 'encoding_name'; + } + else + { + $this->state = 'emit'; + } + } + else + { + $this->state = false; + } + } + + public function encoding_name() + { + if (substr($this->data, $this->position, 8) === 'encoding') + { + $this->position += 8; + $this->skip_whitespace(); + $this->state = 'encoding_equals'; + } + else + { + $this->state = 'standalone_name'; + } + } + + public function encoding_equals() + { + if (substr($this->data, $this->position, 1) === '=') + { + $this->position++; + $this->skip_whitespace(); + $this->state = 'encoding_value'; + } + else + { + $this->state = false; + } + } + + public function encoding_value() + { + if ($this->encoding = $this->get_value()) + { + $this->skip_whitespace(); + if ($this->has_data()) + { + $this->state = 'standalone_name'; + } + else + { + $this->state = 'emit'; + } + } + else + { + $this->state = false; + } + } + + public function standalone_name() + { + if (substr($this->data, $this->position, 10) === 'standalone') + { + $this->position += 10; + $this->skip_whitespace(); + $this->state = 'standalone_equals'; + } + else + { + $this->state = false; + } + } + + public function standalone_equals() + { + if (substr($this->data, $this->position, 1) === '=') + { + $this->position++; + $this->skip_whitespace(); + $this->state = 'standalone_value'; + } + else + { + $this->state = false; + } + } + + public function standalone_value() + { + if ($standalone = $this->get_value()) + { + switch ($standalone) + { + case 'yes': + $this->standalone = true; + break; + + case 'no': + $this->standalone = false; + break; + + default: + $this->state = false; + return; + } + + $this->skip_whitespace(); + if ($this->has_data()) + { + $this->state = false; + } + else + { + $this->state = 'emit'; + } + } + else + { + $this->state = false; + } + } +} diff --git a/sources/wp-includes/SimplePie/gzdecode.php b/sources/wp-includes/SimplePie/gzdecode.php new file mode 100644 index 0000000..52e024e --- /dev/null +++ b/sources/wp-includes/SimplePie/gzdecode.php @@ -0,0 +1,371 @@ +<?php +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + + +/** + * Decode 'gzip' encoded HTTP data + * + * @package SimplePie + * @subpackage HTTP + * @link http://www.gzip.org/format.txt + */ +class SimplePie_gzdecode +{ + /** + * Compressed data + * + * @access private + * @var string + * @see gzdecode::$data + */ + var $compressed_data; + + /** + * Size of compressed data + * + * @access private + * @var int + */ + var $compressed_size; + + /** + * Minimum size of a valid gzip string + * + * @access private + * @var int + */ + var $min_compressed_size = 18; + + /** + * Current position of pointer + * + * @access private + * @var int + */ + var $position = 0; + + /** + * Flags (FLG) + * + * @access private + * @var int + */ + var $flags; + + /** + * Uncompressed data + * + * @access public + * @see gzdecode::$compressed_data + * @var string + */ + var $data; + + /** + * Modified time + * + * @access public + * @var int + */ + var $MTIME; + + /** + * Extra Flags + * + * @access public + * @var int + */ + var $XFL; + + /** + * Operating System + * + * @access public + * @var int + */ + var $OS; + + /** + * Subfield ID 1 + * + * @access public + * @see gzdecode::$extra_field + * @see gzdecode::$SI2 + * @var string + */ + var $SI1; + + /** + * Subfield ID 2 + * + * @access public + * @see gzdecode::$extra_field + * @see gzdecode::$SI1 + * @var string + */ + var $SI2; + + /** + * Extra field content + * + * @access public + * @see gzdecode::$SI1 + * @see gzdecode::$SI2 + * @var string + */ + var $extra_field; + + /** + * Original filename + * + * @access public + * @var string + */ + var $filename; + + /** + * Human readable comment + * + * @access public + * @var string + */ + var $comment; + + /** + * Don't allow anything to be set + * + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + trigger_error("Cannot write property $name", E_USER_ERROR); + } + + /** + * Set the compressed string and related properties + * + * @param string $data + */ + public function __construct($data) + { + $this->compressed_data = $data; + $this->compressed_size = strlen($data); + } + + /** + * Decode the GZIP stream + * + * @return bool Successfulness + */ + public function parse() + { + if ($this->compressed_size >= $this->min_compressed_size) + { + // Check ID1, ID2, and CM + if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08") + { + return false; + } + + // Get the FLG (FLaGs) + $this->flags = ord($this->compressed_data[3]); + + // FLG bits above (1 << 4) are reserved + if ($this->flags > 0x1F) + { + return false; + } + + // Advance the pointer after the above + $this->position += 4; + + // MTIME + $mtime = substr($this->compressed_data, $this->position, 4); + // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness + if (current(unpack('S', "\x00\x01")) === 1) + { + $mtime = strrev($mtime); + } + $this->MTIME = current(unpack('l', $mtime)); + $this->position += 4; + + // Get the XFL (eXtra FLags) + $this->XFL = ord($this->compressed_data[$this->position++]); + + // Get the OS (Operating System) + $this->OS = ord($this->compressed_data[$this->position++]); + + // Parse the FEXTRA + if ($this->flags & 4) + { + // Read subfield IDs + $this->SI1 = $this->compressed_data[$this->position++]; + $this->SI2 = $this->compressed_data[$this->position++]; + + // SI2 set to zero is reserved for future use + if ($this->SI2 === "\x00") + { + return false; + } + + // Get the length of the extra field + $len = current(unpack('v', substr($this->compressed_data, $this->position, 2))); + $this->position += 2; + + // Check the length of the string is still valid + $this->min_compressed_size += $len + 4; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Set the extra field to the given data + $this->extra_field = substr($this->compressed_data, $this->position, $len); + $this->position += $len; + } + else + { + return false; + } + } + + // Parse the FNAME + if ($this->flags & 8) + { + // Get the length of the filename + $len = strcspn($this->compressed_data, "\x00", $this->position); + + // Check the length of the string is still valid + $this->min_compressed_size += $len + 1; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Set the original filename to the given string + $this->filename = substr($this->compressed_data, $this->position, $len); + $this->position += $len + 1; + } + else + { + return false; + } + } + + // Parse the FCOMMENT + if ($this->flags & 16) + { + // Get the length of the comment + $len = strcspn($this->compressed_data, "\x00", $this->position); + + // Check the length of the string is still valid + $this->min_compressed_size += $len + 1; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Set the original comment to the given string + $this->comment = substr($this->compressed_data, $this->position, $len); + $this->position += $len + 1; + } + else + { + return false; + } + } + + // Parse the FHCRC + if ($this->flags & 2) + { + // Check the length of the string is still valid + $this->min_compressed_size += $len + 2; + if ($this->compressed_size >= $this->min_compressed_size) + { + // Read the CRC + $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2))); + + // Check the CRC matches + if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc) + { + $this->position += 2; + } + else + { + return false; + } + } + else + { + return false; + } + } + + // Decompress the actual data + if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false) + { + return false; + } + else + { + $this->position = $this->compressed_size - 8; + } + + // Check CRC of data + $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4))); + $this->position += 4; + /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc)) + { + return false; + }*/ + + // Check ISIZE of data + $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4))); + $this->position += 4; + if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize)) + { + return false; + } + + // Wow, against all odds, we've actually got a valid gzip string + return true; + } + else + { + return false; + } + } +} diff --git a/sources/wp-includes/Text/Diff.php b/sources/wp-includes/Text/Diff.php new file mode 100644 index 0000000..dc24b67 --- /dev/null +++ b/sources/wp-includes/Text/Diff.php @@ -0,0 +1,450 @@ +<?php +/** + * General API for generating and formatting diffs - the differences between + * two sequences of strings. + * + * The original PHP version of this code was written by Geoffrey T. Dairiki + * <dairiki@dairiki.org>, and is used/adapted with his permission. + * + * Copyright 2004 Geoffrey T. Dairiki <dairiki@dairiki.org> + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + */ +class Text_Diff { + + /** + * Array of changes. + * + * @var array + */ + var $_edits; + + /** + * Computes diffs between sequences of strings. + * + * @param string $engine Name of the diffing engine to use. 'auto' + * will automatically select the best. + * @param array $params Parameters to pass to the diffing engine. + * Normally an array of two arrays, each + * containing the lines from a file. + */ + function Text_Diff($engine, $params) + { + // Backward compatibility workaround. + if (!is_string($engine)) { + $params = array($engine, $params); + $engine = 'auto'; + } + + if ($engine == 'auto') { + $engine = extension_loaded('xdiff') ? 'xdiff' : 'native'; + } else { + $engine = basename($engine); + } + + // WP #7391 + require_once dirname(__FILE__).'/Diff/Engine/' . $engine . '.php'; + $class = 'Text_Diff_Engine_' . $engine; + $diff_engine = new $class(); + + $this->_edits = call_user_func_array(array($diff_engine, 'diff'), $params); + } + + /** + * Returns the array of differences. + */ + function getDiff() + { + return $this->_edits; + } + + /** + * returns the number of new (added) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * + * @return integer The number of new lines + */ + function countAddedLines() + { + $count = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_add') || + is_a($edit, 'Text_Diff_Op_change')) { + $count += $edit->nfinal(); + } + } + return $count; + } + + /** + * Returns the number of deleted (removed) lines in a given diff. + * + * @since Text_Diff 1.1.0 + * + * @return integer The number of deleted lines + */ + function countDeletedLines() + { + $count = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_delete') || + is_a($edit, 'Text_Diff_Op_change')) { + $count += $edit->norig(); + } + } + return $count; + } + + /** + * Computes a reversed diff. + * + * Example: + * <code> + * $diff = new Text_Diff($lines1, $lines2); + * $rev = $diff->reverse(); + * </code> + * + * @return Text_Diff A Diff object representing the inverse of the + * original diff. Note that we purposely don't return a + * reference here, since this essentially is a clone() + * method. + */ + function reverse() + { + if (version_compare(zend_version(), '2', '>')) { + $rev = clone($this); + } else { + $rev = $this; + } + $rev->_edits = array(); + foreach ($this->_edits as $edit) { + $rev->_edits[] = $edit->reverse(); + } + return $rev; + } + + /** + * Checks for an empty diff. + * + * @return boolean True if two sequences were identical. + */ + function isEmpty() + { + foreach ($this->_edits as $edit) { + if (!is_a($edit, 'Text_Diff_Op_copy')) { + return false; + } + } + return true; + } + + /** + * Computes the length of the Longest Common Subsequence (LCS). + * + * This is mostly for diagnostic purposes. + * + * @return integer The length of the LCS. + */ + function lcs() + { + $lcs = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_copy')) { + $lcs += count($edit->orig); + } + } + return $lcs; + } + + /** + * Gets the original set of lines. + * + * This reconstructs the $from_lines parameter passed to the constructor. + * + * @return array The original sequence of strings. + */ + function getOriginal() + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->orig) { + array_splice($lines, count($lines), 0, $edit->orig); + } + } + return $lines; + } + + /** + * Gets the final set of lines. + * + * This reconstructs the $to_lines parameter passed to the constructor. + * + * @return array The sequence of strings. + */ + function getFinal() + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->final) { + array_splice($lines, count($lines), 0, $edit->final); + } + } + return $lines; + } + + /** + * Removes trailing newlines from a line of text. This is meant to be used + * with array_walk(). + * + * @param string $line The line to trim. + * @param integer $key The index of the line in the array. Not used. + */ + static function trimNewlines(&$line, $key) + { + $line = str_replace(array("\n", "\r"), '', $line); + } + + /** + * Determines the location of the system temporary directory. + * + * @static + * + * @access protected + * + * @return string A directory name which can be used for temp files. + * Returns false if one could not be found. + */ + function _getTempDir() + { + $tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp', + 'c:\windows\temp', 'c:\winnt\temp'); + + /* Try PHP's upload_tmp_dir directive. */ + $tmp = ini_get('upload_tmp_dir'); + + /* Otherwise, try to determine the TMPDIR environment variable. */ + if (!strlen($tmp)) { + $tmp = getenv('TMPDIR'); + } + + /* If we still cannot determine a value, then cycle through a list of + * preset possibilities. */ + while (!strlen($tmp) && count($tmp_locations)) { + $tmp_check = array_shift($tmp_locations); + if (@is_dir($tmp_check)) { + $tmp = $tmp_check; + } + } + + /* If it is still empty, we have failed, so return false; otherwise + * return the directory determined. */ + return strlen($tmp) ? $tmp : false; + } + + /** + * Checks a diff for validity. + * + * This is here only for debugging purposes. + */ + function _check($from_lines, $to_lines) + { + if (serialize($from_lines) != serialize($this->getOriginal())) { + trigger_error("Reconstructed original doesn't match", E_USER_ERROR); + } + if (serialize($to_lines) != serialize($this->getFinal())) { + trigger_error("Reconstructed final doesn't match", E_USER_ERROR); + } + + $rev = $this->reverse(); + if (serialize($to_lines) != serialize($rev->getOriginal())) { + trigger_error("Reversed original doesn't match", E_USER_ERROR); + } + if (serialize($from_lines) != serialize($rev->getFinal())) { + trigger_error("Reversed final doesn't match", E_USER_ERROR); + } + + $prevtype = null; + foreach ($this->_edits as $edit) { + if ($prevtype == get_class($edit)) { + trigger_error("Edit sequence is non-optimal", E_USER_ERROR); + } + $prevtype = get_class($edit); + } + + return true; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + */ +class Text_MappedDiff extends Text_Diff { + + /** + * Computes a diff between sequences of strings. + * + * This can be used to compute things like case-insensitve diffs, or diffs + * which ignore changes in white-space. + * + * @param array $from_lines An array of strings. + * @param array $to_lines An array of strings. + * @param array $mapped_from_lines This array should have the same size + * number of elements as $from_lines. The + * elements in $mapped_from_lines and + * $mapped_to_lines are what is actually + * compared when computing the diff. + * @param array $mapped_to_lines This array should have the same number + * of elements as $to_lines. + */ + function Text_MappedDiff($from_lines, $to_lines, + $mapped_from_lines, $mapped_to_lines) + { + assert(count($from_lines) == count($mapped_from_lines)); + assert(count($to_lines) == count($mapped_to_lines)); + + parent::Text_Diff($mapped_from_lines, $mapped_to_lines); + + $xi = $yi = 0; + for ($i = 0; $i < count($this->_edits); $i++) { + $orig = &$this->_edits[$i]->orig; + if (is_array($orig)) { + $orig = array_slice($from_lines, $xi, count($orig)); + $xi += count($orig); + } + + $final = &$this->_edits[$i]->final; + if (is_array($final)) { + $final = array_slice($to_lines, $yi, count($final)); + $yi += count($final); + } + } + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ +class Text_Diff_Op { + + var $orig; + var $final; + + function &reverse() + { + trigger_error('Abstract method', E_USER_ERROR); + } + + function norig() + { + return $this->orig ? count($this->orig) : 0; + } + + function nfinal() + { + return $this->final ? count($this->final) : 0; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ +class Text_Diff_Op_copy extends Text_Diff_Op { + + function Text_Diff_Op_copy($orig, $final = false) + { + if (!is_array($final)) { + $final = $orig; + } + $this->orig = $orig; + $this->final = $final; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_copy($this->final, $this->orig); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ +class Text_Diff_Op_delete extends Text_Diff_Op { + + function Text_Diff_Op_delete($lines) + { + $this->orig = $lines; + $this->final = false; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_add($this->orig); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ +class Text_Diff_Op_add extends Text_Diff_Op { + + function Text_Diff_Op_add($lines) + { + $this->final = $lines; + $this->orig = false; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_delete($this->final); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * + * @access private + */ +class Text_Diff_Op_change extends Text_Diff_Op { + + function Text_Diff_Op_change($orig, $final) + { + $this->orig = $orig; + $this->final = $final; + } + + function &reverse() + { + $reverse = new Text_Diff_Op_change($this->final, $this->orig); + return $reverse; + } + +} diff --git a/sources/wp-includes/Text/Diff/Engine/native.php b/sources/wp-includes/Text/Diff/Engine/native.php new file mode 100644 index 0000000..e908cfe --- /dev/null +++ b/sources/wp-includes/Text/Diff/Engine/native.php @@ -0,0 +1,436 @@ +<?php +/** + * Class used internally by Text_Diff to actually compute the diffs. + * + * This class is implemented using native PHP code. + * + * The algorithm used here is mostly lifted from the perl module + * Algorithm::Diff (version 1.06) by Ned Konz, which is available at: + * http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip + * + * More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html + * + * Some ideas (and a bit of code) are taken from analyze.c, of GNU + * diffutils-2.7, which can be found at: + * ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz + * + * Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from + * Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this + * code was written by him, and is used/adapted with his permission. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Geoffrey T. Dairiki <dairiki@dairiki.org> + * @package Text_Diff + */ +class Text_Diff_Engine_native { + + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + $n_from = count($from_lines); + $n_to = count($to_lines); + + $this->xchanged = $this->ychanged = array(); + $this->xv = $this->yv = array(); + $this->xind = $this->yind = array(); + unset($this->seq); + unset($this->in_seq); + unset($this->lcs); + + // Skip leading common lines. + for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { + if ($from_lines[$skip] !== $to_lines[$skip]) { + break; + } + $this->xchanged[$skip] = $this->ychanged[$skip] = false; + } + + // Skip trailing common lines. + $xi = $n_from; $yi = $n_to; + for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { + if ($from_lines[$xi] !== $to_lines[$yi]) { + break; + } + $this->xchanged[$xi] = $this->ychanged[$yi] = false; + } + + // Ignore lines which do not exist in both files. + for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { + $xhash[$from_lines[$xi]] = 1; + } + for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { + $line = $to_lines[$yi]; + if (($this->ychanged[$yi] = empty($xhash[$line]))) { + continue; + } + $yhash[$line] = 1; + $this->yv[] = $line; + $this->yind[] = $yi; + } + for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { + $line = $from_lines[$xi]; + if (($this->xchanged[$xi] = empty($yhash[$line]))) { + continue; + } + $this->xv[] = $line; + $this->xind[] = $xi; + } + + // Find the LCS. + $this->_compareseq(0, count($this->xv), 0, count($this->yv)); + + // Merge edits when possible. + $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged); + $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged); + + // Compute the edit operations. + $edits = array(); + $xi = $yi = 0; + while ($xi < $n_from || $yi < $n_to) { + assert($yi < $n_to || $this->xchanged[$xi]); + assert($xi < $n_from || $this->ychanged[$yi]); + + // Skip matching "snake". + $copy = array(); + while ($xi < $n_from && $yi < $n_to + && !$this->xchanged[$xi] && !$this->ychanged[$yi]) { + $copy[] = $from_lines[$xi++]; + ++$yi; + } + if ($copy) { + $edits[] = new Text_Diff_Op_copy($copy); + } + + // Find deletes & adds. + $delete = array(); + while ($xi < $n_from && $this->xchanged[$xi]) { + $delete[] = $from_lines[$xi++]; + } + + $add = array(); + while ($yi < $n_to && $this->ychanged[$yi]) { + $add[] = $to_lines[$yi++]; + } + + if ($delete && $add) { + $edits[] = new Text_Diff_Op_change($delete, $add); + } elseif ($delete) { + $edits[] = new Text_Diff_Op_delete($delete); + } elseif ($add) { + $edits[] = new Text_Diff_Op_add($add); + } + } + + return $edits; + } + + /** + * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, + * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized + * segments. + * + * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of + * NCHUNKS+1 (X, Y) indexes giving the diving points between sub + * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), + * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == + * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). + * + * This function assumes that the first lines of the specified portions of + * the two files do not match, and likewise that the last lines do not + * match. The caller must trim matching lines from the beginning and end + * of the portions it is going to specify. + */ + function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) + { + $flip = false; + + if ($xlim - $xoff > $ylim - $yoff) { + /* Things seems faster (I'm not sure I understand why) when the + * shortest sequence is in X. */ + $flip = true; + list ($xoff, $xlim, $yoff, $ylim) + = array($yoff, $ylim, $xoff, $xlim); + } + + if ($flip) { + for ($i = $ylim - 1; $i >= $yoff; $i--) { + $ymatches[$this->xv[$i]][] = $i; + } + } else { + for ($i = $ylim - 1; $i >= $yoff; $i--) { + $ymatches[$this->yv[$i]][] = $i; + } + } + + $this->lcs = 0; + $this->seq[0]= $yoff - 1; + $this->in_seq = array(); + $ymids[0] = array(); + + $numer = $xlim - $xoff + $nchunks - 1; + $x = $xoff; + for ($chunk = 0; $chunk < $nchunks; $chunk++) { + if ($chunk > 0) { + for ($i = 0; $i <= $this->lcs; $i++) { + $ymids[$i][$chunk - 1] = $this->seq[$i]; + } + } + + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); + for (; $x < $x1; $x++) { + $line = $flip ? $this->yv[$x] : $this->xv[$x]; + if (empty($ymatches[$line])) { + continue; + } + $matches = $ymatches[$line]; + reset($matches); + while (list(, $y) = each($matches)) { + if (empty($this->in_seq[$y])) { + $k = $this->_lcsPos($y); + assert($k > 0); + $ymids[$k] = $ymids[$k - 1]; + break; + } + } + while (list(, $y) = each($matches)) { + if ($y > $this->seq[$k - 1]) { + assert($y <= $this->seq[$k]); + /* Optimization: this is a common case: next match is + * just replacing previous match. */ + $this->in_seq[$this->seq[$k]] = false; + $this->seq[$k] = $y; + $this->in_seq[$y] = 1; + } elseif (empty($this->in_seq[$y])) { + $k = $this->_lcsPos($y); + assert($k > 0); + $ymids[$k] = $ymids[$k - 1]; + } + } + } + } + + $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); + $ymid = $ymids[$this->lcs]; + for ($n = 0; $n < $nchunks - 1; $n++) { + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); + $y1 = $ymid[$n] + 1; + $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); + } + $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); + + return array($this->lcs, $seps); + } + + function _lcsPos($ypos) + { + $end = $this->lcs; + if ($end == 0 || $ypos > $this->seq[$end]) { + $this->seq[++$this->lcs] = $ypos; + $this->in_seq[$ypos] = 1; + return $this->lcs; + } + + $beg = 1; + while ($beg < $end) { + $mid = (int)(($beg + $end) / 2); + if ($ypos > $this->seq[$mid]) { + $beg = $mid + 1; + } else { + $end = $mid; + } + } + + assert($ypos != $this->seq[$end]); + + $this->in_seq[$this->seq[$end]] = false; + $this->seq[$end] = $ypos; + $this->in_seq[$ypos] = 1; + return $end; + } + + /** + * Finds LCS of two sequences. + * + * The results are recorded in the vectors $this->{x,y}changed[], by + * storing a 1 in the element for each line that is an insertion or + * deletion (ie. is not in the LCS). + * + * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. + * + * Note that XLIM, YLIM are exclusive bounds. All line numbers are + * origin-0 and discarded lines are not counted. + */ + function _compareseq ($xoff, $xlim, $yoff, $ylim) + { + /* Slide down the bottom initial diagonal. */ + while ($xoff < $xlim && $yoff < $ylim + && $this->xv[$xoff] == $this->yv[$yoff]) { + ++$xoff; + ++$yoff; + } + + /* Slide up the top initial diagonal. */ + while ($xlim > $xoff && $ylim > $yoff + && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) { + --$xlim; + --$ylim; + } + + if ($xoff == $xlim || $yoff == $ylim) { + $lcs = 0; + } else { + /* This is ad hoc but seems to work well. $nchunks = + * sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks = + * max(2,min(8,(int)$nchunks)); */ + $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; + list($lcs, $seps) + = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); + } + + if ($lcs == 0) { + /* X and Y sequences have no common subsequence: mark all + * changed. */ + while ($yoff < $ylim) { + $this->ychanged[$this->yind[$yoff++]] = 1; + } + while ($xoff < $xlim) { + $this->xchanged[$this->xind[$xoff++]] = 1; + } + } else { + /* Use the partitions to split this problem into subproblems. */ + reset($seps); + $pt1 = $seps[0]; + while ($pt2 = next($seps)) { + $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); + $pt1 = $pt2; + } + } + } + + /** + * Adjusts inserts/deletes of identical lines to join changes as much as + * possible. + * + * We do something when a run of changed lines include a line at one end + * and has an excluded, identical line at the other. We are free to + * choose which identical line is included. `compareseq' usually chooses + * the one at the beginning, but usually it is cleaner to consider the + * following identical line to be the "change". + * + * This is extracted verbatim from analyze.c (GNU diffutils-2.7). + */ + function _shiftBoundaries($lines, &$changed, $other_changed) + { + $i = 0; + $j = 0; + + assert('count($lines) == count($changed)'); + $len = count($lines); + $other_len = count($other_changed); + + while (1) { + /* Scan forward to find the beginning of another run of + * changes. Also keep track of the corresponding point in the + * other file. + * + * Throughout this code, $i and $j are adjusted together so that + * the first $i elements of $changed and the first $j elements of + * $other_changed both contain the same number of zeros (unchanged + * lines). + * + * Furthermore, $j is always kept so that $j == $other_len or + * $other_changed[$j] == false. */ + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + + while ($i < $len && ! $changed[$i]) { + assert('$j < $other_len && ! $other_changed[$j]'); + $i++; $j++; + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + } + + if ($i == $len) { + break; + } + + $start = $i; + + /* Find the end of this run of changes. */ + while (++$i < $len && $changed[$i]) { + continue; + } + + do { + /* Record the length of this run of changes, so that we can + * later determine whether the run has grown. */ + $runlength = $i - $start; + + /* Move the changed region back, so long as the previous + * unchanged line matches the last changed one. This merges + * with previous changed regions. */ + while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) { + $changed[--$start] = 1; + $changed[--$i] = false; + while ($start > 0 && $changed[$start - 1]) { + $start--; + } + assert('$j > 0'); + while ($other_changed[--$j]) { + continue; + } + assert('$j >= 0 && !$other_changed[$j]'); + } + + /* Set CORRESPONDING to the end of the changed run, at the + * last point where it corresponds to a changed run in the + * other file. CORRESPONDING == LEN means no such point has + * been found. */ + $corresponding = $j < $other_len ? $i : $len; + + /* Move the changed region forward, so long as the first + * changed line matches the following unchanged one. This + * merges with following changed regions. Do this second, so + * that if there are no merges, the changed region is moved + * forward as far as possible. */ + while ($i < $len && $lines[$start] == $lines[$i]) { + $changed[$start++] = false; + $changed[$i++] = 1; + while ($i < $len && $changed[$i]) { + $i++; + } + + assert('$j < $other_len && ! $other_changed[$j]'); + $j++; + if ($j < $other_len && $other_changed[$j]) { + $corresponding = $i; + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + } + } + } while ($runlength != $i - $start); + + /* If possible, move the fully-merged run of changes back to a + * corresponding run in the other file. */ + while ($corresponding < $i) { + $changed[--$start] = 1; + $changed[--$i] = 0; + assert('$j > 0'); + while ($other_changed[--$j]) { + continue; + } + assert('$j >= 0 && !$other_changed[$j]'); + } + } + } + +} diff --git a/sources/wp-includes/Text/Diff/Engine/shell.php b/sources/wp-includes/Text/Diff/Engine/shell.php new file mode 100644 index 0000000..faf3870 --- /dev/null +++ b/sources/wp-includes/Text/Diff/Engine/shell.php @@ -0,0 +1,162 @@ +<?php +/** + * Class used internally by Diff to actually compute the diffs. + * + * This class uses the Unix `diff` program via shell_exec to compute the + * differences between the two input arrays. + * + * Copyright 2007-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Milian Wolff <mail@milianw.de> + * @package Text_Diff + * @since 0.3.0 + */ +class Text_Diff_Engine_shell { + + /** + * Path to the diff executable + * + * @var string + */ + var $_diffCommand = 'diff'; + + /** + * Returns the array of differences. + * + * @param array $from_lines lines of text from old file + * @param array $to_lines lines of text from new file + * + * @return array all changes made (array with Text_Diff_Op_* objects) + */ + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + $temp_dir = Text_Diff::_getTempDir(); + + // Execute gnu diff or similar to get a standard diff file. + $from_file = tempnam($temp_dir, 'Text_Diff'); + $to_file = tempnam($temp_dir, 'Text_Diff'); + $fp = fopen($from_file, 'w'); + fwrite($fp, implode("\n", $from_lines)); + fclose($fp); + $fp = fopen($to_file, 'w'); + fwrite($fp, implode("\n", $to_lines)); + fclose($fp); + $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file); + unlink($from_file); + unlink($to_file); + + if (is_null($diff)) { + // No changes were made + return array(new Text_Diff_Op_copy($from_lines)); + } + + $from_line_no = 1; + $to_line_no = 1; + $edits = array(); + + // Get changed lines by parsing something like: + // 0a1,2 + // 1,2c4,6 + // 1,5d6 + preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff, + $matches, PREG_SET_ORDER); + + foreach ($matches as $match) { + if (!isset($match[5])) { + // This paren is not set every time (see regex). + $match[5] = false; + } + + if ($match[3] == 'a') { + $from_line_no--; + } + + if ($match[3] == 'd') { + $to_line_no--; + } + + if ($from_line_no < $match[1] || $to_line_no < $match[4]) { + // copied lines + assert('$match[1] - $from_line_no == $match[4] - $to_line_no'); + array_push($edits, + new Text_Diff_Op_copy( + $this->_getLines($from_lines, $from_line_no, $match[1] - 1), + $this->_getLines($to_lines, $to_line_no, $match[4] - 1))); + } + + switch ($match[3]) { + case 'd': + // deleted lines + array_push($edits, + new Text_Diff_Op_delete( + $this->_getLines($from_lines, $from_line_no, $match[2]))); + $to_line_no++; + break; + + case 'c': + // changed lines + array_push($edits, + new Text_Diff_Op_change( + $this->_getLines($from_lines, $from_line_no, $match[2]), + $this->_getLines($to_lines, $to_line_no, $match[5]))); + break; + + case 'a': + // added lines + array_push($edits, + new Text_Diff_Op_add( + $this->_getLines($to_lines, $to_line_no, $match[5]))); + $from_line_no++; + break; + } + } + + if (!empty($from_lines)) { + // Some lines might still be pending. Add them as copied + array_push($edits, + new Text_Diff_Op_copy( + $this->_getLines($from_lines, $from_line_no, + $from_line_no + count($from_lines) - 1), + $this->_getLines($to_lines, $to_line_no, + $to_line_no + count($to_lines) - 1))); + } + + return $edits; + } + + /** + * Get lines from either the old or new text + * + * @access private + * + * @param array &$text_lines Either $from_lines or $to_lines + * @param int &$line_no Current line number + * @param int $end Optional end line, when we want to chop more + * than one line. + * + * @return array The chopped lines + */ + function _getLines(&$text_lines, &$line_no, $end = false) + { + if (!empty($end)) { + $lines = array(); + // We can shift even more + while ($line_no <= $end) { + array_push($lines, array_shift($text_lines)); + $line_no++; + } + } else { + $lines = array(array_shift($text_lines)); + $line_no++; + } + + return $lines; + } + +} diff --git a/sources/wp-includes/Text/Diff/Engine/string.php b/sources/wp-includes/Text/Diff/Engine/string.php new file mode 100644 index 0000000..0f3b374 --- /dev/null +++ b/sources/wp-includes/Text/Diff/Engine/string.php @@ -0,0 +1,248 @@ +<?php +/** + * Parses unified or context diffs output from eg. the diff utility. + * + * Example: + * <code> + * $patch = file_get_contents('example.patch'); + * $diff = new Text_Diff('string', array($patch)); + * $renderer = new Text_Diff_Renderer_inline(); + * echo $renderer->render($diff); + * </code> + * + * Copyright 2005 Örjan Persson <o@42mm.org> + * Copyright 2005-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Örjan Persson <o@42mm.org> + * @package Text_Diff + * @since 0.2.0 + */ +class Text_Diff_Engine_string { + + /** + * Parses a unified or context diff. + * + * First param contains the whole diff and the second can be used to force + * a specific diff type. If the second parameter is 'autodetect', the + * diff will be examined to find out which type of diff this is. + * + * @param string $diff The diff content. + * @param string $mode The diff mode of the content in $diff. One of + * 'context', 'unified', or 'autodetect'. + * + * @return array List of all diff operations. + */ + function diff($diff, $mode = 'autodetect') + { + // Detect line breaks. + $lnbr = "\n"; + if (strpos($diff, "\r\n") !== false) { + $lnbr = "\r\n"; + } elseif (strpos($diff, "\r") !== false) { + $lnbr = "\r"; + } + + // Make sure we have a line break at the EOF. + if (substr($diff, -strlen($lnbr)) != $lnbr) { + $diff .= $lnbr; + } + + if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { + return PEAR::raiseError('Type of diff is unsupported'); + } + + if ($mode == 'autodetect') { + $context = strpos($diff, '***'); + $unified = strpos($diff, '---'); + if ($context === $unified) { + return PEAR::raiseError('Type of diff could not be detected'); + } elseif ($context === false || $unified === false) { + $mode = $context !== false ? 'context' : 'unified'; + } else { + $mode = $context < $unified ? 'context' : 'unified'; + } + } + + // Split by new line and remove the diff header, if there is one. + $diff = explode($lnbr, $diff); + if (($mode == 'context' && strpos($diff[0], '***') === 0) || + ($mode == 'unified' && strpos($diff[0], '---') === 0)) { + array_shift($diff); + array_shift($diff); + } + + if ($mode == 'context') { + return $this->parseContextDiff($diff); + } else { + return $this->parseUnifiedDiff($diff); + } + } + + /** + * Parses an array containing the unified diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseUnifiedDiff($diff) + { + $edits = array(); + $end = count($diff) - 1; + for ($i = 0; $i < $end;) { + $diff1 = array(); + switch (substr($diff[$i], 0, 1)) { + case ' ': + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); + $edits[] = new Text_Diff_Op_copy($diff1); + break; + + case '+': + // get all new lines + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); + $edits[] = new Text_Diff_Op_add($diff1); + break; + + case '-': + // get changed or removed lines + $diff2 = array(); + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); + + while ($i < $end && substr($diff[$i], 0, 1) == '+') { + $diff2[] = substr($diff[$i++], 1); + } + if (count($diff2) == 0) { + $edits[] = new Text_Diff_Op_delete($diff1); + } else { + $edits[] = new Text_Diff_Op_change($diff1, $diff2); + } + break; + + default: + $i++; + break; + } + } + + return $edits; + } + + /** + * Parses an array containing the context diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseContextDiff(&$diff) + { + $edits = array(); + $i = $max_i = $j = $max_j = 0; + $end = count($diff) - 1; + while ($i < $end && $j < $end) { + while ($i >= $max_i && $j >= $max_j) { + // Find the boundaries of the diff output of the two files + for ($i = $j; + $i < $end && substr($diff[$i], 0, 3) == '***'; + $i++); + for ($max_i = $i; + $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; + $max_i++); + for ($j = $max_i; + $j < $end && substr($diff[$j], 0, 3) == '---'; + $j++); + for ($max_j = $j; + $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; + $max_j++); + } + + // find what hasn't been changed + $array = array(); + while ($i < $max_i && + $j < $max_j && + strcmp($diff[$i], $diff[$j]) == 0) { + $array[] = substr($diff[$i], 2); + $i++; + $j++; + } + + while ($i < $max_i && ($max_j-$j) <= 1) { + if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { + break; + } + $array[] = substr($diff[$i++], 2); + } + + while ($j < $max_j && ($max_i-$i) <= 1) { + if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { + break; + } + $array[] = substr($diff[$j++], 2); + } + if (count($array) > 0) { + $edits[] = new Text_Diff_Op_copy($array); + } + + if ($i < $max_i) { + $diff1 = array(); + switch (substr($diff[$i], 0, 1)) { + case '!': + $diff2 = array(); + do { + $diff1[] = substr($diff[$i], 2); + if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { + $diff2[] = substr($diff[$j++], 2); + } + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); + $edits[] = new Text_Diff_Op_change($diff1, $diff2); + break; + + case '+': + do { + $diff1[] = substr($diff[$i], 2); + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); + $edits[] = new Text_Diff_Op_add($diff1); + break; + + case '-': + do { + $diff1[] = substr($diff[$i], 2); + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); + $edits[] = new Text_Diff_Op_delete($diff1); + break; + } + } + + if ($j < $max_j) { + $diff2 = array(); + switch (substr($diff[$j], 0, 1)) { + case '+': + do { + $diff2[] = substr($diff[$j++], 2); + } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); + $edits[] = new Text_Diff_Op_add($diff2); + break; + + case '-': + do { + $diff2[] = substr($diff[$j++], 2); + } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); + $edits[] = new Text_Diff_Op_delete($diff2); + break; + } + } + } + + return $edits; + } + +} diff --git a/sources/wp-includes/Text/Diff/Engine/xdiff.php b/sources/wp-includes/Text/Diff/Engine/xdiff.php new file mode 100644 index 0000000..02ce848 --- /dev/null +++ b/sources/wp-includes/Text/Diff/Engine/xdiff.php @@ -0,0 +1,64 @@ +<?php +/** + * Class used internally by Diff to actually compute the diffs. + * + * This class uses the xdiff PECL package (http://pecl.php.net/package/xdiff) + * to compute the differences between the two input arrays. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Jon Parise <jon@horde.org> + * @package Text_Diff + */ +class Text_Diff_Engine_xdiff { + + /** + */ + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + /* Convert the two input arrays into strings for xdiff processing. */ + $from_string = implode("\n", $from_lines); + $to_string = implode("\n", $to_lines); + + /* Diff the two strings and convert the result to an array. */ + $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); + $diff = explode("\n", $diff); + + /* Walk through the diff one line at a time. We build the $edits + * array of diff operations by reading the first character of the + * xdiff output (which is in the "unified diff" format). + * + * Note that we don't have enough information to detect "changed" + * lines using this approach, so we can't add Text_Diff_Op_changed + * instances to the $edits array. The result is still perfectly + * valid, albeit a little less descriptive and efficient. */ + $edits = array(); + foreach ($diff as $line) { + if (!strlen($line)) { + continue; + } + switch ($line[0]) { + case ' ': + $edits[] = new Text_Diff_Op_copy(array(substr($line, 1))); + break; + + case '+': + $edits[] = new Text_Diff_Op_add(array(substr($line, 1))); + break; + + case '-': + $edits[] = new Text_Diff_Op_delete(array(substr($line, 1))); + break; + } + } + + return $edits; + } + +} diff --git a/sources/wp-includes/Text/Diff/Renderer.php b/sources/wp-includes/Text/Diff/Renderer.php new file mode 100644 index 0000000..95c6db4 --- /dev/null +++ b/sources/wp-includes/Text/Diff/Renderer.php @@ -0,0 +1,235 @@ +<?php +/** + * A class to render Diffs in different formats. + * + * This class renders the diff in classic diff format. It is intended that + * this class be customized via inheritance, to obtain fancier outputs. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @package Text_Diff + */ +class Text_Diff_Renderer { + + /** + * Number of leading context "lines" to preserve. + * + * This should be left at zero for this class, but subclasses may want to + * set this to other values. + */ + var $_leading_context_lines = 0; + + /** + * Number of trailing context "lines" to preserve. + * + * This should be left at zero for this class, but subclasses may want to + * set this to other values. + */ + var $_trailing_context_lines = 0; + + /** + * Constructor. + */ + function Text_Diff_Renderer($params = array()) + { + foreach ($params as $param => $value) { + $v = '_' . $param; + if (isset($this->$v)) { + $this->$v = $value; + } + } + } + + /** + * Get any renderer parameters. + * + * @return array All parameters of this renderer object. + */ + function getParams() + { + $params = array(); + foreach (get_object_vars($this) as $k => $v) { + if ($k[0] == '_') { + $params[substr($k, 1)] = $v; + } + } + + return $params; + } + + /** + * Renders a diff. + * + * @param Text_Diff $diff A Text_Diff object. + * + * @return string The formatted output. + */ + function render($diff) + { + $xi = $yi = 1; + $block = false; + $context = array(); + + $nlead = $this->_leading_context_lines; + $ntrail = $this->_trailing_context_lines; + + $output = $this->_startDiff(); + + $diffs = $diff->getDiff(); + foreach ($diffs as $i => $edit) { + /* If these are unchanged (copied) lines, and we want to keep + * leading or trailing context lines, extract them from the copy + * block. */ + if (is_a($edit, 'Text_Diff_Op_copy')) { + /* Do we have any diff blocks yet? */ + if (is_array($block)) { + /* How many lines to keep as context from the copy + * block. */ + $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; + if (count($edit->orig) <= $keep) { + /* We have less lines in the block than we want for + * context => keep the whole block. */ + $block[] = $edit; + } else { + if ($ntrail) { + /* Create a new block with as many lines as we need + * for the trailing context. */ + $context = array_slice($edit->orig, 0, $ntrail); + $block[] = new Text_Diff_Op_copy($context); + } + /* @todo */ + $output .= $this->_block($x0, $ntrail + $xi - $x0, + $y0, $ntrail + $yi - $y0, + $block); + $block = false; + } + } + /* Keep the copy block as the context for the next block. */ + $context = $edit->orig; + } else { + /* Don't we have any diff blocks yet? */ + if (!is_array($block)) { + /* Extract context lines from the preceding copy block. */ + $context = array_slice($context, count($context) - $nlead); + $x0 = $xi - count($context); + $y0 = $yi - count($context); + $block = array(); + if ($context) { + $block[] = new Text_Diff_Op_copy($context); + } + } + $block[] = $edit; + } + + if ($edit->orig) { + $xi += count($edit->orig); + } + if ($edit->final) { + $yi += count($edit->final); + } + } + + if (is_array($block)) { + $output .= $this->_block($x0, $xi - $x0, + $y0, $yi - $y0, + $block); + } + + return $output . $this->_endDiff(); + } + + function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) + { + $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen)); + + foreach ($edits as $edit) { + switch (strtolower(get_class($edit))) { + case 'text_diff_op_copy': + $output .= $this->_context($edit->orig); + break; + + case 'text_diff_op_add': + $output .= $this->_added($edit->final); + break; + + case 'text_diff_op_delete': + $output .= $this->_deleted($edit->orig); + break; + + case 'text_diff_op_change': + $output .= $this->_changed($edit->orig, $edit->final); + break; + } + } + + return $output . $this->_endBlock(); + } + + function _startDiff() + { + return ''; + } + + function _endDiff() + { + return ''; + } + + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + if ($xlen > 1) { + $xbeg .= ',' . ($xbeg + $xlen - 1); + } + if ($ylen > 1) { + $ybeg .= ',' . ($ybeg + $ylen - 1); + } + + // this matches the GNU Diff behaviour + if ($xlen && !$ylen) { + $ybeg--; + } elseif (!$xlen) { + $xbeg--; + } + + return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; + } + + function _startBlock($header) + { + return $header . "\n"; + } + + function _endBlock() + { + return ''; + } + + function _lines($lines, $prefix = ' ') + { + return $prefix . implode("\n$prefix", $lines) . "\n"; + } + + function _context($lines) + { + return $this->_lines($lines, ' '); + } + + function _added($lines) + { + return $this->_lines($lines, '> '); + } + + function _deleted($lines) + { + return $this->_lines($lines, '< '); + } + + function _changed($orig, $final) + { + return $this->_deleted($orig) . "---\n" . $this->_added($final); + } + +} diff --git a/sources/wp-includes/Text/Diff/Renderer/inline.php b/sources/wp-includes/Text/Diff/Renderer/inline.php new file mode 100644 index 0000000..392bd57 --- /dev/null +++ b/sources/wp-includes/Text/Diff/Renderer/inline.php @@ -0,0 +1,206 @@ +<?php +/** + * "Inline" diff renderer. + * + * Copyright 2004-2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Ciprian Popovici + * @package Text_Diff + */ + +/** Text_Diff_Renderer */ + +// WP #7391 +require_once dirname(dirname(__FILE__)) . '/Renderer.php'; + +/** + * "Inline" diff renderer. + * + * This class renders diffs in the Wiki-style "inline" format. + * + * @author Ciprian Popovici + * @package Text_Diff + */ +class Text_Diff_Renderer_inline extends Text_Diff_Renderer { + + /** + * Number of leading context "lines" to preserve. + * + * @var integer + */ + var $_leading_context_lines = 10000; + + /** + * Number of trailing context "lines" to preserve. + * + * @var integer + */ + var $_trailing_context_lines = 10000; + + /** + * Prefix for inserted text. + * + * @var string + */ + var $_ins_prefix = '<ins>'; + + /** + * Suffix for inserted text. + * + * @var string + */ + var $_ins_suffix = '</ins>'; + + /** + * Prefix for deleted text. + * + * @var string + */ + var $_del_prefix = '<del>'; + + /** + * Suffix for deleted text. + * + * @var string + */ + var $_del_suffix = '</del>'; + + /** + * Header for each change block. + * + * @var string + */ + var $_block_header = ''; + + /** + * Whether to split down to character-level. + * + * @var boolean + */ + var $_split_characters = false; + + /** + * What are we currently splitting on? Used to recurse to show word-level + * or character-level changes. + * + * @var string + */ + var $_split_level = 'lines'; + + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + return $this->_block_header; + } + + function _startBlock($header) + { + return $header; + } + + function _lines($lines, $prefix = ' ', $encode = true) + { + if ($encode) { + array_walk($lines, array(&$this, '_encode')); + } + + if ($this->_split_level == 'lines') { + return implode("\n", $lines) . "\n"; + } else { + return implode('', $lines); + } + } + + function _added($lines) + { + array_walk($lines, array(&$this, '_encode')); + $lines[0] = $this->_ins_prefix . $lines[0]; + $lines[count($lines) - 1] .= $this->_ins_suffix; + return $this->_lines($lines, ' ', false); + } + + function _deleted($lines, $words = false) + { + array_walk($lines, array(&$this, '_encode')); + $lines[0] = $this->_del_prefix . $lines[0]; + $lines[count($lines) - 1] .= $this->_del_suffix; + return $this->_lines($lines, ' ', false); + } + + function _changed($orig, $final) + { + /* If we've already split on characters, just display. */ + if ($this->_split_level == 'characters') { + return $this->_deleted($orig) + . $this->_added($final); + } + + /* If we've already split on words, just display. */ + if ($this->_split_level == 'words') { + $prefix = ''; + while ($orig[0] !== false && $final[0] !== false && + substr($orig[0], 0, 1) == ' ' && + substr($final[0], 0, 1) == ' ') { + $prefix .= substr($orig[0], 0, 1); + $orig[0] = substr($orig[0], 1); + $final[0] = substr($final[0], 1); + } + return $prefix . $this->_deleted($orig) . $this->_added($final); + } + + $text1 = implode("\n", $orig); + $text2 = implode("\n", $final); + + /* Non-printing newline marker. */ + $nl = "\0"; + + if ($this->_split_characters) { + $diff = new Text_Diff('native', + array(preg_split('//', $text1), + preg_split('//', $text2))); + } else { + /* We want to split on word boundaries, but we need to preserve + * whitespace as well. Therefore we split on words, but include + * all blocks of whitespace in the wordlist. */ + $diff = new Text_Diff('native', + array($this->_splitOnWords($text1, $nl), + $this->_splitOnWords($text2, $nl))); + } + + /* Get the diff in inline format. */ + $renderer = new Text_Diff_Renderer_inline + (array_merge($this->getParams(), + array('split_level' => $this->_split_characters ? 'characters' : 'words'))); + + /* Run the diff and get the output. */ + return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; + } + + function _splitOnWords($string, $newlineEscape = "\n") + { + // Ignore \0; otherwise the while loop will never finish. + $string = str_replace("\0", '', $string); + + $words = array(); + $length = strlen($string); + $pos = 0; + + while ($pos < $length) { + // Eat a word with any preceding whitespace. + $spaces = strspn(substr($string, $pos), " \n"); + $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); + $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos)); + $pos += $spaces + $nextpos; + } + + return $words; + } + + function _encode(&$string) + { + $string = htmlspecialchars($string); + } + +} diff --git a/sources/wp-includes/admin-bar.php b/sources/wp-includes/admin-bar.php new file mode 100644 index 0000000..70c2a67 --- /dev/null +++ b/sources/wp-includes/admin-bar.php @@ -0,0 +1,798 @@ +<?php +/** + * Admin Bar + * + * This code handles the building and rendering of the press bar. + */ + +/** + * Instantiate the admin bar object and set it up as a global for access elsewhere. + * + * UNHOOKING THIS FUNCTION WILL NOT PROPERLY REMOVE THE ADMIN BAR. + * For that, use show_admin_bar(false) or the 'show_admin_bar' filter. + * + * @since 3.1.0 + * @access private + * @return bool Whether the admin bar was successfully initialized. + */ +function _wp_admin_bar_init() { + global $wp_admin_bar; + + if ( ! is_admin_bar_showing() ) + return false; + + /* Load the admin bar class code ready for instantiation */ + require( ABSPATH . WPINC . '/class-wp-admin-bar.php' ); + + /* Instantiate the admin bar */ + $admin_bar_class = apply_filters( 'wp_admin_bar_class', 'WP_Admin_Bar' ); + if ( class_exists( $admin_bar_class ) ) + $wp_admin_bar = new $admin_bar_class; + else + return false; + + $wp_admin_bar->initialize(); + $wp_admin_bar->add_menus(); + + return true; +} +// Don't remove. Wrong way to disable. +add_action( 'template_redirect', '_wp_admin_bar_init', 0 ); +add_action( 'admin_init', '_wp_admin_bar_init' ); + +/** + * Render the admin bar to the page based on the $wp_admin_bar->menu member var. + * This is called very late on the footer actions so that it will render after anything else being + * added to the footer. + * + * It includes the action "admin_bar_menu" which should be used to hook in and + * add new menus to the admin bar. That way you can be sure that you are adding at most optimal point, + * right before the admin bar is rendered. This also gives you access to the $post global, among others. + * + * @since 3.1.0 + */ +function wp_admin_bar_render() { + global $wp_admin_bar; + + if ( ! is_admin_bar_showing() || ! is_object( $wp_admin_bar ) ) + return false; + + do_action_ref_array( 'admin_bar_menu', array( &$wp_admin_bar ) ); + + do_action( 'wp_before_admin_bar_render' ); + + $wp_admin_bar->render(); + + do_action( 'wp_after_admin_bar_render' ); +} +add_action( 'wp_footer', 'wp_admin_bar_render', 1000 ); +add_action( 'in_admin_header', 'wp_admin_bar_render', 0 ); + +/** + * Add the WordPress logo menu. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_wp_menu( $wp_admin_bar ) { + $wp_admin_bar->add_menu( array( + 'id' => 'wp-logo', + 'title' => '<span class="ab-icon"></span>', + 'href' => self_admin_url( 'about.php' ), + 'meta' => array( + 'title' => __('About WordPress'), + ), + ) ); + + if ( is_user_logged_in() ) { + // Add "About WordPress" link + $wp_admin_bar->add_menu( array( + 'parent' => 'wp-logo', + 'id' => 'about', + 'title' => __('About WordPress'), + 'href' => self_admin_url( 'about.php' ), + ) ); + } + + // Add WordPress.org link + $wp_admin_bar->add_menu( array( + 'parent' => 'wp-logo-external', + 'id' => 'wporg', + 'title' => __('WordPress.org'), + 'href' => __('http://wordpress.org/'), + ) ); + + // Add codex link + $wp_admin_bar->add_menu( array( + 'parent' => 'wp-logo-external', + 'id' => 'documentation', + 'title' => __('Documentation'), + 'href' => __('http://codex.wordpress.org/'), + ) ); + + // Add forums link + $wp_admin_bar->add_menu( array( + 'parent' => 'wp-logo-external', + 'id' => 'support-forums', + 'title' => __('Support Forums'), + 'href' => __('http://wordpress.org/support/'), + ) ); + + // Add feedback link + $wp_admin_bar->add_menu( array( + 'parent' => 'wp-logo-external', + 'id' => 'feedback', + 'title' => __('Feedback'), + 'href' => __('http://wordpress.org/support/forum/requests-and-feedback'), + ) ); +} + +/** + * Add the "My Account" item. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_my_account_item( $wp_admin_bar ) { + $user_id = get_current_user_id(); + $current_user = wp_get_current_user(); + $profile_url = get_edit_profile_url( $user_id ); + + if ( ! $user_id ) + return; + + $avatar = get_avatar( $user_id, 16 ); + $howdy = sprintf( __('Howdy, %1$s'), $current_user->display_name ); + $class = empty( $avatar ) ? '' : 'with-avatar'; + + $wp_admin_bar->add_menu( array( + 'id' => 'my-account', + 'parent' => 'top-secondary', + 'title' => $howdy . $avatar, + 'href' => $profile_url, + 'meta' => array( + 'class' => $class, + 'title' => __('My Account'), + ), + ) ); +} + +/** + * Add the "My Account" submenu items. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_my_account_menu( $wp_admin_bar ) { + $user_id = get_current_user_id(); + $current_user = wp_get_current_user(); + $profile_url = get_edit_profile_url( $user_id ); + + if ( ! $user_id ) + return; + + $wp_admin_bar->add_group( array( + 'parent' => 'my-account', + 'id' => 'user-actions', + ) ); + + $user_info = get_avatar( $user_id, 64 ); + $user_info .= "<span class='display-name'>{$current_user->display_name}</span>"; + + if ( $current_user->display_name !== $current_user->user_login ) + $user_info .= "<span class='username'>{$current_user->user_login}</span>"; + + $wp_admin_bar->add_menu( array( + 'parent' => 'user-actions', + 'id' => 'user-info', + 'title' => $user_info, + 'href' => $profile_url, + 'meta' => array( + 'tabindex' => -1, + ), + ) ); + $wp_admin_bar->add_menu( array( + 'parent' => 'user-actions', + 'id' => 'edit-profile', + 'title' => __( 'Edit My Profile' ), + 'href' => $profile_url, + ) ); + $wp_admin_bar->add_menu( array( + 'parent' => 'user-actions', + 'id' => 'logout', + 'title' => __( 'Log Out' ), + 'href' => wp_logout_url(), + ) ); +} + +/** + * Add the "Site Name" menu. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_site_menu( $wp_admin_bar ) { + global $current_site; + + // Don't show for logged out users. + if ( ! is_user_logged_in() ) + return; + + // Show only when the user is a member of this site, or they're a super admin. + if ( ! is_user_member_of_blog() && ! is_super_admin() ) + return; + + $blogname = get_bloginfo('name'); + + if ( empty( $blogname ) ) + $blogname = preg_replace( '#^(https?://)?(www.)?#', '', get_home_url() ); + + if ( is_network_admin() ) { + $blogname = sprintf( __('Network Admin: %s'), esc_html( $current_site->site_name ) ); + } elseif ( is_user_admin() ) { + $blogname = sprintf( __('Global Dashboard: %s'), esc_html( $current_site->site_name ) ); + } + + $title = wp_html_excerpt( $blogname, 40, '…' ); + + $wp_admin_bar->add_menu( array( + 'id' => 'site-name', + 'title' => $title, + 'href' => is_admin() ? home_url( '/' ) : admin_url(), + ) ); + + // Create submenu items. + + if ( is_admin() ) { + // Add an option to visit the site. + $wp_admin_bar->add_menu( array( + 'parent' => 'site-name', + 'id' => 'view-site', + 'title' => __( 'Visit Site' ), + 'href' => home_url( '/' ), + ) ); + + if ( is_blog_admin() && is_multisite() && current_user_can( 'manage_sites' ) ) { + $wp_admin_bar->add_menu( array( + 'parent' => 'site-name', + 'id' => 'edit-site', + 'title' => __( 'Edit Site' ), + 'href' => network_admin_url( 'site-info.php?id=' . get_current_blog_id() ), + ) ); + } + + } else { + // We're on the front end, link to the Dashboard. + $wp_admin_bar->add_menu( array( + 'parent' => 'site-name', + 'id' => 'dashboard', + 'title' => __( 'Dashboard' ), + 'href' => admin_url(), + ) ); + + // Add the appearance submenu items. + wp_admin_bar_appearance_menu( $wp_admin_bar ); + } +} + +/** + * Add the "My Sites/[Site Name]" menu and all submenus. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_my_sites_menu( $wp_admin_bar ) { + // Don't show for logged out users or single site mode. + if ( ! is_user_logged_in() || ! is_multisite() ) + return; + + // Show only when the user has at least one site, or they're a super admin. + if ( count( $wp_admin_bar->user->blogs ) < 1 && ! is_super_admin() ) + return; + + $wp_admin_bar->add_menu( array( + 'id' => 'my-sites', + 'title' => __( 'My Sites' ), + 'href' => admin_url( 'my-sites.php' ), + ) ); + + if ( is_super_admin() ) { + $wp_admin_bar->add_group( array( + 'parent' => 'my-sites', + 'id' => 'my-sites-super-admin', + ) ); + + $wp_admin_bar->add_menu( array( + 'parent' => 'my-sites-super-admin', + 'id' => 'network-admin', + 'title' => __('Network Admin'), + 'href' => network_admin_url(), + ) ); + + $wp_admin_bar->add_menu( array( + 'parent' => 'network-admin', + 'id' => 'network-admin-d', + 'title' => __( 'Dashboard' ), + 'href' => network_admin_url(), + ) ); + $wp_admin_bar->add_menu( array( + 'parent' => 'network-admin', + 'id' => 'network-admin-s', + 'title' => __( 'Sites' ), + 'href' => network_admin_url( 'sites.php' ), + ) ); + $wp_admin_bar->add_menu( array( + 'parent' => 'network-admin', + 'id' => 'network-admin-u', + 'title' => __( 'Users' ), + 'href' => network_admin_url( 'users.php' ), + ) ); + $wp_admin_bar->add_menu( array( + 'parent' => 'network-admin', + 'id' => 'network-admin-t', + 'title' => __( 'Themes' ), + 'href' => network_admin_url( 'themes.php' ), + ) ); + $wp_admin_bar->add_menu( array( + 'parent' => 'network-admin', + 'id' => 'network-admin-p', + 'title' => __( 'Plugins' ), + 'href' => network_admin_url( 'plugins.php' ), + ) ); + } + + // Add site links + $wp_admin_bar->add_group( array( + 'parent' => 'my-sites', + 'id' => 'my-sites-list', + 'meta' => array( + 'class' => is_super_admin() ? 'ab-sub-secondary' : '', + ), + ) ); + + foreach ( (array) $wp_admin_bar->user->blogs as $blog ) { + switch_to_blog( $blog->userblog_id ); + + $blavatar = '<div class="blavatar"></div>'; + + $blogname = empty( $blog->blogname ) ? $blog->domain : $blog->blogname; + $menu_id = 'blog-' . $blog->userblog_id; + + $wp_admin_bar->add_menu( array( + 'parent' => 'my-sites-list', + 'id' => $menu_id, + 'title' => $blavatar . $blogname, + 'href' => admin_url(), + ) ); + + $wp_admin_bar->add_menu( array( + 'parent' => $menu_id, + 'id' => $menu_id . '-d', + 'title' => __( 'Dashboard' ), + 'href' => admin_url(), + ) ); + + if ( current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) { + $wp_admin_bar->add_menu( array( + 'parent' => $menu_id, + 'id' => $menu_id . '-n', + 'title' => __( 'New Post' ), + 'href' => admin_url( 'post-new.php' ), + ) ); + } + + if ( current_user_can( 'edit_posts' ) ) { + $wp_admin_bar->add_menu( array( + 'parent' => $menu_id, + 'id' => $menu_id . '-c', + 'title' => __( 'Manage Comments' ), + 'href' => admin_url( 'edit-comments.php' ), + ) ); + } + + $wp_admin_bar->add_menu( array( + 'parent' => $menu_id, + 'id' => $menu_id . '-v', + 'title' => __( 'Visit Site' ), + 'href' => home_url( '/' ), + ) ); + + restore_current_blog(); + } +} + +/** + * Provide a shortlink. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_shortlink_menu( $wp_admin_bar ) { + $short = wp_get_shortlink( 0, 'query' ); + $id = 'get-shortlink'; + + if ( empty( $short ) ) + return; + + $html = '<input class="shortlink-input" type="text" readonly="readonly" value="' . esc_attr( $short ) . '" />'; + + $wp_admin_bar->add_menu( array( + 'id' => $id, + 'title' => __( 'Shortlink' ), + 'href' => $short, + 'meta' => array( 'html' => $html ), + ) ); +} + +/** + * Provide an edit link for posts and terms. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_edit_menu( $wp_admin_bar ) { + global $tag, $wp_the_query; + + if ( is_admin() ) { + $current_screen = get_current_screen(); + $post = get_post(); + + if ( 'post' == $current_screen->base + && 'add' != $current_screen->action + && ( $post_type_object = get_post_type_object( $post->post_type ) ) + && current_user_can( 'read_post', $post->ID ) + && ( $post_type_object->public ) + && ( $post_type_object->show_in_admin_bar ) ) + { + $wp_admin_bar->add_menu( array( + 'id' => 'view', + 'title' => $post_type_object->labels->view_item, + 'href' => get_permalink( $post->ID ) + ) ); + } elseif ( 'edit-tags' == $current_screen->base + && isset( $tag ) && is_object( $tag ) + && ( $tax = get_taxonomy( $tag->taxonomy ) ) + && $tax->public ) + { + $wp_admin_bar->add_menu( array( + 'id' => 'view', + 'title' => $tax->labels->view_item, + 'href' => get_term_link( $tag ) + ) ); + } + } else { + $current_object = $wp_the_query->get_queried_object(); + + if ( empty( $current_object ) ) + return; + + if ( ! empty( $current_object->post_type ) + && ( $post_type_object = get_post_type_object( $current_object->post_type ) ) + && current_user_can( 'edit_post', $current_object->ID ) + && $post_type_object->show_ui && $post_type_object->show_in_admin_bar ) + { + $wp_admin_bar->add_menu( array( + 'id' => 'edit', + 'title' => $post_type_object->labels->edit_item, + 'href' => get_edit_post_link( $current_object->ID ) + ) ); + } elseif ( ! empty( $current_object->taxonomy ) + && ( $tax = get_taxonomy( $current_object->taxonomy ) ) + && current_user_can( $tax->cap->edit_terms ) + && $tax->show_ui ) + { + $wp_admin_bar->add_menu( array( + 'id' => 'edit', + 'title' => $tax->labels->edit_item, + 'href' => get_edit_term_link( $current_object->term_id, $current_object->taxonomy ) + ) ); + } + } +} + +/** + * Add "Add New" menu. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_new_content_menu( $wp_admin_bar ) { + $actions = array(); + + $cpts = (array) get_post_types( array( 'show_in_admin_bar' => true ), 'objects' ); + + if ( isset( $cpts['post'] ) && current_user_can( $cpts['post']->cap->create_posts ) ) + $actions[ 'post-new.php' ] = array( $cpts['post']->labels->name_admin_bar, 'new-post' ); + + if ( isset( $cpts['attachment'] ) && current_user_can( 'upload_files' ) ) + $actions[ 'media-new.php' ] = array( $cpts['attachment']->labels->name_admin_bar, 'new-media' ); + + if ( current_user_can( 'manage_links' ) ) + $actions[ 'link-add.php' ] = array( _x( 'Link', 'add new from admin bar' ), 'new-link' ); + + if ( isset( $cpts['page'] ) && current_user_can( $cpts['page']->cap->create_posts ) ) + $actions[ 'post-new.php?post_type=page' ] = array( $cpts['page']->labels->name_admin_bar, 'new-page' ); + + unset( $cpts['post'], $cpts['page'], $cpts['attachment'] ); + + // Add any additional custom post types. + foreach ( $cpts as $cpt ) { + if ( ! current_user_can( $cpt->cap->create_posts ) ) + continue; + + $key = 'post-new.php?post_type=' . $cpt->name; + $actions[ $key ] = array( $cpt->labels->name_admin_bar, 'new-' . $cpt->name ); + } + // Avoid clash with parent node and a 'content' post type. + if ( isset( $actions['post-new.php?post_type=content'] ) ) + $actions['post-new.php?post_type=content'][1] = 'add-new-content'; + + if ( current_user_can( 'create_users' ) || current_user_can( 'promote_users' ) ) + $actions[ 'user-new.php' ] = array( _x( 'User', 'add new from admin bar' ), 'new-user' ); + + if ( ! $actions ) + return; + + $title = '<span class="ab-icon"></span><span class="ab-label">' . _x( 'New', 'admin bar menu group label' ) . '</span>'; + + $wp_admin_bar->add_menu( array( + 'id' => 'new-content', + 'title' => $title, + 'href' => admin_url( current( array_keys( $actions ) ) ), + 'meta' => array( + 'title' => _x( 'Add New', 'admin bar menu group label' ), + ), + ) ); + + foreach ( $actions as $link => $action ) { + list( $title, $id ) = $action; + + $wp_admin_bar->add_menu( array( + 'parent' => 'new-content', + 'id' => $id, + 'title' => $title, + 'href' => admin_url( $link ) + ) ); + } +} + +/** + * Add edit comments link with awaiting moderation count bubble. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_comments_menu( $wp_admin_bar ) { + if ( !current_user_can('edit_posts') ) + return; + + $awaiting_mod = wp_count_comments(); + $awaiting_mod = $awaiting_mod->moderated; + $awaiting_title = esc_attr( sprintf( _n( '%s comment awaiting moderation', '%s comments awaiting moderation', $awaiting_mod ), number_format_i18n( $awaiting_mod ) ) ); + + $icon = '<span class="ab-icon"></span>'; + $title = '<span id="ab-awaiting-mod" class="ab-label awaiting-mod pending-count count-' . $awaiting_mod . '">' . number_format_i18n( $awaiting_mod ) . '</span>'; + + $wp_admin_bar->add_menu( array( + 'id' => 'comments', + 'title' => $icon . $title, + 'href' => admin_url('edit-comments.php'), + 'meta' => array( 'title' => $awaiting_title ), + ) ); +} + +/** + * Add appearance submenu items to the "Site Name" menu. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_appearance_menu( $wp_admin_bar ) { + $wp_admin_bar->add_group( array( 'parent' => 'site-name', 'id' => 'appearance' ) ); + + if ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) ) + $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'themes', 'title' => __('Themes'), 'href' => admin_url('themes.php') ) ); + + if ( ! current_user_can( 'edit_theme_options' ) ) + return; + + $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $wp_admin_bar->add_menu( array( + 'parent' => 'appearance', + 'id' => 'customize', + 'title' => __('Customize'), + 'href' => add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() ), + 'meta' => array( + 'class' => 'hide-if-no-customize', + ), + ) ); + add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' ); + + if ( current_theme_supports( 'widgets' ) ) + $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'widgets', 'title' => __('Widgets'), 'href' => admin_url('widgets.php') ) ); + + if ( current_theme_supports( 'menus' ) || current_theme_supports( 'widgets' ) ) + $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'menus', 'title' => __('Menus'), 'href' => admin_url('nav-menus.php') ) ); + + if ( current_theme_supports( 'custom-background' ) ) + $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'background', 'title' => __('Background'), 'href' => admin_url('themes.php?page=custom-background') ) ); + + if ( current_theme_supports( 'custom-header' ) ) + $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'header', 'title' => __('Header'), 'href' => admin_url('themes.php?page=custom-header') ) ); +} + +/** + * Provide an update link if theme/plugin/core updates are available. + * + * @since 3.1.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_updates_menu( $wp_admin_bar ) { + + $update_data = wp_get_update_data(); + + if ( !$update_data['counts']['total'] ) + return; + + $title = '<span class="ab-icon"></span><span class="ab-label">' . number_format_i18n( $update_data['counts']['total'] ) . '</span>'; + $title .= '<span class="screen-reader-text">' . $update_data['title'] . '</span>'; + + $wp_admin_bar->add_menu( array( + 'id' => 'updates', + 'title' => $title, + 'href' => network_admin_url( 'update-core.php' ), + 'meta' => array( + 'title' => $update_data['title'], + ), + ) ); +} + +/** + * Add search form. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_search_menu( $wp_admin_bar ) { + if ( is_admin() ) + return; + + $form = '<form action="' . esc_url( home_url( '/' ) ) . '" method="get" id="adminbarsearch">'; + $form .= '<input class="adminbar-input" name="s" id="adminbar-search" type="text" value="" maxlength="150" />'; + $form .= '<input type="submit" class="adminbar-button" value="' . __('Search') . '"/>'; + $form .= '</form>'; + + $wp_admin_bar->add_menu( array( + 'parent' => 'top-secondary', + 'id' => 'search', + 'title' => $form, + 'meta' => array( + 'class' => 'admin-bar-search', + 'tabindex' => -1, + ) + ) ); +} + +/** + * Add secondary menus. + * + * @since 3.3.0 + * + * @param WP_Admin_Bar $wp_admin_bar + */ +function wp_admin_bar_add_secondary_groups( $wp_admin_bar ) { + $wp_admin_bar->add_group( array( + 'id' => 'top-secondary', + 'meta' => array( + 'class' => 'ab-top-secondary', + ), + ) ); + + $wp_admin_bar->add_group( array( + 'parent' => 'wp-logo', + 'id' => 'wp-logo-external', + 'meta' => array( + 'class' => 'ab-sub-secondary', + ), + ) ); +} + +/** + * Style and scripts for the admin bar. + * + * @since 3.1.0 + */ +function wp_admin_bar_header() { ?> +<style type="text/css" media="print">#wpadminbar { display:none; }</style> +<?php +} + +/** + * Default admin bar callback. + * + * @since 3.1.0 + */ +function _admin_bar_bump_cb() { ?> +<style type="text/css" media="screen"> + html { margin-top: 28px !important; } + * html body { margin-top: 28px !important; } +</style> +<?php +} + +/** + * Set the display status of the admin bar. + * + * This can be called immediately upon plugin load. It does not need to be called from a function hooked to the init action. + * + * @since 3.1.0 + * + * @param bool $show Whether to allow the admin bar to show. + * @return void + */ +function show_admin_bar( $show ) { + global $show_admin_bar; + $show_admin_bar = (bool) $show; +} + +/** + * Determine whether the admin bar should be showing. + * + * @since 3.1.0 + * + * @return bool Whether the admin bar should be showing. + */ +function is_admin_bar_showing() { + global $show_admin_bar, $pagenow; + + // For all these types of requests, we never want an admin bar. + if ( defined('XMLRPC_REQUEST') || defined('DOING_AJAX') || defined('IFRAME_REQUEST') ) + return false; + + // Integrated into the admin. + if ( is_admin() ) + return true; + + if ( ! isset( $show_admin_bar ) ) { + if ( ! is_user_logged_in() || 'wp-login.php' == $pagenow ) { + $show_admin_bar = false; + } else { + $show_admin_bar = _get_admin_bar_pref(); + } + } + + $show_admin_bar = apply_filters( 'show_admin_bar', $show_admin_bar ); + + return $show_admin_bar; +} + +/** + * Retrieve the admin bar display preference of a user. + * + * @since 3.1.0 + * @access private + * + * @param string $context Context of this preference check. Defaults to 'front'. The 'admin' + * preference is no longer used. + * @param int $user Optional. ID of the user to check, defaults to 0 for current user. + * @return bool Whether the admin bar should be showing for this user. + */ +function _get_admin_bar_pref( $context = 'front', $user = 0 ) { + $pref = get_user_option( "show_admin_bar_{$context}", $user ); + if ( false === $pref ) + return true; + + return 'true' === $pref; +} diff --git a/sources/wp-includes/atomlib.php b/sources/wp-includes/atomlib.php new file mode 100644 index 0000000..4dcddc9 --- /dev/null +++ b/sources/wp-includes/atomlib.php @@ -0,0 +1,352 @@ +<?php +/** + * Atom Syndication Format PHP Library + * + * @package AtomLib + * @link http://code.google.com/p/phpatomlib/ + * + * @author Elias Torres <elias@torrez.us> + * @version 0.4 + * @since 2.3 + */ + +/** + * Structure that store common Atom Feed Properties + * + * @package AtomLib + */ +class AtomFeed { + /** + * Stores Links + * @var array + * @access public + */ + var $links = array(); + /** + * Stores Categories + * @var array + * @access public + */ + var $categories = array(); + /** + * Stores Entries + * + * @var array + * @access public + */ + var $entries = array(); +} + +/** + * Structure that store Atom Entry Properties + * + * @package AtomLib + */ +class AtomEntry { + /** + * Stores Links + * @var array + * @access public + */ + var $links = array(); + /** + * Stores Categories + * @var array + * @access public + */ + var $categories = array(); +} + +/** + * AtomLib Atom Parser API + * + * @package AtomLib + */ +class AtomParser { + + var $NS = 'http://www.w3.org/2005/Atom'; + var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights'); + var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft'); + + var $debug = false; + + var $depth = 0; + var $indent = 2; + var $in_content; + var $ns_contexts = array(); + var $ns_decls = array(); + var $content_ns_decls = array(); + var $content_ns_contexts = array(); + var $is_xhtml = false; + var $is_html = false; + var $is_text = true; + var $skipped_div = false; + + var $FILE = "php://input"; + + var $feed; + var $current; + + function AtomParser() { + + $this->feed = new AtomFeed(); + $this->current = null; + $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";'); + $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";'); + } + + function _p($msg) { + if($this->debug) { + print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n"; + } + } + + function error_handler($log_level, $log_text, $error_file, $error_line) { + $this->error = $log_text; + } + + function parse() { + + set_error_handler(array(&$this, 'error_handler')); + + array_unshift($this->ns_contexts, array()); + + $parser = xml_parser_create_ns(); + xml_set_object($parser, $this); + xml_set_element_handler($parser, "start_element", "end_element"); + xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); + xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0); + xml_set_character_data_handler($parser, "cdata"); + xml_set_default_handler($parser, "_default"); + xml_set_start_namespace_decl_handler($parser, "start_ns"); + xml_set_end_namespace_decl_handler($parser, "end_ns"); + + $this->content = ''; + + $ret = true; + + $fp = fopen($this->FILE, "r"); + while ($data = fread($fp, 4096)) { + if($this->debug) $this->content .= $data; + + if(!xml_parse($parser, $data, feof($fp))) { + trigger_error(sprintf(__('XML error: %s at line %d')."\n", + xml_error_string(xml_get_error_code($parser)), + xml_get_current_line_number($parser))); + $ret = false; + break; + } + } + fclose($fp); + + xml_parser_free($parser); + + restore_error_handler(); + + return $ret; + } + + function start_element($parser, $name, $attrs) { + + $tag = array_pop(split(":", $name)); + + switch($name) { + case $this->NS . ':feed': + $this->current = $this->feed; + break; + case $this->NS . ':entry': + $this->current = new AtomEntry(); + break; + }; + + $this->_p("start_element('$name')"); + #$this->_p(print_r($this->ns_contexts,true)); + #$this->_p('current(' . $this->current . ')'); + + array_unshift($this->ns_contexts, $this->ns_decls); + + $this->depth++; + + if(!empty($this->in_content)) { + + $this->content_ns_decls = array(); + + if($this->is_html || $this->is_text) + trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup."); + + $attrs_prefix = array(); + + // resolve prefixes for attributes + foreach($attrs as $key => $value) { + $with_prefix = $this->ns_to_prefix($key, true); + $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value); + } + + $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix))); + if(strlen($attrs_str) > 0) { + $attrs_str = " " . $attrs_str; + } + + $with_prefix = $this->ns_to_prefix($name); + + if(!$this->is_declared_content_ns($with_prefix[0])) { + array_push($this->content_ns_decls, $with_prefix[0]); + } + + $xmlns_str = ''; + if(count($this->content_ns_decls) > 0) { + array_unshift($this->content_ns_contexts, $this->content_ns_decls); + $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0]))); + if(strlen($xmlns_str) > 0) { + $xmlns_str = " " . $xmlns_str; + } + } + + array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">")); + + } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) { + $this->in_content = array(); + $this->is_xhtml = $attrs['type'] == 'xhtml'; + $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html'; + $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text'; + $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type'])); + + if(in_array('src',array_keys($attrs))) { + $this->current->$tag = $attrs; + } else { + array_push($this->in_content, array($tag,$this->depth, $type)); + } + } else if($tag == 'link') { + array_push($this->current->links, $attrs); + } else if($tag == 'category') { + array_push($this->current->categories, $attrs); + } + + $this->ns_decls = array(); + } + + function end_element($parser, $name) { + + $tag = array_pop(split(":", $name)); + + $ccount = count($this->in_content); + + # if we are *in* content, then let's proceed to serialize it + if(!empty($this->in_content)) { + # if we are ending the original content element + # then let's finalize the content + if($this->in_content[0][0] == $tag && + $this->in_content[0][1] == $this->depth) { + $origtype = $this->in_content[0][2]; + array_shift($this->in_content); + $newcontent = array(); + foreach($this->in_content as $c) { + if(count($c) == 3) { + array_push($newcontent, $c[2]); + } else { + if($this->is_xhtml || $this->is_text) { + array_push($newcontent, $this->xml_escape($c)); + } else { + array_push($newcontent, $c); + } + } + } + if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) { + $this->current->$tag = array($origtype, join('',$newcontent)); + } else { + $this->current->$tag = join('',$newcontent); + } + $this->in_content = array(); + } else if($this->in_content[$ccount-1][0] == $tag && + $this->in_content[$ccount-1][1] == $this->depth) { + $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>"; + } else { + # else, just finalize the current element's content + $endtag = $this->ns_to_prefix($name); + array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>")); + } + } + + array_shift($this->ns_contexts); + + $this->depth--; + + if($name == ($this->NS . ':entry')) { + array_push($this->feed->entries, $this->current); + $this->current = null; + } + + $this->_p("end_element('$name')"); + } + + function start_ns($parser, $prefix, $uri) { + $this->_p("starting: " . $prefix . ":" . $uri); + array_push($this->ns_decls, array($prefix,$uri)); + } + + function end_ns($parser, $prefix) { + $this->_p("ending: #" . $prefix . "#"); + } + + function cdata($parser, $data) { + $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#"); + if(!empty($this->in_content)) { + array_push($this->in_content, $data); + } + } + + function _default($parser, $data) { + # when does this gets called? + } + + + function ns_to_prefix($qname, $attr=false) { + # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div') + $components = split(":", $qname); + + # grab the last one (e.g 'div') + $name = array_pop($components); + + if(!empty($components)) { + # re-join back the namespace component + $ns = join(":",$components); + foreach($this->ns_contexts as $context) { + foreach($context as $mapping) { + if($mapping[1] == $ns && strlen($mapping[0]) > 0) { + return array($mapping, "$mapping[0]:$name"); + } + } + } + } + + if($attr) { + return array(null, $name); + } else { + foreach($this->ns_contexts as $context) { + foreach($context as $mapping) { + if(strlen($mapping[0]) == 0) { + return array($mapping, $name); + } + } + } + } + } + + function is_declared_content_ns($new_mapping) { + foreach($this->content_ns_contexts as $context) { + foreach($context as $mapping) { + if($new_mapping == $mapping) { + return true; + } + } + } + return false; + } + + function xml_escape($string) + { + return str_replace(array('&','"',"'",'<','>'), + array('&','"',''','<','>'), + $string ); + } +} diff --git a/sources/wp-includes/author-template.php b/sources/wp-includes/author-template.php new file mode 100644 index 0000000..557a1ab --- /dev/null +++ b/sources/wp-includes/author-template.php @@ -0,0 +1,453 @@ +<?php +/** + * Author Template functions for use in themes. + * + * These functions must be used within the WordPress Loop. + * + * @link http://codex.wordpress.org/Author_Templates + * + * @package WordPress + * @subpackage Template + */ + +/** + * Retrieve the author of the current post. + * + * @since 1.5 + * @uses $authordata The current author's DB object. + * @uses apply_filters() Calls 'the_author' hook on the author display name. + * + * @param string $deprecated Deprecated. + * @return string The author's display name. + */ +function get_the_author($deprecated = '') { + global $authordata; + + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.1' ); + + /** + * Filter the display name of the current post's author. + * + * @since 2.9.0 + * + * @param string $authordata->display_name The author's display name. + */ + return apply_filters('the_author', is_object($authordata) ? $authordata->display_name : null); +} + +/** + * Display the name of the author of the current post. + * + * The behavior of this function is based off of old functionality predating + * get_the_author(). This function is not deprecated, but is designed to echo + * the value from get_the_author() and as an result of any old theme that might + * still use the old behavior will also pass the value from get_the_author(). + * + * The normal, expected behavior of this function is to echo the author and not + * return it. However, backwards compatibility has to be maintained. + * + * @since 0.71 + * @see get_the_author() + * @link http://codex.wordpress.org/Template_Tags/the_author + * + * @param string $deprecated Deprecated. + * @param string $deprecated_echo Deprecated. Use get_the_author(). Echo the string or return it. + * @return string The author's display name, from get_the_author(). + */ +function the_author( $deprecated = '', $deprecated_echo = true ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.1' ); + if ( $deprecated_echo !== true ) + _deprecated_argument( __FUNCTION__, '1.5', __('Use <code>get_the_author()</code> instead if you do not want the value echoed.') ); + if ( $deprecated_echo ) + echo get_the_author(); + return get_the_author(); +} + +/** + * Retrieve the author who last edited the current post. + * + * @since 2.8 + * @uses $post The current post's DB object. + * @uses get_post_meta() Retrieves the ID of the author who last edited the current post. + * @uses get_userdata() Retrieves the author's DB object. + * @uses apply_filters() Calls 'the_modified_author' hook on the author display name. + * @return string The author's display name. + */ +function get_the_modified_author() { + if ( $last_id = get_post_meta( get_post()->ID, '_edit_last', true) ) { + $last_user = get_userdata($last_id); + + /** + * Filter the display name of the author who last edited the current post. + * + * @since 2.8.0 + * + * @param string $last_user->display_name The author's display name. + */ + return apply_filters('the_modified_author', $last_user->display_name); + } +} + +/** + * Display the name of the author who last edited the current post. + * + * @since 2.8 + * @see get_the_author() + * @return string The author's display name, from get_the_modified_author(). + */ +function the_modified_author() { + echo get_the_modified_author(); +} + +/** + * Retrieve the requested data of the author of the current post. + * @link http://codex.wordpress.org/Template_Tags/the_author_meta + * @since 2.8.0 + * @uses $authordata The current author's DB object (if $user_id not specified). + * @param string $field selects the field of the users record. + * @param int $user_id Optional. User ID. + * @return string The author's field from the current author's DB object. + */ +function get_the_author_meta( $field = '', $user_id = false ) { + if ( ! $user_id ) { + global $authordata; + $user_id = isset( $authordata->ID ) ? $authordata->ID : 0; + } else { + $authordata = get_userdata( $user_id ); + } + + if ( in_array( $field, array( 'login', 'pass', 'nicename', 'email', 'url', 'registered', 'activation_key', 'status' ) ) ) + $field = 'user_' . $field; + + $value = isset( $authordata->$field ) ? $authordata->$field : ''; + + /** + * Filter the value of the requested user metadata. + * + * The filter name is dynamic and depends on the $field parameter of the function. + * + * @since 2.8.0 + * + * @param string $value The value of the metadata. + * @param int $user_id The user ID. + */ + return apply_filters( 'get_the_author_' . $field, $value, $user_id ); +} + +/** + * Retrieve the requested data of the author of the current post. + * @link http://codex.wordpress.org/Template_Tags/the_author_meta + * @since 2.8.0 + * @param string $field selects the field of the users record. + * @param int $user_id Optional. User ID. + * @echo string The author's field from the current author's DB object. + */ +function the_author_meta( $field = '', $user_id = false ) { + $author_meta = get_the_author_meta( $field, $user_id ); + + /** + * The value of the requested user metadata. + * + * The filter name is dynamic and depends on the $field parameter of the function. + * + * @since 2.8.0 + * + * @param string $author_meta The value of the metadata. + * @param int $user_id The user ID. + */ + echo apply_filters( 'the_author_' . $field, $author_meta, $user_id ); +} + +/** + * Retrieve either author's link or author's name. + * + * If the author has a home page set, return an HTML link, otherwise just return the + * author's name. + * + * @uses get_the_author_meta() + * @uses get_the_author() + */ +function get_the_author_link() { + if ( get_the_author_meta('url') ) { + return '<a href="' . esc_url( get_the_author_meta('url') ) . '" title="' . esc_attr( sprintf(__("Visit %s’s website"), get_the_author()) ) . '" rel="author external">' . get_the_author() . '</a>'; + } else { + return get_the_author(); + } +} + +/** + * Display either author's link or author's name. + * + * If the author has a home page set, echo an HTML link, otherwise just echo the + * author's name. + * + * @link http://codex.wordpress.org/Template_Tags/the_author_link + * @since 2.1 + * @uses get_the_author_link() + */ +function the_author_link() { + echo get_the_author_link(); +} + +/** + * Retrieve the number of posts by the author of the current post. + * + * @since 1.5 + * @uses $post The current post in the Loop's DB object. + * @uses count_user_posts() + * @return int The number of posts by the author. + */ +function get_the_author_posts() { + return count_user_posts( get_post()->post_author ); +} + +/** + * Display the number of posts by the author of the current post. + * + * @link http://codex.wordpress.org/Template_Tags/the_author_posts + * @since 0.71 + * @uses get_the_author_posts() Echoes returned value from function. + */ +function the_author_posts() { + echo get_the_author_posts(); +} + +/** + * Display an HTML link to the author page of the author of the current post. + * + * Does just echo get_author_posts_url() function, like the others do. The + * reason for this, is that another function is used to help in printing the + * link to the author's posts. + * + * @link http://codex.wordpress.org/Template_Tags/the_author_posts_link + * @since 1.2.0 + * @uses $authordata The current author's DB object. + * @uses get_author_posts_url() + * @uses get_the_author() + * @param string $deprecated Deprecated. + */ +function the_author_posts_link($deprecated = '') { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.1' ); + + global $authordata; + if ( !is_object( $authordata ) ) + return false; + $link = sprintf( + '<a href="%1$s" title="%2$s" rel="author">%3$s</a>', + esc_url( get_author_posts_url( $authordata->ID, $authordata->user_nicename ) ), + esc_attr( sprintf( __( 'Posts by %s' ), get_the_author() ) ), + get_the_author() + ); + + /** + * Filter the link to the author page of the author of the current post. + * + * @since 2.9.0 + * + * @param string $link HTML link. + */ + echo apply_filters( 'the_author_posts_link', $link ); +} + +/** + * Retrieve the URL to the author page for the user with the ID provided. + * + * @since 2.1.0 + * @uses $wp_rewrite WP_Rewrite + * @return string The URL to the author's page. + */ +function get_author_posts_url($author_id, $author_nicename = '') { + global $wp_rewrite; + $auth_ID = (int) $author_id; + $link = $wp_rewrite->get_author_permastruct(); + + if ( empty($link) ) { + $file = home_url( '/' ); + $link = $file . '?author=' . $auth_ID; + } else { + if ( '' == $author_nicename ) { + $user = get_userdata($author_id); + if ( !empty($user->user_nicename) ) + $author_nicename = $user->user_nicename; + } + $link = str_replace('%author%', $author_nicename, $link); + $link = home_url( user_trailingslashit( $link ) ); + } + + /** + * Filter the URL to the author's page. + * + * @since 2.1.0 + * + * @param string $link The URL to the author's page. + * @param int $author_id The author's id. + * @param string $author_nicename The author's nice name. + */ + $link = apply_filters( 'author_link', $link, $author_id, $author_nicename ); + + return $link; +} + +/** + * List all the authors of the blog, with several options available. + * + * <ul> + * <li>optioncount (boolean) (false): Show the count in parenthesis next to the + * author's name.</li> + * <li>exclude_admin (boolean) (true): Exclude the 'admin' user that is + * installed by default.</li> + * <li>show_fullname (boolean) (false): Show their full names.</li> + * <li>hide_empty (boolean) (true): Don't show authors without any posts.</li> + * <li>feed (string) (''): If isn't empty, show links to author's feeds.</li> + * <li>feed_image (string) (''): If isn't empty, use this image to link to + * feeds.</li> + * <li>echo (boolean) (true): Set to false to return the output, instead of + * echoing.</li> + * <li>style (string) ('list'): Whether to display list of authors in list form + * or as a string.</li> + * <li>html (bool) (true): Whether to list the items in html form or plaintext. + * </li> + * </ul> + * + * @link http://codex.wordpress.org/Template_Tags/wp_list_authors + * @since 1.2.0 + * @param array $args The argument array. + * @return null|string The output, if echo is set to false. + */ +function wp_list_authors($args = '') { + global $wpdb; + + $defaults = array( + 'orderby' => 'name', 'order' => 'ASC', 'number' => '', + 'optioncount' => false, 'exclude_admin' => true, + 'show_fullname' => false, 'hide_empty' => true, + 'feed' => '', 'feed_image' => '', 'feed_type' => '', 'echo' => true, + 'style' => 'list', 'html' => true + ); + + $args = wp_parse_args( $args, $defaults ); + extract( $args, EXTR_SKIP ); + + $return = ''; + + $query_args = wp_array_slice_assoc( $args, array( 'orderby', 'order', 'number' ) ); + $query_args['fields'] = 'ids'; + $authors = get_users( $query_args ); + + $author_count = array(); + foreach ( (array) $wpdb->get_results("SELECT DISTINCT post_author, COUNT(ID) AS count FROM $wpdb->posts WHERE post_type = 'post' AND " . get_private_posts_cap_sql( 'post' ) . " GROUP BY post_author") as $row ) + $author_count[$row->post_author] = $row->count; + + foreach ( $authors as $author_id ) { + $author = get_userdata( $author_id ); + + if ( $exclude_admin && 'admin' == $author->display_name ) + continue; + + $posts = isset( $author_count[$author->ID] ) ? $author_count[$author->ID] : 0; + + if ( !$posts && $hide_empty ) + continue; + + $link = ''; + + if ( $show_fullname && $author->first_name && $author->last_name ) + $name = "$author->first_name $author->last_name"; + else + $name = $author->display_name; + + if ( !$html ) { + $return .= $name . ', '; + + continue; // No need to go further to process HTML. + } + + if ( 'list' == $style ) { + $return .= '<li>'; + } + + $link = '<a href="' . get_author_posts_url( $author->ID, $author->user_nicename ) . '" title="' . esc_attr( sprintf(__("Posts by %s"), $author->display_name) ) . '">' . $name . '</a>'; + + if ( !empty( $feed_image ) || !empty( $feed ) ) { + $link .= ' '; + if ( empty( $feed_image ) ) { + $link .= '('; + } + + $link .= '<a href="' . get_author_feed_link( $author->ID ) . '"'; + + $alt = $title = ''; + if ( !empty( $feed ) ) { + $title = ' title="' . esc_attr( $feed ) . '"'; + $alt = ' alt="' . esc_attr( $feed ) . '"'; + $name = $feed; + $link .= $title; + } + + $link .= '>'; + + if ( !empty( $feed_image ) ) + $link .= '<img src="' . esc_url( $feed_image ) . '" style="border: none;"' . $alt . $title . ' />'; + else + $link .= $name; + + $link .= '</a>'; + + if ( empty( $feed_image ) ) + $link .= ')'; + } + + if ( $optioncount ) + $link .= ' ('. $posts . ')'; + + $return .= $link; + $return .= ( 'list' == $style ) ? '</li>' : ', '; + } + + $return = rtrim($return, ', '); + + if ( !$echo ) + return $return; + + echo $return; +} + +/** + * Does this site have more than one author + * + * Checks to see if more than one author has published posts. + * + * @since 3.2.0 + * @return bool Whether or not we have more than one author + */ +function is_multi_author() { + global $wpdb; + + if ( false === ( $is_multi_author = get_transient( 'is_multi_author' ) ) ) { + $rows = (array) $wpdb->get_col("SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 2"); + $is_multi_author = 1 < count( $rows ) ? 1 : 0; + set_transient( 'is_multi_author', $is_multi_author ); + } + + /** + * Filter whether the site has more than one author with published posts. + * + * @since 3.2.0 + * + * @param bool $is_multi_author Whether $is_multi_author should evaluate as true. + */ + return apply_filters( 'is_multi_author', (bool) $is_multi_author ); +} + +/** + * Helper function to clear the cache for number of authors. + * + * @private + */ +function __clear_multi_author_cache() { + delete_transient( 'is_multi_author' ); +} +add_action('transition_post_status', '__clear_multi_author_cache'); diff --git a/sources/wp-includes/bookmark-template.php b/sources/wp-includes/bookmark-template.php new file mode 100644 index 0000000..64e73a8 --- /dev/null +++ b/sources/wp-includes/bookmark-template.php @@ -0,0 +1,272 @@ +<?php +/** + * Bookmark Template Functions for usage in Themes + * + * @package WordPress + * @subpackage Template + */ + +/** + * The formatted output of a list of bookmarks. + * + * The $bookmarks array must contain bookmark objects and will be iterated over + * to retrieve the bookmark to be used in the output. + * + * The output is formatted as HTML with no way to change that format. However, + * what is between, before, and after can be changed. The link itself will be + * HTML. + * + * This function is used internally by wp_list_bookmarks() and should not be + * used by themes. + * + * The defaults for overwriting are: + * 'show_updated' - Default is 0 (integer). Will show the time of when the + * bookmark was last updated. + * 'show_description' - Default is 0 (integer). Whether to show the description + * of the bookmark. + * 'show_images' - Default is 1 (integer). Whether to show link image if + * available. + * 'show_name' - Default is 0 (integer). Whether to show link name if + * available. + * 'before' - Default is '<li>' (string). The html or text to prepend to each + * bookmarks. + * 'after' - Default is '</li>' (string). The html or text to append to each + * bookmarks. + * 'link_before' - Default is '' (string). The html or text to prepend to each + * bookmarks inside the <a> tag. + * 'link_after' - Default is '' (string). The html or text to append to each + * bookmarks inside the <a> tag. + * 'between' - Default is '\n' (string). The string for use in between the link, + * description, and image. + * 'show_rating' - Default is 0 (integer). Whether to show the link rating. + * + * @since 2.1.0 + * @access private + * + * @param array $bookmarks List of bookmarks to traverse + * @param string|array $args Optional. Overwrite the defaults. + * @return string Formatted output in HTML + */ +function _walk_bookmarks($bookmarks, $args = '' ) { + $defaults = array( + 'show_updated' => 0, 'show_description' => 0, + 'show_images' => 1, 'show_name' => 0, + 'before' => '<li>', 'after' => '</li>', 'between' => "\n", + 'show_rating' => 0, 'link_before' => '', 'link_after' => '' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + $output = ''; // Blank string to start with. + + foreach ( (array) $bookmarks as $bookmark ) { + if ( !isset($bookmark->recently_updated) ) + $bookmark->recently_updated = false; + $output .= $before; + if ( $show_updated && $bookmark->recently_updated ) + $output .= get_option('links_recently_updated_prepend'); + + $the_link = '#'; + if ( !empty($bookmark->link_url) ) + $the_link = esc_url($bookmark->link_url); + + $desc = esc_attr(sanitize_bookmark_field('link_description', $bookmark->link_description, $bookmark->link_id, 'display')); + $name = esc_attr(sanitize_bookmark_field('link_name', $bookmark->link_name, $bookmark->link_id, 'display')); + $title = $desc; + + if ( $show_updated ) + if ( '00' != substr($bookmark->link_updated_f, 0, 2) ) { + $title .= ' ('; + $title .= sprintf(__('Last updated: %s'), date(get_option('links_updated_date_format'), $bookmark->link_updated_f + (get_option('gmt_offset') * HOUR_IN_SECONDS))); + $title .= ')'; + } + + $alt = ' alt="' . $name . ( $show_description ? ' ' . $title : '' ) . '"'; + + if ( '' != $title ) + $title = ' title="' . $title . '"'; + + $rel = $bookmark->link_rel; + if ( '' != $rel ) + $rel = ' rel="' . esc_attr($rel) . '"'; + + $target = $bookmark->link_target; + if ( '' != $target ) + $target = ' target="' . $target . '"'; + + $output .= '<a href="' . $the_link . '"' . $rel . $title . $target . '>'; + + $output .= $link_before; + + if ( $bookmark->link_image != null && $show_images ) { + if ( strpos($bookmark->link_image, 'http') === 0 ) + $output .= "<img src=\"$bookmark->link_image\" $alt $title />"; + else // If it's a relative path + $output .= "<img src=\"" . get_option('siteurl') . "$bookmark->link_image\" $alt $title />"; + + if ( $show_name ) + $output .= " $name"; + } else { + $output .= $name; + } + + $output .= $link_after; + + $output .= '</a>'; + + if ( $show_updated && $bookmark->recently_updated ) + $output .= get_option('links_recently_updated_append'); + + if ( $show_description && '' != $desc ) + $output .= $between . $desc; + + if ( $show_rating ) + $output .= $between . sanitize_bookmark_field('link_rating', $bookmark->link_rating, $bookmark->link_id, 'display'); + + $output .= "$after\n"; + } // end while + + return $output; +} + +/** + * Retrieve or echo all of the bookmarks. + * + * List of default arguments are as follows: + * 'orderby' - Default is 'name' (string). How to order the links by. String is + * based off of the bookmark scheme. + * 'order' - Default is 'ASC' (string). Either 'ASC' or 'DESC'. Orders in either + * ascending or descending order. + * 'limit' - Default is -1 (integer) or show all. The amount of bookmarks to + * display. + * 'category' - Default is empty string (string). Include the links in what + * category ID(s). + * 'category_name' - Default is empty string (string). Get links by category + * name. + * 'hide_invisible' - Default is 1 (integer). Whether to show (default) or hide + * links marked as 'invisible'. + * 'show_updated' - Default is 0 (integer). Will show the time of when the + * bookmark was last updated. + * 'echo' - Default is 1 (integer). Whether to echo (default) or return the + * formatted bookmarks. + * 'categorize' - Default is 1 (integer). Whether to show links listed by + * category (default) or show links in one column. + * 'show_description' - Default is 0 (integer). Whether to show the description + * of the bookmark. + * + * These options define how the Category name will appear before the category + * links are displayed, if 'categorize' is 1. If 'categorize' is 0, then it will + * display for only the 'title_li' string and only if 'title_li' is not empty. + * 'title_li' - Default is 'Bookmarks' (translatable string). What to show + * before the links appear. + * 'title_before' - Default is '<h2>' (string). The HTML or text to show before + * the 'title_li' string. + * 'title_after' - Default is '</h2>' (string). The HTML or text to show after + * the 'title_li' string. + * 'class' - Default is 'linkcat' (string). The CSS class to use for the + * 'title_li'. + * + * 'category_before' - Default is '<li id="%id" class="%class">'. String must + * contain '%id' and '%class' to get + * the id of the category and the 'class' argument. These are used for + * formatting in themes. + * Argument will be displayed before the 'title_before' argument. + * 'category_after' - Default is '</li>' (string). The HTML or text that will + * appear after the list of links. + * + * These are only used if 'categorize' is set to 1 or true. + * 'category_orderby' - Default is 'name'. How to order the bookmark category + * based on term scheme. + * 'category_order' - Default is 'ASC'. Set the order by either ASC (ascending) + * or DESC (descending). + * + * @see _walk_bookmarks() For other arguments that can be set in this function + * and passed to _walk_bookmarks(). + * @see get_bookmarks() For other arguments that can be set in this function and + * passed to get_bookmarks(). + * @link http://codex.wordpress.org/Template_Tags/wp_list_bookmarks + * + * @since 2.1.0 + * @uses _walk_bookmarks() Used to iterate over all of the bookmarks and return + * the html + * @uses get_terms() Gets all of the categories that are for links. + * + * @param string|array $args Optional. Overwrite the defaults of the function + * @return string|null Will only return if echo option is set to not echo. + * Default is not return anything. + */ +function wp_list_bookmarks($args = '') { + $defaults = array( + 'orderby' => 'name', 'order' => 'ASC', + 'limit' => -1, 'category' => '', 'exclude_category' => '', + 'category_name' => '', 'hide_invisible' => 1, + 'show_updated' => 0, 'echo' => 1, + 'categorize' => 1, 'title_li' => __('Bookmarks'), + 'title_before' => '<h2>', 'title_after' => '</h2>', + 'category_orderby' => 'name', 'category_order' => 'ASC', + 'class' => 'linkcat', 'category_before' => '<li id="%id" class="%class">', + 'category_after' => '</li>' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + $output = ''; + + if ( $categorize ) { + $cats = get_terms( 'link_category', array( 'name__like' => $category_name, 'include' => $category, 'exclude' => $exclude_category, 'orderby' => $category_orderby, 'order' => $category_order, 'hierarchical' => 0 ) ); + if ( empty( $cats ) ) + $categorize = false; + } + + if ( $categorize ) { + // Split the bookmarks into ul's for each category + foreach ( (array) $cats as $cat ) { + $params = array_merge($r, array('category'=>$cat->term_id)); + $bookmarks = get_bookmarks($params); + if ( empty($bookmarks) ) + continue; + $output .= str_replace(array('%id', '%class'), array("linkcat-$cat->term_id", $class), $category_before); + /** + * Filter the bookmarks category name. + * + * @since 2.2.0 + * + * @param string $cat->name The category name of bookmarks. + */ + $catname = apply_filters( 'link_category', $cat->name ); + + $output .= "$title_before$catname$title_after\n\t<ul class='xoxo blogroll'>\n"; + $output .= _walk_bookmarks($bookmarks, $r); + $output .= "\n\t</ul>\n$category_after\n"; + } + } else { + //output one single list using title_li for the title + $bookmarks = get_bookmarks($r); + + if ( !empty($bookmarks) ) { + if ( !empty( $title_li ) ){ + $output .= str_replace(array('%id', '%class'), array("linkcat-$category", $class), $category_before); + $output .= "$title_before$title_li$title_after\n\t<ul class='xoxo blogroll'>\n"; + $output .= _walk_bookmarks($bookmarks, $r); + $output .= "\n\t</ul>\n$category_after\n"; + } else { + $output .= _walk_bookmarks($bookmarks, $r); + } + } + } + + /** + * Filter the bookmarks list before it is echoed or returned. + * + * @since 2.5.0 + * + * @param string $output The HTML list of bookmarks. + */ + $output = apply_filters( 'wp_list_bookmarks', $output ); + + if ( !$echo ) + return $output; + echo $output; +} diff --git a/sources/wp-includes/bookmark.php b/sources/wp-includes/bookmark.php new file mode 100644 index 0000000..9a3ac61 --- /dev/null +++ b/sources/wp-includes/bookmark.php @@ -0,0 +1,387 @@ +<?php +/** + * Link/Bookmark API + * + * @package WordPress + * @subpackage Bookmark + */ + +/** + * Retrieve Bookmark data + * + * @since 2.1.0 + * @uses $wpdb Database Object + * + * @param mixed $bookmark + * @param string $output Optional. Either OBJECT, ARRAY_N, or ARRAY_A constant + * @param string $filter Optional, default is 'raw'. + * @return array|object Type returned depends on $output value. + */ +function get_bookmark($bookmark, $output = OBJECT, $filter = 'raw') { + global $wpdb; + + if ( empty($bookmark) ) { + if ( isset($GLOBALS['link']) ) + $_bookmark = & $GLOBALS['link']; + else + $_bookmark = null; + } elseif ( is_object($bookmark) ) { + wp_cache_add($bookmark->link_id, $bookmark, 'bookmark'); + $_bookmark = $bookmark; + } else { + if ( isset($GLOBALS['link']) && ($GLOBALS['link']->link_id == $bookmark) ) { + $_bookmark = & $GLOBALS['link']; + } elseif ( ! $_bookmark = wp_cache_get($bookmark, 'bookmark') ) { + $_bookmark = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->links WHERE link_id = %d LIMIT 1", $bookmark)); + if ( $_bookmark ) { + $_bookmark->link_category = array_unique( wp_get_object_terms( $_bookmark->link_id, 'link_category', array( 'fields' => 'ids' ) ) ); + wp_cache_add( $_bookmark->link_id, $_bookmark, 'bookmark' ); + } + } + } + + if ( ! $_bookmark ) + return $_bookmark; + + $_bookmark = sanitize_bookmark($_bookmark, $filter); + + if ( $output == OBJECT ) { + return $_bookmark; + } elseif ( $output == ARRAY_A ) { + return get_object_vars($_bookmark); + } elseif ( $output == ARRAY_N ) { + return array_values(get_object_vars($_bookmark)); + } else { + return $_bookmark; + } +} + +/** + * Retrieve single bookmark data item or field. + * + * @since 2.3.0 + * @uses get_bookmark() Gets bookmark object using $bookmark as ID + * @uses sanitize_bookmark_field() Sanitizes Bookmark field based on $context. + * + * @param string $field The name of the data field to return + * @param int $bookmark The bookmark ID to get field + * @param string $context Optional. The context of how the field will be used. + * @return string + */ +function get_bookmark_field( $field, $bookmark, $context = 'display' ) { + $bookmark = (int) $bookmark; + $bookmark = get_bookmark( $bookmark ); + + if ( is_wp_error($bookmark) ) + return $bookmark; + + if ( !is_object($bookmark) ) + return ''; + + if ( !isset($bookmark->$field) ) + return ''; + + return sanitize_bookmark_field($field, $bookmark->$field, $bookmark->link_id, $context); +} + +/** + * Retrieves the list of bookmarks + * + * Attempts to retrieve from the cache first based on MD5 hash of arguments. If + * that fails, then the query will be built from the arguments and executed. The + * results will be stored to the cache. + * + * List of default arguments are as follows: + * 'orderby' - Default is 'name' (string). How to order the links by. String is + * based off of the bookmark scheme. + * 'order' - Default is 'ASC' (string). Either 'ASC' or 'DESC'. Orders in either + * ascending or descending order. + * 'limit' - Default is -1 (integer) or show all. The amount of bookmarks to + * display. + * 'category' - Default is empty string (string). Include the links in what + * category ID(s). + * 'category_name' - Default is empty string (string). Get links by category + * name. + * 'hide_invisible' - Default is 1 (integer). Whether to show (default) or hide + * links marked as 'invisible'. + * 'show_updated' - Default is 0 (integer). Will show the time of when the + * bookmark was last updated. + * 'include' - Default is empty string (string). Include bookmark ID(s) + * separated by commas. + * 'exclude' - Default is empty string (string). Exclude bookmark ID(s) + * separated by commas. + * + * @since 2.1.0 + * @uses $wpdb Database Object + * @link http://codex.wordpress.org/Template_Tags/get_bookmarks + * + * @param string|array $args List of arguments to overwrite the defaults + * @return array List of bookmark row objects + */ +function get_bookmarks($args = '') { + global $wpdb; + + $defaults = array( + 'orderby' => 'name', 'order' => 'ASC', + 'limit' => -1, 'category' => '', + 'category_name' => '', 'hide_invisible' => 1, + 'show_updated' => 0, 'include' => '', + 'exclude' => '', 'search' => '' + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + $cache = array(); + $key = md5( serialize( $r ) ); + if ( $cache = wp_cache_get( 'get_bookmarks', 'bookmark' ) ) { + if ( is_array($cache) && isset( $cache[ $key ] ) ) + return apply_filters('get_bookmarks', $cache[ $key ], $r ); + } + + if ( !is_array($cache) ) + $cache = array(); + + $inclusions = ''; + if ( !empty($include) ) { + $exclude = ''; //ignore exclude, category, and category_name params if using include + $category = ''; + $category_name = ''; + $inclinks = preg_split('/[\s,]+/',$include); + if ( count($inclinks) ) { + foreach ( $inclinks as $inclink ) { + if (empty($inclusions)) + $inclusions = ' AND ( link_id = ' . intval($inclink) . ' '; + else + $inclusions .= ' OR link_id = ' . intval($inclink) . ' '; + } + } + } + if (!empty($inclusions)) + $inclusions .= ')'; + + $exclusions = ''; + if ( !empty($exclude) ) { + $exlinks = preg_split('/[\s,]+/',$exclude); + if ( count($exlinks) ) { + foreach ( $exlinks as $exlink ) { + if (empty($exclusions)) + $exclusions = ' AND ( link_id <> ' . intval($exlink) . ' '; + else + $exclusions .= ' AND link_id <> ' . intval($exlink) . ' '; + } + } + } + if (!empty($exclusions)) + $exclusions .= ')'; + + if ( !empty($category_name) ) { + if ( $category = get_term_by('name', $category_name, 'link_category') ) { + $category = $category->term_id; + } else { + $cache[ $key ] = array(); + wp_cache_set( 'get_bookmarks', $cache, 'bookmark' ); + return apply_filters( 'get_bookmarks', array(), $r ); + } + } + + if ( ! empty($search) ) { + $search = esc_sql( like_escape( $search ) ); + $search = " AND ( (link_url LIKE '%$search%') OR (link_name LIKE '%$search%') OR (link_description LIKE '%$search%') ) "; + } + + $category_query = ''; + $join = ''; + if ( !empty($category) ) { + $incategories = preg_split('/[\s,]+/',$category); + if ( count($incategories) ) { + foreach ( $incategories as $incat ) { + if (empty($category_query)) + $category_query = ' AND ( tt.term_id = ' . intval($incat) . ' '; + else + $category_query .= ' OR tt.term_id = ' . intval($incat) . ' '; + } + } + } + if (!empty($category_query)) { + $category_query .= ") AND taxonomy = 'link_category'"; + $join = " INNER JOIN $wpdb->term_relationships AS tr ON ($wpdb->links.link_id = tr.object_id) INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_taxonomy_id = tr.term_taxonomy_id"; + } + + if ( $show_updated && get_option('links_recently_updated_time') ) { + $recently_updated_test = ", IF (DATE_ADD(link_updated, INTERVAL " . get_option('links_recently_updated_time') . " MINUTE) >= NOW(), 1,0) as recently_updated "; + } else { + $recently_updated_test = ''; + } + + $get_updated = ( $show_updated ) ? ', UNIX_TIMESTAMP(link_updated) AS link_updated_f ' : ''; + + $orderby = strtolower($orderby); + $length = ''; + switch ( $orderby ) { + case 'length': + $length = ", CHAR_LENGTH(link_name) AS length"; + break; + case 'rand': + $orderby = 'rand()'; + break; + case 'link_id': + $orderby = "$wpdb->links.link_id"; + break; + default: + $orderparams = array(); + foreach ( explode(',', $orderby) as $ordparam ) { + $ordparam = trim($ordparam); + $keys = array( 'link_id', 'link_name', 'link_url', 'link_visible', 'link_rating', 'link_owner', 'link_updated', 'link_notes' ); + if ( in_array( 'link_' . $ordparam, $keys ) ) + $orderparams[] = 'link_' . $ordparam; + elseif ( in_array( $ordparam, $keys ) ) + $orderparams[] = $ordparam; + } + $orderby = implode(',', $orderparams); + } + + if ( empty( $orderby ) ) + $orderby = 'link_name'; + + $order = strtoupper( $order ); + if ( '' !== $order && !in_array( $order, array( 'ASC', 'DESC' ) ) ) + $order = 'ASC'; + + $visible = ''; + if ( $hide_invisible ) + $visible = "AND link_visible = 'Y'"; + + $query = "SELECT * $length $recently_updated_test $get_updated FROM $wpdb->links $join WHERE 1=1 $visible $category_query"; + $query .= " $exclusions $inclusions $search"; + $query .= " ORDER BY $orderby $order"; + if ($limit != -1) + $query .= " LIMIT $limit"; + + $results = $wpdb->get_results($query); + + $cache[ $key ] = $results; + wp_cache_set( 'get_bookmarks', $cache, 'bookmark' ); + + return apply_filters('get_bookmarks', $results, $r); +} + +/** + * Sanitizes all bookmark fields + * + * @since 2.3.0 + * + * @param object|array $bookmark Bookmark row + * @param string $context Optional, default is 'display'. How to filter the + * fields + * @return object|array Same type as $bookmark but with fields sanitized. + */ +function sanitize_bookmark($bookmark, $context = 'display') { + $fields = array('link_id', 'link_url', 'link_name', 'link_image', 'link_target', 'link_category', + 'link_description', 'link_visible', 'link_owner', 'link_rating', 'link_updated', + 'link_rel', 'link_notes', 'link_rss', ); + + if ( is_object($bookmark) ) { + $do_object = true; + $link_id = $bookmark->link_id; + } else { + $do_object = false; + $link_id = $bookmark['link_id']; + } + + foreach ( $fields as $field ) { + if ( $do_object ) { + if ( isset($bookmark->$field) ) + $bookmark->$field = sanitize_bookmark_field($field, $bookmark->$field, $link_id, $context); + } else { + if ( isset($bookmark[$field]) ) + $bookmark[$field] = sanitize_bookmark_field($field, $bookmark[$field], $link_id, $context); + } + } + + return $bookmark; +} + +/** + * Sanitizes a bookmark field + * + * Sanitizes the bookmark fields based on what the field name is. If the field + * has a strict value set, then it will be tested for that, else a more generic + * filtering is applied. After the more strict filter is applied, if the + * $context is 'raw' then the value is immediately return. + * + * Hooks exist for the more generic cases. With the 'edit' context, the + * 'edit_$field' filter will be called and passed the $value and $bookmark_id + * respectively. With the 'db' context, the 'pre_$field' filter is called and + * passed the value. The 'display' context is the final context and has the + * $field has the filter name and is passed the $value, $bookmark_id, and + * $context respectively. + * + * @since 2.3.0 + * + * @param string $field The bookmark field + * @param mixed $value The bookmark field value + * @param int $bookmark_id Bookmark ID + * @param string $context How to filter the field value. Either 'raw', 'edit', + * 'attribute', 'js', 'db', or 'display' + * @return mixed The filtered value + */ +function sanitize_bookmark_field($field, $value, $bookmark_id, $context) { + switch ( $field ) { + case 'link_id' : // ints + case 'link_rating' : + $value = (int) $value; + break; + case 'link_category' : // array( ints ) + $value = array_map('absint', (array) $value); + // We return here so that the categories aren't filtered. + // The 'link_category' filter is for the name of a link category, not an array of a link's link categories + return $value; + break; + case 'link_visible' : // bool stored as Y|N + $value = preg_replace('/[^YNyn]/', '', $value); + break; + case 'link_target' : // "enum" + $targets = array('_top', '_blank'); + if ( ! in_array($value, $targets) ) + $value = ''; + break; + } + + if ( 'raw' == $context ) + return $value; + + if ( 'edit' == $context ) { + $value = apply_filters("edit_$field", $value, $bookmark_id); + + if ( 'link_notes' == $field ) { + $value = esc_html( $value ); // textarea_escaped + } else { + $value = esc_attr($value); + } + } else if ( 'db' == $context ) { + $value = apply_filters("pre_$field", $value); + } else { + // Use display filters by default. + $value = apply_filters($field, $value, $bookmark_id, $context); + + if ( 'attribute' == $context ) + $value = esc_attr($value); + else if ( 'js' == $context ) + $value = esc_js($value); + } + + return $value; +} + +/** + * Deletes bookmark cache + * + * @since 2.7.0 + * @uses wp_cache_delete() Deletes the contents of 'get_bookmarks' + */ +function clean_bookmark_cache( $bookmark_id ) { + wp_cache_delete( $bookmark_id, 'bookmark' ); + wp_cache_delete( 'get_bookmarks', 'bookmark' ); + clean_object_term_cache( $bookmark_id, 'link'); +} diff --git a/sources/wp-includes/cache.php b/sources/wp-includes/cache.php new file mode 100644 index 0000000..f517d12 --- /dev/null +++ b/sources/wp-includes/cache.php @@ -0,0 +1,653 @@ +<?php +/** + * Object Cache API + * + * @link http://codex.wordpress.org/Function_Reference/WP_Cache + * + * @package WordPress + * @subpackage Cache + */ + +/** + * Adds data to the cache, if the cache key doesn't already exist. + * + * @since 2.0.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::add() + * + * @param int|string $key The cache key to use for retrieval later + * @param mixed $data The data to add to the cache store + * @param string $group The group to add the cache to + * @param int $expire When the cache data should be expired + * @return bool False if cache key and group already exist, true on success + */ +function wp_cache_add( $key, $data, $group = '', $expire = 0 ) { + global $wp_object_cache; + + return $wp_object_cache->add( $key, $data, $group, (int) $expire ); +} + +/** + * Closes the cache. + * + * This function has ceased to do anything since WordPress 2.5. The + * functionality was removed along with the rest of the persistent cache. This + * does not mean that plugins can't implement this function when they need to + * make sure that the cache is cleaned up after WordPress no longer needs it. + * + * @since 2.0.0 + * + * @return bool Always returns True + */ +function wp_cache_close() { + return true; +} + +/** + * Decrement numeric cache item's value + * + * @since 3.3.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::decr() + * + * @param int|string $key The cache key to increment + * @param int $offset The amount by which to decrement the item's value. Default is 1. + * @param string $group The group the key is in. + * @return false|int False on failure, the item's new value on success. + */ +function wp_cache_decr( $key, $offset = 1, $group = '' ) { + global $wp_object_cache; + + return $wp_object_cache->decr( $key, $offset, $group ); +} + +/** + * Removes the cache contents matching key and group. + * + * @since 2.0.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::delete() + * + * @param int|string $key What the contents in the cache are called + * @param string $group Where the cache contents are grouped + * @return bool True on successful removal, false on failure + */ +function wp_cache_delete($key, $group = '') { + global $wp_object_cache; + + return $wp_object_cache->delete($key, $group); +} + +/** + * Removes all cache items. + * + * @since 2.0.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::flush() + * + * @return bool False on failure, true on success + */ +function wp_cache_flush() { + global $wp_object_cache; + + return $wp_object_cache->flush(); +} + +/** + * Retrieves the cache contents from the cache by key and group. + * + * @since 2.0.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::get() + * + * @param int|string $key What the contents in the cache are called + * @param string $group Where the cache contents are grouped + * @param bool $force Whether to force an update of the local cache from the persistent cache (default is false) + * @param &bool $found Whether key was found in the cache. Disambiguates a return of false, a storable value. + * @return bool|mixed False on failure to retrieve contents or the cache + * contents on success + */ +function wp_cache_get( $key, $group = '', $force = false, &$found = null ) { + global $wp_object_cache; + + return $wp_object_cache->get( $key, $group, $force, $found ); +} + +/** + * Increment numeric cache item's value + * + * @since 3.3.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::incr() + * + * @param int|string $key The cache key to increment + * @param int $offset The amount by which to increment the item's value. Default is 1. + * @param string $group The group the key is in. + * @return false|int False on failure, the item's new value on success. + */ +function wp_cache_incr( $key, $offset = 1, $group = '' ) { + global $wp_object_cache; + + return $wp_object_cache->incr( $key, $offset, $group ); +} + +/** + * Sets up Object Cache Global and assigns it. + * + * @since 2.0.0 + * @global WP_Object_Cache $wp_object_cache WordPress Object Cache + */ +function wp_cache_init() { + $GLOBALS['wp_object_cache'] = new WP_Object_Cache(); +} + +/** + * Replaces the contents of the cache with new data. + * + * @since 2.0.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::replace() + * + * @param int|string $key What to call the contents in the cache + * @param mixed $data The contents to store in the cache + * @param string $group Where to group the cache contents + * @param int $expire When to expire the cache contents + * @return bool False if not exists, true if contents were replaced + */ +function wp_cache_replace( $key, $data, $group = '', $expire = 0 ) { + global $wp_object_cache; + + return $wp_object_cache->replace( $key, $data, $group, (int) $expire ); +} + +/** + * Saves the data to the cache. + * + * @since 2.0 + * @uses $wp_object_cache Object Cache Class + * @see WP_Object_Cache::set() + * + * @param int|string $key What to call the contents in the cache + * @param mixed $data The contents to store in the cache + * @param string $group Where to group the cache contents + * @param int $expire When to expire the cache contents + * @return bool False on failure, true on success + */ +function wp_cache_set( $key, $data, $group = '', $expire = 0 ) { + global $wp_object_cache; + + return $wp_object_cache->set( $key, $data, $group, (int) $expire ); +} + +/** + * Switch the interal blog id. + * + * This changes the blog id used to create keys in blog specific groups. + * + * @since 3.5.0 + * + * @param int $blog_id Blog ID + */ +function wp_cache_switch_to_blog( $blog_id ) { + global $wp_object_cache; + + return $wp_object_cache->switch_to_blog( $blog_id ); +} + +/** + * Adds a group or set of groups to the list of global groups. + * + * @since 2.6.0 + * + * @param string|array $groups A group or an array of groups to add + */ +function wp_cache_add_global_groups( $groups ) { + global $wp_object_cache; + + return $wp_object_cache->add_global_groups( $groups ); +} + +/** + * Adds a group or set of groups to the list of non-persistent groups. + * + * @since 2.6.0 + * + * @param string|array $groups A group or an array of groups to add + */ +function wp_cache_add_non_persistent_groups( $groups ) { + // Default cache doesn't persist so nothing to do here. + return; +} + +/** + * Reset internal cache keys and structures. If the cache backend uses global + * blog or site IDs as part of its cache keys, this function instructs the + * backend to reset those keys and perform any cleanup since blog or site IDs + * have changed since cache init. + * + * This function is deprecated. Use wp_cache_switch_to_blog() instead of this + * function when preparing the cache for a blog switch. For clearing the cache + * during unit tests, consider using wp_cache_init(). wp_cache_init() is not + * recommended outside of unit tests as the performance penality for using it is + * high. + * + * @since 2.6.0 + * @deprecated 3.5.0 + */ +function wp_cache_reset() { + _deprecated_function( __FUNCTION__, '3.5' ); + + global $wp_object_cache; + + return $wp_object_cache->reset(); +} + +/** + * WordPress Object Cache + * + * The WordPress Object Cache is used to save on trips to the database. The + * Object Cache stores all of the cache data to memory and makes the cache + * contents available by using a key, which is used to name and later retrieve + * the cache contents. + * + * The Object Cache can be replaced by other caching mechanisms by placing files + * in the wp-content folder which is looked at in wp-settings. If that file + * exists, then this file will not be included. + * + * @package WordPress + * @subpackage Cache + * @since 2.0 + */ +class WP_Object_Cache { + + /** + * Holds the cached objects + * + * @var array + * @access private + * @since 2.0.0 + */ + var $cache = array (); + + /** + * The amount of times the cache data was already stored in the cache. + * + * @since 2.5.0 + * @access private + * @var int + */ + var $cache_hits = 0; + + /** + * Amount of times the cache did not have the request in cache + * + * @var int + * @access public + * @since 2.0.0 + */ + var $cache_misses = 0; + + /** + * List of global groups + * + * @var array + * @access protected + * @since 3.0.0 + */ + var $global_groups = array(); + + /** + * The blog prefix to prepend to keys in non-global groups. + * + * @var int + * @access private + * @since 3.5.0 + */ + var $blog_prefix; + + /** + * Adds data to the cache if it doesn't already exist. + * + * @uses WP_Object_Cache::_exists Checks to see if the cache already has data. + * @uses WP_Object_Cache::set Sets the data after the checking the cache + * contents existence. + * + * @since 2.0.0 + * + * @param int|string $key What to call the contents in the cache + * @param mixed $data The contents to store in the cache + * @param string $group Where to group the cache contents + * @param int $expire When to expire the cache contents + * @return bool False if cache key and group already exist, true on success + */ + function add( $key, $data, $group = 'default', $expire = 0 ) { + if ( wp_suspend_cache_addition() ) + return false; + + if ( empty( $group ) ) + $group = 'default'; + + $id = $key; + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $id = $this->blog_prefix . $key; + + if ( $this->_exists( $id, $group ) ) + return false; + + return $this->set( $key, $data, $group, (int) $expire ); + } + + /** + * Sets the list of global groups. + * + * @since 3.0.0 + * + * @param array $groups List of groups that are global. + */ + function add_global_groups( $groups ) { + $groups = (array) $groups; + + $groups = array_fill_keys( $groups, true ); + $this->global_groups = array_merge( $this->global_groups, $groups ); + } + + /** + * Decrement numeric cache item's value + * + * @since 3.3.0 + * + * @param int|string $key The cache key to increment + * @param int $offset The amount by which to decrement the item's value. Default is 1. + * @param string $group The group the key is in. + * @return false|int False on failure, the item's new value on success. + */ + function decr( $key, $offset = 1, $group = 'default' ) { + if ( empty( $group ) ) + $group = 'default'; + + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $key = $this->blog_prefix . $key; + + if ( ! $this->_exists( $key, $group ) ) + return false; + + if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) + $this->cache[ $group ][ $key ] = 0; + + $offset = (int) $offset; + + $this->cache[ $group ][ $key ] -= $offset; + + if ( $this->cache[ $group ][ $key ] < 0 ) + $this->cache[ $group ][ $key ] = 0; + + return $this->cache[ $group ][ $key ]; + } + + /** + * Remove the contents of the cache key in the group + * + * If the cache key does not exist in the group and $force parameter is set + * to false, then nothing will happen. The $force parameter is set to false + * by default. + * + * @since 2.0.0 + * + * @param int|string $key What the contents in the cache are called + * @param string $group Where the cache contents are grouped + * @param bool $force Optional. Whether to force the unsetting of the cache + * key in the group + * @return bool False if the contents weren't deleted and true on success + */ + function delete($key, $group = 'default', $force = false) { + if ( empty( $group ) ) + $group = 'default'; + + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $key = $this->blog_prefix . $key; + + if ( ! $force && ! $this->_exists( $key, $group ) ) + return false; + + unset( $this->cache[$group][$key] ); + return true; + } + + /** + * Clears the object cache of all data + * + * @since 2.0.0 + * + * @return bool Always returns true + */ + function flush() { + $this->cache = array (); + + return true; + } + + /** + * Retrieves the cache contents, if it exists + * + * The contents will be first attempted to be retrieved by searching by the + * key in the cache group. If the cache is hit (success) then the contents + * are returned. + * + * On failure, the number of cache misses will be incremented. + * + * @since 2.0.0 + * + * @param int|string $key What the contents in the cache are called + * @param string $group Where the cache contents are grouped + * @param string $force Whether to force a refetch rather than relying on the local cache (default is false) + * @return bool|mixed False on failure to retrieve contents or the cache + * contents on success + */ + function get( $key, $group = 'default', $force = false, &$found = null ) { + if ( empty( $group ) ) + $group = 'default'; + + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $key = $this->blog_prefix . $key; + + if ( $this->_exists( $key, $group ) ) { + $found = true; + $this->cache_hits += 1; + if ( is_object($this->cache[$group][$key]) ) + return clone $this->cache[$group][$key]; + else + return $this->cache[$group][$key]; + } + + $found = false; + $this->cache_misses += 1; + return false; + } + + /** + * Increment numeric cache item's value + * + * @since 3.3.0 + * + * @param int|string $key The cache key to increment + * @param int $offset The amount by which to increment the item's value. Default is 1. + * @param string $group The group the key is in. + * @return false|int False on failure, the item's new value on success. + */ + function incr( $key, $offset = 1, $group = 'default' ) { + if ( empty( $group ) ) + $group = 'default'; + + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $key = $this->blog_prefix . $key; + + if ( ! $this->_exists( $key, $group ) ) + return false; + + if ( ! is_numeric( $this->cache[ $group ][ $key ] ) ) + $this->cache[ $group ][ $key ] = 0; + + $offset = (int) $offset; + + $this->cache[ $group ][ $key ] += $offset; + + if ( $this->cache[ $group ][ $key ] < 0 ) + $this->cache[ $group ][ $key ] = 0; + + return $this->cache[ $group ][ $key ]; + } + + /** + * Replace the contents in the cache, if contents already exist + * + * @since 2.0.0 + * @see WP_Object_Cache::set() + * + * @param int|string $key What to call the contents in the cache + * @param mixed $data The contents to store in the cache + * @param string $group Where to group the cache contents + * @param int $expire When to expire the cache contents + * @return bool False if not exists, true if contents were replaced + */ + function replace( $key, $data, $group = 'default', $expire = 0 ) { + if ( empty( $group ) ) + $group = 'default'; + + $id = $key; + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $id = $this->blog_prefix . $key; + + if ( ! $this->_exists( $id, $group ) ) + return false; + + return $this->set( $key, $data, $group, (int) $expire ); + } + + /** + * Reset keys + * + * @since 3.0.0 + * @deprecated 3.5.0 + */ + function reset() { + _deprecated_function( __FUNCTION__, '3.5', 'switch_to_blog()' ); + + // Clear out non-global caches since the blog ID has changed. + foreach ( array_keys( $this->cache ) as $group ) { + if ( ! isset( $this->global_groups[ $group ] ) ) + unset( $this->cache[ $group ] ); + } + } + + /** + * Sets the data contents into the cache + * + * The cache contents is grouped by the $group parameter followed by the + * $key. This allows for duplicate ids in unique groups. Therefore, naming of + * the group should be used with care and should follow normal function + * naming guidelines outside of core WordPress usage. + * + * The $expire parameter is not used, because the cache will automatically + * expire for each time a page is accessed and PHP finishes. The method is + * more for cache plugins which use files. + * + * @since 2.0.0 + * + * @param int|string $key What to call the contents in the cache + * @param mixed $data The contents to store in the cache + * @param string $group Where to group the cache contents + * @param int $expire Not Used + * @return bool Always returns true + */ + function set( $key, $data, $group = 'default', $expire = 0 ) { + if ( empty( $group ) ) + $group = 'default'; + + if ( $this->multisite && ! isset( $this->global_groups[ $group ] ) ) + $key = $this->blog_prefix . $key; + + if ( is_object( $data ) ) + $data = clone $data; + + $this->cache[$group][$key] = $data; + return true; + } + + /** + * Echoes the stats of the caching. + * + * Gives the cache hits, and cache misses. Also prints every cached group, + * key and the data. + * + * @since 2.0.0 + */ + function stats() { + echo "<p>"; + echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />"; + echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />"; + echo "</p>"; + echo '<ul>'; + foreach ($this->cache as $group => $cache) { + echo "<li><strong>Group:</strong> $group - ( " . number_format( strlen( serialize( $cache ) ) / 1024, 2 ) . 'k )</li>'; + } + echo '</ul>'; + } + + /** + * Switch the interal blog id. + * + * This changes the blog id used to create keys in blog specific groups. + * + * @since 3.5.0 + * + * @param int $blog_id Blog ID + */ + function switch_to_blog( $blog_id ) { + $blog_id = (int) $blog_id; + $this->blog_prefix = $this->multisite ? $blog_id . ':' : ''; + } + + /** + * Utility function to determine whether a key exists in the cache. + * + * @since 3.4.0 + * + * @access protected + */ + protected function _exists( $key, $group ) { + return isset( $this->cache[ $group ] ) && ( isset( $this->cache[ $group ][ $key ] ) || array_key_exists( $key, $this->cache[ $group ] ) ); + } + + /** + * Sets up object properties; PHP 5 style constructor + * + * @since 2.0.8 + * @return null|WP_Object_Cache If cache is disabled, returns null. + */ + function __construct() { + global $blog_id; + + $this->multisite = is_multisite(); + $this->blog_prefix = $this->multisite ? $blog_id . ':' : ''; + + + /** + * @todo This should be moved to the PHP4 style constructor, PHP5 + * already calls __destruct() + */ + register_shutdown_function( array( $this, '__destruct' ) ); + } + + /** + * Will save the object cache before object is completely destroyed. + * + * Called upon object destruction, which should be when PHP ends. + * + * @since 2.0.8 + * + * @return bool True value. Won't be used by PHP + */ + function __destruct() { + return true; + } +} diff --git a/sources/wp-includes/canonical.php b/sources/wp-includes/canonical.php new file mode 100644 index 0000000..231855e --- /dev/null +++ b/sources/wp-includes/canonical.php @@ -0,0 +1,560 @@ +<?php +/** + * Canonical API to handle WordPress Redirecting + * + * Based on "Permalink Redirect" from Scott Yang and "Enforce www. Preference" + * by Mark Jaquith + * + * @package WordPress + * @since 2.3.0 + */ + +/** + * Redirects incoming links to the proper URL based on the site url. + * + * Search engines consider www.somedomain.com and somedomain.com to be two + * different URLs when they both go to the same location. This SEO enhancement + * prevents penalty for duplicate content by redirecting all incoming links to + * one or the other. + * + * Prevents redirection for feeds, trackbacks, searches, comment popup, and + * admin URLs. Does not redirect on non-pretty-permalink-supporting IIS 7+, + * page/post previews, WP admin, Trackbacks, robots.txt, searches, or on POST + * requests. + * + * Will also attempt to find the correct link when a user enters a URL that does + * not exist based on exact WordPress query. Will instead try to parse the URL + * or query in an attempt to figure the correct page to go to. + * + * @since 2.3.0 + * @uses $wp_rewrite + * @uses $is_IIS + * + * @param string $requested_url Optional. The URL that was requested, used to + * figure if redirect is needed. + * @param bool $do_redirect Optional. Redirect to the new URL. + * @return null|false|string Null, if redirect not needed. False, if redirect + * not needed or the string of the URL + */ +function redirect_canonical( $requested_url = null, $do_redirect = true ) { + global $wp_rewrite, $is_IIS, $wp_query, $wpdb; + + if ( is_trackback() || is_search() || is_comments_popup() || is_admin() || !empty($_POST) || is_preview() || is_robots() || ( $is_IIS && !iis7_supports_permalinks() ) ) + return; + + if ( !$requested_url ) { + // build the URL in the address bar + $requested_url = is_ssl() ? 'https://' : 'http://'; + $requested_url .= $_SERVER['HTTP_HOST']; + $requested_url .= $_SERVER['REQUEST_URI']; + } + + $original = @parse_url($requested_url); + if ( false === $original ) + return; + + // Some PHP setups turn requests for / into /index.php in REQUEST_URI + // See: http://trac.wordpress.org/ticket/5017 + // See: http://trac.wordpress.org/ticket/7173 + // Disabled, for now: + // $original['path'] = preg_replace('|/index\.php$|', '/', $original['path']); + + $redirect = $original; + $redirect_url = false; + + // Notice fixing + if ( !isset($redirect['path']) ) + $redirect['path'] = ''; + if ( !isset($redirect['query']) ) + $redirect['query'] = ''; + + if ( is_feed() && ( $id = get_query_var( 'p' ) ) ) { + if ( $redirect_url = get_post_comments_feed_link( $id, get_query_var( 'feed' ) ) ) { + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'p', 'page_id', 'attachment_id', 'pagename', 'name', 'post_type', 'feed'), $redirect_url ); + $redirect['path'] = parse_url( $redirect_url, PHP_URL_PATH ); + } + } + + if ( is_singular() && 1 > $wp_query->post_count && ($id = get_query_var('p')) ) { + + $vars = $wpdb->get_results( $wpdb->prepare("SELECT post_type, post_parent FROM $wpdb->posts WHERE ID = %d", $id) ); + + if ( isset($vars[0]) && $vars = $vars[0] ) { + if ( 'revision' == $vars->post_type && $vars->post_parent > 0 ) + $id = $vars->post_parent; + + if ( $redirect_url = get_permalink($id) ) + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'p', 'page_id', 'attachment_id', 'pagename', 'name', 'post_type' ), $redirect_url ); + } + } + + // These tests give us a WP-generated permalink + if ( is_404() ) { + + // Redirect ?page_id, ?p=, ?attachment_id= to their respective url's + $id = max( get_query_var('p'), get_query_var('page_id'), get_query_var('attachment_id') ); + if ( $id && $redirect_post = get_post($id) ) { + $post_type_obj = get_post_type_object($redirect_post->post_type); + if ( $post_type_obj->public ) { + $redirect_url = get_permalink($redirect_post); + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'p', 'page_id', 'attachment_id', 'pagename', 'name', 'post_type' ), $redirect_url ); + } + } + + if ( get_query_var( 'day' ) && get_query_var( 'monthnum' ) && get_query_var( 'year' ) ) { + $year = get_query_var( 'year' ); + $month = get_query_var( 'monthnum' ); + $day = get_query_var( 'day' ); + $date = sprintf( '%04d-%02d-%02d', $year, $month, $day ); + if ( ! wp_checkdate( $month, $day, $year, $date ) ) { + $redirect_url = get_month_link( $year, $month ); + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'year', 'monthnum', 'day' ), $redirect_url ); + } + } elseif ( get_query_var( 'monthnum' ) && get_query_var( 'year' ) && 12 < get_query_var( 'monthnum' ) ) { + $redirect_url = get_year_link( get_query_var( 'year' ) ); + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'year', 'monthnum' ), $redirect_url ); + } + + if ( ! $redirect_url ) { + if ( $redirect_url = redirect_guess_404_permalink() ) { + $redirect['query'] = _remove_qs_args_if_not_in_url( $redirect['query'], array( 'page', 'feed', 'p', 'page_id', 'attachment_id', 'pagename', 'name', 'post_type' ), $redirect_url ); + } + } + + } elseif ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) { + // rewriting of old ?p=X, ?m=2004, ?m=200401, ?m=20040101 + if ( is_attachment() && !empty($_GET['attachment_id']) && ! $redirect_url ) { + if ( $redirect_url = get_attachment_link(get_query_var('attachment_id')) ) + $redirect['query'] = remove_query_arg('attachment_id', $redirect['query']); + } elseif ( is_single() && !empty($_GET['p']) && ! $redirect_url ) { + if ( $redirect_url = get_permalink(get_query_var('p')) ) + $redirect['query'] = remove_query_arg(array('p', 'post_type'), $redirect['query']); + } elseif ( is_single() && !empty($_GET['name']) && ! $redirect_url ) { + if ( $redirect_url = get_permalink( $wp_query->get_queried_object_id() ) ) + $redirect['query'] = remove_query_arg('name', $redirect['query']); + } elseif ( is_page() && !empty($_GET['page_id']) && ! $redirect_url ) { + if ( $redirect_url = get_permalink(get_query_var('page_id')) ) + $redirect['query'] = remove_query_arg('page_id', $redirect['query']); + } elseif ( is_page() && !is_feed() && isset($wp_query->queried_object) && 'page' == get_option('show_on_front') && $wp_query->queried_object->ID == get_option('page_on_front') && ! $redirect_url ) { + $redirect_url = home_url('/'); + } elseif ( is_home() && !empty($_GET['page_id']) && 'page' == get_option('show_on_front') && get_query_var('page_id') == get_option('page_for_posts') && ! $redirect_url ) { + if ( $redirect_url = get_permalink(get_option('page_for_posts')) ) + $redirect['query'] = remove_query_arg('page_id', $redirect['query']); + } elseif ( !empty($_GET['m']) && ( is_year() || is_month() || is_day() ) ) { + $m = get_query_var('m'); + switch ( strlen($m) ) { + case 4: // Yearly + $redirect_url = get_year_link($m); + break; + case 6: // Monthly + $redirect_url = get_month_link( substr($m, 0, 4), substr($m, 4, 2) ); + break; + case 8: // Daily + $redirect_url = get_day_link(substr($m, 0, 4), substr($m, 4, 2), substr($m, 6, 2)); + break; + } + if ( $redirect_url ) + $redirect['query'] = remove_query_arg('m', $redirect['query']); + // now moving on to non ?m=X year/month/day links + } elseif ( is_day() && get_query_var('year') && get_query_var('monthnum') && !empty($_GET['day']) ) { + if ( $redirect_url = get_day_link(get_query_var('year'), get_query_var('monthnum'), get_query_var('day')) ) + $redirect['query'] = remove_query_arg(array('year', 'monthnum', 'day'), $redirect['query']); + } elseif ( is_month() && get_query_var('year') && !empty($_GET['monthnum']) ) { + if ( $redirect_url = get_month_link(get_query_var('year'), get_query_var('monthnum')) ) + $redirect['query'] = remove_query_arg(array('year', 'monthnum'), $redirect['query']); + } elseif ( is_year() && !empty($_GET['year']) ) { + if ( $redirect_url = get_year_link(get_query_var('year')) ) + $redirect['query'] = remove_query_arg('year', $redirect['query']); + } elseif ( is_author() && !empty($_GET['author']) && preg_match( '|^[0-9]+$|', $_GET['author'] ) ) { + $author = get_userdata(get_query_var('author')); + if ( ( false !== $author ) && $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE $wpdb->posts.post_author = %d AND $wpdb->posts.post_status = 'publish' LIMIT 1", $author->ID ) ) ) { + if ( $redirect_url = get_author_posts_url($author->ID, $author->user_nicename) ) + $redirect['query'] = remove_query_arg('author', $redirect['query']); + } + } elseif ( is_category() || is_tag() || is_tax() ) { // Terms (Tags/categories) + + $term_count = 0; + foreach ( $wp_query->tax_query->queries as $tax_query ) + $term_count += count( $tax_query['terms'] ); + + $obj = $wp_query->get_queried_object(); + if ( $term_count <= 1 && !empty($obj->term_id) && ( $tax_url = get_term_link((int)$obj->term_id, $obj->taxonomy) ) && !is_wp_error($tax_url) ) { + if ( !empty($redirect['query']) ) { + // Strip taxonomy query vars off the url. + $qv_remove = array( 'term', 'taxonomy'); + if ( is_category() ) { + $qv_remove[] = 'category_name'; + $qv_remove[] = 'cat'; + } elseif ( is_tag() ) { + $qv_remove[] = 'tag'; + $qv_remove[] = 'tag_id'; + } else { // Custom taxonomies will have a custom query var, remove those too: + $tax_obj = get_taxonomy( $obj->taxonomy ); + if ( false !== $tax_obj->query_var ) + $qv_remove[] = $tax_obj->query_var; + } + + $rewrite_vars = array_diff( array_keys($wp_query->query), array_keys($_GET) ); + + if ( !array_diff($rewrite_vars, array_keys($_GET)) ) { // Check to see if all the Query vars are coming from the rewrite, none are set via $_GET + $redirect['query'] = remove_query_arg($qv_remove, $redirect['query']); //Remove all of the per-tax qv's + + // Create the destination url for this taxonomy + $tax_url = parse_url($tax_url); + if ( ! empty($tax_url['query']) ) { // Taxonomy accessible via ?taxonomy=..&term=.. or any custom qv.. + parse_str($tax_url['query'], $query_vars); + $redirect['query'] = add_query_arg($query_vars, $redirect['query']); + } else { // Taxonomy is accessible via a "pretty-URL" + $redirect['path'] = $tax_url['path']; + } + + } else { // Some query vars are set via $_GET. Unset those from $_GET that exist via the rewrite + foreach ( $qv_remove as $_qv ) { + if ( isset($rewrite_vars[$_qv]) ) + $redirect['query'] = remove_query_arg($_qv, $redirect['query']); + } + } + } + + } + } elseif ( is_single() && strpos($wp_rewrite->permalink_structure, '%category%') !== false && $cat = get_query_var( 'category_name' ) ) { + $category = get_category_by_path( $cat ); + $post_terms = wp_get_object_terms($wp_query->get_queried_object_id(), 'category', array('fields' => 'tt_ids')); + if ( (!$category || is_wp_error($category)) || ( !is_wp_error($post_terms) && !empty($post_terms) && !in_array($category->term_taxonomy_id, $post_terms) ) ) + $redirect_url = get_permalink($wp_query->get_queried_object_id()); + } + + // Post Paging + if ( is_singular() && ! is_front_page() && get_query_var('page') ) { + if ( !$redirect_url ) + $redirect_url = get_permalink( get_queried_object_id() ); + $redirect_url = trailingslashit( $redirect_url ) . user_trailingslashit( get_query_var( 'page' ), 'single_paged' ); + $redirect['query'] = remove_query_arg( 'page', $redirect['query'] ); + } + + // paging and feeds + if ( get_query_var('paged') || is_feed() || get_query_var('cpage') ) { + while ( preg_match( "#/$wp_rewrite->pagination_base/?[0-9]+?(/+)?$#", $redirect['path'] ) || preg_match( '#/(comments/?)?(feed|rss|rdf|atom|rss2)(/+)?$#', $redirect['path'] ) || preg_match( '#/comment-page-[0-9]+(/+)?$#', $redirect['path'] ) ) { + // Strip off paging and feed + $redirect['path'] = preg_replace("#/$wp_rewrite->pagination_base/?[0-9]+?(/+)?$#", '/', $redirect['path']); // strip off any existing paging + $redirect['path'] = preg_replace('#/(comments/?)?(feed|rss2?|rdf|atom)(/+|$)#', '/', $redirect['path']); // strip off feed endings + $redirect['path'] = preg_replace('#/comment-page-[0-9]+?(/+)?$#', '/', $redirect['path']); // strip off any existing comment paging + } + + $addl_path = ''; + if ( is_feed() && in_array( get_query_var('feed'), $wp_rewrite->feeds ) ) { + $addl_path = !empty( $addl_path ) ? trailingslashit($addl_path) : ''; + if ( !is_singular() && get_query_var( 'withcomments' ) ) + $addl_path .= 'comments/'; + if ( ( 'rss' == get_default_feed() && 'feed' == get_query_var('feed') ) || 'rss' == get_query_var('feed') ) + $addl_path .= user_trailingslashit( 'feed/' . ( ( get_default_feed() == 'rss2' ) ? '' : 'rss2' ), 'feed' ); + else + $addl_path .= user_trailingslashit( 'feed/' . ( ( get_default_feed() == get_query_var('feed') || 'feed' == get_query_var('feed') ) ? '' : get_query_var('feed') ), 'feed' ); + $redirect['query'] = remove_query_arg( 'feed', $redirect['query'] ); + } elseif ( is_feed() && 'old' == get_query_var('feed') ) { + $old_feed_files = array( + 'wp-atom.php' => 'atom', + 'wp-commentsrss2.php' => 'comments_rss2', + 'wp-feed.php' => get_default_feed(), + 'wp-rdf.php' => 'rdf', + 'wp-rss.php' => 'rss2', + 'wp-rss2.php' => 'rss2', + ); + if ( isset( $old_feed_files[ basename( $redirect['path'] ) ] ) ) { + $redirect_url = get_feed_link( $old_feed_files[ basename( $redirect['path'] ) ] ); + wp_redirect( $redirect_url, 301 ); + die(); + } + } + + if ( get_query_var('paged') > 0 ) { + $paged = get_query_var('paged'); + $redirect['query'] = remove_query_arg( 'paged', $redirect['query'] ); + if ( !is_feed() ) { + if ( $paged > 1 && !is_single() ) { + $addl_path = ( !empty( $addl_path ) ? trailingslashit($addl_path) : '' ) . user_trailingslashit("$wp_rewrite->pagination_base/$paged", 'paged'); + } elseif ( !is_single() ) { + $addl_path = !empty( $addl_path ) ? trailingslashit($addl_path) : ''; + } + } elseif ( $paged > 1 ) { + $redirect['query'] = add_query_arg( 'paged', $paged, $redirect['query'] ); + } + } + + if ( get_option('page_comments') && ( ( 'newest' == get_option('default_comments_page') && get_query_var('cpage') > 0 ) || ( 'newest' != get_option('default_comments_page') && get_query_var('cpage') > 1 ) ) ) { + $addl_path = ( !empty( $addl_path ) ? trailingslashit($addl_path) : '' ) . user_trailingslashit( 'comment-page-' . get_query_var('cpage'), 'commentpaged' ); + $redirect['query'] = remove_query_arg( 'cpage', $redirect['query'] ); + } + + $redirect['path'] = user_trailingslashit( preg_replace('|/' . preg_quote( $wp_rewrite->index, '|' ) . '/?$|', '/', $redirect['path']) ); // strip off trailing /index.php/ + if ( !empty( $addl_path ) && $wp_rewrite->using_index_permalinks() && strpos($redirect['path'], '/' . $wp_rewrite->index . '/') === false ) + $redirect['path'] = trailingslashit($redirect['path']) . $wp_rewrite->index . '/'; + if ( !empty( $addl_path ) ) + $redirect['path'] = trailingslashit($redirect['path']) . $addl_path; + $redirect_url = $redirect['scheme'] . '://' . $redirect['host'] . $redirect['path']; + } + + if ( 'wp-register.php' == basename( $redirect['path'] ) ) { + if ( is_multisite() ) + /** This filter is documented in wp-login.php */ + $redirect_url = apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) ); + else + $redirect_url = site_url( 'wp-login.php?action=register' ); + wp_redirect( $redirect_url, 301 ); + die(); + } + } + + // tack on any additional query vars + $redirect['query'] = preg_replace( '#^\??&*?#', '', $redirect['query'] ); + if ( $redirect_url && !empty($redirect['query']) ) { + parse_str( $redirect['query'], $_parsed_query ); + $redirect = @parse_url($redirect_url); + + if ( ! empty( $_parsed_query['name'] ) && ! empty( $redirect['query'] ) ) { + parse_str( $redirect['query'], $_parsed_redirect_query ); + + if ( empty( $_parsed_redirect_query['name'] ) ) + unset( $_parsed_query['name'] ); + } + + $_parsed_query = rawurlencode_deep( $_parsed_query ); + $redirect_url = add_query_arg( $_parsed_query, $redirect_url ); + } + + if ( $redirect_url ) + $redirect = @parse_url($redirect_url); + + // www.example.com vs example.com + $user_home = @parse_url(home_url()); + if ( !empty($user_home['host']) ) + $redirect['host'] = $user_home['host']; + if ( empty($user_home['path']) ) + $user_home['path'] = '/'; + + // Handle ports + if ( !empty($user_home['port']) ) + $redirect['port'] = $user_home['port']; + else + unset($redirect['port']); + + // trailing /index.php + $redirect['path'] = preg_replace('|/' . preg_quote( $wp_rewrite->index, '|' ) . '/*?$|', '/', $redirect['path']); + + // Remove trailing spaces from the path + $redirect['path'] = preg_replace( '#(%20| )+$#', '', $redirect['path'] ); + + if ( !empty( $redirect['query'] ) ) { + // Remove trailing spaces from certain terminating query string args + $redirect['query'] = preg_replace( '#((p|page_id|cat|tag)=[^&]*?)(%20| )+$#', '$1', $redirect['query'] ); + + // Clean up empty query strings + $redirect['query'] = trim(preg_replace( '#(^|&)(p|page_id|cat|tag)=?(&|$)#', '&', $redirect['query']), '&'); + + // Redirect obsolete feeds + $redirect['query'] = preg_replace( '#(^|&)feed=rss(&|$)#', '$1feed=rss2$2', $redirect['query'] ); + + // Remove redundant leading ampersands + $redirect['query'] = preg_replace( '#^\??&*?#', '', $redirect['query'] ); + } + + // strip /index.php/ when we're not using PATHINFO permalinks + if ( !$wp_rewrite->using_index_permalinks() ) + $redirect['path'] = str_replace( '/' . $wp_rewrite->index . '/', '/', $redirect['path'] ); + + // trailing slashes + if ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() && !is_404() && (!is_front_page() || ( is_front_page() && (get_query_var('paged') > 1) ) ) ) { + $user_ts_type = ''; + if ( get_query_var('paged') > 0 ) { + $user_ts_type = 'paged'; + } else { + foreach ( array('single', 'category', 'page', 'day', 'month', 'year', 'home') as $type ) { + $func = 'is_' . $type; + if ( call_user_func($func) ) { + $user_ts_type = $type; + break; + } + } + } + $redirect['path'] = user_trailingslashit($redirect['path'], $user_ts_type); + } elseif ( is_front_page() ) { + $redirect['path'] = trailingslashit($redirect['path']); + } + + // Strip multiple slashes out of the URL + if ( strpos($redirect['path'], '//') > -1 ) + $redirect['path'] = preg_replace('|/+|', '/', $redirect['path']); + + // Always trailing slash the Front Page URL + if ( trailingslashit( $redirect['path'] ) == trailingslashit( $user_home['path'] ) ) + $redirect['path'] = trailingslashit($redirect['path']); + + // Ignore differences in host capitalization, as this can lead to infinite redirects + // Only redirect no-www <=> yes-www + if ( strtolower($original['host']) == strtolower($redirect['host']) || + ( strtolower($original['host']) != 'www.' . strtolower($redirect['host']) && 'www.' . strtolower($original['host']) != strtolower($redirect['host']) ) ) + $redirect['host'] = $original['host']; + + $compare_original = array($original['host'], $original['path']); + + if ( !empty( $original['port'] ) ) + $compare_original[] = $original['port']; + + if ( !empty( $original['query'] ) ) + $compare_original[] = $original['query']; + + $compare_redirect = array($redirect['host'], $redirect['path']); + + if ( !empty( $redirect['port'] ) ) + $compare_redirect[] = $redirect['port']; + + if ( !empty( $redirect['query'] ) ) + $compare_redirect[] = $redirect['query']; + + if ( $compare_original !== $compare_redirect ) { + $redirect_url = $redirect['scheme'] . '://' . $redirect['host']; + if ( !empty($redirect['port']) ) + $redirect_url .= ':' . $redirect['port']; + $redirect_url .= $redirect['path']; + if ( !empty($redirect['query']) ) + $redirect_url .= '?' . $redirect['query']; + } + + if ( !$redirect_url || $redirect_url == $requested_url ) + return false; + + // Hex encoded octets are case-insensitive. + if ( false !== strpos($requested_url, '%') ) { + if ( !function_exists('lowercase_octets') ) { + function lowercase_octets($matches) { + return strtolower( $matches[0] ); + } + } + $requested_url = preg_replace_callback('|%[a-fA-F0-9][a-fA-F0-9]|', 'lowercase_octets', $requested_url); + } + + /** + * Filter the canonical redirect URL. + * + * Returning false to this filter will cancel the redirect. + * + * @since 2.3.0 + * + * @param string $redirect_url The redirect URL. + * @param string $requested_url The requested URL. + */ + $redirect_url = apply_filters( 'redirect_canonical', $redirect_url, $requested_url ); + + if ( !$redirect_url || $redirect_url == $requested_url ) // yes, again -- in case the filter aborted the request + return false; + + if ( $do_redirect ) { + // protect against chained redirects + if ( !redirect_canonical($redirect_url, false) ) { + wp_redirect($redirect_url, 301); + exit(); + } else { + // Debug + // die("1: $redirect_url<br />2: " . redirect_canonical( $redirect_url, false ) ); + return false; + } + } else { + return $redirect_url; + } +} + +/** + * Removes arguments from a query string if they are not present in a URL + * DO NOT use this in plugin code. + * + * @since 3.4 + * @access private + * + * @return string The altered query string + */ +function _remove_qs_args_if_not_in_url( $query_string, Array $args_to_check, $url ) { + $parsed_url = @parse_url( $url ); + if ( ! empty( $parsed_url['query'] ) ) { + parse_str( $parsed_url['query'], $parsed_query ); + foreach ( $args_to_check as $qv ) { + if ( !isset( $parsed_query[$qv] ) ) + $query_string = remove_query_arg( $qv, $query_string ); + } + } else { + $query_string = remove_query_arg( $args_to_check, $query_string ); + } + return $query_string; +} + +/** + * Attempts to guess the correct URL based on query vars + * + * @since 2.3.0 + * @uses $wpdb + * + * @return bool|string The correct URL if one is found. False on failure. + */ +function redirect_guess_404_permalink() { + global $wpdb, $wp_rewrite; + + if ( get_query_var('name') ) { + $where = $wpdb->prepare("post_name LIKE %s", like_escape( get_query_var('name') ) . '%'); + + // if any of post_type, year, monthnum, or day are set, use them to refine the query + if ( get_query_var('post_type') ) + $where .= $wpdb->prepare(" AND post_type = %s", get_query_var('post_type')); + else + $where .= " AND post_type IN ('" . implode( "', '", get_post_types( array( 'public' => true ) ) ) . "')"; + + if ( get_query_var('year') ) + $where .= $wpdb->prepare(" AND YEAR(post_date) = %d", get_query_var('year')); + if ( get_query_var('monthnum') ) + $where .= $wpdb->prepare(" AND MONTH(post_date) = %d", get_query_var('monthnum')); + if ( get_query_var('day') ) + $where .= $wpdb->prepare(" AND DAYOFMONTH(post_date) = %d", get_query_var('day')); + + $post_id = $wpdb->get_var("SELECT ID FROM $wpdb->posts WHERE $where AND post_status = 'publish'"); + if ( ! $post_id ) + return false; + if ( get_query_var( 'feed' ) ) + return get_post_comments_feed_link( $post_id, get_query_var( 'feed' ) ); + elseif ( get_query_var( 'page' ) ) + return trailingslashit( get_permalink( $post_id ) ) . user_trailingslashit( get_query_var( 'page' ), 'single_paged' ); + else + return get_permalink( $post_id ); + } + + return false; +} + +add_action('template_redirect', 'redirect_canonical'); + +function wp_redirect_admin_locations() { + global $wp_rewrite; + if ( ! ( is_404() && $wp_rewrite->using_permalinks() ) ) + return; + + $admins = array( + home_url( 'wp-admin', 'relative' ), + home_url( 'dashboard', 'relative' ), + home_url( 'admin', 'relative' ), + site_url( 'dashboard', 'relative' ), + site_url( 'admin', 'relative' ), + ); + if ( in_array( untrailingslashit( $_SERVER['REQUEST_URI'] ), $admins ) ) { + wp_redirect( admin_url() ); + exit; + } + + $logins = array( + home_url( 'wp-login.php', 'relative' ), + home_url( 'login', 'relative' ), + site_url( 'login', 'relative' ), + ); + if ( in_array( untrailingslashit( $_SERVER['REQUEST_URI'] ), $logins ) ) { + wp_redirect( site_url( 'wp-login.php', 'login' ) ); + exit; + } +} + +add_action( 'template_redirect', 'wp_redirect_admin_locations', 1000 ); diff --git a/sources/wp-includes/capabilities.php b/sources/wp-includes/capabilities.php new file mode 100644 index 0000000..75a834b --- /dev/null +++ b/sources/wp-includes/capabilities.php @@ -0,0 +1,1472 @@ +<?php +/** + * WordPress Roles and Capabilities. + * + * @package WordPress + * @subpackage User + */ + +/** + * WordPress User Roles. + * + * The role option is simple, the structure is organized by role name that store + * the name in value of the 'name' key. The capabilities are stored as an array + * in the value of the 'capability' key. + * + * <code> + * array ( + * 'rolename' => array ( + * 'name' => 'rolename', + * 'capabilities' => array() + * ) + * ) + * </code> + * + * @since 2.0.0 + * @package WordPress + * @subpackage User + */ +class WP_Roles { + /** + * List of roles and capabilities. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $roles; + + /** + * List of the role objects. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $role_objects = array(); + + /** + * List of role names. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $role_names = array(); + + /** + * Option name for storing role list. + * + * @since 2.0.0 + * @access public + * @var string + */ + var $role_key; + + /** + * Whether to use the database for retrieval and storage. + * + * @since 2.1.0 + * @access public + * @var bool + */ + var $use_db = true; + + /** + * Constructor + * + * @since 2.0.0 + */ + function __construct() { + $this->_init(); + } + + /** + * Set up the object properties. + * + * The role key is set to the current prefix for the $wpdb object with + * 'user_roles' appended. If the $wp_user_roles global is set, then it will + * be used and the role option will not be updated or used. + * + * @since 2.1.0 + * @access protected + * @uses $wpdb Used to get the database prefix. + * @global array $wp_user_roles Used to set the 'roles' property value. + */ + function _init () { + global $wpdb, $wp_user_roles; + $this->role_key = $wpdb->get_blog_prefix() . 'user_roles'; + if ( ! empty( $wp_user_roles ) ) { + $this->roles = $wp_user_roles; + $this->use_db = false; + } else { + $this->roles = get_option( $this->role_key ); + } + + if ( empty( $this->roles ) ) + return; + + $this->role_objects = array(); + $this->role_names = array(); + foreach ( array_keys( $this->roles ) as $role ) { + $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] ); + $this->role_names[$role] = $this->roles[$role]['name']; + } + } + + /** + * Reinitialize the object + * + * Recreates the role objects. This is typically called only by switch_to_blog() + * after switching wpdb to a new blog ID. + * + * @since 3.5.0 + * @access public + */ + function reinit() { + // There is no need to reinit if using the wp_user_roles global. + if ( ! $this->use_db ) + return; + + global $wpdb, $wp_user_roles; + + // Duplicated from _init() to avoid an extra function call. + $this->role_key = $wpdb->get_blog_prefix() . 'user_roles'; + $this->roles = get_option( $this->role_key ); + if ( empty( $this->roles ) ) + return; + + $this->role_objects = array(); + $this->role_names = array(); + foreach ( array_keys( $this->roles ) as $role ) { + $this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] ); + $this->role_names[$role] = $this->roles[$role]['name']; + } + } + + /** + * Add role name with capabilities to list. + * + * Updates the list of roles, if the role doesn't already exist. + * + * The capabilities are defined in the following format `array( 'read' => true );` + * To explicitly deny a role a capability you set the value for that capability to false. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + * @param string $display_name Role display name. + * @param array $capabilities List of role capabilities in the above format. + * @return WP_Role|null WP_Role object if role is added, null if already exists. + */ + function add_role( $role, $display_name, $capabilities = array() ) { + if ( isset( $this->roles[$role] ) ) + return; + + $this->roles[$role] = array( + 'name' => $display_name, + 'capabilities' => $capabilities + ); + if ( $this->use_db ) + update_option( $this->role_key, $this->roles ); + $this->role_objects[$role] = new WP_Role( $role, $capabilities ); + $this->role_names[$role] = $display_name; + return $this->role_objects[$role]; + } + + /** + * Remove role by name. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + */ + function remove_role( $role ) { + if ( ! isset( $this->role_objects[$role] ) ) + return; + + unset( $this->role_objects[$role] ); + unset( $this->role_names[$role] ); + unset( $this->roles[$role] ); + + if ( $this->use_db ) + update_option( $this->role_key, $this->roles ); + + if ( get_option( 'default_role' ) == $role ) + update_option( 'default_role', 'subscriber' ); + } + + /** + * Add capability to role. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + * @param string $cap Capability name. + * @param bool $grant Optional, default is true. Whether role is capable of performing capability. + */ + function add_cap( $role, $cap, $grant = true ) { + if ( ! isset( $this->roles[$role] ) ) + return; + + $this->roles[$role]['capabilities'][$cap] = $grant; + if ( $this->use_db ) + update_option( $this->role_key, $this->roles ); + } + + /** + * Remove capability from role. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + * @param string $cap Capability name. + */ + function remove_cap( $role, $cap ) { + if ( ! isset( $this->roles[$role] ) ) + return; + + unset( $this->roles[$role]['capabilities'][$cap] ); + if ( $this->use_db ) + update_option( $this->role_key, $this->roles ); + } + + /** + * Retrieve role object by name. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + * @return WP_Role|null WP_Role object if found, null if the role does not exist. + */ + function get_role( $role ) { + if ( isset( $this->role_objects[$role] ) ) + return $this->role_objects[$role]; + else + return null; + } + + /** + * Retrieve list of role names. + * + * @since 2.0.0 + * @access public + * + * @return array List of role names. + */ + function get_names() { + return $this->role_names; + } + + /** + * Whether role name is currently in the list of available roles. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name to look up. + * @return bool + */ + function is_role( $role ) { + return isset( $this->role_names[$role] ); + } +} + +/** + * WordPress Role class. + * + * @since 2.0.0 + * @package WordPress + * @subpackage User + */ +class WP_Role { + /** + * Role name. + * + * @since 2.0.0 + * @access public + * @var string + */ + var $name; + + /** + * List of capabilities the role contains. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $capabilities; + + /** + * Constructor - Set up object properties. + * + * The list of capabilities, must have the key as the name of the capability + * and the value a boolean of whether it is granted to the role. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + * @param array $capabilities List of capabilities. + */ + function __construct( $role, $capabilities ) { + $this->name = $role; + $this->capabilities = $capabilities; + } + + /** + * Assign role a capability. + * + * @see WP_Roles::add_cap() Method uses implementation for role. + * @since 2.0.0 + * @access public + * + * @param string $cap Capability name. + * @param bool $grant Whether role has capability privilege. + */ + function add_cap( $cap, $grant = true ) { + global $wp_roles; + + if ( ! isset( $wp_roles ) ) + $wp_roles = new WP_Roles(); + + $this->capabilities[$cap] = $grant; + $wp_roles->add_cap( $this->name, $cap, $grant ); + } + + /** + * Remove capability from role. + * + * This is a container for {@link WP_Roles::remove_cap()} to remove the + * capability from the role. That is to say, that {@link + * WP_Roles::remove_cap()} implements the functionality, but it also makes + * sense to use this class, because you don't need to enter the role name. + * + * @since 2.0.0 + * @access public + * + * @param string $cap Capability name. + */ + function remove_cap( $cap ) { + global $wp_roles; + + if ( ! isset( $wp_roles ) ) + $wp_roles = new WP_Roles(); + + unset( $this->capabilities[$cap] ); + $wp_roles->remove_cap( $this->name, $cap ); + } + + /** + * Whether role has capability. + * + * The capabilities is passed through the 'role_has_cap' filter. The first + * parameter for the hook is the list of capabilities the class has + * assigned. The second parameter is the capability name to look for. The + * third and final parameter for the hook is the role name. + * + * @since 2.0.0 + * @access public + * + * @param string $cap Capability name. + * @return bool True, if user has capability. False, if doesn't have capability. + */ + function has_cap( $cap ) { + $capabilities = apply_filters( 'role_has_cap', $this->capabilities, $cap, $this->name ); + if ( !empty( $capabilities[$cap] ) ) + return $capabilities[$cap]; + else + return false; + } + +} + +/** + * WordPress User class. + * + * @since 2.0.0 + * @package WordPress + * @subpackage User + */ +class WP_User { + /** + * User data container. + * + * @since 2.0.0 + * @access private + * @var array + */ + var $data; + + /** + * The user's ID. + * + * @since 2.1.0 + * @access public + * @var int + */ + var $ID = 0; + + /** + * The individual capabilities the user has been given. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $caps = array(); + + /** + * User metadata option name. + * + * @since 2.0.0 + * @access public + * @var string + */ + var $cap_key; + + /** + * The roles the user is part of. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $roles = array(); + + /** + * All capabilities the user has, including individual and role based. + * + * @since 2.0.0 + * @access public + * @var array + */ + var $allcaps = array(); + + /** + * The filter context applied to user data fields. + * + * @since 2.9.0 + * @access private + * @var string + */ + var $filter = null; + + private static $back_compat_keys; + + /** + * Constructor + * + * Retrieves the userdata and passes it to {@link WP_User::init()}. + * + * @since 2.0.0 + * @access public + * + * @param int|string|stdClass|WP_User $id User's ID, a WP_User object, or a user object from the DB. + * @param string $name Optional. User's username + * @param int $blog_id Optional Blog ID, defaults to current blog. + * @return WP_User + */ + function __construct( $id = 0, $name = '', $blog_id = '' ) { + if ( ! isset( self::$back_compat_keys ) ) { + $prefix = $GLOBALS['wpdb']->prefix; + self::$back_compat_keys = array( + 'user_firstname' => 'first_name', + 'user_lastname' => 'last_name', + 'user_description' => 'description', + 'user_level' => $prefix . 'user_level', + $prefix . 'usersettings' => $prefix . 'user-settings', + $prefix . 'usersettingstime' => $prefix . 'user-settings-time', + ); + } + + if ( is_a( $id, 'WP_User' ) ) { + $this->init( $id->data, $blog_id ); + return; + } elseif ( is_object( $id ) ) { + $this->init( $id, $blog_id ); + return; + } + + if ( ! empty( $id ) && ! is_numeric( $id ) ) { + $name = $id; + $id = 0; + } + + if ( $id ) + $data = self::get_data_by( 'id', $id ); + else + $data = self::get_data_by( 'login', $name ); + + if ( $data ) + $this->init( $data, $blog_id ); + } + + /** + * Sets up object properties, including capabilities. + * + * @param object $data User DB row object + * @param int $blog_id Optional. The blog id to initialize for + */ + function init( $data, $blog_id = '' ) { + $this->data = $data; + $this->ID = (int) $data->ID; + + $this->for_blog( $blog_id ); + } + + /** + * Return only the main user fields + * + * @since 3.3.0 + * + * @param string $field The field to query against: 'id', 'slug', 'email' or 'login' + * @param string|int $value The field value + * @return object Raw user object + */ + static function get_data_by( $field, $value ) { + global $wpdb; + + if ( 'id' == $field ) { + // Make sure the value is numeric to avoid casting objects, for example, + // to int 1. + if ( ! is_numeric( $value ) ) + return false; + $value = intval( $value ); + if ( $value < 1 ) + return false; + } else { + $value = trim( $value ); + } + + if ( !$value ) + return false; + + switch ( $field ) { + case 'id': + $user_id = $value; + $db_field = 'ID'; + break; + case 'slug': + $user_id = wp_cache_get($value, 'userslugs'); + $db_field = 'user_nicename'; + break; + case 'email': + $user_id = wp_cache_get($value, 'useremail'); + $db_field = 'user_email'; + break; + case 'login': + $value = sanitize_user( $value ); + $user_id = wp_cache_get($value, 'userlogins'); + $db_field = 'user_login'; + break; + default: + return false; + } + + if ( false !== $user_id ) { + if ( $user = wp_cache_get( $user_id, 'users' ) ) + return $user; + } + + if ( !$user = $wpdb->get_row( $wpdb->prepare( + "SELECT * FROM $wpdb->users WHERE $db_field = %s", $value + ) ) ) + return false; + + update_user_caches( $user ); + + return $user; + } + + /** + * Magic method for checking the existence of a certain custom field + * + * @since 3.3.0 + */ + function __isset( $key ) { + if ( 'id' == $key ) { + _deprecated_argument( 'WP_User->id', '2.1', __( 'Use <code>WP_User->ID</code> instead.' ) ); + $key = 'ID'; + } + + if ( isset( $this->data->$key ) ) + return true; + + if ( isset( self::$back_compat_keys[ $key ] ) ) + $key = self::$back_compat_keys[ $key ]; + + return metadata_exists( 'user', $this->ID, $key ); + } + + /** + * Magic method for accessing custom fields + * + * @since 3.3.0 + */ + function __get( $key ) { + if ( 'id' == $key ) { + _deprecated_argument( 'WP_User->id', '2.1', __( 'Use <code>WP_User->ID</code> instead.' ) ); + return $this->ID; + } + + if ( isset( $this->data->$key ) ) { + $value = $this->data->$key; + } else { + if ( isset( self::$back_compat_keys[ $key ] ) ) + $key = self::$back_compat_keys[ $key ]; + $value = get_user_meta( $this->ID, $key, true ); + } + + if ( $this->filter ) { + $value = sanitize_user_field( $key, $value, $this->ID, $this->filter ); + } + + return $value; + } + + /** + * Magic method for setting custom fields + * + * @since 3.3.0 + */ + function __set( $key, $value ) { + if ( 'id' == $key ) { + _deprecated_argument( 'WP_User->id', '2.1', __( 'Use <code>WP_User->ID</code> instead.' ) ); + $this->ID = $value; + return; + } + + $this->data->$key = $value; + } + + /** + * Determine whether the user exists in the database. + * + * @since 3.4.0 + * @access public + * + * @return bool True if user exists in the database, false if not. + */ + function exists() { + return ! empty( $this->ID ); + } + + /** + * Retrieve the value of a property or meta key. + * + * Retrieves from the users and usermeta table. + * + * @since 3.3.0 + * + * @param string $key Property + */ + function get( $key ) { + return $this->__get( $key ); + } + + /** + * Determine whether a property or meta key is set + * + * Consults the users and usermeta tables. + * + * @since 3.3.0 + * + * @param string $key Property + */ + function has_prop( $key ) { + return $this->__isset( $key ); + } + + /* + * Return an array representation. + * + * @since 3.5.0 + * + * @return array Array representation. + */ + function to_array() { + return get_object_vars( $this->data ); + } + + /** + * Set up capability object properties. + * + * Will set the value for the 'cap_key' property to current database table + * prefix, followed by 'capabilities'. Will then check to see if the + * property matching the 'cap_key' exists and is an array. If so, it will be + * used. + * + * @access protected + * @since 2.1.0 + * + * @param string $cap_key Optional capability key + */ + function _init_caps( $cap_key = '' ) { + global $wpdb; + + if ( empty($cap_key) ) + $this->cap_key = $wpdb->get_blog_prefix() . 'capabilities'; + else + $this->cap_key = $cap_key; + + $this->caps = get_user_meta( $this->ID, $this->cap_key, true ); + + if ( ! is_array( $this->caps ) ) + $this->caps = array(); + + $this->get_role_caps(); + } + + /** + * Retrieve all of the role capabilities and merge with individual capabilities. + * + * All of the capabilities of the roles the user belongs to are merged with + * the users individual roles. This also means that the user can be denied + * specific roles that their role might have, but the specific user isn't + * granted permission to. + * + * @since 2.0.0 + * @uses $wp_roles + * @access public + * + * @return array List of all capabilities for the user. + */ + function get_role_caps() { + global $wp_roles; + + if ( ! isset( $wp_roles ) ) + $wp_roles = new WP_Roles(); + + //Filter out caps that are not role names and assign to $this->roles + if ( is_array( $this->caps ) ) + $this->roles = array_filter( array_keys( $this->caps ), array( $wp_roles, 'is_role' ) ); + + //Build $allcaps from role caps, overlay user's $caps + $this->allcaps = array(); + foreach ( (array) $this->roles as $role ) { + $the_role = $wp_roles->get_role( $role ); + $this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities ); + } + $this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps ); + + return $this->allcaps; + } + + /** + * Add role to user. + * + * Updates the user's meta data option with capabilities and roles. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + */ + function add_role( $role ) { + $this->caps[$role] = true; + update_user_meta( $this->ID, $this->cap_key, $this->caps ); + $this->get_role_caps(); + $this->update_user_level_from_caps(); + } + + /** + * Remove role from user. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + */ + function remove_role( $role ) { + if ( !in_array($role, $this->roles) ) + return; + unset( $this->caps[$role] ); + update_user_meta( $this->ID, $this->cap_key, $this->caps ); + $this->get_role_caps(); + $this->update_user_level_from_caps(); + } + + /** + * Set the role of the user. + * + * This will remove the previous roles of the user and assign the user the + * new one. You can set the role to an empty string and it will remove all + * of the roles from the user. + * + * @since 2.0.0 + * @access public + * + * @param string $role Role name. + */ + function set_role( $role ) { + if ( 1 == count( $this->roles ) && $role == current( $this->roles ) ) + return; + + foreach ( (array) $this->roles as $oldrole ) + unset( $this->caps[$oldrole] ); + + $old_roles = $this->roles; + if ( !empty( $role ) ) { + $this->caps[$role] = true; + $this->roles = array( $role => true ); + } else { + $this->roles = false; + } + update_user_meta( $this->ID, $this->cap_key, $this->caps ); + $this->get_role_caps(); + $this->update_user_level_from_caps(); + do_action( 'set_user_role', $this->ID, $role, $old_roles ); + } + + /** + * Choose the maximum level the user has. + * + * Will compare the level from the $item parameter against the $max + * parameter. If the item is incorrect, then just the $max parameter value + * will be returned. + * + * Used to get the max level based on the capabilities the user has. This + * is also based on roles, so if the user is assigned the Administrator role + * then the capability 'level_10' will exist and the user will get that + * value. + * + * @since 2.0.0 + * @access public + * + * @param int $max Max level of user. + * @param string $item Level capability name. + * @return int Max Level. + */ + function level_reduction( $max, $item ) { + if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) { + $level = intval( $matches[1] ); + return max( $max, $level ); + } else { + return $max; + } + } + + /** + * Update the maximum user level for the user. + * + * Updates the 'user_level' user metadata (includes prefix that is the + * database table prefix) with the maximum user level. Gets the value from + * the all of the capabilities that the user has. + * + * @since 2.0.0 + * @access public + */ + function update_user_level_from_caps() { + global $wpdb; + $this->user_level = array_reduce( array_keys( $this->allcaps ), array( $this, 'level_reduction' ), 0 ); + update_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level', $this->user_level ); + } + + /** + * Add capability and grant or deny access to capability. + * + * @since 2.0.0 + * @access public + * + * @param string $cap Capability name. + * @param bool $grant Whether to grant capability to user. + */ + function add_cap( $cap, $grant = true ) { + $this->caps[$cap] = $grant; + update_user_meta( $this->ID, $this->cap_key, $this->caps ); + } + + /** + * Remove capability from user. + * + * @since 2.0.0 + * @access public + * + * @param string $cap Capability name. + */ + function remove_cap( $cap ) { + if ( ! isset( $this->caps[$cap] ) ) + return; + unset( $this->caps[$cap] ); + update_user_meta( $this->ID, $this->cap_key, $this->caps ); + } + + /** + * Remove all of the capabilities of the user. + * + * @since 2.1.0 + * @access public + */ + function remove_all_caps() { + global $wpdb; + $this->caps = array(); + delete_user_meta( $this->ID, $this->cap_key ); + delete_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level' ); + $this->get_role_caps(); + } + + /** + * Whether user has capability or role name. + * + * This is useful for looking up whether the user has a specific role + * assigned to the user. The second optional parameter can also be used to + * check for capabilities against a specific object, such as a post or user. + * + * @since 2.0.0 + * @access public + * + * @param string|int $cap Capability or role name to search. + * @return bool True, if user has capability; false, if user does not have capability. + */ + function has_cap( $cap ) { + if ( is_numeric( $cap ) ) { + _deprecated_argument( __FUNCTION__, '2.0', __('Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead.') ); + $cap = $this->translate_level_to_cap( $cap ); + } + + $args = array_slice( func_get_args(), 1 ); + $args = array_merge( array( $cap, $this->ID ), $args ); + $caps = call_user_func_array( 'map_meta_cap', $args ); + + // Multisite super admin has all caps by definition, Unless specifically denied. + if ( is_multisite() && is_super_admin( $this->ID ) ) { + if ( in_array('do_not_allow', $caps) ) + return false; + return true; + } + + // Must have ALL requested caps + $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args, $this ); + $capabilities['exist'] = true; // Everyone is allowed to exist + foreach ( (array) $caps as $cap ) { + if ( empty( $capabilities[ $cap ] ) ) + return false; + } + + return true; + } + + /** + * Convert numeric level to level capability name. + * + * Prepends 'level_' to level number. + * + * @since 2.0.0 + * @access public + * + * @param int $level Level number, 1 to 10. + * @return string + */ + function translate_level_to_cap( $level ) { + return 'level_' . $level; + } + + /** + * Set the blog to operate on. Defaults to the current blog. + * + * @since 3.0.0 + * + * @param int $blog_id Optional Blog ID, defaults to current blog. + */ + function for_blog( $blog_id = '' ) { + global $wpdb; + if ( ! empty( $blog_id ) ) + $cap_key = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities'; + else + $cap_key = ''; + $this->_init_caps( $cap_key ); + } +} + +/** + * Map meta capabilities to primitive capabilities. + * + * This does not actually compare whether the user ID has the actual capability, + * just what the capability or capabilities are. Meta capability list value can + * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post', + * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'. + * + * @since 2.0.0 + * + * @param string $cap Capability name. + * @param int $user_id User ID. + * @return array Actual capabilities for meta capability. + */ +function map_meta_cap( $cap, $user_id ) { + $args = array_slice( func_get_args(), 2 ); + $caps = array(); + + switch ( $cap ) { + case 'remove_user': + $caps[] = 'remove_users'; + break; + case 'promote_user': + $caps[] = 'promote_users'; + break; + case 'edit_user': + case 'edit_users': + // Allow user to edit itself + if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] ) + break; + + // If multisite these caps are allowed only for super admins. + if ( is_multisite() && !is_super_admin( $user_id ) ) + $caps[] = 'do_not_allow'; + else + $caps[] = 'edit_users'; // edit_user maps to edit_users. + break; + case 'delete_post': + case 'delete_page': + $post = get_post( $args[0] ); + + if ( 'revision' == $post->post_type ) { + $post = get_post( $post->post_parent ); + } + + $post_type = get_post_type_object( $post->post_type ); + + if ( ! $post_type->map_meta_cap ) { + $caps[] = $post_type->cap->$cap; + // Prior to 3.1 we would re-call map_meta_cap here. + if ( 'delete_post' == $cap ) + $cap = $post_type->cap->$cap; + break; + } + + $post_author_id = $post->post_author; + + // If no author set yet, default to current user for cap checks. + if ( ! $post_author_id ) + $post_author_id = $user_id; + + // If the user is the author... + if ( $user_id == $post_author_id ) { + // If the post is published... + if ( 'publish' == $post->post_status ) { + $caps[] = $post_type->cap->delete_published_posts; + } elseif ( 'trash' == $post->post_status ) { + if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) + $caps[] = $post_type->cap->delete_published_posts; + } else { + // If the post is draft... + $caps[] = $post_type->cap->delete_posts; + } + } else { + // The user is trying to edit someone else's post. + $caps[] = $post_type->cap->delete_others_posts; + // The post is published, extra cap required. + if ( 'publish' == $post->post_status ) + $caps[] = $post_type->cap->delete_published_posts; + elseif ( 'private' == $post->post_status ) + $caps[] = $post_type->cap->delete_private_posts; + } + break; + // edit_post breaks down to edit_posts, edit_published_posts, or + // edit_others_posts + case 'edit_post': + case 'edit_page': + $post = get_post( $args[0] ); + if ( empty( $post ) ) + break; + + if ( 'revision' == $post->post_type ) { + $post = get_post( $post->post_parent ); + } + + $post_type = get_post_type_object( $post->post_type ); + + if ( ! $post_type->map_meta_cap ) { + $caps[] = $post_type->cap->$cap; + // Prior to 3.1 we would re-call map_meta_cap here. + if ( 'edit_post' == $cap ) + $cap = $post_type->cap->$cap; + break; + } + + $post_author_id = $post->post_author; + + // If no author set yet, default to current user for cap checks. + if ( ! $post_author_id ) + $post_author_id = $user_id; + + // If the user is the author... + if ( $user_id == $post_author_id ) { + // If the post is published... + if ( 'publish' == $post->post_status ) { + $caps[] = $post_type->cap->edit_published_posts; + } elseif ( 'trash' == $post->post_status ) { + if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) + $caps[] = $post_type->cap->edit_published_posts; + } else { + // If the post is draft... + $caps[] = $post_type->cap->edit_posts; + } + } else { + // The user is trying to edit someone else's post. + $caps[] = $post_type->cap->edit_others_posts; + // The post is published, extra cap required. + if ( 'publish' == $post->post_status ) + $caps[] = $post_type->cap->edit_published_posts; + elseif ( 'private' == $post->post_status ) + $caps[] = $post_type->cap->edit_private_posts; + } + break; + case 'read_post': + case 'read_page': + $post = get_post( $args[0] ); + + if ( 'revision' == $post->post_type ) { + $post = get_post( $post->post_parent ); + } + + $post_type = get_post_type_object( $post->post_type ); + + if ( ! $post_type->map_meta_cap ) { + $caps[] = $post_type->cap->$cap; + // Prior to 3.1 we would re-call map_meta_cap here. + if ( 'read_post' == $cap ) + $cap = $post_type->cap->$cap; + break; + } + + $status_obj = get_post_status_object( $post->post_status ); + if ( $status_obj->public ) { + $caps[] = $post_type->cap->read; + break; + } + + $post_author_id = $post->post_author; + + // If no author set yet, default to current user for cap checks. + if ( ! $post_author_id ) + $post_author_id = $user_id; + + if ( $user_id == $post_author_id ) + $caps[] = $post_type->cap->read; + elseif ( $status_obj->private ) + $caps[] = $post_type->cap->read_private_posts; + else + $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); + break; + case 'publish_post': + $post = get_post( $args[0] ); + $post_type = get_post_type_object( $post->post_type ); + + $caps[] = $post_type->cap->publish_posts; + break; + case 'edit_post_meta': + case 'delete_post_meta': + case 'add_post_meta': + $post = get_post( $args[0] ); + $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); + + $meta_key = isset( $args[ 1 ] ) ? $args[ 1 ] : false; + + if ( $meta_key && has_filter( "auth_post_meta_{$meta_key}" ) ) { + $allowed = apply_filters( "auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps ); + if ( ! $allowed ) + $caps[] = $cap; + } elseif ( $meta_key && is_protected_meta( $meta_key, 'post' ) ) { + $caps[] = $cap; + } + break; + case 'edit_comment': + $comment = get_comment( $args[0] ); + if ( empty( $comment ) ) + break; + $post = get_post( $comment->comment_post_ID ); + $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); + break; + case 'unfiltered_upload': + if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) ) ) + $caps[] = $cap; + else + $caps[] = 'do_not_allow'; + break; + case 'unfiltered_html' : + // Disallow unfiltered_html for all users, even admins and super admins. + if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) + $caps[] = 'do_not_allow'; + elseif ( is_multisite() && ! is_super_admin( $user_id ) ) + $caps[] = 'do_not_allow'; + else + $caps[] = $cap; + break; + case 'edit_files': + case 'edit_plugins': + case 'edit_themes': + // Disallow the file editors. + if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) + $caps[] = 'do_not_allow'; + elseif ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) + $caps[] = 'do_not_allow'; + elseif ( is_multisite() && ! is_super_admin( $user_id ) ) + $caps[] = 'do_not_allow'; + else + $caps[] = $cap; + break; + case 'update_plugins': + case 'delete_plugins': + case 'install_plugins': + case 'update_themes': + case 'delete_themes': + case 'install_themes': + case 'update_core': + // Disallow anything that creates, deletes, or updates core, plugin, or theme files. + // Files in uploads are excepted. + if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) + $caps[] = 'do_not_allow'; + elseif ( is_multisite() && ! is_super_admin( $user_id ) ) + $caps[] = 'do_not_allow'; + else + $caps[] = $cap; + break; + case 'activate_plugins': + $caps[] = $cap; + if ( is_multisite() ) { + // update_, install_, and delete_ are handled above with is_super_admin(). + $menu_perms = get_site_option( 'menu_items', array() ); + if ( empty( $menu_perms['plugins'] ) ) + $caps[] = 'manage_network_plugins'; + } + break; + case 'delete_user': + case 'delete_users': + // If multisite only super admins can delete users. + if ( is_multisite() && ! is_super_admin( $user_id ) ) + $caps[] = 'do_not_allow'; + else + $caps[] = 'delete_users'; // delete_user maps to delete_users. + break; + case 'create_users': + if ( !is_multisite() ) + $caps[] = $cap; + elseif ( is_super_admin() || get_site_option( 'add_new_users' ) ) + $caps[] = $cap; + else + $caps[] = 'do_not_allow'; + break; + case 'manage_links' : + if ( get_option( 'link_manager_enabled' ) ) + $caps[] = $cap; + else + $caps[] = 'do_not_allow'; + break; + default: + // Handle meta capabilities for custom post types. + $post_type_meta_caps = _post_type_meta_capabilities(); + if ( isset( $post_type_meta_caps[ $cap ] ) ) { + $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args ); + return call_user_func_array( 'map_meta_cap', $args ); + } + + // If no meta caps match, return the original cap. + $caps[] = $cap; + } + + return apply_filters('map_meta_cap', $caps, $cap, $user_id, $args); +} + +/** + * Whether current user has capability or role. + * + * @since 2.0.0 + * + * @param string $capability Capability or role name. + * @return bool + */ +function current_user_can( $capability ) { + $current_user = wp_get_current_user(); + + if ( empty( $current_user ) ) + return false; + + $args = array_slice( func_get_args(), 1 ); + $args = array_merge( array( $capability ), $args ); + + return call_user_func_array( array( $current_user, 'has_cap' ), $args ); +} + +/** + * Whether current user has a capability or role for a given blog. + * + * @since 3.0.0 + * + * @param int $blog_id Blog ID + * @param string $capability Capability or role name. + * @return bool + */ +function current_user_can_for_blog( $blog_id, $capability ) { + if ( is_multisite() ) + switch_to_blog( $blog_id ); + + $current_user = wp_get_current_user(); + + if ( empty( $current_user ) ) + return false; + + $args = array_slice( func_get_args(), 2 ); + $args = array_merge( array( $capability ), $args ); + + $can = call_user_func_array( array( $current_user, 'has_cap' ), $args ); + + if ( is_multisite() ) + restore_current_blog(); + + return $can; +} + +/** + * Whether author of supplied post has capability or role. + * + * @since 2.9.0 + * + * @param int|object $post Post ID or post object. + * @param string $capability Capability or role name. + * @return bool + */ +function author_can( $post, $capability ) { + if ( !$post = get_post($post) ) + return false; + + $author = get_userdata( $post->post_author ); + + if ( ! $author ) + return false; + + $args = array_slice( func_get_args(), 2 ); + $args = array_merge( array( $capability ), $args ); + + return call_user_func_array( array( $author, 'has_cap' ), $args ); +} + +/** + * Whether a particular user has capability or role. + * + * @since 3.1.0 + * + * @param int|object $user User ID or object. + * @param string $capability Capability or role name. + * @return bool + */ +function user_can( $user, $capability ) { + if ( ! is_object( $user ) ) + $user = get_userdata( $user ); + + if ( ! $user || ! $user->exists() ) + return false; + + $args = array_slice( func_get_args(), 2 ); + $args = array_merge( array( $capability ), $args ); + + return call_user_func_array( array( $user, 'has_cap' ), $args ); +} + +/** + * Retrieve role object. + * + * @see WP_Roles::get_role() Uses method to retrieve role object. + * @since 2.0.0 + * + * @param string $role Role name. + * @return WP_Role|null WP_Role object if found, null if the role does not exist. + */ +function get_role( $role ) { + global $wp_roles; + + if ( ! isset( $wp_roles ) ) + $wp_roles = new WP_Roles(); + + return $wp_roles->get_role( $role ); +} + +/** + * Add role, if it does not exist. + * + * @see WP_Roles::add_role() Uses method to add role. + * @since 2.0.0 + * + * @param string $role Role name. + * @param string $display_name Display name for role. + * @param array $capabilities List of capabilities, e.g. array( 'edit_posts' => true, 'delete_posts' => false ); + * @return WP_Role|null WP_Role object if role is added, null if already exists. + */ +function add_role( $role, $display_name, $capabilities = array() ) { + global $wp_roles; + + if ( ! isset( $wp_roles ) ) + $wp_roles = new WP_Roles(); + + return $wp_roles->add_role( $role, $display_name, $capabilities ); +} + +/** + * Remove role, if it exists. + * + * @see WP_Roles::remove_role() Uses method to remove role. + * @since 2.0.0 + * + * @param string $role Role name. + */ +function remove_role( $role ) { + global $wp_roles; + + if ( ! isset( $wp_roles ) ) + $wp_roles = new WP_Roles(); + + $wp_roles->remove_role( $role ); +} + +/** + * Retrieve a list of super admins. + * + * @since 3.0.0 + * + * @uses $super_admins Super admins global variable, if set. + * + * @return array List of super admin logins + */ +function get_super_admins() { + global $super_admins; + + if ( isset($super_admins) ) + return $super_admins; + else + return get_site_option( 'site_admins', array('admin') ); +} + +/** + * Determine if user is a site admin. + * + * @since 3.0.0 + * + * @param int $user_id (Optional) The ID of a user. Defaults to the current user. + * @return bool True if the user is a site admin. + */ +function is_super_admin( $user_id = false ) { + if ( ! $user_id || $user_id == get_current_user_id() ) + $user = wp_get_current_user(); + else + $user = get_userdata( $user_id ); + + if ( ! $user || ! $user->exists() ) + return false; + + if ( is_multisite() ) { + $super_admins = get_super_admins(); + if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) ) + return true; + } else { + if ( $user->has_cap('delete_users') ) + return true; + } + + return false; +} diff --git a/sources/wp-includes/category-template.php b/sources/wp-includes/category-template.php new file mode 100644 index 0000000..57f7cb9 --- /dev/null +++ b/sources/wp-includes/category-template.php @@ -0,0 +1,1215 @@ +<?php +/** + * Category Template Tags and API. + * + * @package WordPress + * @subpackage Template + */ + +/** + * Retrieve category link URL. + * + * @since 1.0.0 + * @see get_term_link() + * + * @param int|object $category Category ID or object. + * @return string Link on success, empty string if category does not exist. + */ +function get_category_link( $category ) { + if ( ! is_object( $category ) ) + $category = (int) $category; + + $category = get_term_link( $category, 'category' ); + + if ( is_wp_error( $category ) ) + return ''; + + return $category; +} + +/** + * Retrieve category parents with separator. + * + * @since 1.2.0 + * + * @param int $id Category ID. + * @param bool $link Optional, default is false. Whether to format with link. + * @param string $separator Optional, default is '/'. How to separate categories. + * @param bool $nicename Optional, default is false. Whether to use nice name for display. + * @param array $visited Optional. Already linked to categories to prevent duplicates. + * @return string|WP_Error A list of category parents on success, WP_Error on failure. + */ +function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) { + $chain = ''; + $parent = get_term( $id, 'category' ); + if ( is_wp_error( $parent ) ) + return $parent; + + if ( $nicename ) + $name = $parent->slug; + else + $name = $parent->name; + + if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) { + $visited[] = $parent->parent; + $chain .= get_category_parents( $parent->parent, $link, $separator, $nicename, $visited ); + } + + if ( $link ) + $chain .= '<a href="' . esc_url( get_category_link( $parent->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $parent->name ) ) . '">'.$name.'</a>' . $separator; + else + $chain .= $name.$separator; + return $chain; +} + +/** + * Retrieve post categories. + * + * @since 0.71 + * @uses $post + * + * @param int $id Optional, default to current post ID. The post ID. + * @return array + */ +function get_the_category( $id = false ) { + $categories = get_the_terms( $id, 'category' ); + if ( ! $categories || is_wp_error( $categories ) ) + $categories = array(); + + $categories = array_values( $categories ); + + foreach ( array_keys( $categories ) as $key ) { + _make_cat_compat( $categories[$key] ); + } + + // Filter name is plural because we return alot of categories (possibly more than #13237) not just one + return apply_filters( 'get_the_categories', $categories ); +} + +/** + * Sort categories by name. + * + * Used by usort() as a callback, should not be used directly. Can actually be + * used to sort any term object. + * + * @since 2.3.0 + * @access private + * + * @param object $a + * @param object $b + * @return int + */ +function _usort_terms_by_name( $a, $b ) { + return strcmp( $a->name, $b->name ); +} + +/** + * Sort categories by ID. + * + * Used by usort() as a callback, should not be used directly. Can actually be + * used to sort any term object. + * + * @since 2.3.0 + * @access private + * + * @param object $a + * @param object $b + * @return int + */ +function _usort_terms_by_ID( $a, $b ) { + if ( $a->term_id > $b->term_id ) + return 1; + elseif ( $a->term_id < $b->term_id ) + return -1; + else + return 0; +} + +/** + * Retrieve category name based on category ID. + * + * @since 0.71 + * + * @param int $cat_ID Category ID. + * @return string|WP_Error Category name on success, WP_Error on failure. + */ +function get_the_category_by_ID( $cat_ID ) { + $cat_ID = (int) $cat_ID; + $category = get_term( $cat_ID, 'category' ); + if ( is_wp_error( $category ) ) + return $category; + return $category->name; +} + +/** + * Retrieve category list in either HTML list or custom format. + * + * @since 1.5.1 + * + * @param string $separator Optional, default is empty string. Separator for between the categories. + * @param string $parents Optional. How to display the parents. + * @param int $post_id Optional. Post ID to retrieve categories. + * @return string + */ +function get_the_category_list( $separator = '', $parents='', $post_id = false ) { + global $wp_rewrite; + if ( ! is_object_in_taxonomy( get_post_type( $post_id ), 'category' ) ) + return apply_filters( 'the_category', '', $separator, $parents ); + + $categories = get_the_category( $post_id ); + if ( empty( $categories ) ) + return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents ); + + $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"'; + + $thelist = ''; + if ( '' == $separator ) { + $thelist .= '<ul class="post-categories">'; + foreach ( $categories as $category ) { + $thelist .= "\n\t<li>"; + switch ( strtolower( $parents ) ) { + case 'multiple': + if ( $category->parent ) + $thelist .= get_category_parents( $category->parent, true, $separator ); + $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a></li>'; + break; + case 'single': + $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>'; + if ( $category->parent ) + $thelist .= get_category_parents( $category->parent, false, $separator ); + $thelist .= $category->name.'</a></li>'; + break; + case '': + default: + $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a></li>'; + } + } + $thelist .= '</ul>'; + } else { + $i = 0; + foreach ( $categories as $category ) { + if ( 0 < $i ) + $thelist .= $separator; + switch ( strtolower( $parents ) ) { + case 'multiple': + if ( $category->parent ) + $thelist .= get_category_parents( $category->parent, true, $separator ); + $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a>'; + break; + case 'single': + $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>'; + if ( $category->parent ) + $thelist .= get_category_parents( $category->parent, false, $separator ); + $thelist .= "$category->name</a>"; + break; + case '': + default: + $thelist .= '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a>'; + } + ++$i; + } + } + return apply_filters( 'the_category', $thelist, $separator, $parents ); +} + +/** + * Check if the current post in within any of the given categories. + * + * The given categories are checked against the post's categories' term_ids, names and slugs. + * Categories given as integers will only be checked against the post's categories' term_ids. + * + * Prior to v2.5 of WordPress, category names were not supported. + * Prior to v2.7, category slugs were not supported. + * Prior to v2.7, only one category could be compared: in_category( $single_category ). + * Prior to v2.7, this function could only be used in the WordPress Loop. + * As of 2.7, the function can be used anywhere if it is provided a post ID or post object. + * + * @since 1.2.0 + * @uses has_category() + * + * @param int|string|array $category Category ID, name or slug, or array of said. + * @param int|object $post Optional. Post to check instead of the current post. (since 2.7.0) + * @return bool True if the current post is in any of the given categories. + */ +function in_category( $category, $post = null ) { + if ( empty( $category ) ) + return false; + + return has_category( $category, $post ); +} + +/** + * Display the category list for the post. + * + * @since 0.71 + * + * @param string $separator Optional, default is empty string. Separator for between the categories. + * @param string $parents Optional. How to display the parents. + * @param int $post_id Optional. Post ID to retrieve categories. + */ +function the_category( $separator = '', $parents='', $post_id = false ) { + echo get_the_category_list( $separator, $parents, $post_id ); +} + +/** + * Retrieve category description. + * + * @since 1.0.0 + * + * @param int $category Optional. Category ID. Will use global category ID by default. + * @return string Category description, available. + */ +function category_description( $category = 0 ) { + return term_description( $category, 'category' ); +} + +/** + * Display or retrieve the HTML dropdown list of categories. + * + * The list of arguments is below: + * 'show_option_all' (string) - Text to display for showing all categories. + * 'show_option_none' (string) - Text to display for showing no categories. + * 'orderby' (string) default is 'ID' - What column to use for ordering the + * categories. + * 'order' (string) default is 'ASC' - What direction to order categories. + * 'show_count' (bool|int) default is 0 - Whether to show how many posts are + * in the category. + * 'hide_empty' (bool|int) default is 1 - Whether to hide categories that + * don't have any posts attached to them. + * 'child_of' (int) default is 0 - See {@link get_categories()}. + * 'exclude' (string) - See {@link get_categories()}. + * 'echo' (bool|int) default is 1 - Whether to display or retrieve content. + * 'depth' (int) - The max depth. + * 'tab_index' (int) - Tab index for select element. + * 'name' (string) - The name attribute value for select element. + * 'id' (string) - The ID attribute value for select element. Defaults to name if omitted. + * 'class' (string) - The class attribute value for select element. + * 'selected' (int) - Which category ID is selected. + * 'taxonomy' (string) - The name of the taxonomy to retrieve. Defaults to category. + * + * The 'hierarchical' argument, which is disabled by default, will override the + * depth argument, unless it is true. When the argument is false, it will + * display all of the categories. When it is enabled it will use the value in + * the 'depth' argument. + * + * @since 2.1.0 + * + * @param string|array $args Optional. Override default arguments. + * @return string HTML content only if 'echo' argument is 0. + */ +function wp_dropdown_categories( $args = '' ) { + $defaults = array( + 'show_option_all' => '', 'show_option_none' => '', + 'orderby' => 'id', 'order' => 'ASC', + 'show_count' => 0, + 'hide_empty' => 1, 'child_of' => 0, + 'exclude' => '', 'echo' => 1, + 'selected' => 0, 'hierarchical' => 0, + 'name' => 'cat', 'id' => '', + 'class' => 'postform', 'depth' => 0, + 'tab_index' => 0, 'taxonomy' => 'category', + 'hide_if_empty' => false + ); + + $defaults['selected'] = ( is_category() ) ? get_query_var( 'cat' ) : 0; + + // Back compat. + if ( isset( $args['type'] ) && 'link' == $args['type'] ) { + _deprecated_argument( __FUNCTION__, '3.0', '' ); + $args['taxonomy'] = 'link_category'; + } + + $r = wp_parse_args( $args, $defaults ); + + if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) { + $r['pad_counts'] = true; + } + + extract( $r ); + + $tab_index_attribute = ''; + if ( (int) $tab_index > 0 ) + $tab_index_attribute = " tabindex=\"$tab_index\""; + + $categories = get_terms( $taxonomy, $r ); + $name = esc_attr( $name ); + $class = esc_attr( $class ); + $id = $id ? esc_attr( $id ) : $name; + + if ( ! $r['hide_if_empty'] || ! empty($categories) ) + $output = "<select name='$name' id='$id' class='$class' $tab_index_attribute>\n"; + else + $output = ''; + + if ( empty($categories) && ! $r['hide_if_empty'] && !empty($show_option_none) ) { + $show_option_none = apply_filters( 'list_cats', $show_option_none ); + $output .= "\t<option value='-1' selected='selected'>$show_option_none</option>\n"; + } + + if ( ! empty( $categories ) ) { + + if ( $show_option_all ) { + $show_option_all = apply_filters( 'list_cats', $show_option_all ); + $selected = ( '0' === strval($r['selected']) ) ? " selected='selected'" : ''; + $output .= "\t<option value='0'$selected>$show_option_all</option>\n"; + } + + if ( $show_option_none ) { + $show_option_none = apply_filters( 'list_cats', $show_option_none ); + $selected = ( '-1' === strval($r['selected']) ) ? " selected='selected'" : ''; + $output .= "\t<option value='-1'$selected>$show_option_none</option>\n"; + } + + if ( $hierarchical ) + $depth = $r['depth']; // Walk the full depth. + else + $depth = -1; // Flat. + + $output .= walk_category_dropdown_tree( $categories, $depth, $r ); + } + + if ( ! $r['hide_if_empty'] || ! empty($categories) ) + $output .= "</select>\n"; + + $output = apply_filters( 'wp_dropdown_cats', $output ); + + if ( $echo ) + echo $output; + + return $output; +} + +/** + * Display or retrieve the HTML list of categories. + * + * The list of arguments is below: + * 'show_option_all' (string) - Text to display for showing all categories. + * 'orderby' (string) default is 'ID' - What column to use for ordering the + * categories. + * 'order' (string) default is 'ASC' - What direction to order categories. + * 'show_count' (bool|int) default is 0 - Whether to show how many posts are + * in the category. + * 'hide_empty' (bool|int) default is 1 - Whether to hide categories that + * don't have any posts attached to them. + * 'use_desc_for_title' (bool|int) default is 1 - Whether to use the + * description instead of the category title. + * 'feed' - See {@link get_categories()}. + * 'feed_type' - See {@link get_categories()}. + * 'feed_image' - See {@link get_categories()}. + * 'child_of' (int) default is 0 - See {@link get_categories()}. + * 'exclude' (string) - See {@link get_categories()}. + * 'exclude_tree' (string) - See {@link get_categories()}. + * 'echo' (bool|int) default is 1 - Whether to display or retrieve content. + * 'current_category' (int) - See {@link get_categories()}. + * 'hierarchical' (bool) - See {@link get_categories()}. + * 'title_li' (string) - See {@link get_categories()}. + * 'depth' (int) - The max depth. + * + * @since 2.1.0 + * + * @param string|array $args Optional. Override default arguments. + * @return string HTML content only if 'echo' argument is 0. + */ +function wp_list_categories( $args = '' ) { + $defaults = array( + 'show_option_all' => '', 'show_option_none' => __('No categories'), + 'orderby' => 'name', 'order' => 'ASC', + 'style' => 'list', + 'show_count' => 0, 'hide_empty' => 1, + 'use_desc_for_title' => 1, 'child_of' => 0, + 'feed' => '', 'feed_type' => '', + 'feed_image' => '', 'exclude' => '', + 'exclude_tree' => '', 'current_category' => 0, + 'hierarchical' => true, 'title_li' => __( 'Categories' ), + 'echo' => 1, 'depth' => 0, + 'taxonomy' => 'category' + ); + + $r = wp_parse_args( $args, $defaults ); + + if ( !isset( $r['pad_counts'] ) && $r['show_count'] && $r['hierarchical'] ) + $r['pad_counts'] = true; + + if ( true == $r['hierarchical'] ) { + $r['exclude_tree'] = $r['exclude']; + $r['exclude'] = ''; + } + + if ( !isset( $r['class'] ) ) + $r['class'] = ( 'category' == $r['taxonomy'] ) ? 'categories' : $r['taxonomy']; + + extract( $r ); + + if ( !taxonomy_exists($taxonomy) ) + return false; + + $categories = get_categories( $r ); + + $output = ''; + if ( $title_li && 'list' == $style ) + $output = '<li class="' . esc_attr( $class ) . '">' . $title_li . '<ul>'; + + if ( empty( $categories ) ) { + if ( ! empty( $show_option_none ) ) { + if ( 'list' == $style ) + $output .= '<li>' . $show_option_none . '</li>'; + else + $output .= $show_option_none; + } + } else { + if ( ! empty( $show_option_all ) ) { + $posts_page = ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) ) ? get_permalink( get_option( 'page_for_posts' ) ) : home_url( '/' ); + $posts_page = esc_url( $posts_page ); + if ( 'list' == $style ) + $output .= "<li><a href='$posts_page'>$show_option_all</a></li>"; + else + $output .= "<a href='$posts_page'>$show_option_all</a>"; + } + + if ( empty( $r['current_category'] ) && ( is_category() || is_tax() || is_tag() ) ) { + $current_term_object = get_queried_object(); + if ( $current_term_object && $r['taxonomy'] === $current_term_object->taxonomy ) + $r['current_category'] = get_queried_object_id(); + } + + if ( $hierarchical ) + $depth = $r['depth']; + else + $depth = -1; // Flat. + + $output .= walk_category_tree( $categories, $depth, $r ); + } + + if ( $title_li && 'list' == $style ) + $output .= '</ul></li>'; + + $output = apply_filters( 'wp_list_categories', $output, $args ); + + if ( $echo ) + echo $output; + else + return $output; +} + +/** + * Display tag cloud. + * + * The text size is set by the 'smallest' and 'largest' arguments, which will + * use the 'unit' argument value for the CSS text size unit. The 'format' + * argument can be 'flat' (default), 'list', or 'array'. The flat value for the + * 'format' argument will separate tags with spaces. The list value for the + * 'format' argument will format the tags in a UL HTML list. The array value for + * the 'format' argument will return in PHP array type format. + * + * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'. + * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC'. + * + * The 'number' argument is how many tags to return. By default, the limit will + * be to return the top 45 tags in the tag cloud list. + * + * The 'topic_count_text_callback' argument is a function, which, given the count + * of the posts with that tag, returns a text for the tooltip of the tag link. + * + * The 'exclude' and 'include' arguments are used for the {@link get_tags()} + * function. Only one should be used, because only one will be used and the + * other ignored, if they are both set. + * + * @since 2.3.0 + * + * @param array|string $args Optional. Override default arguments. + * @return array Generated tag cloud, only if no failures and 'array' is set for the 'format' argument. + */ +function wp_tag_cloud( $args = '' ) { + $defaults = array( + 'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45, + 'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC', + 'exclude' => '', 'include' => '', 'link' => 'view', 'taxonomy' => 'post_tag', 'echo' => true + ); + $args = wp_parse_args( $args, $defaults ); + + $tags = get_terms( $args['taxonomy'], array_merge( $args, array( 'orderby' => 'count', 'order' => 'DESC' ) ) ); // Always query top tags + + if ( empty( $tags ) || is_wp_error( $tags ) ) + return; + + foreach ( $tags as $key => $tag ) { + if ( 'edit' == $args['link'] ) + $link = get_edit_tag_link( $tag->term_id, $tag->taxonomy ); + else + $link = get_term_link( intval($tag->term_id), $tag->taxonomy ); + if ( is_wp_error( $link ) ) + return false; + + $tags[ $key ]->link = $link; + $tags[ $key ]->id = $tag->term_id; + } + + $return = wp_generate_tag_cloud( $tags, $args ); // Here's where those top tags get sorted according to $args + + $return = apply_filters( 'wp_tag_cloud', $return, $args ); + + if ( 'array' == $args['format'] || empty($args['echo']) ) + return $return; + + echo $return; +} + +/** + * Default text for tooltip for tag links + * + * @param integer $count number of posts with that tag + * @return string text for the tooltip of a tag link. + */ +function default_topic_count_text( $count ) { + return sprintf( _n('%s topic', '%s topics', $count), number_format_i18n( $count ) ); +} + +/** + * Default topic count scaling for tag links + * + * @param integer $count number of posts with that tag + * @return integer scaled count + */ +function default_topic_count_scale( $count ) { + return round(log10($count + 1) * 100); +} + +/** + * Generates a tag cloud (heatmap) from provided data. + * + * The text size is set by the 'smallest' and 'largest' arguments, which will + * use the 'unit' argument value for the CSS text size unit. The 'format' + * argument can be 'flat' (default), 'list', or 'array'. The flat value for the + * 'format' argument will separate tags with spaces. The list value for the + * 'format' argument will format the tags in a UL HTML list. The array value for + * the 'format' argument will return in PHP array type format. + * + * The 'tag_cloud_sort' filter allows you to override the sorting. + * Passed to the filter: $tags array and $args array, has to return the $tags array + * after sorting it. + * + * The 'orderby' argument will accept 'name' or 'count' and defaults to 'name'. + * The 'order' is the direction to sort, defaults to 'ASC' and can be 'DESC' or + * 'RAND'. + * + * The 'number' argument is how many tags to return. By default, the limit will + * be to return the entire tag cloud list. + * + * The 'topic_count_text_callback' argument is a function, which given the count + * of the posts with that tag returns a text for the tooltip of the tag link. + * + * @todo Complete functionality. + * @since 2.3.0 + * + * @param array $tags List of tags. + * @param string|array $args Optional, override default arguments. + * @return string + */ +function wp_generate_tag_cloud( $tags, $args = '' ) { + $defaults = array( + 'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 0, + 'format' => 'flat', 'separator' => "\n", 'orderby' => 'name', 'order' => 'ASC', + 'topic_count_text_callback' => 'default_topic_count_text', + 'topic_count_scale_callback' => 'default_topic_count_scale', 'filter' => 1, + ); + + if ( !isset( $args['topic_count_text_callback'] ) && isset( $args['single_text'] ) && isset( $args['multiple_text'] ) ) { + $body = 'return sprintf ( + _n(' . var_export($args['single_text'], true) . ', ' . var_export($args['multiple_text'], true) . ', $count), + number_format_i18n( $count ));'; + $args['topic_count_text_callback'] = create_function('$count', $body); + } + + $args = wp_parse_args( $args, $defaults ); + extract( $args ); + + if ( empty( $tags ) ) + return; + + $tags_sorted = apply_filters( 'tag_cloud_sort', $tags, $args ); + if ( $tags_sorted != $tags ) { // the tags have been sorted by a plugin + $tags = $tags_sorted; + unset($tags_sorted); + } else { + if ( 'RAND' == $order ) { + shuffle($tags); + } else { + // SQL cannot save you; this is a second (potentially different) sort on a subset of data. + if ( 'name' == $orderby ) + uasort( $tags, '_wp_object_name_sort_cb' ); + else + uasort( $tags, '_wp_object_count_sort_cb' ); + + if ( 'DESC' == $order ) + $tags = array_reverse( $tags, true ); + } + } + + if ( $number > 0 ) + $tags = array_slice($tags, 0, $number); + + $counts = array(); + $real_counts = array(); // For the alt tag + foreach ( (array) $tags as $key => $tag ) { + $real_counts[ $key ] = $tag->count; + $counts[ $key ] = $topic_count_scale_callback($tag->count); + } + + $min_count = min( $counts ); + $spread = max( $counts ) - $min_count; + if ( $spread <= 0 ) + $spread = 1; + $font_spread = $largest - $smallest; + if ( $font_spread < 0 ) + $font_spread = 1; + $font_step = $font_spread / $spread; + + $a = array(); + + foreach ( $tags as $key => $tag ) { + $count = $counts[ $key ]; + $real_count = $real_counts[ $key ]; + $tag_link = '#' != $tag->link ? esc_url( $tag->link ) : '#'; + $tag_id = isset($tags[ $key ]->id) ? $tags[ $key ]->id : $key; + $tag_name = $tags[ $key ]->name; + $a[] = "<a href='$tag_link' class='tag-link-$tag_id' title='" . esc_attr( call_user_func( $topic_count_text_callback, $real_count, $tag, $args ) ) . "' style='font-size: " . + str_replace( ',', '.', ( $smallest + ( ( $count - $min_count ) * $font_step ) ) ) + . "$unit;'>$tag_name</a>"; + } + + switch ( $format ) : + case 'array' : + $return =& $a; + break; + case 'list' : + $return = "<ul class='wp-tag-cloud'>\n\t<li>"; + $return .= join( "</li>\n\t<li>", $a ); + $return .= "</li>\n</ul>\n"; + break; + default : + $return = join( $separator, $a ); + break; + endswitch; + + if ( $filter ) + return apply_filters( 'wp_generate_tag_cloud', $return, $tags, $args ); + else + return $return; +} + +/** + * Callback for comparing objects based on name + * + * @since 3.1.0 + * @access private + */ +function _wp_object_name_sort_cb( $a, $b ) { + return strnatcasecmp( $a->name, $b->name ); +} + +/** + * Callback for comparing objects based on count + * + * @since 3.1.0 + * @access private + */ +function _wp_object_count_sort_cb( $a, $b ) { + return ( $a->count > $b->count ); +} + +// +// Helper functions +// + +/** + * Retrieve HTML list content for category list. + * + * @uses Walker_Category to create HTML list content. + * @since 2.1.0 + * @see Walker_Category::walk() for parameters and return description. + */ +function walk_category_tree() { + $args = func_get_args(); + // the user's options are the third parameter + if ( empty($args[2]['walker']) || !is_a($args[2]['walker'], 'Walker') ) + $walker = new Walker_Category; + else + $walker = $args[2]['walker']; + + return call_user_func_array(array( &$walker, 'walk' ), $args ); +} + +/** + * Retrieve HTML dropdown (select) content for category list. + * + * @uses Walker_CategoryDropdown to create HTML dropdown content. + * @since 2.1.0 + * @see Walker_CategoryDropdown::walk() for parameters and return description. + */ +function walk_category_dropdown_tree() { + $args = func_get_args(); + // the user's options are the third parameter + if ( empty($args[2]['walker']) || !is_a($args[2]['walker'], 'Walker') ) + $walker = new Walker_CategoryDropdown; + else + $walker = $args[2]['walker']; + + return call_user_func_array(array( &$walker, 'walk' ), $args ); +} + +/** + * Create HTML list of categories. + * + * @package WordPress + * @since 2.1.0 + * @uses Walker + */ +class Walker_Category extends Walker { + /** + * What the class handles. + * + * @see Walker::$tree_type + * @since 2.1.0 + * @var string + */ + var $tree_type = 'category'; + + /** + * Database fields to use. + * + * @see Walker::$db_fields + * @since 2.1.0 + * @todo Decouple this + * @var array + */ + var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); + + /** + * Starts the list before the elements are added. + * + * @see Walker::start_lvl() + * + * @since 2.1.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of category. Used for tab indentation. + * @param array $args An array of arguments. Will only append content if style argument value is 'list'. + * @see wp_list_categories() + */ + function start_lvl( &$output, $depth = 0, $args = array() ) { + if ( 'list' != $args['style'] ) + return; + + $indent = str_repeat("\t", $depth); + $output .= "$indent<ul class='children'>\n"; + } + + /** + * Ends the list of after the elements are added. + * + * @see Walker::end_lvl() + * + * @since 2.1.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of category. Used for tab indentation. + * @param array $args An array of arguments. Will only append content if style argument value is 'list'. + * @wsee wp_list_categories() + */ + function end_lvl( &$output, $depth = 0, $args = array() ) { + if ( 'list' != $args['style'] ) + return; + + $indent = str_repeat("\t", $depth); + $output .= "$indent</ul>\n"; + } + + /** + * Start the element output. + * + * @see Walker::start_el() + * + * @since 2.1.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $category Category data object. + * @param int $depth Depth of category in reference to parents. Default 0. + * @param array $args An array of arguments. @see wp_list_categories() + * @param int $id ID of the current category. + */ + function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) { + extract($args); + + $cat_name = esc_attr( $category->name ); + $cat_name = apply_filters( 'list_cats', $cat_name, $category ); + $link = '<a href="' . esc_url( get_term_link($category) ) . '" '; + if ( $use_desc_for_title == 0 || empty($category->description) ) + $link .= 'title="' . esc_attr( sprintf(__( 'View all posts filed under %s' ), $cat_name) ) . '"'; + else + $link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"'; + $link .= '>'; + $link .= $cat_name . '</a>'; + + if ( !empty($feed_image) || !empty($feed) ) { + $link .= ' '; + + if ( empty($feed_image) ) + $link .= '('; + + $link .= '<a href="' . esc_url( get_term_feed_link( $category->term_id, $category->taxonomy, $feed_type ) ) . '"'; + + if ( empty($feed) ) { + $alt = ' alt="' . sprintf(__( 'Feed for all posts filed under %s' ), $cat_name ) . '"'; + } else { + $title = ' title="' . $feed . '"'; + $alt = ' alt="' . $feed . '"'; + $name = $feed; + $link .= $title; + } + + $link .= '>'; + + if ( empty($feed_image) ) + $link .= $name; + else + $link .= "<img src='$feed_image'$alt$title" . ' />'; + + $link .= '</a>'; + + if ( empty($feed_image) ) + $link .= ')'; + } + + if ( !empty($show_count) ) + $link .= ' (' . intval($category->count) . ')'; + + if ( 'list' == $args['style'] ) { + $output .= "\t<li"; + $class = 'cat-item cat-item-' . $category->term_id; + if ( !empty($current_category) ) { + $_current_category = get_term( $current_category, $category->taxonomy ); + if ( $category->term_id == $current_category ) + $class .= ' current-cat'; + elseif ( $category->term_id == $_current_category->parent ) + $class .= ' current-cat-parent'; + } + $output .= ' class="' . $class . '"'; + $output .= ">$link\n"; + } else { + $output .= "\t$link<br />\n"; + } + } + + /** + * Ends the element output, if needed. + * + * @see Walker::end_el() + * + * @since 2.1.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $page Not used. + * @param int $depth Depth of category. Not used. + * @param array $args An array of arguments. Only uses 'list' for whether should append to output. @see wp_list_categories() + */ + function end_el( &$output, $page, $depth = 0, $args = array() ) { + if ( 'list' != $args['style'] ) + return; + + $output .= "</li>\n"; + } + +} + +/** + * Create HTML dropdown list of Categories. + * + * @package WordPress + * @since 2.1.0 + * @uses Walker + */ +class Walker_CategoryDropdown extends Walker { + /** + * @see Walker::$tree_type + * @since 2.1.0 + * @var string + */ + var $tree_type = 'category'; + + /** + * @see Walker::$db_fields + * @since 2.1.0 + * @todo Decouple this + * @var array + */ + var $db_fields = array ('parent' => 'parent', 'id' => 'term_id'); + + /** + * Start the element output. + * + * @see Walker::start_el() + * @since 2.1.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $category Category data object. + * @param int $depth Depth of category. Used for padding. + * @param array $args Uses 'selected' and 'show_count' keys, if they exist. @see wp_dropdown_categories() + */ + function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) { + $pad = str_repeat(' ', $depth * 3); + + $cat_name = apply_filters('list_cats', $category->name, $category); + $output .= "\t<option class=\"level-$depth\" value=\"".$category->term_id."\""; + if ( $category->term_id == $args['selected'] ) + $output .= ' selected="selected"'; + $output .= '>'; + $output .= $pad.$cat_name; + if ( $args['show_count'] ) + $output .= '  ('. $category->count .')'; + $output .= "</option>\n"; + } +} + +// +// Tags +// + +/** + * Retrieve the link to the tag. + * + * @since 2.3.0 + * @see get_term_link() + * + * @param int|object $tag Tag ID or object. + * @return string Link on success, empty string if tag does not exist. + */ +function get_tag_link( $tag ) { + if ( ! is_object( $tag ) ) + $tag = (int) $tag; + + $tag = get_term_link( $tag, 'post_tag' ); + + if ( is_wp_error( $tag ) ) + return ''; + + return $tag; +} + +/** + * Retrieve the tags for a post. + * + * @since 2.3.0 + * @uses apply_filters() Calls 'get_the_tags' filter on the list of post tags. + * + * @param int $id Post ID. + * @return array|bool Array of tag objects on success, false on failure. + */ +function get_the_tags( $id = 0 ) { + return apply_filters( 'get_the_tags', get_the_terms( $id, 'post_tag' ) ); +} + +/** + * Retrieve the tags for a post formatted as a string. + * + * @since 2.3.0 + * @uses apply_filters() Calls 'the_tags' filter on string list of tags. + * + * @param string $before Optional. Before tags. + * @param string $sep Optional. Between tags. + * @param string $after Optional. After tags. + * @param int $id Optional. Post ID. Defaults to the current post. + * @return string|bool|WP_Error A list of tags on success, false or WP_Error on failure. + */ +function get_the_tag_list( $before = '', $sep = '', $after = '', $id = 0 ) { + return apply_filters( 'the_tags', get_the_term_list( $id, 'post_tag', $before, $sep, $after ), $before, $sep, $after, $id ); +} + +/** + * Retrieve the tags for a post. + * + * @since 2.3.0 + * + * @param string $before Optional. Before list. + * @param string $sep Optional. Separate items using this. + * @param string $after Optional. After list. + */ +function the_tags( $before = null, $sep = ', ', $after = '' ) { + if ( null === $before ) + $before = __('Tags: '); + echo get_the_tag_list($before, $sep, $after); +} + +/** + * Retrieve tag description. + * + * @since 2.8 + * + * @param int $tag Optional. Tag ID. Will use global tag ID by default. + * @return string Tag description, available. + */ +function tag_description( $tag = 0 ) { + return term_description( $tag ); +} + +/** + * Retrieve term description. + * + * @since 2.8 + * + * @param int $term Optional. Term ID. Will use global term ID by default. + * @param string $taxonomy Optional taxonomy name. Defaults to 'post_tag'. + * @return string Term description, available. + */ +function term_description( $term = 0, $taxonomy = 'post_tag' ) { + if ( ! $term && ( is_tax() || is_tag() || is_category() ) ) { + $term = get_queried_object(); + if ( $term ) { + $taxonomy = $term->taxonomy; + $term = $term->term_id; + } + } + $description = get_term_field( 'description', $term, $taxonomy ); + return is_wp_error( $description ) ? '' : $description; +} + +/** + * Retrieve the terms of the taxonomy that are attached to the post. + * + * @since 2.5.0 + * + * @param int|object $post Post ID or object. + * @param string $taxonomy Taxonomy name. + * @return array|bool|WP_Error Array of term objects on success, false or WP_Error on failure. + */ +function get_the_terms( $post, $taxonomy ) { + if ( ! $post = get_post( $post ) ) + return false; + + $terms = get_object_term_cache( $post->ID, $taxonomy ); + if ( false === $terms ) { + $terms = wp_get_object_terms( $post->ID, $taxonomy ); + wp_cache_add($post->ID, $terms, $taxonomy . '_relationships'); + } + + $terms = apply_filters( 'get_the_terms', $terms, $post->ID, $taxonomy ); + + if ( empty( $terms ) ) + return false; + + return $terms; +} + +/** + * Retrieve a post's terms as a list with specified format. + * + * @since 2.5.0 + * + * @param int $id Post ID. + * @param string $taxonomy Taxonomy name. + * @param string $before Optional. Before list. + * @param string $sep Optional. Separate items using this. + * @param string $after Optional. After list. + * @return string|bool|WP_Error A list of terms on success, false or WP_Error on failure. + */ +function get_the_term_list( $id, $taxonomy, $before = '', $sep = '', $after = '' ) { + $terms = get_the_terms( $id, $taxonomy ); + + if ( is_wp_error( $terms ) ) + return $terms; + + if ( empty( $terms ) ) + return false; + + foreach ( $terms as $term ) { + $link = get_term_link( $term, $taxonomy ); + if ( is_wp_error( $link ) ) + return $link; + $term_links[] = '<a href="' . esc_url( $link ) . '" rel="tag">' . $term->name . '</a>'; + } + + $term_links = apply_filters( "term_links-$taxonomy", $term_links ); + + return $before . join( $sep, $term_links ) . $after; +} + +/** + * Display the terms in a list. + * + * @since 2.5.0 + * + * @param int $id Post ID. + * @param string $taxonomy Taxonomy name. + * @param string $before Optional. Before list. + * @param string $sep Optional. Separate items using this. + * @param string $after Optional. After list. + * @return null|bool False on WordPress error. Returns null when displaying. + */ +function the_terms( $id, $taxonomy, $before = '', $sep = ', ', $after = '' ) { + $term_list = get_the_term_list( $id, $taxonomy, $before, $sep, $after ); + + if ( is_wp_error( $term_list ) ) + return false; + + echo apply_filters('the_terms', $term_list, $taxonomy, $before, $sep, $after); +} + +/** + * Check if the current post has any of given category. + * + * @since 3.1.0 + * + * @param string|int|array $category Optional. The category name/term_id/slug or array of them to check for. + * @param int|object $post Optional. Post to check instead of the current post. + * @return bool True if the current post has any of the given categories (or any category, if no category specified). + */ +function has_category( $category = '', $post = null ) { + return has_term( $category, 'category', $post ); +} + +/** + * Check if the current post has any of given tags. + * + * The given tags are checked against the post's tags' term_ids, names and slugs. + * Tags given as integers will only be checked against the post's tags' term_ids. + * If no tags are given, determines if post has any tags. + * + * Prior to v2.7 of WordPress, tags given as integers would also be checked against the post's tags' names and slugs (in addition to term_ids) + * Prior to v2.7, this function could only be used in the WordPress Loop. + * As of 2.7, the function can be used anywhere if it is provided a post ID or post object. + * + * @since 2.6.0 + * + * @param string|int|array $tag Optional. The tag name/term_id/slug or array of them to check for. + * @param int|object $post Optional. Post to check instead of the current post. (since 2.7.0) + * @return bool True if the current post has any of the given tags (or any tag, if no tag specified). + */ +function has_tag( $tag = '', $post = null ) { + return has_term( $tag, 'post_tag', $post ); +} + +/** + * Check if the current post has any of given terms. + * + * The given terms are checked against the post's terms' term_ids, names and slugs. + * Terms given as integers will only be checked against the post's terms' term_ids. + * If no terms are given, determines if post has any terms. + * + * @since 3.1.0 + * + * @param string|int|array $term Optional. The term name/term_id/slug or array of them to check for. + * @param string $taxonomy Taxonomy name + * @param int|object $post Optional. Post to check instead of the current post. + * @return bool True if the current post has any of the given tags (or any tag, if no tag specified). + */ +function has_term( $term = '', $taxonomy = '', $post = null ) { + $post = get_post($post); + + if ( !$post ) + return false; + + $r = is_object_in_term( $post->ID, $taxonomy, $term ); + if ( is_wp_error( $r ) ) + return false; + + return $r; +} diff --git a/sources/wp-includes/category.php b/sources/wp-includes/category.php new file mode 100644 index 0000000..6bf7bac --- /dev/null +++ b/sources/wp-includes/category.php @@ -0,0 +1,359 @@ +<?php +/** + * WordPress Category API + * + * @package WordPress + */ + +/** + * Retrieves all category IDs. + * + * @since 2.0.0 + * @link http://codex.wordpress.org/Function_Reference/get_all_category_ids + * + * @return object List of all of the category IDs. + */ +function get_all_category_ids() { + if ( ! $cat_ids = wp_cache_get( 'all_category_ids', 'category' ) ) { + $cat_ids = get_terms( 'category', array('fields' => 'ids', 'get' => 'all') ); + wp_cache_add( 'all_category_ids', $cat_ids, 'category' ); + } + + return $cat_ids; +} + +/** + * Retrieve list of category objects. + * + * If you change the type to 'link' in the arguments, then the link categories + * will be returned instead. Also all categories will be updated to be backwards + * compatible with pre-2.3 plugins and themes. + * + * @since 2.1.0 + * @see get_terms() Type of arguments that can be changed. + * @link http://codex.wordpress.org/Function_Reference/get_categories + * + * @param string|array $args Optional. Change the defaults retrieving categories. + * @return array List of categories. + */ +function get_categories( $args = '' ) { + $defaults = array( 'taxonomy' => 'category' ); + $args = wp_parse_args( $args, $defaults ); + + $taxonomy = $args['taxonomy']; + /** + * Filter the taxonomy used to retrieve terms when calling get_categories(). + * + * @since 2.7.0 + * + * @param string $taxonomy Taxonomy to retrieve terms from. + * @param array $args An array of arguments. @see get_terms() + */ + $taxonomy = apply_filters( 'get_categories_taxonomy', $taxonomy, $args ); + + // Back compat + if ( isset($args['type']) && 'link' == $args['type'] ) { + _deprecated_argument( __FUNCTION__, '3.0', '' ); + $taxonomy = $args['taxonomy'] = 'link_category'; + } + + $categories = (array) get_terms( $taxonomy, $args ); + + foreach ( array_keys( $categories ) as $k ) + _make_cat_compat( $categories[$k] ); + + return $categories; +} + +/** + * Retrieves category data given a category ID or category object. + * + * If you pass the $category parameter an object, which is assumed to be the + * category row object retrieved the database. It will cache the category data. + * + * If you pass $category an integer of the category ID, then that category will + * be retrieved from the database, if it isn't already cached, and pass it back. + * + * If you look at get_term(), then both types will be passed through several + * filters and finally sanitized based on the $filter parameter value. + * + * The category will converted to maintain backwards compatibility. + * + * @since 1.5.1 + * @uses get_term() Used to get the category data from the taxonomy. + * + * @param int|object $category Category ID or Category row object + * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N + * @param string $filter Optional. Default is raw or no WordPress defined filter will applied. + * @return mixed Category data in type defined by $output parameter. + */ +function get_category( $category, $output = OBJECT, $filter = 'raw' ) { + $category = get_term( $category, 'category', $output, $filter ); + if ( is_wp_error( $category ) ) + return $category; + + _make_cat_compat( $category ); + + return $category; +} + +/** + * Retrieve category based on URL containing the category slug. + * + * Breaks the $category_path parameter up to get the category slug. + * + * Tries to find the child path and will return it. If it doesn't find a + * match, then it will return the first category matching slug, if $full_match, + * is set to false. If it does not, then it will return null. + * + * It is also possible that it will return a WP_Error object on failure. Check + * for it when using this function. + * + * @since 2.1.0 + * + * @param string $category_path URL containing category slugs. + * @param bool $full_match Optional. Whether full path should be matched. + * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N + * @return null|object|array Null on failure. Type is based on $output value. + */ +function get_category_by_path( $category_path, $full_match = true, $output = OBJECT ) { + $category_path = rawurlencode( urldecode( $category_path ) ); + $category_path = str_replace( '%2F', '/', $category_path ); + $category_path = str_replace( '%20', ' ', $category_path ); + $category_paths = '/' . trim( $category_path, '/' ); + $leaf_path = sanitize_title( basename( $category_paths ) ); + $category_paths = explode( '/', $category_paths ); + $full_path = ''; + foreach ( (array) $category_paths as $pathdir ) + $full_path .= ( $pathdir != '' ? '/' : '' ) . sanitize_title( $pathdir ); + + $categories = get_terms( 'category', array('get' => 'all', 'slug' => $leaf_path) ); + + if ( empty( $categories ) ) + return null; + + foreach ( $categories as $category ) { + $path = '/' . $leaf_path; + $curcategory = $category; + while ( ( $curcategory->parent != 0 ) && ( $curcategory->parent != $curcategory->term_id ) ) { + $curcategory = get_term( $curcategory->parent, 'category' ); + if ( is_wp_error( $curcategory ) ) + return $curcategory; + $path = '/' . $curcategory->slug . $path; + } + + if ( $path == $full_path ) { + $category = get_term( $category->term_id, 'category', $output ); + _make_cat_compat( $category ); + return $category; + } + } + + // If full matching is not required, return the first cat that matches the leaf. + if ( ! $full_match ) { + $category = get_term( reset( $categories )->term_id, 'category', $output ); + _make_cat_compat( $category ); + return $category; + } + + return null; +} + +/** + * Retrieve category object by category slug. + * + * @since 2.3.0 + * + * @param string $slug The category slug. + * @return object Category data object + */ +function get_category_by_slug( $slug ) { + $category = get_term_by( 'slug', $slug, 'category' ); + if ( $category ) + _make_cat_compat( $category ); + + return $category; +} + +/** + * Retrieve the ID of a category from its name. + * + * @since 1.0.0 + * + * @param string $cat_name Category name. + * @return int 0, if failure and ID of category on success. + */ +function get_cat_ID( $cat_name ) { + $cat = get_term_by( 'name', $cat_name, 'category' ); + if ( $cat ) + return $cat->term_id; + return 0; +} + +/** + * Retrieve the name of a category from its ID. + * + * @since 1.0.0 + * + * @param int $cat_id Category ID + * @return string Category name, or an empty string if category doesn't exist. + */ +function get_cat_name( $cat_id ) { + $cat_id = (int) $cat_id; + $category = get_term( $cat_id, 'category' ); + if ( ! $category || is_wp_error( $category ) ) + return ''; + return $category->name; +} + +/** + * Check if a category is an ancestor of another category. + * + * You can use either an id or the category object for both parameters. If you + * use an integer the category will be retrieved. + * + * @since 2.1.0 + * + * @param int|object $cat1 ID or object to check if this is the parent category. + * @param int|object $cat2 The child category. + * @return bool Whether $cat2 is child of $cat1 + */ +function cat_is_ancestor_of( $cat1, $cat2 ) { + return term_is_ancestor_of( $cat1, $cat2, 'category' ); +} + +/** + * Sanitizes category data based on context. + * + * @since 2.3.0 + * @uses sanitize_term() See this function for what context are supported. + * + * @param object|array $category Category data + * @param string $context Optional. Default is 'display'. + * @return object|array Same type as $category with sanitized data for safe use. + */ +function sanitize_category( $category, $context = 'display' ) { + return sanitize_term( $category, 'category', $context ); +} + +/** + * Sanitizes data in single category key field. + * + * @since 2.3.0 + * @uses sanitize_term_field() See function for more details. + * + * @param string $field Category key to sanitize + * @param mixed $value Category value to sanitize + * @param int $cat_id Category ID + * @param string $context What filter to use, 'raw', 'display', etc. + * @return mixed Same type as $value after $value has been sanitized. + */ +function sanitize_category_field( $field, $value, $cat_id, $context ) { + return sanitize_term_field( $field, $value, $cat_id, 'category', $context ); +} + +/* Tags */ + +/** + * Retrieves all post tags. + * + * @since 2.3.0 + * @see get_terms() For list of arguments to pass. + * @uses apply_filters() Calls 'get_tags' hook on array of tags and with $args. + * + * @param string|array $args Tag arguments to use when retrieving tags. + * @return array List of tags. + */ +function get_tags( $args = '' ) { + $tags = get_terms( 'post_tag', $args ); + + if ( empty( $tags ) ) { + $return = array(); + return $return; + } + + /** + * Filter the array of term objects returned for the 'post_tag' taxonomy. + * + * @since 2.3.0 + * + * @param array $tags Array of 'post_tag' term objects. + * @param array $args An array of arguments. @see get_terms() + */ + $tags = apply_filters( 'get_tags', $tags, $args ); + return $tags; +} + +/** + * Retrieve post tag by tag ID or tag object. + * + * If you pass the $tag parameter an object, which is assumed to be the tag row + * object retrieved the database. It will cache the tag data. + * + * If you pass $tag an integer of the tag ID, then that tag will + * be retrieved from the database, if it isn't already cached, and pass it back. + * + * If you look at get_term(), then both types will be passed through several + * filters and finally sanitized based on the $filter parameter value. + * + * @since 2.3.0 + * + * @param int|object $tag + * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N + * @param string $filter Optional. Default is raw or no WordPress defined filter will applied. + * @return object|array Return type based on $output value. + */ +function get_tag( $tag, $output = OBJECT, $filter = 'raw' ) { + return get_term( $tag, 'post_tag', $output, $filter ); +} + +/* Cache */ + +/** + * Remove the category cache data based on ID. + * + * @since 2.1.0 + * @uses clean_term_cache() Clears the cache for the category based on ID + * + * @param int $id Category ID + */ +function clean_category_cache( $id ) { + clean_term_cache( $id, 'category' ); +} + +/** + * Update category structure to old pre 2.3 from new taxonomy structure. + * + * This function was added for the taxonomy support to update the new category + * structure with the old category one. This will maintain compatibility with + * plugins and themes which depend on the old key or property names. + * + * The parameter should only be passed a variable and not create the array or + * object inline to the parameter. The reason for this is that parameter is + * passed by reference and PHP will fail unless it has the variable. + * + * There is no return value, because everything is updated on the variable you + * pass to it. This is one of the features with using pass by reference in PHP. + * + * @since 2.3.0 + * @access private + * + * @param array|object $category Category Row object or array + */ +function _make_cat_compat( &$category ) { + if ( is_object( $category ) ) { + $category->cat_ID = &$category->term_id; + $category->category_count = &$category->count; + $category->category_description = &$category->description; + $category->cat_name = &$category->name; + $category->category_nicename = &$category->slug; + $category->category_parent = &$category->parent; + } elseif ( is_array( $category ) && isset( $category['term_id'] ) ) { + $category['cat_ID'] = &$category['term_id']; + $category['category_count'] = &$category['count']; + $category['category_description'] = &$category['description']; + $category['cat_name'] = &$category['name']; + $category['category_nicename'] = &$category['slug']; + $category['category_parent'] = &$category['parent']; + } +} diff --git a/sources/wp-includes/certificates/ca-bundle.crt b/sources/wp-includes/certificates/ca-bundle.crt new file mode 100644 index 0000000..b531fc4 --- /dev/null +++ b/sources/wp-includes/certificates/ca-bundle.crt @@ -0,0 +1,3554 @@ +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012 +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## + +# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $ + +EE Certification Centre Root CA +=============================== +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy +dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw +MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB +UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy +ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM +TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 +rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw +93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN +P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ +MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF +BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj +xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM +lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU +3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM +dcGWxZ0= +-----END CERTIFICATE----- + +GTE CyberTrust Global Root +========================== +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg +Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG +A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz +MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL +Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 +IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u +sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql +HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID +AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW +M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF +NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- + +Thawte Server CA +================ +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE +AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j +b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV +BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u +c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG +A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 +ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl +/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 +1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J +GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ +GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +Thawte Premium Server CA +======================== +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE +AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl +ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU +VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 +aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ +cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 +aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh +Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ +qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm +SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf +8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t +UCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +Equifax Secure CA +================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE +ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT +B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR +fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW +8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE +CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS +spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 +zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB +BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 +70+sB3c4 +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 1 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy +MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE +NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i +o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq +kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4 +RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 3 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy +MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD +VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS +xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi +up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1 +mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA +TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah +WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf +Tqj/ZA1k +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO +FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 +lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB +MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT +1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD +Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 +-----END CERTIFICATE----- + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +ValiCert Class 1 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy +MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi +GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm +DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG +lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX +icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP +Orf1LXLI +-----END CERTIFICATE----- + +ValiCert Class 2 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC +CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf +ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ +SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV +UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 +W9ViH0Pd +-----END CERTIFICATE----- + +RSA Root Certificate 1 +====================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td +3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H +BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs +3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF +V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r +on+jjBXu +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 +EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc +cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw +EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj +055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f +j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 +xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa +t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS +tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM +8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW +Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX +Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt +mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd +RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG +UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- + +Entrust.net Secure Server CA +============================ +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg +cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl +ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG +A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi +eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p +dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ +aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 +gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw +ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw +CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l +dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw +NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow +HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN +Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 +n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC +AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER +gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B +AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS +o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z +2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX +OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Equifax Secure Global eBusiness CA +================================== +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp +bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx +HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds +b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV +PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN +qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn +hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs +MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN +I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY +NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 1 +============================= +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB +LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE +ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz +IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ +1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a +IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk +MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW +Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF +AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 +lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ +KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 2 +============================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE +ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y +MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT +DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn +2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5 +BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx +JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e +uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1 +jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia +78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm +V+GRMOrN +-----END CERTIFICATE----- + +AddTrust Low-Value Services Root +================================ +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU +cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw +CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO +ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 +54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr +oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 +Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui +GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w +HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT +RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw +HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt +ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph +iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr +mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj +ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +AddTrust External Root +====================== +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD +VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw +NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU +cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 ++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw +Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo +aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy +2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 +7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL +VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk +VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl +j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 +e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u +G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +AddTrust Public Services Root +============================= +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU +cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ +BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l +dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu +nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i +d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG +Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw +HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G +A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G +A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 +JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL ++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 +Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H +EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +AddTrust Qualified Certificates Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU +cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx +CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ +IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx +64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 +KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o +L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR +wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU +MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE +BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y +azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG +GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze +RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB +iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +RSA Security 2048 v3 +==================== +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK +ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy +MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb +BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 +Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb +WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH +KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP ++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E +FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY +v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj +0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj +VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 +nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA +pKnXwiJPZ9d37CAFYd4= +-----END CERTIFICATE----- + +GeoTrust Global CA +================== +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw +MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo +BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet +8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc +T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU +vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk +DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q +zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 +d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 +mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p +XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm +Mw== +-----END CERTIFICATE----- + +GeoTrust Global CA 2 +==================== +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw +MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ +NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k +LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA +Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b +HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH +K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 +srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh +ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL +OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC +x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF +H4z1Ir+rzoPz4iIprn2DQKi6bA== +-----END CERTIFICATE----- + +GeoTrust Universal CA +===================== +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 +MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu +Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t +JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e +RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs +7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d +8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V +qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga +Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB +Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu +KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 +ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 +XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 +qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL +oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK +xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF +KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 +DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK +xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU +p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI +P/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +======================= +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 +MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg +SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 +DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 +j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q +JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a +QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 +WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP +20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn +ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC +SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG +8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 ++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ +4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ +mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq +A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg +Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP +pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d +FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp +gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm +X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +America Online Root Certification Authority 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG +v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z +DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh +sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP +8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z +o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf +GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF +VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft +3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g +Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- + +America Online Root Certification Authority 2 +============================================= +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en +fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 +f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO +qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN +RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 +gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn +6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid +FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 +Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj +B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op +aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY +T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p ++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg +JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy +zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO +ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh +1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf +GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff +Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP +cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= +-----END CERTIFICATE----- + +Visa eCommerce Root +=================== +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG +EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug +QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 +WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm +VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL +F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b +RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 +TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI +/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs +GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc +CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW +YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz +zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu +YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +Certum Root CA +============== +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK +ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla +Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u +by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x +wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL +kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ +89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K +Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P +NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ +GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg +GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ +0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS +qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +Comodo Secure Services root +=========================== +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw +MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu +Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi +BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP +9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc +rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC +oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V +p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E +FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj +YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm +aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm +4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL +DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw +pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H +RR3B7Hzs/Sk= +-----END CERTIFICATE----- + +Comodo Trusted Services root +============================ +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw +MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h +bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw +IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 +3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y +/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 +juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS +ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud +DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp +ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl +cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw +uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA +BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l +R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O +9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA +============================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE +ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w +HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh +bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt +vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P +jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca +C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth +vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 +22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV +HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v +dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN +BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR +EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw +MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y +nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +TDC Internet Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE +ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx +NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu +ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j +xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL +znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc +5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 +otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI +AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM +VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM +MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC +AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe +UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G +CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m +gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb +O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU +Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- + +UTN DATACorp SGC Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ +BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa +MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w +HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy +dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys +raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo +wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA +9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv +33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud +DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 +BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD +LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 +DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 +I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx +EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP +DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +UTN USERFirst Hardware Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd +BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx +OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 +eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz +ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI +wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd +tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 +i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf +Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw +gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF +UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF +BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW +XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 +lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn +iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 +nfhmqA== +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx +NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp +cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn +MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU +xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH +NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW +DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV +d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud +EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v +cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P +AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh +bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD +VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi +fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD +L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN +UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n +ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 +erfutGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +================================== +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx +NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt +YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg +MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw +ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J +1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O +by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl +6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c +8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ +BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j +aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B +Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj +aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y +ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA +PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y +gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ +PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 +IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes +t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +NetLock Notary (Class A) Root +============================= +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI +EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j +ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX +DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH +EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD +VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz +cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM +D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ +z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC +/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 +tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 +4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG +A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC +Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv +bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn +LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 +ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz +IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh +IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu +b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh +bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg +Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp +bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 +ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP +ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB +CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr +KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM +8CgHrTwXZoi1/baI +-----END CERTIFICATE----- + +NetLock Business (Class B) Root +=============================== +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg +VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD +VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv +bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg +VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S +o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr +1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV +HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ +RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh +dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 +ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv +c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg +YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz +Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA +bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl +IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 +YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj +cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM +43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR +stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +NetLock Express (Class C) Root +============================== +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ +BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j +ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z +W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 +euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw +DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN +RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn +YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB +IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i +aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 +ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y +emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k +IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ +UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg +YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 +xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW +gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj +YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH +AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw +Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg +U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 +LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh +cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT +dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC +AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh +3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm +vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk +fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 +fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ +EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl +1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ +lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro +g14= +-----END CERTIFICATE----- + +Taiwan GRCA +=========== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG +EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X +DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv +dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN +w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 +BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O +1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO +htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov +J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 +Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t +B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB +O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 +lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV +HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 +09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj +Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 +Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU +D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz +DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk +Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk +7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ +CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy ++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS +-----END CERTIFICATE----- + +Firmaprofesional Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT +GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp +Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA +ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL +MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT +OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2 +ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V +j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH +lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf +3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8 +NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww +KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG +AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD +ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf +wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm +7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG +VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA= +-----END CERTIFICATE----- + +Wells Fargo Root CA +=================== +-----BEGIN CERTIFICATE----- +MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl +bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv +MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX +x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3 +E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5 +OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j +sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj +YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF +BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD +ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv +m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R +OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx +x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023 +tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +-----END CERTIFICATE----- + +Swisscom Root CA 1 +================== +-----BEGIN CERTIFICATE----- +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 +NY6E0F/6MBr1mmz0DlP5OlvRHA== +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +Certplus Class 2 Primary CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE +BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN +OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy +dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR +5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ +Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO +YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e +e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME +CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ +YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t +L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD +P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R +TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ +7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW +//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +DST ACES CA X6 +============== +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT +MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha +MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE +CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI +DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa +pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow +GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy +MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu +Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy +dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU +CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 +5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t +Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs +vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 +oKfN5XozNmr6mis= +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 1 +============================================== +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP +MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 +acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx +MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg +U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB +TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC +aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX +yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i +Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ +8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 +W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME +BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 +sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE +q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY +nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 2 +============================================== +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP +MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg +QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN +MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr +dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G +A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls +acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe +LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI +x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g +QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr +5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB +AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt +Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ +hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P +9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 +UrbnBEI= +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ +cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN +b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 +nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge +RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt +tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI +hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K +Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN +NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa +Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG +1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 +MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg +SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv +KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT +FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs +oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ +1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc +q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K +aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p +afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF +AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE +uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 +jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH +z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +============================================================ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln +biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh +dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz +j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD +Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ +Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r +fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv +Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG +SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ +X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE +KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC +Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE +ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +WellsSecure Public Root Certificate Authority +============================================= +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM +F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw +NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl +bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD +VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 +iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 +i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 +bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB +K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB +AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu +cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm +lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB +i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww +GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI +K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 +bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj +qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es +E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ +tylv2G0xffX8oRAHh84vWdw+WNs= +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +IGC/A +===== +-----BEGIN CERTIFICATE----- +MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD +VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE +Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy +MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI +EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT +STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 +TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW +So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy +HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd +frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ +tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB +egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC +iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK +q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q +MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg +Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI +lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF +0mBWWg== +-----END CERTIFICATE----- + +Security Communication EV RootCA1 +================================= +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE +BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl +Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO +/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX +WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z +ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 +bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK +9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm +iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG +Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW +mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW +T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GA CA +=============================== +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE +BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG +A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH +bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD +VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw +IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 +IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 +Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg +Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD +d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ +/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R +LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm +MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 ++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY +okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE +BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL +EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 +MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz +dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT +GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG +d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N +oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc +QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ +PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb +MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG +IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD +VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 +LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A +dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA +4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg +AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA +egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 +Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO +PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv +c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h +cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw +IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT +WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV +MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER +MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp +Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal +HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT +nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE +aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK +yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB +S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. +====================================== +-----BEGIN CERTIFICATE----- +MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT +AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg +LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w +HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ +U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh +IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN +yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU +2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 +4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP +2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm +8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf +HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa +Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK +5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b +czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g +ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF +BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug +cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf +AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX +EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v +/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 +MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 +3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk +eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f +/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h +RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU +Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 2 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw +MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw +IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 +xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ +Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u +SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G +dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ +KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj +TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP +JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk +vQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 3 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw +MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W +yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo +6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ +uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk +2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE +O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 +yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 +IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal +092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc +5A== +-----END CERTIFICATE----- + +TC TrustCenter Universal CA I +============================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN +MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg +VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw +JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC +qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv +xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw +ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O +gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j +BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG +1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy +vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 +ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a +7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----END CERTIFICATE----- + +Deutsche Telekom Root CA 2 +========================== +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT +RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG +A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 +MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G +A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS +b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 +bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI +KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY +AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK +Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV +jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV +HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr +E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy +zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 +rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G +dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +ComSign Secured CA +================== +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE +AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w +NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD +QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs +49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH +7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB +kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 +9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw +AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t +U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA +j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC +AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a +BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp +FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP +51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 +============================================================================================================================= +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH +DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q +aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry +b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV +BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg +S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 +MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl +IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF +n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl +IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft +dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl +cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO +Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 +xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR +6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd +BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 +N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT +y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh +LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M +dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +Buypass Class 2 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 +MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M +cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 +0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 +0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R +uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV +1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt +7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 +fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w +wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho +-----END CERTIFICATE----- + +Buypass Class 3 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 +MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx +ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 +n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia +AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c +1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 +pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA +EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 +htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj +el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- + +EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 +========================================================================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +CNNIC ROOT +========== +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE +ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw +OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD +o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz +VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT +VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or +czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK +y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC +wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S +lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 +Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM +O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 +BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 +G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m +mxE= +-----END CERTIFICATE----- + +ApplicationCA - Japanese Government +=================================== +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT +SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw +MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl +cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 +fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN +wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE +jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu +nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU +WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV +BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD +vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs +o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g +/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD +io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW +dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +============================================= +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz +NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo +YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT +LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j +K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE +c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C +IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu +dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr +2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 +cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE +Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s +t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +=========================== +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC +VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu +IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg +Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV +MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG +b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt +IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS +LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 +8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU +mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN +G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K +rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w +ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD +VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG +A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At +P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC ++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY +7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW +vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ +KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK +A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC +8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm +er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC +VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 +b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz +ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU +cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo +b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 +Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz +rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw +HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u +Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD +A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx +AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) FÅ‘tanúsítvány +============================================ +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA - G2 +================================== +-----BEGIN CERTIFICATE----- +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 +66+KAQ== +-----END CERTIFICATE----- + +CA Disig +======== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK +QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw +MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz +bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm +GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD +Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo +hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt +ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w +gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P +AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz +aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff +ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa +BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t +WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 +mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ +CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K +ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA +4Z7CRneC9VkGjCFMhwnN5ag= +-----END CERTIFICATE----- + +Juur-SK +======= +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA +c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw +DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG +SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy +aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf +TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC ++Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw +UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa +Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF +MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD +HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh +AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA +cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr +AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw +cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE +FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G +A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo +ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL +abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 +IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh +Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 +yyqcjg== +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +ACEDICOM Root +============= +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky +CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX +bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ +D/xwzoiQ +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi +=================================================== +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz +ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 +MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 +cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u +aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY +8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y +jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI +JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk +9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG +SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d +F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq +D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 +Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq +fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +TC TrustCenter Universal CA III +=============================== +-----BEGIN CERTIFICATE----- +MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe +Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU +QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex +KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt +QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO +juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut +CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1 +M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G +A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA +g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+ +KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK +BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV +CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq +woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +Certinomis - Autorité Racine +============================= +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg +LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG +A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw +JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa +wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly +Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw +2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N +jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q +c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC +lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb +xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g +530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna +4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x +WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva +R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 +nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B +CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv +JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE +qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b +WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE +wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ +vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- + +Root CA Generalitat Valenciana +============================== +-----BEGIN CERTIFICATE----- +MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE +ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 +IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 +WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE +CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 +F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B +ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ +D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte +JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB +AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n +dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB +ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl +AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA +YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy +AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA +aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt +AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA +YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu +AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA +OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 +dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV +BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G +A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S +b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh +TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz +Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 +NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH +iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt ++GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= +-----END CERTIFICATE----- + +A-Trust-nQual-03 +================ +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE +Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy +a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R +dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw +RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 +ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 +c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA +zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n +yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE +SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 +iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V +cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV +eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 +ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr +sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd +JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS +mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 +ahq97BvIxYSazQ== +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ +Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 +dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu +c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv +bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 +aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 +fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm +N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN +Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T +tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX +e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA +2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs +HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib +D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +StartCom Certification Authority G2 +=================================== +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE +ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O +o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG +4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi +Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul +Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs +O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H +vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L +nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS +FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa +z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ +KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk +J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ +JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG +/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc +nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld +blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc +l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm +7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm +obp573PYtlNXLfbQ4ddI +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- diff --git a/sources/wp-includes/class-IXR.php b/sources/wp-includes/class-IXR.php new file mode 100644 index 0000000..f8fbc00 --- /dev/null +++ b/sources/wp-includes/class-IXR.php @@ -0,0 +1,1070 @@ +<?php +/** + * IXR - The Incutio XML-RPC Library + * + * Copyright (c) 2010, Incutio Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of Incutio Ltd. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @package IXR + * @since 1.5 + * + * @copyright Incutio Ltd 2010 (http://www.incutio.com) + * @version 1.7.4 7th September 2010 + * @author Simon Willison + * @link http://scripts.incutio.com/xmlrpc/ Site/manual + * @license http://www.opensource.org/licenses/bsd-license.php BSD + */ + +/** + * IXR_Value + * + * @package IXR + * @since 1.5 + */ +class IXR_Value { + var $data; + var $type; + + function IXR_Value($data, $type = false) + { + $this->data = $data; + if (!$type) { + $type = $this->calculateType(); + } + $this->type = $type; + if ($type == 'struct') { + // Turn all the values in the array in to new IXR_Value objects + foreach ($this->data as $key => $value) { + $this->data[$key] = new IXR_Value($value); + } + } + if ($type == 'array') { + for ($i = 0, $j = count($this->data); $i < $j; $i++) { + $this->data[$i] = new IXR_Value($this->data[$i]); + } + } + } + + function calculateType() + { + if ($this->data === true || $this->data === false) { + return 'boolean'; + } + if (is_integer($this->data)) { + return 'int'; + } + if (is_double($this->data)) { + return 'double'; + } + + // Deal with IXR object types base64 and date + if (is_object($this->data) && is_a($this->data, 'IXR_Date')) { + return 'date'; + } + if (is_object($this->data) && is_a($this->data, 'IXR_Base64')) { + return 'base64'; + } + + // If it is a normal PHP object convert it in to a struct + if (is_object($this->data)) { + $this->data = get_object_vars($this->data); + return 'struct'; + } + if (!is_array($this->data)) { + return 'string'; + } + + // We have an array - is it an array or a struct? + if ($this->isStruct($this->data)) { + return 'struct'; + } else { + return 'array'; + } + } + + function getXml() + { + // Return XML for this value + switch ($this->type) { + case 'boolean': + return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>'; + break; + case 'int': + return '<int>'.$this->data.'</int>'; + break; + case 'double': + return '<double>'.$this->data.'</double>'; + break; + case 'string': + return '<string>'.htmlspecialchars($this->data).'</string>'; + break; + case 'array': + $return = '<array><data>'."\n"; + foreach ($this->data as $item) { + $return .= ' <value>'.$item->getXml()."</value>\n"; + } + $return .= '</data></array>'; + return $return; + break; + case 'struct': + $return = '<struct>'."\n"; + foreach ($this->data as $name => $value) { + $name = htmlspecialchars($name); + $return .= " <member><name>$name</name><value>"; + $return .= $value->getXml()."</value></member>\n"; + } + $return .= '</struct>'; + return $return; + break; + case 'date': + case 'base64': + return $this->data->getXml(); + break; + } + return false; + } + + /** + * Checks whether or not the supplied array is a struct or not + * + * @param unknown_type $array + * @return boolean + */ + function isStruct($array) + { + $expected = 0; + foreach ($array as $key => $value) { + if ((string)$key != (string)$expected) { + return true; + } + $expected++; + } + return false; + } +} + +/** + * IXR_MESSAGE + * + * @package IXR + * @since 1.5 + * + */ +class IXR_Message +{ + var $message; + var $messageType; // methodCall / methodResponse / fault + var $faultCode; + var $faultString; + var $methodName; + var $params; + + // Current variable stacks + var $_arraystructs = array(); // The stack used to keep track of the current array/struct + var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array + var $_currentStructName = array(); // A stack as well + var $_param; + var $_value; + var $_currentTag; + var $_currentTagContents; + // The XML parser + var $_parser; + + function IXR_Message($message) + { + $this->message =& $message; + } + + function parse() + { + // first remove the XML declaration + // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages + $header = preg_replace( '/<\?xml.*?\?'.'>/', '', substr($this->message, 0, 100), 1); + $this->message = substr_replace($this->message, $header, 0, 100); + if (trim($this->message) == '') { + return false; + } + $this->_parser = xml_parser_create(); + // Set XML parser to take the case of tags in to account + xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); + // Set XML parser callback functions + xml_set_object($this->_parser, $this); + xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); + xml_set_character_data_handler($this->_parser, 'cdata'); + $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages + $final = false; + do { + if (strlen($this->message) <= $chunk_size) { + $final = true; + } + $part = substr($this->message, 0, $chunk_size); + $this->message = substr($this->message, $chunk_size); + if (!xml_parse($this->_parser, $part, $final)) { + return false; + } + if ($final) { + break; + } + } while (true); + xml_parser_free($this->_parser); + + // Grab the error messages, if any + if ($this->messageType == 'fault') { + $this->faultCode = $this->params[0]['faultCode']; + $this->faultString = $this->params[0]['faultString']; + } + return true; + } + + function tag_open($parser, $tag, $attr) + { + $this->_currentTagContents = ''; + $this->currentTag = $tag; + switch($tag) { + case 'methodCall': + case 'methodResponse': + case 'fault': + $this->messageType = $tag; + break; + /* Deal with stacks of arrays and structs */ + case 'data': // data is to all intents and puposes more interesting than array + $this->_arraystructstypes[] = 'array'; + $this->_arraystructs[] = array(); + break; + case 'struct': + $this->_arraystructstypes[] = 'struct'; + $this->_arraystructs[] = array(); + break; + } + } + + function cdata($parser, $cdata) + { + $this->_currentTagContents .= $cdata; + } + + function tag_close($parser, $tag) + { + $valueFlag = false; + switch($tag) { + case 'int': + case 'i4': + $value = (int)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'double': + $value = (double)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'string': + $value = (string)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'dateTime.iso8601': + $value = new IXR_Date(trim($this->_currentTagContents)); + $valueFlag = true; + break; + case 'value': + // "If no type is indicated, the type is string." + if (trim($this->_currentTagContents) != '') { + $value = (string)$this->_currentTagContents; + $valueFlag = true; + } + break; + case 'boolean': + $value = (boolean)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'base64': + $value = base64_decode($this->_currentTagContents); + $valueFlag = true; + break; + /* Deal with stacks of arrays and structs */ + case 'data': + case 'struct': + $value = array_pop($this->_arraystructs); + array_pop($this->_arraystructstypes); + $valueFlag = true; + break; + case 'member': + array_pop($this->_currentStructName); + break; + case 'name': + $this->_currentStructName[] = trim($this->_currentTagContents); + break; + case 'methodName': + $this->methodName = trim($this->_currentTagContents); + break; + } + + if ($valueFlag) { + if (count($this->_arraystructs) > 0) { + // Add value to struct or array + if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') { + // Add to struct + $this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value; + } else { + // Add to array + $this->_arraystructs[count($this->_arraystructs)-1][] = $value; + } + } else { + // Just add as a paramater + $this->params[] = $value; + } + } + $this->_currentTagContents = ''; + } +} + +/** + * IXR_Server + * + * @package IXR + * @since 1.5 + */ +class IXR_Server +{ + var $data; + var $callbacks = array(); + var $message; + var $capabilities; + + function IXR_Server($callbacks = false, $data = false, $wait = false) + { + $this->setCapabilities(); + if ($callbacks) { + $this->callbacks = $callbacks; + } + $this->setCallbacks(); + if (!$wait) { + $this->serve($data); + } + } + + function serve($data = false) + { + if (!$data) { + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') { + header('Content-Type: text/plain'); // merged from WP #9093 + die('XML-RPC server accepts POST requests only.'); + } + + global $HTTP_RAW_POST_DATA; + if (empty($HTTP_RAW_POST_DATA)) { + // workaround for a bug in PHP 5.2.2 - http://bugs.php.net/bug.php?id=41293 + $data = file_get_contents('php://input'); + } else { + $data =& $HTTP_RAW_POST_DATA; + } + } + $this->message = new IXR_Message($data); + if (!$this->message->parse()) { + $this->error(-32700, 'parse error. not well formed'); + } + if ($this->message->messageType != 'methodCall') { + $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); + } + $result = $this->call($this->message->methodName, $this->message->params); + + // Is the result an error? + if (is_a($result, 'IXR_Error')) { + $this->error($result); + } + + // Encode the result + $r = new IXR_Value($result); + $resultxml = $r->getXml(); + + // Create the XML + $xml = <<<EOD +<methodResponse> + <params> + <param> + <value> + $resultxml + </value> + </param> + </params> +</methodResponse> + +EOD; + // Send it + $this->output($xml); + } + + function call($methodname, $args) + { + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.'); + } + $method = $this->callbacks[$methodname]; + + // Perform the callback and send the response + if (count($args) == 1) { + // If only one paramater just send that instead of the whole array + $args = $args[0]; + } + + // Are we dealing with a function or a method? + if (is_string($method) && substr($method, 0, 5) == 'this:') { + // It's a class method - check it exists + $method = substr($method, 5); + if (!method_exists($this, $method)) { + return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.'); + } + + //Call the method + $result = $this->$method($args); + } else { + // It's a function - does it exist? + if (is_array($method)) { + if (!is_callable(array($method[0], $method[1]))) { + return new IXR_Error(-32601, 'server error. requested object method "'.$method[1].'" does not exist.'); + } + } else if (!function_exists($method)) { + return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.'); + } + + // Call the function + $result = call_user_func($method, $args); + } + return $result; + } + + function error($error, $message = false) + { + // Accepts either an error object or an error code and message + if ($message && !is_object($error)) { + $error = new IXR_Error($error, $message); + } + $this->output($error->getXml()); + } + + function output($xml) + { + $charset = function_exists('get_option') ? get_option('blog_charset') : ''; + if ($charset) + $xml = '<?xml version="1.0" encoding="'.$charset.'"?>'."\n".$xml; + else + $xml = '<?xml version="1.0"?>'."\n".$xml; + $length = strlen($xml); + header('Connection: close'); + header('Content-Length: '.$length); + if ($charset) + header('Content-Type: text/xml; charset='.$charset); + else + header('Content-Type: text/xml'); + header('Date: '.date('r')); + echo $xml; + exit; + } + + function hasMethod($method) + { + return in_array($method, array_keys($this->callbacks)); + } + + function setCapabilities() + { + // Initialises capabilities array + $this->capabilities = array( + 'xmlrpc' => array( + 'specUrl' => 'http://www.xmlrpc.com/spec', + 'specVersion' => 1 + ), + 'faults_interop' => array( + 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', + 'specVersion' => 20010516 + ), + 'system.multicall' => array( + 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', + 'specVersion' => 1 + ), + ); + } + + function getCapabilities($args) + { + return $this->capabilities; + } + + function setCallbacks() + { + $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; + $this->callbacks['system.listMethods'] = 'this:listMethods'; + $this->callbacks['system.multicall'] = 'this:multiCall'; + } + + function listMethods($args) + { + // Returns a list of methods - uses array_reverse to ensure user defined + // methods are listed before server defined methods + return array_reverse(array_keys($this->callbacks)); + } + + function multiCall($methodcalls) + { + // See http://www.xmlrpc.com/discuss/msgReader$1208 + $return = array(); + foreach ($methodcalls as $call) { + $method = $call['methodName']; + $params = $call['params']; + if ($method == 'system.multicall') { + $result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden'); + } else { + $result = $this->call($method, $params); + } + if (is_a($result, 'IXR_Error')) { + $return[] = array( + 'faultCode' => $result->code, + 'faultString' => $result->message + ); + } else { + $return[] = array($result); + } + } + return $return; + } +} + +/** + * IXR_Request + * + * @package IXR + * @since 1.5 + */ +class IXR_Request +{ + var $method; + var $args; + var $xml; + + function IXR_Request($method, $args) + { + $this->method = $method; + $this->args = $args; + $this->xml = <<<EOD +<?xml version="1.0"?> +<methodCall> +<methodName>{$this->method}</methodName> +<params> + +EOD; + foreach ($this->args as $arg) { + $this->xml .= '<param><value>'; + $v = new IXR_Value($arg); + $this->xml .= $v->getXml(); + $this->xml .= "</value></param>\n"; + } + $this->xml .= '</params></methodCall>'; + } + + function getLength() + { + return strlen($this->xml); + } + + function getXml() + { + return $this->xml; + } +} + +/** + * IXR_Client + * + * @package IXR + * @since 1.5 + * + */ +class IXR_Client +{ + var $server; + var $port; + var $path; + var $useragent; + var $response; + var $message = false; + var $debug = false; + var $timeout; + var $headers = array(); + + // Storage place for an error message + var $error = false; + + function IXR_Client($server, $path = false, $port = 80, $timeout = 15) + { + if (!$path) { + // Assume we have been given a URL instead + $bits = parse_url($server); + $this->server = $bits['host']; + $this->port = isset($bits['port']) ? $bits['port'] : 80; + $this->path = isset($bits['path']) ? $bits['path'] : '/'; + + // Make absolutely sure we have a path + if (!$this->path) { + $this->path = '/'; + } + } else { + $this->server = $server; + $this->path = $path; + $this->port = $port; + } + $this->useragent = 'The Incutio XML-RPC PHP Library'; + $this->timeout = $timeout; + } + + function query() + { + $args = func_get_args(); + $method = array_shift($args); + $request = new IXR_Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + $r = "\r\n"; + $request = "POST {$this->path} HTTP/1.0$r"; + + // Merged from WP #8145 - allow custom headers + $this->headers['Host'] = $this->server; + $this->headers['Content-Type'] = 'text/xml'; + $this->headers['User-Agent'] = $this->useragent; + $this->headers['Content-Length']= $length; + + foreach( $this->headers as $header => $value ) { + $request .= "{$header}: {$value}{$r}"; + } + $request .= $r; + + $request .= $xml; + + // Now send the request + if ($this->debug) { + echo '<pre class="ixr_request">'.htmlspecialchars($request)."\n</pre>\n\n"; + } + + if ($this->timeout) { + $fp = @fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = @fsockopen($this->server, $this->port, $errno, $errstr); + } + if (!$fp) { + $this->error = new IXR_Error(-32300, 'transport error - could not open socket'); + return false; + } + fputs($fp, $request); + $contents = ''; + $debugContents = ''; + $gotFirstLine = false; + $gettingHeaders = true; + while (!feof($fp)) { + $line = fgets($fp, 4096); + if (!$gotFirstLine) { + // Check line for '200' + if (strstr($line, '200') === false) { + $this->error = new IXR_Error(-32300, 'transport error - HTTP status code was not 200'); + return false; + } + $gotFirstLine = true; + } + if (trim($line) == '') { + $gettingHeaders = false; + } + if (!$gettingHeaders) { + // merged from WP #12559 - remove trim + $contents .= $line; + } + if ($this->debug) { + $debugContents .= $line; + } + } + if ($this->debug) { + echo '<pre class="ixr_response">'.htmlspecialchars($debugContents)."\n</pre>\n\n"; + } + + // Now parse what we've got back + $this->message = new IXR_Message($contents); + if (!$this->message->parse()) { + // XML error + $this->error = new IXR_Error(-32700, 'parse error. not well formed'); + return false; + } + + // Is the message a fault? + if ($this->message->messageType == 'fault') { + $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); + return false; + } + + // Message must be OK + return true; + } + + function getResponse() + { + // methodResponses can only have one param - return that + return $this->message->params[0]; + } + + function isError() + { + return (is_object($this->error)); + } + + function getErrorCode() + { + return $this->error->code; + } + + function getErrorMessage() + { + return $this->error->message; + } +} + + +/** + * IXR_Error + * + * @package IXR + * @since 1.5 + */ +class IXR_Error +{ + var $code; + var $message; + + function IXR_Error($code, $message) + { + $this->code = $code; + $this->message = htmlspecialchars($message); + } + + function getXml() + { + $xml = <<<EOD +<methodResponse> + <fault> + <value> + <struct> + <member> + <name>faultCode</name> + <value><int>{$this->code}</int></value> + </member> + <member> + <name>faultString</name> + <value><string>{$this->message}</string></value> + </member> + </struct> + </value> + </fault> +</methodResponse> + +EOD; + return $xml; + } +} + +/** + * IXR_Date + * + * @package IXR + * @since 1.5 + */ +class IXR_Date { + var $year; + var $month; + var $day; + var $hour; + var $minute; + var $second; + var $timezone; + + function IXR_Date($time) + { + // $time can be a PHP timestamp or an ISO one + if (is_numeric($time)) { + $this->parseTimestamp($time); + } else { + $this->parseIso($time); + } + } + + function parseTimestamp($timestamp) + { + $this->year = date('Y', $timestamp); + $this->month = date('m', $timestamp); + $this->day = date('d', $timestamp); + $this->hour = date('H', $timestamp); + $this->minute = date('i', $timestamp); + $this->second = date('s', $timestamp); + $this->timezone = ''; + } + + function parseIso($iso) + { + $this->year = substr($iso, 0, 4); + $this->month = substr($iso, 4, 2); + $this->day = substr($iso, 6, 2); + $this->hour = substr($iso, 9, 2); + $this->minute = substr($iso, 12, 2); + $this->second = substr($iso, 15, 2); + $this->timezone = substr($iso, 17); + } + + function getIso() + { + return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone; + } + + function getXml() + { + return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>'; + } + + function getTimestamp() + { + return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year); + } +} + +/** + * IXR_Base64 + * + * @package IXR + * @since 1.5 + */ +class IXR_Base64 +{ + var $data; + + function IXR_Base64($data) + { + $this->data = $data; + } + + function getXml() + { + return '<base64>'.base64_encode($this->data).'</base64>'; + } +} + +/** + * IXR_IntrospectionServer + * + * @package IXR + * @since 1.5 + */ +class IXR_IntrospectionServer extends IXR_Server +{ + var $signatures; + var $help; + + function IXR_IntrospectionServer() + { + $this->setCallbacks(); + $this->setCapabilities(); + $this->capabilities['introspection'] = array( + 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', + 'specVersion' => 1 + ); + $this->addCallback( + 'system.methodSignature', + 'this:methodSignature', + array('array', 'string'), + 'Returns an array describing the return type and required parameters of a method' + ); + $this->addCallback( + 'system.getCapabilities', + 'this:getCapabilities', + array('struct'), + 'Returns a struct describing the XML-RPC specifications supported by this server' + ); + $this->addCallback( + 'system.listMethods', + 'this:listMethods', + array('array'), + 'Returns an array of available methods on this server' + ); + $this->addCallback( + 'system.methodHelp', + 'this:methodHelp', + array('string', 'string'), + 'Returns a documentation string for the specified method' + ); + } + + function addCallback($method, $callback, $args, $help) + { + $this->callbacks[$method] = $callback; + $this->signatures[$method] = $args; + $this->help[$method] = $help; + } + + function call($methodname, $args) + { + // Make sure it's in an array + if ($args && !is_array($args)) { + $args = array($args); + } + + // Over-rides default call method, adds signature check + if (!$this->hasMethod($methodname)) { + return new IXR_Error(-32601, 'server error. requested method "'.$this->message->methodName.'" not specified.'); + } + $method = $this->callbacks[$methodname]; + $signature = $this->signatures[$methodname]; + $returnType = array_shift($signature); + + // Check the number of arguments + if (count($args) != count($signature)) { + return new IXR_Error(-32602, 'server error. wrong number of method parameters'); + } + + // Check the argument types + $ok = true; + $argsbackup = $args; + for ($i = 0, $j = count($args); $i < $j; $i++) { + $arg = array_shift($args); + $type = array_shift($signature); + switch ($type) { + case 'int': + case 'i4': + if (is_array($arg) || !is_int($arg)) { + $ok = false; + } + break; + case 'base64': + case 'string': + if (!is_string($arg)) { + $ok = false; + } + break; + case 'boolean': + if ($arg !== false && $arg !== true) { + $ok = false; + } + break; + case 'float': + case 'double': + if (!is_float($arg)) { + $ok = false; + } + break; + case 'date': + case 'dateTime.iso8601': + if (!is_a($arg, 'IXR_Date')) { + $ok = false; + } + break; + } + if (!$ok) { + return new IXR_Error(-32602, 'server error. invalid method parameters'); + } + } + // It passed the test - run the "real" method call + return parent::call($methodname, $argsbackup); + } + + function methodSignature($method) + { + if (!$this->hasMethod($method)) { + return new IXR_Error(-32601, 'server error. requested method "'.$method.'" not specified.'); + } + // We should be returning an array of types + $types = $this->signatures[$method]; + $return = array(); + foreach ($types as $type) { + switch ($type) { + case 'string': + $return[] = 'string'; + break; + case 'int': + case 'i4': + $return[] = 42; + break; + case 'double': + $return[] = 3.1415; + break; + case 'dateTime.iso8601': + $return[] = new IXR_Date(time()); + break; + case 'boolean': + $return[] = true; + break; + case 'base64': + $return[] = new IXR_Base64('base64'); + break; + case 'array': + $return[] = array('array'); + break; + case 'struct': + $return[] = array('struct' => 'struct'); + break; + } + } + return $return; + } + + function methodHelp($method) + { + return $this->help[$method]; + } +} + +/** + * IXR_ClientMulticall + * + * @package IXR + * @since 1.5 + */ +class IXR_ClientMulticall extends IXR_Client +{ + var $calls = array(); + + function IXR_ClientMulticall($server, $path = false, $port = 80) + { + parent::IXR_Client($server, $path, $port); + $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; + } + + function addCall() + { + $args = func_get_args(); + $methodName = array_shift($args); + $struct = array( + 'methodName' => $methodName, + 'params' => $args + ); + $this->calls[] = $struct; + } + + function query() + { + // Prepare multicall, then call the parent::query() method + return parent::query('system.multicall', $this->calls); + } +} diff --git a/sources/wp-includes/class-feed.php b/sources/wp-includes/class-feed.php new file mode 100644 index 0000000..c33b302 --- /dev/null +++ b/sources/wp-includes/class-feed.php @@ -0,0 +1,140 @@ +<?php + +if ( !class_exists('SimplePie') ) + require_once( ABSPATH . WPINC . '/class-simplepie.php' ); + +class WP_Feed_Cache extends SimplePie_Cache { + /** + * Create a new SimplePie_Cache object + * + * @static + * @access public + */ + function create($location, $filename, $extension) { + return new WP_Feed_Cache_Transient($location, $filename, $extension); + } +} + +class WP_Feed_Cache_Transient { + var $name; + var $mod_name; + var $lifetime = 43200; //Default lifetime in cache of 12 hours + + function __construct($location, $filename, $extension) { + $this->name = 'feed_' . $filename; + $this->mod_name = 'feed_mod_' . $filename; + + $lifetime = $this->lifetime; + /** + * Filter the transient lifetime of the feed cache. + * + * @since 2.8.0 + * + * @param int $lifetime Cache duration in seconds. Default is 43200 seconds (12 hours). + * @param string $filename Unique identifier for the cache object. + */ + $this->lifetime = apply_filters( 'wp_feed_cache_transient_lifetime', $lifetime, $filename); + } + + function save($data) { + if ( is_a($data, 'SimplePie') ) + $data = $data->data; + + set_transient($this->name, $data, $this->lifetime); + set_transient($this->mod_name, time(), $this->lifetime); + return true; + } + + function load() { + return get_transient($this->name); + } + + function mtime() { + return get_transient($this->mod_name); + } + + function touch() { + return set_transient($this->mod_name, time(), $this->lifetime); + } + + function unlink() { + delete_transient($this->name); + delete_transient($this->mod_name); + return true; + } +} + +class WP_SimplePie_File extends SimplePie_File { + + function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) { + $this->url = $url; + $this->timeout = $timeout; + $this->redirects = $redirects; + $this->headers = $headers; + $this->useragent = $useragent; + + $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE; + + if ( preg_match('/^http(s)?:\/\//i', $url) ) { + $args = array( + 'timeout' => $this->timeout, + 'redirection' => $this->redirects, + ); + + if ( !empty($this->headers) ) + $args['headers'] = $this->headers; + + if ( SIMPLEPIE_USERAGENT != $this->useragent ) //Use default WP user agent unless custom has been specified + $args['user-agent'] = $this->useragent; + + $res = wp_safe_remote_request($url, $args); + + if ( is_wp_error($res) ) { + $this->error = 'WP HTTP Error: ' . $res->get_error_message(); + $this->success = false; + } else { + $this->headers = wp_remote_retrieve_headers( $res ); + $this->body = wp_remote_retrieve_body( $res ); + $this->status_code = wp_remote_retrieve_response_code( $res ); + } + } else { + $this->error = ''; + $this->success = false; + } + } +} + +/** + * WordPress SimplePie Sanitization Class + * + * Extension of the SimplePie_Sanitize class to use KSES, because + * we cannot universally count on DOMDocument being available + * + * @package WordPress + * @since 3.5.0 + */ +class WP_SimplePie_Sanitize_KSES extends SimplePie_Sanitize { + public function sanitize( $data, $type, $base = '' ) { + $data = trim( $data ); + if ( $type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML ) { + if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data)) { + $type |= SIMPLEPIE_CONSTRUCT_HTML; + } + else { + $type |= SIMPLEPIE_CONSTRUCT_TEXT; + } + } + if ( $type & SIMPLEPIE_CONSTRUCT_BASE64 ) { + $data = base64_decode( $data ); + } + if ( $type & ( SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML ) ) { + $data = wp_kses_post( $data ); + if ( $this->output_encoding !== 'UTF-8' ) { + $data = $this->registry->call( 'Misc', 'change_encoding', array( $data, 'UTF-8', $this->output_encoding ) ); + } + return $data; + } else { + return parent::sanitize( $data, $type, $base ); + } + } +} diff --git a/sources/wp-includes/class-http.php b/sources/wp-includes/class-http.php new file mode 100644 index 0000000..c75b47e --- /dev/null +++ b/sources/wp-includes/class-http.php @@ -0,0 +1,1954 @@ +<?php +/** + * Simple and uniform HTTP request API. + * + * Standardizes the HTTP requests for WordPress. Handles cookies, gzip encoding and decoding, chunk + * decoding, if HTTP 1.1 and various other difficult HTTP protocol implementations. + * + * @link http://trac.wordpress.org/ticket/4779 HTTP API Proposal + * + * @package WordPress + * @subpackage HTTP + * @since 2.7.0 + */ + +/** + * WordPress HTTP Class for managing HTTP Transports and making HTTP requests. + * + * This class is used to consistently make outgoing HTTP requests easy for developers + * while still being compatible with the many PHP configurations under which + * WordPress runs. + * + * Debugging includes several actions, which pass different variables for debugging the HTTP API. + * + * @package WordPress + * @subpackage HTTP + * @since 2.7.0 + */ +class WP_Http { + + /** + * Send a HTTP request to a URI. + * + * The body and headers are part of the arguments. The 'body' argument is for the body and will + * accept either a string or an array. The 'headers' argument should be an array, but a string + * is acceptable. If the 'body' argument is an array, then it will automatically be escaped + * using http_build_query(). + * + * The only URI that are supported in the HTTP Transport implementation are the HTTP and HTTPS + * protocols. + * + * The defaults are 'method', 'timeout', 'redirection', 'httpversion', 'blocking' and + * 'user-agent'. + * + * Accepted 'method' values are 'GET', 'POST', and 'HEAD', some transports technically allow + * others, but should not be assumed. The 'timeout' is used to sent how long the connection + * should stay open before failing when no response. 'redirection' is used to track how many + * redirects were taken and used to sent the amount for other transports, but not all transports + * accept setting that value. + * + * The 'httpversion' option is used to sent the HTTP version and accepted values are '1.0', and + * '1.1' and should be a string. The 'user-agent' option is the user-agent and is used to + * replace the default user-agent, which is 'WordPress/WP_Version', where WP_Version is the + * value from $wp_version. + * + * The 'blocking' parameter can be used to specify if the calling code requires the result of + * the HTTP request. If set to false, the request will be sent to the remote server, and + * processing returned to the calling code immediately, the caller will know if the request + * suceeded or failed, but will not receive any response from the remote server. + * + * @access public + * @since 2.7.0 + * + * @param string $url URI resource. + * @param str|array $args Optional. Override the defaults. + * @return array|object Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + function request( $url, $args = array() ) { + global $wp_version; + + $defaults = array( + 'method' => 'GET', + 'timeout' => apply_filters( 'http_request_timeout', 5), + 'redirection' => apply_filters( 'http_request_redirection_count', 5), + 'httpversion' => apply_filters( 'http_request_version', '1.0'), + 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) ), + 'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false ), + 'blocking' => true, + 'headers' => array(), + 'cookies' => array(), + 'body' => null, + 'compress' => false, + 'decompress' => true, + 'sslverify' => true, + 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', + 'stream' => false, + 'filename' => null, + 'limit_response_size' => null, + ); + + // Pre-parse for the HEAD checks. + $args = wp_parse_args( $args ); + + // By default, Head requests do not cause redirections. + if ( isset($args['method']) && 'HEAD' == $args['method'] ) + $defaults['redirection'] = 0; + + $r = wp_parse_args( $args, $defaults ); + $r = apply_filters( 'http_request_args', $r, $url ); + + // The transports decrement this, store a copy of the original value for loop purposes. + if ( ! isset( $r['_redirection'] ) ) + $r['_redirection'] = $r['redirection']; + + // Allow plugins to short-circuit the request + $pre = apply_filters( 'pre_http_request', false, $r, $url ); + if ( false !== $pre ) + return $pre; + + if ( function_exists( 'wp_kses_bad_protocol' ) ) { + if ( $r['reject_unsafe_urls'] ) + $url = wp_http_validate_url( $url ); + $url = wp_kses_bad_protocol( $url, array( 'http', 'https', 'ssl' ) ); + } + + $arrURL = @parse_url( $url ); + + if ( empty( $url ) || empty( $arrURL['scheme'] ) ) + return new WP_Error('http_request_failed', __('A valid URL was not provided.')); + + if ( $this->block_request( $url ) ) + return new WP_Error( 'http_request_failed', __( 'User has blocked requests through HTTP.' ) ); + + // Determine if this is a https call and pass that on to the transport functions + // so that we can blacklist the transports that do not support ssl verification + $r['ssl'] = $arrURL['scheme'] == 'https' || $arrURL['scheme'] == 'ssl'; + + // Determine if this request is to OUR install of WordPress + $homeURL = parse_url( get_bloginfo( 'url' ) ); + $r['local'] = $homeURL['host'] == $arrURL['host'] || 'localhost' == $arrURL['host']; + unset( $homeURL ); + + // If we are streaming to a file but no filename was given drop it in the WP temp dir + // and pick its name using the basename of the $url + if ( $r['stream'] && empty( $r['filename'] ) ) + $r['filename'] = get_temp_dir() . basename( $url ); + + // Force some settings if we are streaming to a file and check for existence and perms of destination directory + if ( $r['stream'] ) { + $r['blocking'] = true; + if ( ! wp_is_writable( dirname( $r['filename'] ) ) ) + return new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) ); + } + + if ( is_null( $r['headers'] ) ) + $r['headers'] = array(); + + if ( ! is_array( $r['headers'] ) ) { + $processedHeaders = WP_Http::processHeaders( $r['headers'], $url ); + $r['headers'] = $processedHeaders['headers']; + } + + if ( isset( $r['headers']['User-Agent'] ) ) { + $r['user-agent'] = $r['headers']['User-Agent']; + unset( $r['headers']['User-Agent'] ); + } + + if ( isset( $r['headers']['user-agent'] ) ) { + $r['user-agent'] = $r['headers']['user-agent']; + unset( $r['headers']['user-agent'] ); + } + + if ( '1.1' == $r['httpversion'] && !isset( $r['headers']['connection'] ) ) { + $r['headers']['connection'] = 'close'; + } + + // Construct Cookie: header if any cookies are set + WP_Http::buildCookieHeader( $r ); + + // Avoid issues where mbstring.func_overload is enabled + mbstring_binary_safe_encoding(); + + if ( ! isset( $r['headers']['Accept-Encoding'] ) ) { + if ( $encoding = WP_Http_Encoding::accept_encoding( $url, $r ) ) + $r['headers']['Accept-Encoding'] = $encoding; + } + + if ( ( ! is_null( $r['body'] ) && '' != $r['body'] ) || 'POST' == $r['method'] || 'PUT' == $r['method'] ) { + if ( is_array( $r['body'] ) || is_object( $r['body'] ) ) { + $r['body'] = http_build_query( $r['body'], null, '&' ); + + if ( ! isset( $r['headers']['Content-Type'] ) ) + $r['headers']['Content-Type'] = 'application/x-www-form-urlencoded; charset=' . get_option( 'blog_charset' ); + } + + if ( '' === $r['body'] ) + $r['body'] = null; + + if ( ! isset( $r['headers']['Content-Length'] ) && ! isset( $r['headers']['content-length'] ) ) + $r['headers']['Content-Length'] = strlen( $r['body'] ); + } + + $response = $this->_dispatch_request( $url, $r ); + + reset_mbstring_encoding(); + + if ( is_wp_error( $response ) ) + return $response; + + // Append cookies that were used in this request to the response + if ( ! empty( $r['cookies'] ) ) { + $cookies_set = wp_list_pluck( $response['cookies'], 'name' ); + foreach ( $r['cookies'] as $cookie ) { + if ( ! in_array( $cookie->name, $cookies_set ) && $cookie->test( $url ) ) { + $response['cookies'][] = $cookie; + } + } + } + + return $response; + } + + /** + * Tests which transports are capable of supporting the request. + * + * @since 3.2.0 + * @access private + * + * @param array $args Request arguments + * @param string $url URL to Request + * + * @return string|bool Class name for the first transport that claims to support the request. False if no transport claims to support the request. + */ + public function _get_first_available_transport( $args, $url = null ) { + $request_order = apply_filters( 'http_api_transports', array( 'curl', 'streams' ), $args, $url ); + + // Loop over each transport on each HTTP request looking for one which will serve this request's needs + foreach ( $request_order as $transport ) { + $class = 'WP_HTTP_' . $transport; + + // Check to see if this transport is a possibility, calls the transport statically + if ( !call_user_func( array( $class, 'test' ), $args, $url ) ) + continue; + + return $class; + } + + return false; + } + + /** + * Dispatches a HTTP request to a supporting transport. + * + * Tests each transport in order to find a transport which matches the request arguments. + * Also caches the transport instance to be used later. + * + * The order for requests is cURL, and then PHP Streams. + * + * @since 3.2.0 + * @access private + * + * @param string $url URL to Request + * @param array $args Request arguments + * @return array|object Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + private function _dispatch_request( $url, $args ) { + static $transports = array(); + + $class = $this->_get_first_available_transport( $args, $url ); + if ( !$class ) + return new WP_Error( 'http_failure', __( 'There are no HTTP transports available which can complete the requested request.' ) ); + + // Transport claims to support request, instantiate it and give it a whirl. + if ( empty( $transports[$class] ) ) + $transports[$class] = new $class; + + $response = $transports[$class]->request( $url, $args ); + + do_action( 'http_api_debug', $response, 'response', $class, $args, $url ); + + if ( is_wp_error( $response ) ) + return $response; + + return apply_filters( 'http_response', $response, $args, $url ); + } + + /** + * Uses the POST HTTP method. + * + * Used for sending data that is expected to be in the body. + * + * @access public + * @since 2.7.0 + * + * @param string $url URI resource. + * @param str|array $args Optional. Override the defaults. + * @return array|object Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + function post($url, $args = array()) { + $defaults = array('method' => 'POST'); + $r = wp_parse_args( $args, $defaults ); + return $this->request($url, $r); + } + + /** + * Uses the GET HTTP method. + * + * Used for sending data that is expected to be in the body. + * + * @access public + * @since 2.7.0 + * + * @param string $url URI resource. + * @param str|array $args Optional. Override the defaults. + * @return array|object Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + function get($url, $args = array()) { + $defaults = array('method' => 'GET'); + $r = wp_parse_args( $args, $defaults ); + return $this->request($url, $r); + } + + /** + * Uses the HEAD HTTP method. + * + * Used for sending data that is expected to be in the body. + * + * @access public + * @since 2.7.0 + * + * @param string $url URI resource. + * @param str|array $args Optional. Override the defaults. + * @return array|object Array containing 'headers', 'body', 'response', 'cookies', 'filename'. A WP_Error instance upon error + */ + function head($url, $args = array()) { + $defaults = array('method' => 'HEAD'); + $r = wp_parse_args( $args, $defaults ); + return $this->request($url, $r); + } + + /** + * Parses the responses and splits the parts into headers and body. + * + * @access public + * @static + * @since 2.7.0 + * + * @param string $strResponse The full response string + * @return array Array with 'headers' and 'body' keys. + */ + public static function processResponse($strResponse) { + $res = explode("\r\n\r\n", $strResponse, 2); + + return array('headers' => $res[0], 'body' => isset($res[1]) ? $res[1] : ''); + } + + /** + * Transform header string into an array. + * + * If an array is given then it is assumed to be raw header data with numeric keys with the + * headers as the values. No headers must be passed that were already processed. + * + * @access public + * @static + * @since 2.7.0 + * + * @param string|array $headers + * @param string $url The URL that was requested + * @return array Processed string headers. If duplicate headers are encountered, + * Then a numbered array is returned as the value of that header-key. + */ + public static function processHeaders( $headers, $url = '' ) { + // split headers, one per array element + if ( is_string($headers) ) { + // tolerate line terminator: CRLF = LF (RFC 2616 19.3) + $headers = str_replace("\r\n", "\n", $headers); + // unfold folded header fields. LWS = [CRLF] 1*( SP | HT ) <US-ASCII SP, space (32)>, <US-ASCII HT, horizontal-tab (9)> (RFC 2616 2.2) + $headers = preg_replace('/\n[ \t]/', ' ', $headers); + // create the headers array + $headers = explode("\n", $headers); + } + + $response = array('code' => 0, 'message' => ''); + + // If a redirection has taken place, The headers for each page request may have been passed. + // In this case, determine the final HTTP header and parse from there. + for ( $i = count($headers)-1; $i >= 0; $i-- ) { + if ( !empty($headers[$i]) && false === strpos($headers[$i], ':') ) { + $headers = array_splice($headers, $i); + break; + } + } + + $cookies = array(); + $newheaders = array(); + foreach ( (array) $headers as $tempheader ) { + if ( empty($tempheader) ) + continue; + + if ( false === strpos($tempheader, ':') ) { + $stack = explode(' ', $tempheader, 3); + $stack[] = ''; + list( , $response['code'], $response['message']) = $stack; + continue; + } + + list($key, $value) = explode(':', $tempheader, 2); + + $key = strtolower( $key ); + $value = trim( $value ); + + if ( isset( $newheaders[ $key ] ) ) { + if ( ! is_array( $newheaders[ $key ] ) ) + $newheaders[$key] = array( $newheaders[ $key ] ); + $newheaders[ $key ][] = $value; + } else { + $newheaders[ $key ] = $value; + } + if ( 'set-cookie' == $key ) + $cookies[] = new WP_Http_Cookie( $value, $url ); + } + + return array('response' => $response, 'headers' => $newheaders, 'cookies' => $cookies); + } + + /** + * Takes the arguments for a ::request() and checks for the cookie array. + * + * If it's found, then it upgrades any basic name => value pairs to WP_Http_Cookie instances, + * which are each parsed into strings and added to the Cookie: header (within the arguments array). + * Edits the array by reference. + * + * @access public + * @version 2.8.0 + * @static + * + * @param array $r Full array of args passed into ::request() + */ + public static function buildCookieHeader( &$r ) { + if ( ! empty($r['cookies']) ) { + // Upgrade any name => value cookie pairs to WP_HTTP_Cookie instances + foreach ( $r['cookies'] as $name => $value ) { + if ( ! is_object( $value ) ) + $r['cookies'][ $name ] = new WP_HTTP_Cookie( array( 'name' => $name, 'value' => $value ) ); + } + + $cookies_header = ''; + foreach ( (array) $r['cookies'] as $cookie ) { + $cookies_header .= $cookie->getHeaderValue() . '; '; + } + + $cookies_header = substr( $cookies_header, 0, -2 ); + $r['headers']['cookie'] = $cookies_header; + } + } + + /** + * Decodes chunk transfer-encoding, based off the HTTP 1.1 specification. + * + * Based off the HTTP http_encoding_dechunk function. + * + * @link http://tools.ietf.org/html/rfc2616#section-19.4.6 Process for chunked decoding. + * + * @access public + * @since 2.7.0 + * @static + * + * @param string $body Body content + * @return string Chunked decoded body on success or raw body on failure. + */ + public static function chunkTransferDecode( $body ) { + // The body is not chunked encoded or is malformed. + if ( ! preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', trim( $body ) ) ) + return $body; + + $parsed_body = ''; + $body_original = $body; // We'll be altering $body, so need a backup in case of error + + while ( true ) { + $has_chunk = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $body, $match ); + if ( ! $has_chunk || empty( $match[1] ) ) + return $body_original; + + $length = hexdec( $match[1] ); + $chunk_length = strlen( $match[0] ); + + // Parse out the chunk of data + $parsed_body .= substr( $body, $chunk_length, $length ); + + // Remove the chunk from the raw data + $body = substr( $body, $length + $chunk_length ); + + // End of document + if ( '0' === trim( $body ) ) + return $parsed_body; + } + } + + /** + * Block requests through the proxy. + * + * Those who are behind a proxy and want to prevent access to certain hosts may do so. This will + * prevent plugins from working and core functionality, if you don't include api.wordpress.org. + * + * You block external URL requests by defining WP_HTTP_BLOCK_EXTERNAL as true in your wp-config.php + * file and this will only allow localhost and your blog to make requests. The constant + * WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the + * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow, wildcard domains + * are supported, eg *.wordpress.org will allow for all subdomains of wordpress.org to be contacted. + * + * @since 2.8.0 + * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests. + * @link http://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_ACCESSIBLE_HOSTS + * + * @param string $uri URI of url. + * @return bool True to block, false to allow. + */ + function block_request($uri) { + // We don't need to block requests, because nothing is blocked. + if ( ! defined( 'WP_HTTP_BLOCK_EXTERNAL' ) || ! WP_HTTP_BLOCK_EXTERNAL ) + return false; + + $check = parse_url($uri); + if ( ! $check ) + return true; + + $home = parse_url( get_option('siteurl') ); + + // Don't block requests back to ourselves by default + if ( $check['host'] == 'localhost' || $check['host'] == $home['host'] ) + return apply_filters('block_local_requests', false); + + if ( !defined('WP_ACCESSIBLE_HOSTS') ) + return true; + + static $accessible_hosts; + static $wildcard_regex = false; + if ( null == $accessible_hosts ) { + $accessible_hosts = preg_split('|,\s*|', WP_ACCESSIBLE_HOSTS); + + if ( false !== strpos(WP_ACCESSIBLE_HOSTS, '*') ) { + $wildcard_regex = array(); + foreach ( $accessible_hosts as $host ) + $wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) ); + $wildcard_regex = '/^(' . implode('|', $wildcard_regex) . ')$/i'; + } + } + + if ( !empty($wildcard_regex) ) + return !preg_match($wildcard_regex, $check['host']); + else + return !in_array( $check['host'], $accessible_hosts ); //Inverse logic, If it's in the array, then we can't access it. + + } + + static function make_absolute_url( $maybe_relative_path, $url ) { + if ( empty( $url ) ) + return $maybe_relative_path; + + // Check for a scheme + if ( false !== strpos( $maybe_relative_path, '://' ) ) + return $maybe_relative_path; + + if ( ! $url_parts = @parse_url( $url ) ) + return $maybe_relative_path; + + if ( ! $relative_url_parts = @parse_url( $maybe_relative_path ) ) + return $maybe_relative_path; + + $absolute_path = $url_parts['scheme'] . '://' . $url_parts['host']; + if ( isset( $url_parts['port'] ) ) + $absolute_path .= ':' . $url_parts['port']; + + // Start off with the Absolute URL path + $path = ! empty( $url_parts['path'] ) ? $url_parts['path'] : '/'; + + // If it's a root-relative path, then great + if ( ! empty( $relative_url_parts['path'] ) && '/' == $relative_url_parts['path'][0] ) { + $path = $relative_url_parts['path']; + + // Else it's a relative path + } elseif ( ! empty( $relative_url_parts['path'] ) ) { + // Strip off any file components from the absolute path + $path = substr( $path, 0, strrpos( $path, '/' ) + 1 ); + + // Build the new path + $path .= $relative_url_parts['path']; + + // Strip all /path/../ out of the path + while ( strpos( $path, '../' ) > 1 ) { + $path = preg_replace( '![^/]+/\.\./!', '', $path ); + } + + // Strip any final leading ../ from the path + $path = preg_replace( '!^/(\.\./)+!', '', $path ); + } + + // Add the Query string + if ( ! empty( $relative_url_parts['query'] ) ) + $path .= '?' . $relative_url_parts['query']; + + return $absolute_path . '/' . ltrim( $path, '/' ); + } + + /** + * Handles HTTP Redirects and follows them if appropriate. + * + * @since 3.7.0 + * + * @param string $url The URL which was requested. + * @param array $args The Arguements which were used to make the request. + * @param array $response The Response of the HTTP request. + * @return false|object False if no redirect is present, a WP_HTTP or WP_Error result otherwise. + */ + static function handle_redirects( $url, $args, $response ) { + // If no redirects are present, or, redirects were not requested, perform no action. + if ( ! isset( $response['headers']['location'] ) || 0 === $args['_redirection'] ) + return false; + + // Only perform redirections on redirection http codes + if ( $response['response']['code'] > 399 || $response['response']['code'] < 300 ) + return false; + + // Don't redirect if we've run out of redirects + if ( $args['redirection']-- <= 0 ) + return new WP_Error( 'http_request_failed', __('Too many redirects.') ); + + $redirect_location = $response['headers']['location']; + + // If there were multiple Location headers, use the last header specified + if ( is_array( $redirect_location ) ) + $redirect_location = array_pop( $redirect_location ); + + $redirect_location = WP_HTTP::make_absolute_url( $redirect_location, $url ); + + // POST requests should not POST to a redirected location + if ( 'POST' == $args['method'] ) { + if ( in_array( $response['response']['code'], array( 302, 303 ) ) ) + $args['method'] = 'GET'; + } + + // Include valid cookies in the redirect process + if ( ! empty( $response['cookies'] ) ) { + foreach ( $response['cookies'] as $cookie ) { + if ( $cookie->test( $redirect_location ) ) + $args['cookies'][] = $cookie; + } + } + + return wp_remote_request( $redirect_location, $args ); + } + + /** + * Determines if a specified string represents an IP address or not. + * + * This function also detects the type of the IP address, returning either + * '4' or '6' to represent a IPv4 and IPv6 address respectively. + * This does not verify if the IP is a valid IP, only that it appears to be + * an IP address. + * + * @see http://home.deds.nl/~aeron/regex/ for IPv6 regex + * + * @since 3.7.0 + * @static + * + * @param string $maybe_ip A suspected IP address + * @return integer|bool Upon success, '4' or '6' to represent a IPv4 or IPv6 address, false upon failure + */ + static function is_ip_address( $maybe_ip ) { + if ( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $maybe_ip ) ) + return 4; + + if ( false !== strpos( $maybe_ip, ':' ) && preg_match( '/^(((?=.*(::))(?!.*\3.+\3))\3?|([\dA-F]{1,4}(\3|:\b|$)|\2))(?4){5}((?4){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i', trim( $maybe_ip, ' []' ) ) ) + return 6; + + return false; + } + +} + +/** + * HTTP request method uses PHP Streams to retrieve the url. + * + * @package WordPress + * @subpackage HTTP + * + * @since 2.7.0 + * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). + */ +class WP_Http_Streams { + /** + * Send a HTTP request to a URI using PHP Streams. + * + * @see WP_Http::request For default options descriptions. + * + * @since 2.7.0 + * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). + * + * @access public + * @param string $url URI resource. + * @param string|array $args Optional. Override the defaults. + * @return array 'headers', 'body', 'response', 'cookies' and 'filename' keys. + */ + function request($url, $args = array()) { + $defaults = array( + 'method' => 'GET', 'timeout' => 5, + 'redirection' => 5, 'httpversion' => '1.0', + 'blocking' => true, + 'headers' => array(), 'body' => null, 'cookies' => array() + ); + + $r = wp_parse_args( $args, $defaults ); + + if ( isset($r['headers']['User-Agent']) ) { + $r['user-agent'] = $r['headers']['User-Agent']; + unset($r['headers']['User-Agent']); + } else if ( isset($r['headers']['user-agent']) ) { + $r['user-agent'] = $r['headers']['user-agent']; + unset($r['headers']['user-agent']); + } + + // Construct Cookie: header if any cookies are set + WP_Http::buildCookieHeader( $r ); + + $arrURL = parse_url($url); + + $connect_host = $arrURL['host']; + + $secure_transport = ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' ); + if ( ! isset( $arrURL['port'] ) ) { + if ( $arrURL['scheme'] == 'ssl' || $arrURL['scheme'] == 'https' ) { + $arrURL['port'] = 443; + $secure_transport = true; + } else { + $arrURL['port'] = 80; + } + } + + if ( isset( $r['headers']['Host'] ) || isset( $r['headers']['host'] ) ) { + if ( isset( $r['headers']['Host'] ) ) + $arrURL['host'] = $r['headers']['Host']; + else + $arrURL['host'] = $r['headers']['host']; + unset( $r['headers']['Host'], $r['headers']['host'] ); + } + + // Certain versions of PHP have issues with 'localhost' and IPv6, It attempts to connect to ::1, + // which fails when the server is not set up for it. For compatibility, always connect to the IPv4 address. + if ( 'localhost' == strtolower( $connect_host ) ) + $connect_host = '127.0.0.1'; + + $connect_host = $secure_transport ? 'ssl://' . $connect_host : 'tcp://' . $connect_host; + + $is_local = isset( $r['local'] ) && $r['local']; + $ssl_verify = isset( $r['sslverify'] ) && $r['sslverify']; + if ( $is_local ) + $ssl_verify = apply_filters( 'https_local_ssl_verify', $ssl_verify ); + elseif ( ! $is_local ) + $ssl_verify = apply_filters( 'https_ssl_verify', $ssl_verify ); + + $proxy = new WP_HTTP_Proxy(); + + $context = stream_context_create( array( + 'ssl' => array( + 'verify_peer' => $ssl_verify, + //'CN_match' => $arrURL['host'], // This is handled by self::verify_ssl_certificate() + 'capture_peer_cert' => $ssl_verify, + 'SNI_enabled' => true, + 'cafile' => $r['sslcertificates'], + 'allow_self_signed' => ! $ssl_verify, + ) + ) ); + + $timeout = (int) floor( $r['timeout'] ); + $utimeout = $timeout == $r['timeout'] ? 0 : 1000000 * $r['timeout'] % 1000000; + $connect_timeout = max( $timeout, 1 ); + + $connection_error = null; // Store error number + $connection_error_str = null; // Store error string + + if ( !WP_DEBUG ) { + // In the event that the SSL connection fails, silence the many PHP Warnings + if ( $secure_transport ) + $error_reporting = error_reporting(0); + + if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) + $handle = @stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + else + $handle = @stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + + if ( $secure_transport ) + error_reporting( $error_reporting ); + + } else { + if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) + $handle = stream_socket_client( 'tcp://' . $proxy->host() . ':' . $proxy->port(), $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + else + $handle = stream_socket_client( $connect_host . ':' . $arrURL['port'], $connection_error, $connection_error_str, $connect_timeout, STREAM_CLIENT_CONNECT, $context ); + } + + if ( false === $handle ) { + // SSL connection failed due to expired/invalid cert, or, OpenSSL configuration is broken + if ( $secure_transport && 0 === $connection_error && '' === $connection_error_str ) + return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); + + return new WP_Error('http_request_failed', $connection_error . ': ' . $connection_error_str ); + } + + // Verify that the SSL certificate is valid for this request + if ( $secure_transport && $ssl_verify && ! $proxy->is_enabled() ) { + if ( ! self::verify_ssl_certificate( $handle, $arrURL['host'] ) ) + return new WP_Error( 'http_request_failed', __( 'The SSL certificate for the host could not be verified.' ) ); + } + + stream_set_timeout( $handle, $timeout, $utimeout ); + + if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) //Some proxies require full URL in this field. + $requestPath = $url; + else + $requestPath = $arrURL['path'] . ( isset($arrURL['query']) ? '?' . $arrURL['query'] : '' ); + + if ( empty($requestPath) ) + $requestPath .= '/'; + + $strHeaders = strtoupper($r['method']) . ' ' . $requestPath . ' HTTP/' . $r['httpversion'] . "\r\n"; + + if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) + $strHeaders .= 'Host: ' . $arrURL['host'] . ':' . $arrURL['port'] . "\r\n"; + else + $strHeaders .= 'Host: ' . $arrURL['host'] . "\r\n"; + + if ( isset($r['user-agent']) ) + $strHeaders .= 'User-agent: ' . $r['user-agent'] . "\r\n"; + + if ( is_array($r['headers']) ) { + foreach ( (array) $r['headers'] as $header => $headerValue ) + $strHeaders .= $header . ': ' . $headerValue . "\r\n"; + } else { + $strHeaders .= $r['headers']; + } + + if ( $proxy->use_authentication() ) + $strHeaders .= $proxy->authentication_header() . "\r\n"; + + $strHeaders .= "\r\n"; + + if ( ! is_null($r['body']) ) + $strHeaders .= $r['body']; + + fwrite($handle, $strHeaders); + + if ( ! $r['blocking'] ) { + stream_set_blocking( $handle, 0 ); + fclose( $handle ); + return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); + } + + $strResponse = ''; + $bodyStarted = false; + $keep_reading = true; + $block_size = 4096; + if ( isset( $r['limit_response_size'] ) ) + $block_size = min( $block_size, $r['limit_response_size'] ); + + // If streaming to a file setup the file handle + if ( $r['stream'] ) { + if ( ! WP_DEBUG ) + $stream_handle = @fopen( $r['filename'], 'w+' ); + else + $stream_handle = fopen( $r['filename'], 'w+' ); + if ( ! $stream_handle ) + return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); + + $bytes_written = 0; + while ( ! feof($handle) && $keep_reading ) { + $block = fread( $handle, $block_size ); + if ( ! $bodyStarted ) { + $strResponse .= $block; + if ( strpos( $strResponse, "\r\n\r\n" ) ) { + $process = WP_Http::processResponse( $strResponse ); + $bodyStarted = true; + $block = $process['body']; + unset( $strResponse ); + $process['body'] = ''; + } + } + + $this_block_size = strlen( $block ); + + if ( isset( $r['limit_response_size'] ) && ( $bytes_written + $this_block_size ) > $r['limit_response_size'] ) + $block = substr( $block, 0, ( $r['limit_response_size'] - $bytes_written ) ); + + $bytes_written_to_file = fwrite( $stream_handle, $block ); + + if ( $bytes_written_to_file != $this_block_size ) { + fclose( $handle ); + fclose( $stream_handle ); + return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); + } + + $bytes_written += $bytes_written_to_file; + + $keep_reading = !isset( $r['limit_response_size'] ) || $bytes_written < $r['limit_response_size']; + } + + fclose( $stream_handle ); + + } else { + $header_length = 0; + while ( ! feof( $handle ) && $keep_reading ) { + $block = fread( $handle, $block_size ); + $strResponse .= $block; + if ( ! $bodyStarted && strpos( $strResponse, "\r\n\r\n" ) ) { + $header_length = strpos( $strResponse, "\r\n\r\n" ) + 4; + $bodyStarted = true; + } + $keep_reading = ( ! $bodyStarted || !isset( $r['limit_response_size'] ) || strlen( $strResponse ) < ( $header_length + $r['limit_response_size'] ) ); + } + + $process = WP_Http::processResponse( $strResponse ); + unset( $strResponse ); + + } + + fclose( $handle ); + + $arrHeaders = WP_Http::processHeaders( $process['headers'], $url ); + + $response = array( + 'headers' => $arrHeaders['headers'], + 'body' => null, // Not yet processed + 'response' => $arrHeaders['response'], + 'cookies' => $arrHeaders['cookies'], + 'filename' => $r['filename'] + ); + + // Handle redirects + if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) + return $redirect_response; + + // If the body was chunk encoded, then decode it. + if ( ! empty( $process['body'] ) && isset( $arrHeaders['headers']['transfer-encoding'] ) && 'chunked' == $arrHeaders['headers']['transfer-encoding'] ) + $process['body'] = WP_Http::chunkTransferDecode($process['body']); + + if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) ) + $process['body'] = WP_Http_Encoding::decompress( $process['body'] ); + + if ( isset( $r['limit_response_size'] ) && strlen( $process['body'] ) > $r['limit_response_size'] ) + $process['body'] = substr( $process['body'], 0, $r['limit_response_size'] ); + + $response['body'] = $process['body']; + + return $response; + } + + /** + * Verifies the received SSL certificate against it's Common Names and subjectAltName fields + * + * PHP's SSL verifications only verify that it's a valid Certificate, it doesn't verify if + * the certificate is valid for the hostname which was requested. + * This function verifies the requested hostname against certificate's subjectAltName field, + * if that is empty, or contains no DNS entries, a fallback to the Common Name field is used. + * + * IP Address support is included if the request is being made to an IP address. + * + * @since 3.7.0 + * @static + * + * @param stream $stream The PHP Stream which the SSL request is being made over + * @param string $host The hostname being requested + * @return bool If the cerficiate presented in $stream is valid for $host + */ + static function verify_ssl_certificate( $stream, $host ) { + $context_options = stream_context_get_options( $stream ); + + if ( empty( $context_options['ssl']['peer_certificate'] ) ) + return false; + + $cert = openssl_x509_parse( $context_options['ssl']['peer_certificate'] ); + if ( ! $cert ) + return false; + + // If the request is being made to an IP address, we'll validate against IP fields in the cert (if they exist) + $host_type = ( WP_HTTP::is_ip_address( $host ) ? 'ip' : 'dns' ); + + $certificate_hostnames = array(); + if ( ! empty( $cert['extensions']['subjectAltName'] ) ) { + $match_against = preg_split( '/,\s*/', $cert['extensions']['subjectAltName'] ); + foreach ( $match_against as $match ) { + list( $match_type, $match_host ) = explode( ':', $match ); + if ( $host_type == strtolower( trim( $match_type ) ) ) // IP: or DNS: + $certificate_hostnames[] = strtolower( trim( $match_host ) ); + } + } elseif ( !empty( $cert['subject']['CN'] ) ) { + // Only use the CN when the certificate includes no subjectAltName extension + $certificate_hostnames[] = strtolower( $cert['subject']['CN'] ); + } + + // Exact hostname/IP matches + if ( in_array( strtolower( $host ), $certificate_hostnames ) ) + return true; + + // IP's can't be wildcards, Stop processing + if ( 'ip' == $host_type ) + return false; + + // Test to see if the domain is at least 2 deep for wildcard support + if ( substr_count( $host, '.' ) < 2 ) + return false; + + // Wildcard subdomains certs (*.example.com) are valid for a.example.com but not a.b.example.com + $wildcard_host = preg_replace( '/^[^.]+\./', '*.', $host ); + + return in_array( strtolower( $wildcard_host ), $certificate_hostnames ); + } + + /** + * Whether this class can be used for retrieving an URL. + * + * @static + * @access public + * @since 2.7.0 + * @since 3.7.0 Combined with the fsockopen transport and switched to stream_socket_client(). + * + * @return boolean False means this class can not be used, true means it can. + */ + public static function test( $args = array() ) { + if ( ! function_exists( 'stream_socket_client' ) ) + return false; + + $is_ssl = isset( $args['ssl'] ) && $args['ssl']; + + if ( $is_ssl ) { + if ( ! extension_loaded( 'openssl' ) ) + return false; + if ( ! function_exists( 'openssl_x509_parse' ) ) + return false; + } + + return apply_filters( 'use_streams_transport', true, $args ); + } +} + +/** + * Deprecated HTTP Transport method which used fsockopen. + * + * This class is not used, and is included for backwards compatibility only. + * All code should make use of WP_HTTP directly through it's API. + * + * @see WP_HTTP::request + * + * @package WordPress + * @subpackage HTTP + * + * @since 2.7.0 + * @deprecated 3.7.0 Please use WP_HTTP::request() directly + */ +class WP_HTTP_Fsockopen extends WP_HTTP_Streams { + // For backwards compatibility for users who are using the class directly +} + +/** + * HTTP request method uses Curl extension to retrieve the url. + * + * Requires the Curl extension to be installed. + * + * @package WordPress + * @subpackage HTTP + * @since 2.7.0 + */ +class WP_Http_Curl { + + /** + * Temporary header storage for during requests. + * + * @since 3.2.0 + * @access private + * @var string + */ + private $headers = ''; + + /** + * Temporary body storage for during requests. + * + * @since 3.6.0 + * @access private + * @var string + */ + private $body = ''; + + /** + * The maximum amount of data to recieve from the remote server + * + * @since 3.6.0 + * @access private + * @var int + */ + private $max_body_length = false; + + /** + * The file resource used for streaming to file. + * + * @since 3.6.0 + * @access private + * @var resource + */ + private $stream_handle = false; + + /** + * Send a HTTP request to a URI using cURL extension. + * + * @access public + * @since 2.7.0 + * + * @param string $url + * @param str|array $args Optional. Override the defaults. + * @return array 'headers', 'body', 'response', 'cookies' and 'filename' keys. + */ + function request($url, $args = array()) { + $defaults = array( + 'method' => 'GET', 'timeout' => 5, + 'redirection' => 5, 'httpversion' => '1.0', + 'blocking' => true, + 'headers' => array(), 'body' => null, 'cookies' => array() + ); + + $r = wp_parse_args( $args, $defaults ); + + if ( isset($r['headers']['User-Agent']) ) { + $r['user-agent'] = $r['headers']['User-Agent']; + unset($r['headers']['User-Agent']); + } else if ( isset($r['headers']['user-agent']) ) { + $r['user-agent'] = $r['headers']['user-agent']; + unset($r['headers']['user-agent']); + } + + // Construct Cookie: header if any cookies are set. + WP_Http::buildCookieHeader( $r ); + + $handle = curl_init(); + + // cURL offers really easy proxy support. + $proxy = new WP_HTTP_Proxy(); + + if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { + + curl_setopt( $handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP ); + curl_setopt( $handle, CURLOPT_PROXY, $proxy->host() ); + curl_setopt( $handle, CURLOPT_PROXYPORT, $proxy->port() ); + + if ( $proxy->use_authentication() ) { + curl_setopt( $handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY ); + curl_setopt( $handle, CURLOPT_PROXYUSERPWD, $proxy->authentication() ); + } + } + + $is_local = isset($r['local']) && $r['local']; + $ssl_verify = isset($r['sslverify']) && $r['sslverify']; + if ( $is_local ) + $ssl_verify = apply_filters('https_local_ssl_verify', $ssl_verify); + elseif ( ! $is_local ) + $ssl_verify = apply_filters('https_ssl_verify', $ssl_verify); + + // CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since + // a value of 0 will allow an unlimited timeout. + $timeout = (int) ceil( $r['timeout'] ); + curl_setopt( $handle, CURLOPT_CONNECTTIMEOUT, $timeout ); + curl_setopt( $handle, CURLOPT_TIMEOUT, $timeout ); + + curl_setopt( $handle, CURLOPT_URL, $url); + curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); + curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); + curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); + curl_setopt( $handle, CURLOPT_CAINFO, $r['sslcertificates'] ); + curl_setopt( $handle, CURLOPT_USERAGENT, $r['user-agent'] ); + // The option doesn't work with safe mode or when open_basedir is set, and there's a + // bug #17490 with redirected POST requests, so handle redirections outside Curl. + curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, false ); + if ( defined( 'CURLOPT_PROTOCOLS' ) ) // PHP 5.2.10 / cURL 7.19.4 + curl_setopt( $handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS ); + + switch ( $r['method'] ) { + case 'HEAD': + curl_setopt( $handle, CURLOPT_NOBODY, true ); + break; + case 'POST': + curl_setopt( $handle, CURLOPT_POST, true ); + curl_setopt( $handle, CURLOPT_POSTFIELDS, $r['body'] ); + break; + case 'PUT': + curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'PUT' ); + curl_setopt( $handle, CURLOPT_POSTFIELDS, $r['body'] ); + break; + default: + curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, $r['method'] ); + if ( ! is_null( $r['body'] ) ) + curl_setopt( $handle, CURLOPT_POSTFIELDS, $r['body'] ); + break; + } + + if ( true === $r['blocking'] ) { + curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( $this, 'stream_headers' ) ); + curl_setopt( $handle, CURLOPT_WRITEFUNCTION, array( $this, 'stream_body' ) ); + } + + curl_setopt( $handle, CURLOPT_HEADER, false ); + + if ( isset( $r['limit_response_size'] ) ) + $this->max_body_length = intval( $r['limit_response_size'] ); + else + $this->max_body_length = false; + + // If streaming to a file open a file handle, and setup our curl streaming handler + if ( $r['stream'] ) { + if ( ! WP_DEBUG ) + $this->stream_handle = @fopen( $r['filename'], 'w+' ); + else + $this->stream_handle = fopen( $r['filename'], 'w+' ); + if ( ! $this->stream_handle ) + return new WP_Error( 'http_request_failed', sprintf( __( 'Could not open handle for fopen() to %s' ), $r['filename'] ) ); + } else { + $this->stream_handle = false; + } + + if ( !empty( $r['headers'] ) ) { + // cURL expects full header strings in each element + $headers = array(); + foreach ( $r['headers'] as $name => $value ) { + $headers[] = "{$name}: $value"; + } + curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers ); + } + + if ( $r['httpversion'] == '1.0' ) + curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 ); + else + curl_setopt( $handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); + + // Cookies are not handled by the HTTP API currently. Allow for plugin authors to handle it + // themselves... Although, it is somewhat pointless without some reference. + do_action_ref_array( 'http_api_curl', array(&$handle) ); + + // We don't need to return the body, so don't. Just execute request and return. + if ( ! $r['blocking'] ) { + curl_exec( $handle ); + + if ( $curl_error = curl_error( $handle ) ) { + curl_close( $handle ); + return new WP_Error( 'http_request_failed', $curl_error ); + } + if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) { + curl_close( $handle ); + return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); + } + + curl_close( $handle ); + return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() ); + } + + $theResponse = curl_exec( $handle ); + $theHeaders = WP_Http::processHeaders( $this->headers, $url ); + $theBody = $this->body; + + $this->headers = ''; + $this->body = ''; + + $curl_error = curl_errno( $handle ); + + // If an error occured, or, no response + if ( $curl_error || ( 0 == strlen( $theBody ) && empty( $theHeaders['headers'] ) ) ) { + if ( CURLE_WRITE_ERROR /* 23 */ == $curl_error && $r['stream'] ) { + fclose( $this->stream_handle ); + return new WP_Error( 'http_request_failed', __( 'Failed to write request to temporary file.' ) ); + } + if ( $curl_error = curl_error( $handle ) ) { + curl_close( $handle ); + return new WP_Error( 'http_request_failed', $curl_error ); + } + if ( in_array( curl_getinfo( $handle, CURLINFO_HTTP_CODE ), array( 301, 302 ) ) ) { + curl_close( $handle ); + return new WP_Error( 'http_request_failed', __( 'Too many redirects.' ) ); + } + } + + $response = array(); + $response['code'] = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); + $response['message'] = get_status_header_desc($response['code']); + + curl_close( $handle ); + + if ( $r['stream'] ) + fclose( $this->stream_handle ); + + $response = array( + 'headers' => $theHeaders['headers'], + 'body' => null, + 'response' => $response, + 'cookies' => $theHeaders['cookies'], + 'filename' => $r['filename'] + ); + + // Handle redirects + if ( false !== ( $redirect_response = WP_HTTP::handle_redirects( $url, $r, $response ) ) ) + return $redirect_response; + + if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) ) + $theBody = WP_Http_Encoding::decompress( $theBody ); + + $response['body'] = $theBody; + + return $response; + } + + /** + * Grab the headers of the cURL request + * + * Each header is sent individually to this callback, so we append to the $header property for temporary storage + * + * @since 3.2.0 + * @access private + * @return int + */ + private function stream_headers( $handle, $headers ) { + $this->headers .= $headers; + return strlen( $headers ); + } + + /** + * Grab the body of the cURL request + * + * The contents of the document are passed in chunks, so we append to the $body property for temporary storage. + * Returning a length shorter than the length of $data passed in will cause cURL to abort the request as "completed" + * + * @since 3.6.0 + * @access private + * @return int + */ + private function stream_body( $handle, $data ) { + $data_length = strlen( $data ); + + if ( $this->max_body_length && ( strlen( $this->body ) + $data_length ) > $this->max_body_length ) + $data = substr( $data, 0, ( $this->max_body_length - $data_length ) ); + + if ( $this->stream_handle ) { + $bytes_written = fwrite( $this->stream_handle, $data ); + } else { + $this->body .= $data; + $bytes_written = $data_length; + } + + // Upon event of this function returning less than strlen( $data ) curl will error with CURLE_WRITE_ERROR + return $bytes_written; + } + + /** + * Whether this class can be used for retrieving an URL. + * + * @static + * @since 2.7.0 + * + * @return boolean False means this class can not be used, true means it can. + */ + public static function test( $args = array() ) { + if ( ! function_exists( 'curl_init' ) || ! function_exists( 'curl_exec' ) ) + return false; + + $is_ssl = isset( $args['ssl'] ) && $args['ssl']; + + if ( $is_ssl ) { + $curl_version = curl_version(); + if ( ! (CURL_VERSION_SSL & $curl_version['features']) ) // Does this cURL version support SSL requests? + return false; + } + + return apply_filters( 'use_curl_transport', true, $args ); + } +} + +/** + * Adds Proxy support to the WordPress HTTP API. + * + * There are caveats to proxy support. It requires that defines be made in the wp-config.php file to + * enable proxy support. There are also a few filters that plugins can hook into for some of the + * constants. + * + * Please note that only BASIC authentication is supported by most transports. + * cURL MAY support more methods (such as NTLM authentication) depending on your environment. + * + * The constants are as follows: + * <ol> + * <li>WP_PROXY_HOST - Enable proxy support and host for connecting.</li> + * <li>WP_PROXY_PORT - Proxy port for connection. No default, must be defined.</li> + * <li>WP_PROXY_USERNAME - Proxy username, if it requires authentication.</li> + * <li>WP_PROXY_PASSWORD - Proxy password, if it requires authentication.</li> + * <li>WP_PROXY_BYPASS_HOSTS - Will prevent the hosts in this list from going through the proxy. + * You do not need to have localhost and the blog host in this list, because they will not be passed + * through the proxy. The list should be presented in a comma separated list, wildcards using * are supported, eg. *.wordpress.org</li> + * </ol> + * + * An example can be as seen below. + * <code> + * define('WP_PROXY_HOST', '192.168.84.101'); + * define('WP_PROXY_PORT', '8080'); + * define('WP_PROXY_BYPASS_HOSTS', 'localhost, www.example.com, *.wordpress.org'); + * </code> + * + * @link http://core.trac.wordpress.org/ticket/4011 Proxy support ticket in WordPress. + * @link http://core.trac.wordpress.org/ticket/14636 Allow wildcard domains in WP_PROXY_BYPASS_HOSTS + * @since 2.8 + */ +class WP_HTTP_Proxy { + + /** + * Whether proxy connection should be used. + * + * @since 2.8 + * @use WP_PROXY_HOST + * @use WP_PROXY_PORT + * + * @return bool + */ + function is_enabled() { + return defined('WP_PROXY_HOST') && defined('WP_PROXY_PORT'); + } + + /** + * Whether authentication should be used. + * + * @since 2.8 + * @use WP_PROXY_USERNAME + * @use WP_PROXY_PASSWORD + * + * @return bool + */ + function use_authentication() { + return defined('WP_PROXY_USERNAME') && defined('WP_PROXY_PASSWORD'); + } + + /** + * Retrieve the host for the proxy server. + * + * @since 2.8 + * + * @return string + */ + function host() { + if ( defined('WP_PROXY_HOST') ) + return WP_PROXY_HOST; + + return ''; + } + + /** + * Retrieve the port for the proxy server. + * + * @since 2.8 + * + * @return string + */ + function port() { + if ( defined('WP_PROXY_PORT') ) + return WP_PROXY_PORT; + + return ''; + } + + /** + * Retrieve the username for proxy authentication. + * + * @since 2.8 + * + * @return string + */ + function username() { + if ( defined('WP_PROXY_USERNAME') ) + return WP_PROXY_USERNAME; + + return ''; + } + + /** + * Retrieve the password for proxy authentication. + * + * @since 2.8 + * + * @return string + */ + function password() { + if ( defined('WP_PROXY_PASSWORD') ) + return WP_PROXY_PASSWORD; + + return ''; + } + + /** + * Retrieve authentication string for proxy authentication. + * + * @since 2.8 + * + * @return string + */ + function authentication() { + return $this->username() . ':' . $this->password(); + } + + /** + * Retrieve header string for proxy authentication. + * + * @since 2.8 + * + * @return string + */ + function authentication_header() { + return 'Proxy-Authorization: Basic ' . base64_encode( $this->authentication() ); + } + + /** + * Whether URL should be sent through the proxy server. + * + * We want to keep localhost and the blog URL from being sent through the proxy server, because + * some proxies can not handle this. We also have the constant available for defining other + * hosts that won't be sent through the proxy. + * + * @uses WP_PROXY_BYPASS_HOSTS + * @since 2.8.0 + * + * @param string $uri URI to check. + * @return bool True, to send through the proxy and false if, the proxy should not be used. + */ + function send_through_proxy( $uri ) { + // parse_url() only handles http, https type URLs, and will emit E_WARNING on failure. + // This will be displayed on blogs, which is not reasonable. + $check = @parse_url($uri); + + // Malformed URL, can not process, but this could mean ssl, so let through anyway. + if ( $check === false ) + return true; + + $home = parse_url( get_option('siteurl') ); + + $result = apply_filters( 'pre_http_send_through_proxy', null, $uri, $check, $home ); + if ( ! is_null( $result ) ) + return $result; + + if ( $check['host'] == 'localhost' || $check['host'] == $home['host'] ) + return false; + + if ( !defined('WP_PROXY_BYPASS_HOSTS') ) + return true; + + static $bypass_hosts; + static $wildcard_regex = false; + if ( null == $bypass_hosts ) { + $bypass_hosts = preg_split('|,\s*|', WP_PROXY_BYPASS_HOSTS); + + if ( false !== strpos(WP_PROXY_BYPASS_HOSTS, '*') ) { + $wildcard_regex = array(); + foreach ( $bypass_hosts as $host ) + $wildcard_regex[] = str_replace( '\*', '.+', preg_quote( $host, '/' ) ); + $wildcard_regex = '/^(' . implode('|', $wildcard_regex) . ')$/i'; + } + } + + if ( !empty($wildcard_regex) ) + return !preg_match($wildcard_regex, $check['host']); + else + return !in_array( $check['host'], $bypass_hosts ); + } +} +/** + * Internal representation of a single cookie. + * + * Returned cookies are represented using this class, and when cookies are set, if they are not + * already a WP_Http_Cookie() object, then they are turned into one. + * + * @todo The WordPress convention is to use underscores instead of camelCase for function and method + * names. Need to switch to use underscores instead for the methods. + * + * @package WordPress + * @subpackage HTTP + * @since 2.8.0 + */ +class WP_Http_Cookie { + + /** + * Cookie name. + * + * @since 2.8.0 + * @var string + */ + var $name; + + /** + * Cookie value. + * + * @since 2.8.0 + * @var string + */ + var $value; + + /** + * When the cookie expires. + * + * @since 2.8.0 + * @var string + */ + var $expires; + + /** + * Cookie URL path. + * + * @since 2.8.0 + * @var string + */ + var $path; + + /** + * Cookie Domain. + * + * @since 2.8.0 + * @var string + */ + var $domain; + + /** + * Sets up this cookie object. + * + * The parameter $data should be either an associative array containing the indices names below + * or a header string detailing it. + * + * If it's an array, it should include the following elements: + * <ol> + * <li>Name</li> + * <li>Value - should NOT be urlencoded already.</li> + * <li>Expires - (optional) String or int (UNIX timestamp).</li> + * <li>Path (optional)</li> + * <li>Domain (optional)</li> + * <li>Port (optional)</li> + * </ol> + * + * @access public + * @since 2.8.0 + * + * @param string|array $data Raw cookie data. + * @param string $requested_url The URL which the cookie was set on, used for default 'domain' and 'port' values + */ + function __construct( $data, $requested_url = '' ) { + if ( $requested_url ) + $arrURL = @parse_url( $requested_url ); + if ( isset( $arrURL['host'] ) ) + $this->domain = $arrURL['host']; + $this->path = isset( $arrURL['path'] ) ? $arrURL['path'] : '/'; + if ( '/' != substr( $this->path, -1 ) ) + $this->path = dirname( $this->path ) . '/'; + + if ( is_string( $data ) ) { + // Assume it's a header string direct from a previous request + $pairs = explode( ';', $data ); + + // Special handling for first pair; name=value. Also be careful of "=" in value + $name = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) ); + $value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 ); + $this->name = $name; + $this->value = urldecode( $value ); + array_shift( $pairs ); //Removes name=value from items. + + // Set everything else as a property + foreach ( $pairs as $pair ) { + $pair = rtrim($pair); + if ( empty($pair) ) //Handles the cookie ending in ; which results in a empty final pair + continue; + + list( $key, $val ) = strpos( $pair, '=' ) ? explode( '=', $pair ) : array( $pair, '' ); + $key = strtolower( trim( $key ) ); + if ( 'expires' == $key ) + $val = strtotime( $val ); + $this->$key = $val; + } + } else { + if ( !isset( $data['name'] ) ) + return false; + + // Set properties based directly on parameters + foreach ( array( 'name', 'value', 'path', 'domain', 'port' ) as $field ) { + if ( isset( $data[ $field ] ) ) + $this->$field = $data[ $field ]; + } + + if ( isset( $data['expires'] ) ) + $this->expires = is_int( $data['expires'] ) ? $data['expires'] : strtotime( $data['expires'] ); + else + $this->expires = null; + } + } + + /** + * Confirms that it's OK to send this cookie to the URL checked against. + * + * Decision is based on RFC 2109/2965, so look there for details on validity. + * + * @access public + * @since 2.8.0 + * + * @param string $url URL you intend to send this cookie to + * @return boolean true if allowed, false otherwise. + */ + function test( $url ) { + if ( is_null( $this->name ) ) + return false; + + // Expires - if expired then nothing else matters + if ( isset( $this->expires ) && time() > $this->expires ) + return false; + + // Get details on the URL we're thinking about sending to + $url = parse_url( $url ); + $url['port'] = isset( $url['port'] ) ? $url['port'] : ( 'https' == $url['scheme'] ? 443 : 80 ); + $url['path'] = isset( $url['path'] ) ? $url['path'] : '/'; + + // Values to use for comparison against the URL + $path = isset( $this->path ) ? $this->path : '/'; + $port = isset( $this->port ) ? $this->port : null; + $domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] ); + if ( false === stripos( $domain, '.' ) ) + $domain .= '.local'; + + // Host - very basic check that the request URL ends with the domain restriction (minus leading dot) + $domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain; + if ( substr( $url['host'], -strlen( $domain ) ) != $domain ) + return false; + + // Port - supports "port-lists" in the format: "80,8000,8080" + if ( !empty( $port ) && !in_array( $url['port'], explode( ',', $port) ) ) + return false; + + // Path - request path must start with path restriction + if ( substr( $url['path'], 0, strlen( $path ) ) != $path ) + return false; + + return true; + } + + /** + * Convert cookie name and value back to header string. + * + * @access public + * @since 2.8.0 + * + * @return string Header encoded cookie name and value. + */ + function getHeaderValue() { + if ( ! isset( $this->name ) || ! isset( $this->value ) ) + return ''; + + return $this->name . '=' . apply_filters( 'wp_http_cookie_value', $this->value, $this->name ); + } + + /** + * Retrieve cookie header for usage in the rest of the WordPress HTTP API. + * + * @access public + * @since 2.8.0 + * + * @return string + */ + function getFullHeader() { + return 'Cookie: ' . $this->getHeaderValue(); + } +} + +/** + * Implementation for deflate and gzip transfer encodings. + * + * Includes RFC 1950, RFC 1951, and RFC 1952. + * + * @since 2.8 + * @package WordPress + * @subpackage HTTP + */ +class WP_Http_Encoding { + + /** + * Compress raw string using the deflate format. + * + * Supports the RFC 1951 standard. + * + * @since 2.8 + * + * @param string $raw String to compress. + * @param int $level Optional, default is 9. Compression level, 9 is highest. + * @param string $supports Optional, not used. When implemented it will choose the right compression based on what the server supports. + * @return string|bool False on failure. + */ + public static function compress( $raw, $level = 9, $supports = null ) { + return gzdeflate( $raw, $level ); + } + + /** + * Decompression of deflated string. + * + * Will attempt to decompress using the RFC 1950 standard, and if that fails + * then the RFC 1951 standard deflate will be attempted. Finally, the RFC + * 1952 standard gzip decode will be attempted. If all fail, then the + * original compressed string will be returned. + * + * @since 2.8 + * + * @param string $compressed String to decompress. + * @param int $length The optional length of the compressed data. + * @return string|bool False on failure. + */ + public static function decompress( $compressed, $length = null ) { + + if ( empty($compressed) ) + return $compressed; + + if ( false !== ( $decompressed = @gzinflate( $compressed ) ) ) + return $decompressed; + + if ( false !== ( $decompressed = WP_Http_Encoding::compatible_gzinflate( $compressed ) ) ) + return $decompressed; + + if ( false !== ( $decompressed = @gzuncompress( $compressed ) ) ) + return $decompressed; + + if ( function_exists('gzdecode') ) { + $decompressed = @gzdecode( $compressed ); + + if ( false !== $decompressed ) + return $decompressed; + } + + return $compressed; + } + + /** + * Decompression of deflated string while staying compatible with the majority of servers. + * + * Certain Servers will return deflated data with headers which PHP's gzinflate() + * function cannot handle out of the box. The following function has been created from + * various snippets on the gzinflate() PHP documentation. + * + * Warning: Magic numbers within. Due to the potential different formats that the compressed + * data may be returned in, some "magic offsets" are needed to ensure proper decompression + * takes place. For a simple progmatic way to determine the magic offset in use, see: + * http://core.trac.wordpress.org/ticket/18273 + * + * @since 2.8.1 + * @link http://core.trac.wordpress.org/ticket/18273 + * @link http://au2.php.net/manual/en/function.gzinflate.php#70875 + * @link http://au2.php.net/manual/en/function.gzinflate.php#77336 + * + * @param string $gzData String to decompress. + * @return string|bool False on failure. + */ + public static function compatible_gzinflate($gzData) { + + // Compressed data might contain a full header, if so strip it for gzinflate() + if ( substr($gzData, 0, 3) == "\x1f\x8b\x08" ) { + $i = 10; + $flg = ord( substr($gzData, 3, 1) ); + if ( $flg > 0 ) { + if ( $flg & 4 ) { + list($xlen) = unpack('v', substr($gzData, $i, 2) ); + $i = $i + 2 + $xlen; + } + if ( $flg & 8 ) + $i = strpos($gzData, "\0", $i) + 1; + if ( $flg & 16 ) + $i = strpos($gzData, "\0", $i) + 1; + if ( $flg & 2 ) + $i = $i + 2; + } + $decompressed = @gzinflate( substr($gzData, $i, -8) ); + if ( false !== $decompressed ) + return $decompressed; + } + + // Compressed data from java.util.zip.Deflater amongst others. + $decompressed = @gzinflate( substr($gzData, 2) ); + if ( false !== $decompressed ) + return $decompressed; + + return false; + } + + /** + * What encoding types to accept and their priority values. + * + * @since 2.8 + * + * @return string Types of encoding to accept. + */ + public static function accept_encoding( $url, $args ) { + $type = array(); + $compression_enabled = WP_Http_Encoding::is_available(); + + if ( ! $args['decompress'] ) // decompression specifically disabled + $compression_enabled = false; + elseif ( $args['stream'] ) // disable when streaming to file + $compression_enabled = false; + elseif ( isset( $args['limit_response_size'] ) ) // If only partial content is being requested, we won't be able to decompress it + $compression_enabled = false; + + if ( $compression_enabled ) { + if ( function_exists( 'gzinflate' ) ) + $type[] = 'deflate;q=1.0'; + + if ( function_exists( 'gzuncompress' ) ) + $type[] = 'compress;q=0.5'; + + if ( function_exists( 'gzdecode' ) ) + $type[] = 'gzip;q=0.5'; + } + + $type = apply_filters( 'wp_http_accept_encoding', $type, $url, $args ); + + return implode(', ', $type); + } + + /** + * What encoding the content used when it was compressed to send in the headers. + * + * @since 2.8 + * + * @return string Content-Encoding string to send in the header. + */ + public static function content_encoding() { + return 'deflate'; + } + + /** + * Whether the content be decoded based on the headers. + * + * @since 2.8 + * + * @param array|string $headers All of the available headers. + * @return bool + */ + public static function should_decode($headers) { + if ( is_array( $headers ) ) { + if ( array_key_exists('content-encoding', $headers) && ! empty( $headers['content-encoding'] ) ) + return true; + } else if ( is_string( $headers ) ) { + return ( stripos($headers, 'content-encoding:') !== false ); + } + + return false; + } + + /** + * Whether decompression and compression are supported by the PHP version. + * + * Each function is tested instead of checking for the zlib extension, to + * ensure that the functions all exist in the PHP version and aren't + * disabled. + * + * @since 2.8 + * + * @return bool + */ + public static function is_available() { + return ( function_exists('gzuncompress') || function_exists('gzdeflate') || function_exists('gzinflate') ); + } +} diff --git a/sources/wp-includes/class-json.php b/sources/wp-includes/class-json.php new file mode 100644 index 0000000..417592f --- /dev/null +++ b/sources/wp-includes/class-json.php @@ -0,0 +1,936 @@ +<?php +if ( ! class_exists( 'Services_JSON' ) ) : +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ +/** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * @category + * @package Services_JSON + * @author Michal Migurski <mike-json@teczno.com> + * @author Matt Knapp <mdknapp[at]gmail[dot]com> + * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> + * @copyright 2005 Michal Migurski + * @version CVS: $Id: JSON.php 305040 2010-11-02 23:19:03Z alan_k $ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_SLICE', 1); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_STR', 2); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_ARR', 3); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_OBJ', 4); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_CMT', 5); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_LOOSE_TYPE', 16); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_SUPPRESS_ERRORS', 32); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_USE_TO_JSON', 64); + +/** + * Converts to and from JSON format. + * + * Brief example of use: + * + * <code> + * // create a new instance of Services_JSON + * $json = new Services_JSON(); + * + * // convert a complexe value to JSON notation, and send it to the browser + * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); + * $output = $json->encode($value); + * + * print($output); + * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] + * + * // accept incoming POST data, assumed to be in JSON notation + * $input = file_get_contents('php://input', 1000000); + * $value = $json->decode($input); + * </code> + */ +class Services_JSON +{ + /** + * constructs a new JSON instance + * + * @param int $use object behavior flags; combine with boolean-OR + * + * possible values: + * - SERVICES_JSON_LOOSE_TYPE: loose typing. + * "{...}" syntax creates associative arrays + * instead of objects in decode(). + * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. + * Values which can't be encoded (e.g. resources) + * appear as NULL instead of throwing errors. + * By default, a deeply-nested resource will + * bubble up with an error, so all return values + * from encode() should be checked with isError() + * - SERVICES_JSON_USE_TO_JSON: call toJSON when serializing objects + * It serializes the return value from the toJSON call rather + * than the object it'self, toJSON can return associative arrays, + * strings or numbers, if you return an object, make sure it does + * not have a toJSON method, otherwise an error will occur. + */ + function Services_JSON($use = 0) + { + $this->use = $use; + $this->_mb_strlen = function_exists('mb_strlen'); + $this->_mb_convert_encoding = function_exists('mb_convert_encoding'); + $this->_mb_substr = function_exists('mb_substr'); + } + // private - cache the mbstring lookup results.. + var $_mb_strlen = false; + var $_mb_substr = false; + var $_mb_convert_encoding = false; + + /** + * convert a string from one UTF-16 char to one UTF-8 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf16 UTF-16 character + * @return string UTF-8 character + * @access private + */ + function utf162utf8($utf16) + { + // oh please oh please oh please oh please oh please + if($this->_mb_convert_encoding) { + return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); + } + + $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); + + switch(true) { + case ((0x7F & $bytes) == $bytes): + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x7F & $bytes); + + case (0x07FF & $bytes) == $bytes: + // return a 2-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xC0 | (($bytes >> 6) & 0x1F)) + . chr(0x80 | ($bytes & 0x3F)); + + case (0xFFFF & $bytes) == $bytes: + // return a 3-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xE0 | (($bytes >> 12) & 0x0F)) + . chr(0x80 | (($bytes >> 6) & 0x3F)) + . chr(0x80 | ($bytes & 0x3F)); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + function utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if($this->_mb_convert_encoding) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch($this->strlen8($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format (and sends JSON Header) + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + function encode($var) + { + header('Content-type: application/json'); + return $this->encodeUnsafe($var); + } + /** + * encodes an arbitrary variable into JSON format without JSON Header - warning - may allow XSS!!!!) + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + function encodeUnsafe($var) + { + // see bug #16908 - regarding numeric locale printing + $lc = setlocale(LC_NUMERIC, 0); + setlocale(LC_NUMERIC, 'C'); + $ret = $this->_encode($var); + setlocale(LC_NUMERIC, $lc); + return $ret; + + } + /** + * PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + function _encode($var) + { + + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = $this->strlen8($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + if ($c+1 >= $strlen_var) { + $c += 1; + $ascii .= '?'; + break; + } + + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + if ($c+2 >= $strlen_var) { + $c += 2; + $ascii .= '?'; + break; + } + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + @ord($var{$c + 1}), + @ord($var{$c + 2})); + $c += 2; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + if ($c+3 >= $strlen_var) { + $c += 3; + $ascii .= '?'; + break; + } + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + if ($c+4 >= $strlen_var) { + $c += 4; + $ascii .= '?'; + break; + } + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + if ($c+5 >= $strlen_var) { + $c += 5; + $ascii .= '?'; + break; + } + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + $properties = array_map(array($this, 'name_value'), + array_keys($var), + array_values($var)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + // treat it like a regular array + $elements = array_map(array($this, '_encode'), $var); + + foreach($elements as $element) { + if(Services_JSON::isError($element)) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + + // support toJSON methods. + if (($this->use & SERVICES_JSON_USE_TO_JSON) && method_exists($var, 'toJSON')) { + // this may end up allowing unlimited recursion + // so we check the return value to make sure it's not got the same method. + $recode = $var->toJSON(); + + if (method_exists($recode, 'toJSON')) { + + return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) + ? 'null' + : new Services_JSON_Error(get_class($var). + " toJSON returned an object with a toJSON method."); + + } + + return $this->_encode( $recode ); + } + + $vars = get_object_vars($var); + + $properties = array_map(array($this, 'name_value'), + array_keys($vars), + array_values($vars)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) + ? 'null' + : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + function name_value($name, $value) + { + $encoded_value = $this->_encode($value); + + if(Services_JSON::isError($encoded_value)) { + return $encoded_value; + } + + return $this->_encode(strval($name)) . ':' . $encoded_value; + } + + /** + * reduce a string by removing leading and trailing comments and whitespace + * + * @param $str string string value to strip of comments and whitespace + * + * @return string string value stripped of comments and whitespace + * @access private + */ + function reduce_string($str) + { + $str = preg_replace(array( + + // eliminate single line comments in '// ...' form + '#^\s*//(.+)$#m', + + // eliminate multi-line comments in '/* ... */' form, at start of string + '#^\s*/\*(.+)\*/#Us', + + // eliminate multi-line comments in '/* ... */' form, at end of string + '#/\*(.+)\*/\s*$#Us' + + ), '', $str); + + // eliminate extraneous space + return trim($str); + } + + /** + * decodes a JSON string into appropriate variable + * + * @param string $str JSON-formatted string + * + * @return mixed number, boolean, string, array, or object + * corresponding to given JSON input string. + * See argument 1 to Services_JSON() above for object-output behavior. + * Note that decode() always returns strings + * in ASCII or UTF-8 format! + * @access public + */ + function decode($str) + { + $str = $this->reduce_string($str); + + switch (strtolower($str)) { + case 'true': + return true; + + case 'false': + return false; + + case 'null': + return null; + + default: + $m = array(); + + if (is_numeric($str)) { + // Lookie-loo, it's a number + + // This would work on its own, but I'm trying to be + // good about returning integers where appropriate: + // return (float)$str; + + // Return float or int, as appropriate + return ((float)$str == (integer)$str) + ? (integer)$str + : (float)$str; + + } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { + // STRINGS RETURNED IN UTF-8 FORMAT + $delim = $this->substr8($str, 0, 1); + $chrs = $this->substr8($str, 1, -1); + $utf8 = ''; + $strlen_chrs = $this->strlen8($chrs); + + for ($c = 0; $c < $strlen_chrs; ++$c) { + + $substr_chrs_c_2 = $this->substr8($chrs, $c, 2); + $ord_chrs_c = ord($chrs{$c}); + + switch (true) { + case $substr_chrs_c_2 == '\b': + $utf8 .= chr(0x08); + ++$c; + break; + case $substr_chrs_c_2 == '\t': + $utf8 .= chr(0x09); + ++$c; + break; + case $substr_chrs_c_2 == '\n': + $utf8 .= chr(0x0A); + ++$c; + break; + case $substr_chrs_c_2 == '\f': + $utf8 .= chr(0x0C); + ++$c; + break; + case $substr_chrs_c_2 == '\r': + $utf8 .= chr(0x0D); + ++$c; + break; + + case $substr_chrs_c_2 == '\\"': + case $substr_chrs_c_2 == '\\\'': + case $substr_chrs_c_2 == '\\\\': + case $substr_chrs_c_2 == '\\/': + if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || + ($delim == "'" && $substr_chrs_c_2 != '\\"')) { + $utf8 .= $chrs{++$c}; + } + break; + + case preg_match('/\\\u[0-9A-F]{4}/i', $this->substr8($chrs, $c, 6)): + // single, escaped unicode character + $utf16 = chr(hexdec($this->substr8($chrs, ($c + 2), 2))) + . chr(hexdec($this->substr8($chrs, ($c + 4), 2))); + $utf8 .= $this->utf162utf8($utf16); + $c += 5; + break; + + case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): + $utf8 .= $chrs{$c}; + break; + + case ($ord_chrs_c & 0xE0) == 0xC0: + // characters U-00000080 - U-000007FF, mask 110XXXXX + //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= $this->substr8($chrs, $c, 2); + ++$c; + break; + + case ($ord_chrs_c & 0xF0) == 0xE0: + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= $this->substr8($chrs, $c, 3); + $c += 2; + break; + + case ($ord_chrs_c & 0xF8) == 0xF0: + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= $this->substr8($chrs, $c, 4); + $c += 3; + break; + + case ($ord_chrs_c & 0xFC) == 0xF8: + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= $this->substr8($chrs, $c, 5); + $c += 4; + break; + + case ($ord_chrs_c & 0xFE) == 0xFC: + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= $this->substr8($chrs, $c, 6); + $c += 5; + break; + + } + + } + + return $utf8; + + } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { + // array, or object notation + + if ($str{0} == '[') { + $stk = array(SERVICES_JSON_IN_ARR); + $arr = array(); + } else { + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = array(); + } else { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = new stdClass(); + } + } + + array_push($stk, array('what' => SERVICES_JSON_SLICE, + 'where' => 0, + 'delim' => false)); + + $chrs = $this->substr8($str, 1, -1); + $chrs = $this->reduce_string($chrs); + + if ($chrs == '') { + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } else { + return $obj; + + } + } + + //print("\nparsing {$chrs}\n"); + + $strlen_chrs = $this->strlen8($chrs); + + for ($c = 0; $c <= $strlen_chrs; ++$c) { + + $top = end($stk); + $substr_chrs_c_2 = $this->substr8($chrs, $c, 2); + + if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { + // found a comma that is not inside a string, array, etc., + // OR we've reached the end of the character list + $slice = $this->substr8($chrs, $top['where'], ($c - $top['where'])); + array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); + //print("Found split at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + // we are in an array, so just push an element onto the stack + array_push($arr, $this->decode($slice)); + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + // we are in an object, so figure + // out the property name and set an + // element in an associative array, + // for now + $parts = array(); + + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:/Uis', $slice, $parts)) { + // "name":value pair + $key = $this->decode($parts[1]); + $val = $this->decode(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B")); + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } elseif (preg_match('/^\s*(\w+)\s*:/Uis', $slice, $parts)) { + // name:value pair, where name is unquoted + $key = $parts[1]; + $val = $this->decode(trim(substr($slice, strlen($parts[0])), ", \t\n\r\0\x0B")); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } + + } + + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { + // found a quote, and we are not inside a string + array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); + //print("Found start of string at {$c}\n"); + + } elseif (($chrs{$c} == $top['delim']) && + ($top['what'] == SERVICES_JSON_IN_STR) && + (($this->strlen8($this->substr8($chrs, 0, $c)) - $this->strlen8(rtrim($this->substr8($chrs, 0, $c), '\\'))) % 2 != 1)) { + // found a quote, we're in a string, and it's not escaped + // we know that it's not escaped becase there is _not_ an + // odd number of backslashes at the end of the string so far + array_pop($stk); + //print("Found end of string at {$c}: ".$this->substr8($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '[') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-bracket, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); + //print("Found start of array at {$c}\n"); + + } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { + // found a right-bracket, and we're in an array + array_pop($stk); + //print("Found end of array at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '{') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-brace, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); + //print("Found start of object at {$c}\n"); + + } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { + // found a right-brace, and we're in an object + array_pop($stk); + //print("Found end of object at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($substr_chrs_c_2 == '/*') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a comment start, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); + $c++; + //print("Found start of comment at {$c}\n"); + + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { + // found a comment end, and we're in one now + array_pop($stk); + $c++; + + for ($i = $top['where']; $i <= $c; ++$i) + $chrs = substr_replace($chrs, ' ', $i, 1); + + //print("Found end of comment at {$c}: ".$this->substr8($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } + + } + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + return $obj; + + } + + } + } + } + + /** + * @todo Ultimately, this should just call PEAR::isError() + */ + function isError($data, $code = null) + { + if (class_exists('pear')) { + return PEAR::isError($data, $code); + } elseif (is_object($data) && (get_class($data) == 'services_json_error' || + is_subclass_of($data, 'services_json_error'))) { + return true; + } + + return false; + } + + /** + * Calculates length of string in bytes + * @param string + * @return integer length + */ + function strlen8( $str ) + { + if ( $this->_mb_strlen ) { + return mb_strlen( $str, "8bit" ); + } + return strlen( $str ); + } + + /** + * Returns part of a string, interpreting $start and $length as number of bytes. + * @param string + * @param integer start + * @param integer length + * @return integer length + */ + function substr8( $string, $start, $length=false ) + { + if ( $length === false ) { + $length = $this->strlen8( $string ) - $start; + } + if ( $this->_mb_substr ) { + return mb_substr( $string, $start, $length, "8bit" ); + } + return substr( $string, $start, $length ); + } + +} + +if (class_exists('PEAR_Error')) { + + class Services_JSON_Error extends PEAR_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + parent::PEAR_Error($message, $code, $mode, $options, $userinfo); + } + } + +} else { + + /** + * @todo Ultimately, this class shall be descended from PEAR_Error + */ + class Services_JSON_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + + } + } + +} + +endif; diff --git a/sources/wp-includes/class-oembed.php b/sources/wp-includes/class-oembed.php new file mode 100644 index 0000000..cc36b2e --- /dev/null +++ b/sources/wp-includes/class-oembed.php @@ -0,0 +1,397 @@ +<?php +/** + * API for fetching the HTML to embed remote content based on a provided URL. + * Used internally by the {@link WP_Embed} class, but is designed to be generic. + * + * @link http://codex.wordpress.org/oEmbed oEmbed Codex Article + * @link http://oembed.com/ oEmbed Homepage + * + * @package WordPress + * @subpackage oEmbed + */ + +/** + * oEmbed class. + * + * @package WordPress + * @subpackage oEmbed + * @since 2.9.0 + */ +class WP_oEmbed { + var $providers = array(); + + /** + * Constructor + * + * @uses apply_filters() Filters a list of pre-defined oEmbed providers. + */ + function __construct() { + $providers = array( + '#https?://(www\.)?youtube\.com/watch.*#i' => array( 'http://www.youtube.com/oembed', true ), + 'http://youtu.be/*' => array( 'http://www.youtube.com/oembed', false ), + 'http://blip.tv/*' => array( 'http://blip.tv/oembed/', false ), + '#https?://(www\.)?vimeo\.com/.*#i' => array( 'http://vimeo.com/api/oembed.{format}', true ), + '#https?://(www\.)?dailymotion\.com/.*#i' => array( 'http://www.dailymotion.com/services/oembed', true ), + 'http://dai.ly/*' => array( 'http://www.dailymotion.com/services/oembed', false ), + '#https?://(www\.)?flickr\.com/.*#i' => array( 'http://www.flickr.com/services/oembed/', true ), + 'http://flic.kr/*' => array( 'http://www.flickr.com/services/oembed/', false ), + '#https?://(.+\.)?smugmug\.com/.*#i' => array( 'http://api.smugmug.com/services/oembed/', true ), + '#https?://(www\.)?hulu\.com/watch/.*#i' => array( 'http://www.hulu.com/api/oembed.{format}', true ), + '#https?://(www\.)?viddler\.com/.*#i' => array( 'http://lab.viddler.com/services/oembed/', true ), + 'http://qik.com/*' => array( 'http://qik.com/api/oembed.{format}', false ), + 'http://revision3.com/*' => array( 'http://revision3.com/api/oembed/', false ), + 'http://i*.photobucket.com/albums/*' => array( 'http://photobucket.com/oembed', false ), + 'http://gi*.photobucket.com/groups/*' => array( 'http://photobucket.com/oembed', false ), + '#https?://(www\.)?scribd\.com/.*#i' => array( 'http://www.scribd.com/services/oembed', true ), + 'http://wordpress.tv/*' => array( 'http://wordpress.tv/oembed/', false ), + '#https?://(.+\.)?polldaddy\.com/.*#i' => array( 'http://polldaddy.com/oembed/', true ), + '#https?://(www\.)?funnyordie\.com/videos/.*#i' => array( 'http://www.funnyordie.com/oembed', true ), + '#https?://(www\.)?twitter\.com/.+?/status(es)?/.*#i'=> array( 'http://api.twitter.com/1/statuses/oembed.{format}', true ), + '#https?://(www\.)?soundcloud\.com/.*#i' => array( 'http://soundcloud.com/oembed', true ), + '#https?://(www\.)?slideshare\.net/*#' => array( 'http://www.slideshare.net/api/oembed/2', true ), + '#http://instagr(\.am|am\.com)/p/.*#i' => array( 'http://api.instagram.com/oembed', true ), + '#https?://(www\.)?rdio\.com/.*#i' => array( 'http://www.rdio.com/api/oembed/', true ), + '#https?://rd\.io/x/.*#i' => array( 'http://www.rdio.com/api/oembed/', true ), + '#https?://(open|play)\.spotify\.com/.*#i' => array( 'https://embed.spotify.com/oembed/', true ), + ); + /** + * Filter the list of oEmbed providers. + * + * Discovery is disabled for users lacking the unfiltered_html capability. + * Only providers in this array will be used for those users. + * + * @see wp_oembed_add_provider() + * + * @since 2.9.0 + * + * @param array $providers An array of popular oEmbed providers. + */ + $this->providers = apply_filters( 'oembed_providers', $providers ); + + // Fix any embeds that contain new lines in the middle of the HTML which breaks wpautop(). + add_filter( 'oembed_dataparse', array($this, '_strip_newlines'), 10, 3 ); + } + + /** + * The do-it-all function that takes a URL and attempts to return the HTML. + * + * @see WP_oEmbed::discover() + * @see WP_oEmbed::fetch() + * @see WP_oEmbed::data2html() + * + * @param string $url The URL to the content that should be attempted to be embedded. + * @param array $args Optional arguments. Usually passed from a shortcode. + * @return bool|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed. + */ + function get_html( $url, $args = '' ) { + $provider = false; + + if ( !isset($args['discover']) ) + $args['discover'] = true; + + foreach ( $this->providers as $matchmask => $data ) { + list( $providerurl, $regex ) = $data; + + // Turn the asterisk-type provider URLs into regex + if ( !$regex ) { + $matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i'; + $matchmask = preg_replace( '|^#http\\\://|', '#https?\://', $matchmask ); + } + + if ( preg_match( $matchmask, $url ) ) { + $provider = str_replace( '{format}', 'json', $providerurl ); // JSON is easier to deal with than XML + break; + } + } + + if ( !$provider && $args['discover'] ) + $provider = $this->discover( $url ); + + if ( !$provider || false === $data = $this->fetch( $provider, $url, $args ) ) + return false; + + /** + * Filter the HTML returned by the oEmbed provider. + * + * @since 2.9.0 + * + * @param string $data The returned oEmbed HTML. + * @param string $url URL of the content to be embedded. + * @param array $args Optional arguments, usually passed from a shortcode. + */ + return apply_filters( 'oembed_result', $this->data2html( $data, $url ), $url, $args ); + } + + /** + * Attempts to find oEmbed provider discovery <link> tags at the given URL. + * + * @param string $url The URL that should be inspected for discovery <link> tags. + * @return bool|string False on failure, otherwise the oEmbed provider URL. + */ + function discover( $url ) { + $providers = array(); + + // Fetch URL content + if ( $html = wp_remote_retrieve_body( wp_safe_remote_get( $url ) ) ) { + + /** + * Filter the link types that contain oEmbed provider URLs. + * + * @since 2.9.0 + * + * @param array $format Array of oEmbed link types. Accepts 'application/json+oembed', + * 'text/xml+oembed', and 'application/xml+oembed' (incorrect, + * used by at least Vimeo). + */ + $linktypes = apply_filters( 'oembed_linktypes', array( + 'application/json+oembed' => 'json', + 'text/xml+oembed' => 'xml', + 'application/xml+oembed' => 'xml', + ) ); + + // Strip <body> + $html = substr( $html, 0, stripos( $html, '</head>' ) ); + + // Do a quick check + $tagfound = false; + foreach ( $linktypes as $linktype => $format ) { + if ( stripos($html, $linktype) ) { + $tagfound = true; + break; + } + } + + if ( $tagfound && preg_match_all( '/<link([^<>]+)>/i', $html, $links ) ) { + foreach ( $links[1] as $link ) { + $atts = shortcode_parse_atts( $link ); + + if ( !empty($atts['type']) && !empty($linktypes[$atts['type']]) && !empty($atts['href']) ) { + $providers[$linktypes[$atts['type']]] = $atts['href']; + + // Stop here if it's JSON (that's all we need) + if ( 'json' == $linktypes[$atts['type']] ) + break; + } + } + } + } + + // JSON is preferred to XML + if ( !empty($providers['json']) ) + return $providers['json']; + elseif ( !empty($providers['xml']) ) + return $providers['xml']; + else + return false; + } + + /** + * Connects to a oEmbed provider and returns the result. + * + * @param string $provider The URL to the oEmbed provider. + * @param string $url The URL to the content that is desired to be embedded. + * @param array $args Optional arguments. Usually passed from a shortcode. + * @return bool|object False on failure, otherwise the result in the form of an object. + */ + function fetch( $provider, $url, $args = '' ) { + $args = wp_parse_args( $args, wp_embed_defaults() ); + + $provider = add_query_arg( 'maxwidth', (int) $args['width'], $provider ); + $provider = add_query_arg( 'maxheight', (int) $args['height'], $provider ); + $provider = add_query_arg( 'url', urlencode($url), $provider ); + + /** + * Filter the oEmbed URL to be fetched. + * + * @since 2.9.0 + * + * @param string $provider URL of the oEmbed provider. + * @param string $url URL of the content to be embedded. + * @param array $args Optional arguments, usually passed from a shortcode. + */ + $provider = apply_filters( 'oembed_fetch_url', $provider, $url, $args ); + + foreach( array( 'json', 'xml' ) as $format ) { + $result = $this->_fetch_with_format( $provider, $format ); + if ( is_wp_error( $result ) && 'not-implemented' == $result->get_error_code() ) + continue; + return ( $result && ! is_wp_error( $result ) ) ? $result : false; + } + return false; + } + + /** + * Fetches result from an oEmbed provider for a specific format and complete provider URL + * + * @since 3.0.0 + * @access private + * @param string $provider_url_with_args URL to the provider with full arguments list (url, maxheight, etc.) + * @param string $format Format to use + * @return bool|object False on failure, otherwise the result in the form of an object. + */ + function _fetch_with_format( $provider_url_with_args, $format ) { + $provider_url_with_args = add_query_arg( 'format', $format, $provider_url_with_args ); + $response = wp_safe_remote_get( $provider_url_with_args ); + if ( 501 == wp_remote_retrieve_response_code( $response ) ) + return new WP_Error( 'not-implemented' ); + if ( ! $body = wp_remote_retrieve_body( $response ) ) + return false; + $parse_method = "_parse_$format"; + return $this->$parse_method( $body ); + } + + /** + * Parses a json response body. + * + * @since 3.0.0 + * @access private + */ + function _parse_json( $response_body ) { + return ( ( $data = json_decode( trim( $response_body ) ) ) && is_object( $data ) ) ? $data : false; + } + + /** + * Parses an XML response body. + * + * @since 3.0.0 + * @access private + */ + function _parse_xml( $response_body ) { + if ( ! function_exists( 'libxml_disable_entity_loader' ) ) + return false; + + $loader = libxml_disable_entity_loader( true ); + $errors = libxml_use_internal_errors( true ); + + $return = $this->_parse_xml_body( $response_body ); + + libxml_use_internal_errors( $errors ); + libxml_disable_entity_loader( $loader ); + + return $return; + } + + /** + * Helper function for parsing an XML response body. + * + * @since 3.6.0 + * @access private + */ + private function _parse_xml_body( $response_body ) { + if ( ! function_exists( 'simplexml_import_dom' ) || ! class_exists( 'DOMDocument' ) ) + return false; + + $dom = new DOMDocument; + $success = $dom->loadXML( $response_body ); + if ( ! $success ) + return false; + + if ( isset( $dom->doctype ) ) + return false; + + foreach ( $dom->childNodes as $child ) { + if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) + return false; + } + + $xml = simplexml_import_dom( $dom ); + if ( ! $xml ) + return false; + + $return = new stdClass; + foreach ( $xml as $key => $value ) { + $return->$key = (string) $value; + } + + return $return; + } + + /** + * Converts a data object from {@link WP_oEmbed::fetch()} and returns the HTML. + * + * @param object $data A data object result from an oEmbed provider. + * @param string $url The URL to the content that is desired to be embedded. + * @return bool|string False on error, otherwise the HTML needed to embed. + */ + function data2html( $data, $url ) { + if ( ! is_object( $data ) || empty( $data->type ) ) + return false; + + $return = false; + + switch ( $data->type ) { + case 'photo': + if ( empty( $data->url ) || empty( $data->width ) || empty( $data->height ) ) + break; + if ( ! is_string( $data->url ) || ! is_numeric( $data->width ) || ! is_numeric( $data->height ) ) + break; + + $title = ! empty( $data->title ) && is_string( $data->title ) ? $data->title : ''; + $return = '<a href="' . esc_url( $url ) . '"><img src="' . esc_url( $data->url ) . '" alt="' . esc_attr($title) . '" width="' . esc_attr($data->width) . '" height="' . esc_attr($data->height) . '" /></a>'; + break; + + case 'video': + case 'rich': + if ( ! empty( $data->html ) && is_string( $data->html ) ) + $return = $data->html; + break; + + case 'link': + if ( ! empty( $data->title ) && is_string( $data->title ) ) + $return = '<a href="' . esc_url( $url ) . '">' . esc_html( $data->title ) . '</a>'; + break; + + default: + $return = false; + } + + /** + * Filter the returned oEmbed HTML. + * + * Use this filter to add support for custom data types, or to filter the result. + * + * @since 2.9.0 + * + * @param string $return The returned oEmbed HTML. + * @param object $data A data object result from an oEmbed provider. + * @param string $url The URL of the content to be embedded. + */ + return apply_filters( 'oembed_dataparse', $return, $data, $url ); + } + + /** + * Strip any new lines from the HTML. + * + * @access private + * @param string $html Existing HTML. + * @param object $data Data object from WP_oEmbed::data2html() + * @param string $url The original URL passed to oEmbed. + * @return string Possibly modified $html + */ + function _strip_newlines( $html, $data, $url ) { + if ( false !== strpos( $html, "\n" ) ) + $html = str_replace( array( "\r\n", "\n" ), '', $html ); + + return $html; + } +} + +/** + * Returns the initialized {@link WP_oEmbed} object + * + * @since 2.9.0 + * @access private + * + * @see WP_oEmbed + * @uses WP_oEmbed + * + * @return WP_oEmbed object. + */ +function _wp_oembed_get_object() { + static $wp_oembed; + + if ( is_null($wp_oembed) ) + $wp_oembed = new WP_oEmbed(); + + return $wp_oembed; +} diff --git a/sources/wp-includes/class-phpass.php b/sources/wp-includes/class-phpass.php new file mode 100644 index 0000000..2fed5d7 --- /dev/null +++ b/sources/wp-includes/class-phpass.php @@ -0,0 +1,260 @@ +<?php +/** + * Portable PHP password hashing framework. + * @package phpass + * @since 2.5 + * @version 0.3 / WordPress + * @link http://www.openwall.com/phpass/ + */ + +# +# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in +# the public domain. Revised in subsequent years, still public domain. +# +# There's absolutely no warranty. +# +# Please be sure to update the Version line if you edit this file in any way. +# It is suggested that you leave the main version number intact, but indicate +# your project name (after the slash) and add your own revision information. +# +# Please do not change the "private" password hashing method implemented in +# here, thereby making your hashes incompatible. However, if you must, please +# change the hash type identifier (the "$P$") to something different. +# +# Obviously, since this code is in the public domain, the above are not +# requirements (there can be none), but merely suggestions. +# + +/** + * Portable PHP password hashing framework. + * + * @package phpass + * @version 0.3 / WordPress + * @link http://www.openwall.com/phpass/ + * @since 2.5 + */ +class PasswordHash { + var $itoa64; + var $iteration_count_log2; + var $portable_hashes; + var $random_state; + + function PasswordHash($iteration_count_log2, $portable_hashes) + { + $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) + $iteration_count_log2 = 8; + $this->iteration_count_log2 = $iteration_count_log2; + + $this->portable_hashes = $portable_hashes; + + $this->random_state = microtime() . uniqid(rand(), TRUE); // removed getmypid() for compatibility reasons + } + + function get_random_bytes($count) + { + $output = ''; + if ( @is_readable('/dev/urandom') && + ($fh = @fopen('/dev/urandom', 'rb'))) { + $output = fread($fh, $count); + fclose($fh); + } + + if (strlen($output) < $count) { + $output = ''; + for ($i = 0; $i < $count; $i += 16) { + $this->random_state = + md5(microtime() . $this->random_state); + $output .= + pack('H*', md5($this->random_state)); + } + $output = substr($output, 0, $count); + } + + return $output; + } + + function encode64($input, $count) + { + $output = ''; + $i = 0; + do { + $value = ord($input[$i++]); + $output .= $this->itoa64[$value & 0x3f]; + if ($i < $count) + $value |= ord($input[$i]) << 8; + $output .= $this->itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) + break; + if ($i < $count) + $value |= ord($input[$i]) << 16; + $output .= $this->itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) + break; + $output .= $this->itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return $output; + } + + function gensalt_private($input) + { + $output = '$P$'; + $output .= $this->itoa64[min($this->iteration_count_log2 + + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; + $output .= $this->encode64($input, 6); + + return $output; + } + + function crypt_private($password, $setting) + { + $output = '*0'; + if (substr($setting, 0, 2) == $output) + $output = '*1'; + + $id = substr($setting, 0, 3); + # We use "$P$", phpBB3 uses "$H$" for the same thing + if ($id != '$P$' && $id != '$H$') + return $output; + + $count_log2 = strpos($this->itoa64, $setting[3]); + if ($count_log2 < 7 || $count_log2 > 30) + return $output; + + $count = 1 << $count_log2; + + $salt = substr($setting, 4, 8); + if (strlen($salt) != 8) + return $output; + + # We're kind of forced to use MD5 here since it's the only + # cryptographic primitive available in all versions of PHP + # currently in use. To implement our own low-level crypto + # in PHP would result in much worse performance and + # consequently in lower iteration counts and hashes that are + # quicker to crack (by non-PHP code). + if (PHP_VERSION >= '5') { + $hash = md5($salt . $password, TRUE); + do { + $hash = md5($hash . $password, TRUE); + } while (--$count); + } else { + $hash = pack('H*', md5($salt . $password)); + do { + $hash = pack('H*', md5($hash . $password)); + } while (--$count); + } + + $output = substr($setting, 0, 12); + $output .= $this->encode64($hash, 16); + + return $output; + } + + function gensalt_extended($input) + { + $count_log2 = min($this->iteration_count_log2 + 8, 24); + # This should be odd to not reveal weak DES keys, and the + # maximum valid value is (2**24 - 1) which is odd anyway. + $count = (1 << $count_log2) - 1; + + $output = '_'; + $output .= $this->itoa64[$count & 0x3f]; + $output .= $this->itoa64[($count >> 6) & 0x3f]; + $output .= $this->itoa64[($count >> 12) & 0x3f]; + $output .= $this->itoa64[($count >> 18) & 0x3f]; + + $output .= $this->encode64($input, 3); + + return $output; + } + + function gensalt_blowfish($input) + { + # This one needs to use a different order of characters and a + # different encoding scheme from the one in encode64() above. + # We care because the last character in our encoded string will + # only represent 2 bits. While two known implementations of + # bcrypt will happily accept and correct a salt string which + # has the 4 unused bits set to non-zero, we do not want to take + # chances and we also do not want to waste an additional byte + # of entropy. + $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + $output = '$2a$'; + $output .= chr(ord('0') + $this->iteration_count_log2 / 10); + $output .= chr(ord('0') + $this->iteration_count_log2 % 10); + $output .= '$'; + + $i = 0; + do { + $c1 = ord($input[$i++]); + $output .= $itoa64[$c1 >> 2]; + $c1 = ($c1 & 0x03) << 4; + if ($i >= 16) { + $output .= $itoa64[$c1]; + break; + } + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 4; + $output .= $itoa64[$c1]; + $c1 = ($c2 & 0x0f) << 2; + + $c2 = ord($input[$i++]); + $c1 |= $c2 >> 6; + $output .= $itoa64[$c1]; + $output .= $itoa64[$c2 & 0x3f]; + } while (1); + + return $output; + } + + function HashPassword($password) + { + $random = ''; + + if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) { + $random = $this->get_random_bytes(16); + $hash = + crypt($password, $this->gensalt_blowfish($random)); + if (strlen($hash) == 60) + return $hash; + } + + if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) { + if (strlen($random) < 3) + $random = $this->get_random_bytes(3); + $hash = + crypt($password, $this->gensalt_extended($random)); + if (strlen($hash) == 20) + return $hash; + } + + if (strlen($random) < 6) + $random = $this->get_random_bytes(6); + $hash = + $this->crypt_private($password, + $this->gensalt_private($random)); + if (strlen($hash) == 34) + return $hash; + + # Returning '*' on error is safe here, but would _not_ be safe + # in a crypt(3)-like function used _both_ for generating new + # hashes and for validating passwords against existing hashes. + return '*'; + } + + function CheckPassword($password, $stored_hash) + { + $hash = $this->crypt_private($password, $stored_hash); + if ($hash[0] == '*') + $hash = crypt($password, $stored_hash); + + return $hash === $stored_hash; + } +} + +?> diff --git a/sources/wp-includes/class-phpmailer.php b/sources/wp-includes/class-phpmailer.php new file mode 100644 index 0000000..238474e --- /dev/null +++ b/sources/wp-includes/class-phpmailer.php @@ -0,0 +1,2826 @@ +<?php +/*~ class.phpmailer.php +.---------------------------------------------------------------------------. +| Software: PHPMailer - PHP email class | +| Version: 5.2.4 | +| Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ | +| ------------------------------------------------------------------------- | +| Admin: Jim Jagielski (project admininistrator) | +| Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | +| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | +| : Jim Jagielski (jimjag) jimjag@gmail.com | +| Founder: Brent R. Matzelle (original founder) | +| Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. | +| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | +| Copyright (c) 2001-2003, Brent R. Matzelle | +| ------------------------------------------------------------------------- | +| License: Distributed under the Lesser General Public License (LGPL) | +| http://www.gnu.org/copyleft/lesser.html | +| This program is distributed in the hope that it will be useful - WITHOUT | +| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | +| FITNESS FOR A PARTICULAR PURPOSE. | +'---------------------------------------------------------------------------' +*/ + +/** + * PHPMailer - PHP email creation and transport class + * NOTE: Requires PHP version 5 or later + * @package PHPMailer + * @author Andy Prevost + * @author Marcus Bointon + * @author Jim Jagielski + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + */ + +if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n"); + +/** + * PHP email creation and transport class + * @package PHPMailer + */ +class PHPMailer { + + ///////////////////////////////////////////////// + // PROPERTIES, PUBLIC + ///////////////////////////////////////////////// + + /** + * Email priority (1 = High, 3 = Normal, 5 = low). + * @var int + */ + public $Priority = 3; + + /** + * Sets the CharSet of the message. + * @var string + */ + public $CharSet = 'iso-8859-1'; + + /** + * Sets the Content-type of the message. + * @var string + */ + public $ContentType = 'text/plain'; + + /** + * Sets the Encoding of the message. Options for this are + * "8bit", "7bit", "binary", "base64", and "quoted-printable". + * @var string + */ + public $Encoding = '8bit'; + + /** + * Holds the most recent mailer error message. + * @var string + */ + public $ErrorInfo = ''; + + /** + * Sets the From email address for the message. + * @var string + */ + public $From = 'root@localhost'; + + /** + * Sets the From name of the message. + * @var string + */ + public $FromName = 'Root User'; + + /** + * Sets the Sender email (Return-Path) of the message. If not empty, + * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * @var string + */ + public $Sender = ''; + + /** + * Sets the Return-Path of the message. If empty, it will + * be set to either From or Sender. + * @var string + */ + public $ReturnPath = ''; + + /** + * Sets the Subject of the message. + * @var string + */ + public $Subject = ''; + + /** + * Sets the Body of the message. This can be either an HTML or text body. + * If HTML then run IsHTML(true). + * @var string + */ + public $Body = ''; + + /** + * Sets the text-only body of the message. This automatically sets the + * email to multipart/alternative. This body can be read by mail + * clients that do not have HTML email capability such as mutt. Clients + * that can read HTML will view the normal Body. + * @var string + */ + public $AltBody = ''; + + /** + * Stores the complete compiled MIME message body. + * @var string + * @access protected + */ + protected $MIMEBody = ''; + + /** + * Stores the complete compiled MIME message headers. + * @var string + * @access protected + */ + protected $MIMEHeader = ''; + + /** + * Stores the extra header list which CreateHeader() doesn't fold in + * @var string + * @access protected + */ + protected $mailHeader = ''; + + /** + * Sets word wrapping on the body of the message to a given number of + * characters. + * @var int + */ + public $WordWrap = 0; + + /** + * Method to send mail: ("mail", "sendmail", or "smtp"). + * @var string + */ + public $Mailer = 'mail'; + + /** + * Sets the path of the sendmail program. + * @var string + */ + public $Sendmail = '/usr/sbin/sendmail'; + + /** + * Determine if mail() uses a fully sendmail compatible MTA that + * supports sendmail's "-oi -f" options + * @var boolean + */ + public $UseSendmailOptions = true; + + /** + * Path to PHPMailer plugins. Useful if the SMTP class + * is in a different directory than the PHP include path. + * @var string + */ + public $PluginDir = ''; + + /** + * Sets the email address that a reading confirmation will be sent. + * @var string + */ + public $ConfirmReadingTo = ''; + + /** + * Sets the hostname to use in Message-Id and Received headers + * and as default HELO string. If empty, the value returned + * by SERVER_NAME is used or 'localhost.localdomain'. + * @var string + */ + public $Hostname = ''; + + /** + * Sets the message ID to be used in the Message-Id header. + * If empty, a unique id will be generated. + * @var string + */ + public $MessageID = ''; + + /** + * Sets the message Date to be used in the Date header. + * If empty, the current date will be added. + * @var string + */ + public $MessageDate = ''; + + ///////////////////////////////////////////////// + // PROPERTIES FOR SMTP + ///////////////////////////////////////////////// + + /** + * Sets the SMTP hosts. + * + * All hosts must be separated by a + * semicolon. You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * Hosts will be tried in order. + * @var string + */ + public $Host = 'localhost'; + + /** + * Sets the default SMTP server port. + * @var int + */ + public $Port = 25; + + /** + * Sets the SMTP HELO of the message (Default is $Hostname). + * @var string + */ + public $Helo = ''; + + /** + * Sets connection prefix. Options are "", "ssl" or "tls" + * @var string + */ + public $SMTPSecure = ''; + + /** + * Sets SMTP authentication. Utilizes the Username and Password variables. + * @var bool + */ + public $SMTPAuth = false; + + /** + * Sets SMTP username. + * @var string + */ + public $Username = ''; + + /** + * Sets SMTP password. + * @var string + */ + public $Password = ''; + + /** + * Sets SMTP auth type. Options are LOGIN | PLAIN | NTLM (default LOGIN) + * @var string + */ + public $AuthType = ''; + + /** + * Sets SMTP realm. + * @var string + */ + public $Realm = ''; + + /** + * Sets SMTP workstation. + * @var string + */ + public $Workstation = ''; + + /** + * Sets the SMTP server timeout in seconds. + * This function will not work with the win32 version. + * @var int + */ + public $Timeout = 10; + + /** + * Sets SMTP class debugging on or off. + * @var bool + */ + public $SMTPDebug = false; + + /** + * Sets the function/method to use for debugging output. + * Right now we only honor "echo" or "error_log" + * @var string + */ + public $Debugoutput = "echo"; + + /** + * Prevents the SMTP connection from being closed after each mail + * sending. If this is set to true then to close the connection + * requires an explicit call to SmtpClose(). + * @var bool + */ + public $SMTPKeepAlive = false; + + /** + * Provides the ability to have the TO field process individual + * emails, instead of sending to entire TO addresses + * @var bool + */ + public $SingleTo = false; + + /** + * If SingleTo is true, this provides the array to hold the email addresses + * @var bool + */ + public $SingleToArray = array(); + + /** + * Provides the ability to change the generic line ending + * NOTE: The default remains '\n'. We force CRLF where we KNOW + * it must be used via self::CRLF + * @var string + */ + public $LE = "\n"; + + /** + * Used with DKIM Signing + * required parameter if DKIM is enabled + * + * domain selector example domainkey + * @var string + */ + public $DKIM_selector = ''; + + /** + * Used with DKIM Signing + * required if DKIM is enabled, in format of email address 'you@yourdomain.com' typically used as the source of the email + * @var string + */ + public $DKIM_identity = ''; + + /** + * Used with DKIM Signing + * optional parameter if your private key requires a passphras + * @var string + */ + public $DKIM_passphrase = ''; + + /** + * Used with DKIM Singing + * required if DKIM is enabled, in format of email address 'domain.com' + * @var string + */ + public $DKIM_domain = ''; + + /** + * Used with DKIM Signing + * required if DKIM is enabled, path to private key file + * @var string + */ + public $DKIM_private = ''; + + /** + * Callback Action function name. + * The function that handles the result of the send email action. + * It is called out by Send() for each email sent. + * + * Value can be: + * - 'function_name' for function names + * - 'Class::Method' for static method calls + * - array($object, 'Method') for calling methods on $object + * See http://php.net/is_callable manual page for more details. + * + * Parameters: + * bool $result result of the send action + * string $to email address of the recipient + * string $cc cc email addresses + * string $bcc bcc email addresses + * string $subject the subject + * string $body the email body + * string $from email address of sender + * @var string + */ + public $action_function = ''; //'callbackAction'; + + /** + * Sets the PHPMailer Version number + * @var string + */ + public $Version = '5.2.4'; + + /** + * What to use in the X-Mailer header + * @var string NULL for default, whitespace for None, or actual string to use + */ + public $XMailer = ''; + + ///////////////////////////////////////////////// + // PROPERTIES, PRIVATE AND PROTECTED + ///////////////////////////////////////////////// + + /** + * @var SMTP An instance of the SMTP sender class + * @access protected + */ + protected $smtp = null; + /** + * @var array An array of 'to' addresses + * @access protected + */ + protected $to = array(); + /** + * @var array An array of 'cc' addresses + * @access protected + */ + protected $cc = array(); + /** + * @var array An array of 'bcc' addresses + * @access protected + */ + protected $bcc = array(); + /** + * @var array An array of reply-to name and address + * @access protected + */ + protected $ReplyTo = array(); + /** + * @var array An array of all kinds of addresses: to, cc, bcc, replyto + * @access protected + */ + protected $all_recipients = array(); + /** + * @var array An array of attachments + * @access protected + */ + protected $attachment = array(); + /** + * @var array An array of custom headers + * @access protected + */ + protected $CustomHeader = array(); + /** + * @var string The message's MIME type + * @access protected + */ + protected $message_type = ''; + /** + * @var array An array of MIME boundary strings + * @access protected + */ + protected $boundary = array(); + /** + * @var array An array of available languages + * @access protected + */ + protected $language = array(); + /** + * @var integer The number of errors encountered + * @access protected + */ + protected $error_count = 0; + /** + * @var string The filename of a DKIM certificate file + * @access protected + */ + protected $sign_cert_file = ''; + /** + * @var string The filename of a DKIM key file + * @access protected + */ + protected $sign_key_file = ''; + /** + * @var string The password of a DKIM key + * @access protected + */ + protected $sign_key_pass = ''; + /** + * @var boolean Whether to throw exceptions for errors + * @access protected + */ + protected $exceptions = false; + + ///////////////////////////////////////////////// + // CONSTANTS + ///////////////////////////////////////////////// + + const STOP_MESSAGE = 0; // message only, continue processing + const STOP_CONTINUE = 1; // message?, likely ok to continue processing + const STOP_CRITICAL = 2; // message, plus full stop, critical error reached + const CRLF = "\r\n"; // SMTP RFC specified EOL + + ///////////////////////////////////////////////// + // METHODS, VARIABLES + ///////////////////////////////////////////////// + + /** + * Calls actual mail() function, but in a safe_mode aware fashion + * Also, unless sendmail_path points to sendmail (or something that + * claims to be sendmail), don't pass params (not a perfect fix, + * but it will do) + * @param string $to To + * @param string $subject Subject + * @param string $body Message Body + * @param string $header Additional Header(s) + * @param string $params Params + * @access private + * @return bool + */ + private function mail_passthru($to, $subject, $body, $header, $params) { + if ( ini_get('safe_mode') || !($this->UseSendmailOptions) ) { + $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header); + } else { + $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header, $params); + } + return $rt; + } + + /** + * Outputs debugging info via user-defined method + * @param string $str + */ + private function edebug($str) { + if ($this->Debugoutput == "error_log") { + error_log($str); + } else { + echo $str; + } + } + + /** + * Constructor + * @param boolean $exceptions Should we throw external exceptions? + */ + public function __construct($exceptions = false) { + $this->exceptions = ($exceptions == true); + } + + /** + * Sets message type to HTML. + * @param bool $ishtml + * @return void + */ + public function IsHTML($ishtml = true) { + if ($ishtml) { + $this->ContentType = 'text/html'; + } else { + $this->ContentType = 'text/plain'; + } + } + + /** + * Sets Mailer to send message using SMTP. + * @return void + */ + public function IsSMTP() { + $this->Mailer = 'smtp'; + } + + /** + * Sets Mailer to send message using PHP mail() function. + * @return void + */ + public function IsMail() { + $this->Mailer = 'mail'; + } + + /** + * Sets Mailer to send message using the $Sendmail program. + * @return void + */ + public function IsSendmail() { + if (!stristr(ini_get('sendmail_path'), 'sendmail')) { + $this->Sendmail = '/var/qmail/bin/sendmail'; + } + $this->Mailer = 'sendmail'; + } + + /** + * Sets Mailer to send message using the qmail MTA. + * @return void + */ + public function IsQmail() { + if (stristr(ini_get('sendmail_path'), 'qmail')) { + $this->Sendmail = '/var/qmail/bin/sendmail'; + } + $this->Mailer = 'sendmail'; + } + + ///////////////////////////////////////////////// + // METHODS, RECIPIENTS + ///////////////////////////////////////////////// + + /** + * Adds a "To" address. + * @param string $address + * @param string $name + * @return boolean true on success, false if address already used + */ + public function AddAddress($address, $name = '') { + return $this->AddAnAddress('to', $address, $name); + } + + /** + * Adds a "Cc" address. + * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address + * @param string $name + * @return boolean true on success, false if address already used + */ + public function AddCC($address, $name = '') { + return $this->AddAnAddress('cc', $address, $name); + } + + /** + * Adds a "Bcc" address. + * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address + * @param string $name + * @return boolean true on success, false if address already used + */ + public function AddBCC($address, $name = '') { + return $this->AddAnAddress('bcc', $address, $name); + } + + /** + * Adds a "Reply-to" address. + * @param string $address + * @param string $name + * @return boolean + */ + public function AddReplyTo($address, $name = '') { + return $this->AddAnAddress('Reply-To', $address, $name); + } + + /** + * Adds an address to one of the recipient arrays + * Addresses that have been added already return false, but do not throw exceptions + * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' + * @param string $address The email address to send to + * @param string $name + * @throws phpmailerException + * @return boolean true on success, false if address already used or invalid in some way + * @access protected + */ + protected function AddAnAddress($kind, $address, $name = '') { + if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) { + $this->SetError($this->Lang('Invalid recipient array').': '.$kind); + if ($this->exceptions) { + throw new phpmailerException('Invalid recipient array: ' . $kind); + } + if ($this->SMTPDebug) { + $this->edebug($this->Lang('Invalid recipient array').': '.$kind); + } + return false; + } + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + if (!$this->ValidateAddress($address)) { + $this->SetError($this->Lang('invalid_address').': '. $address); + if ($this->exceptions) { + throw new phpmailerException($this->Lang('invalid_address').': '.$address); + } + if ($this->SMTPDebug) { + $this->edebug($this->Lang('invalid_address').': '.$address); + } + return false; + } + if ($kind != 'Reply-To') { + if (!isset($this->all_recipients[strtolower($address)])) { + array_push($this->$kind, array($address, $name)); + $this->all_recipients[strtolower($address)] = true; + return true; + } + } else { + if (!array_key_exists(strtolower($address), $this->ReplyTo)) { + $this->ReplyTo[strtolower($address)] = array($address, $name); + return true; + } + } + return false; +} + +/** + * Set the From and FromName properties + * @param string $address + * @param string $name + * @param int $auto Also set Reply-To and Sender + * @throws phpmailerException + * @return boolean + */ + public function SetFrom($address, $name = '', $auto = 1) { + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + if (!$this->ValidateAddress($address)) { + $this->SetError($this->Lang('invalid_address').': '. $address); + if ($this->exceptions) { + throw new phpmailerException($this->Lang('invalid_address').': '.$address); + } + if ($this->SMTPDebug) { + $this->edebug($this->Lang('invalid_address').': '.$address); + } + return false; + } + $this->From = $address; + $this->FromName = $name; + if ($auto) { + if (empty($this->ReplyTo)) { + $this->AddAnAddress('Reply-To', $address, $name); + } + if (empty($this->Sender)) { + $this->Sender = $address; + } + } + return true; + } + + /** + * Check that a string looks roughly like an email address should + * Static so it can be used without instantiation, public so people can overload + * Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is + * based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to + * not allow a@b type valid addresses :( + * Some Versions of PHP break on the regex though, likely due to PCRE, so use + * the older validation method for those users. (http://php.net/manual/en/pcre.installation.php) + * @link http://squiloople.com/2009/12/20/email-address-validation/ + * @copyright regex Copyright Michael Rushton 2009-10 | http://squiloople.com/ | Feel free to use and redistribute this code. But please keep this copyright notice. + * @param string $address The email address to check + * @return boolean + * @static + * @access public + */ + public static function ValidateAddress($address) { + if ((defined('PCRE_VERSION')) && (version_compare(PCRE_VERSION, '8.0') >= 0)) { + return preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[ ])+|(?>[ ]*\x0D\x0A)?[ ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){7,})((?6)(?>:(?6)){0,5})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){5,})(?8)?::(?>((?6)(?>:(?6)){0,3}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address); + } elseif (function_exists('filter_var')) { //Introduced in PHP 5.2 + if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) { + return false; + } else { + return true; + } + } else { + return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address); + } + } + + ///////////////////////////////////////////////// + // METHODS, MAIL SENDING + ///////////////////////////////////////////////// + + /** + * Creates message and assigns Mailer. If the message is + * not sent successfully then it returns false. Use the ErrorInfo + * variable to view description of the error. + * @throws phpmailerException + * @return bool + */ + public function Send() { + try { + if(!$this->PreSend()) return false; + return $this->PostSend(); + } catch (phpmailerException $e) { + $this->mailHeader = ''; + $this->SetError($e->getMessage()); + if ($this->exceptions) { + throw $e; + } + return false; + } + } + + /** + * Prep mail by constructing all message entities + * @throws phpmailerException + * @return bool + */ + public function PreSend() { + try { + $this->mailHeader = ""; + if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { + throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL); + } + + // Set whether the message is multipart/alternative + if(!empty($this->AltBody)) { + $this->ContentType = 'multipart/alternative'; + } + + $this->error_count = 0; // reset errors + $this->SetMessageType(); + //Refuse to send an empty message + if (empty($this->Body)) { + throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL); + } + + $this->MIMEHeader = $this->CreateHeader(); + $this->MIMEBody = $this->CreateBody(); + + // To capture the complete message when using mail(), create + // an extra header list which CreateHeader() doesn't fold in + if ($this->Mailer == 'mail') { + if (count($this->to) > 0) { + $this->mailHeader .= $this->AddrAppend("To", $this->to); + } else { + $this->mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;"); + } + $this->mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject)))); + // if(count($this->cc) > 0) { + // $this->mailHeader .= $this->AddrAppend("Cc", $this->cc); + // } + } + + // digitally sign with DKIM if enabled + if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) { + $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody); + $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader; + } + + return true; + + } catch (phpmailerException $e) { + $this->SetError($e->getMessage()); + if ($this->exceptions) { + throw $e; + } + return false; + } + } + + /** + * Actual Email transport function + * Send the email via the selected mechanism + * @throws phpmailerException + * @return bool + */ + public function PostSend() { + try { + // Choose the mailer and send through it + switch($this->Mailer) { + case 'sendmail': + return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody); + case 'smtp': + return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody); + case 'mail': + return $this->MailSend($this->MIMEHeader, $this->MIMEBody); + default: + return $this->MailSend($this->MIMEHeader, $this->MIMEBody); + } + } catch (phpmailerException $e) { + $this->SetError($e->getMessage()); + if ($this->exceptions) { + throw $e; + } + if ($this->SMTPDebug) { + $this->edebug($e->getMessage()."\n"); + } + } + return false; + } + + /** + * Sends mail using the $Sendmail program. + * @param string $header The message headers + * @param string $body The message body + * @throws phpmailerException + * @access protected + * @return bool + */ + protected function SendmailSend($header, $body) { + if ($this->Sender != '') { + $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } else { + $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); + } + if ($this->SingleTo === true) { + foreach ($this->SingleToArray as $val) { + if(!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, "To: " . $val . "\n"); + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + // implement call back function if it exists + $isSent = ($result == 0) ? 1 : 0; + $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body); + if($result != 0) { + throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + } else { + if(!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + // implement call back function if it exists + $isSent = ($result == 0) ? 1 : 0; + $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body); + if($result != 0) { + throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + return true; + } + + /** + * Sends mail using the PHP mail() function. + * @param string $header The message headers + * @param string $body The message body + * @throws phpmailerException + * @access protected + * @return bool + */ + protected function MailSend($header, $body) { + $toArr = array(); + foreach($this->to as $t) { + $toArr[] = $this->AddrFormat($t); + } + $to = implode(', ', $toArr); + + if (empty($this->Sender)) { + $params = " "; + } else { + $params = sprintf("-f%s", $this->Sender); + } + if ($this->Sender != '' and !ini_get('safe_mode')) { + $old_from = ini_get('sendmail_from'); + ini_set('sendmail_from', $this->Sender); + } + $rt = false; + if ($this->SingleTo === true && count($toArr) > 1) { + foreach ($toArr as $val) { + $rt = $this->mail_passthru($val, $this->Subject, $body, $header, $params); + // implement call back function if it exists + $isSent = ($rt == 1) ? 1 : 0; + $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body); + } + } else { + $rt = $this->mail_passthru($to, $this->Subject, $body, $header, $params); + // implement call back function if it exists + $isSent = ($rt == 1) ? 1 : 0; + $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body); + } + if (isset($old_from)) { + ini_set('sendmail_from', $old_from); + } + if(!$rt) { + throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL); + } + return true; + } + + /** + * Sends mail via SMTP using PhpSMTP + * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. + * @param string $header The message headers + * @param string $body The message body + * @throws phpmailerException + * @uses SMTP + * @access protected + * @return bool + */ + protected function SmtpSend($header, $body) { + require_once $this->PluginDir . 'class-smtp.php'; + $bad_rcpt = array(); + + if(!$this->SmtpConnect()) { + throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL); + } + $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; + if(!$this->smtp->Mail($smtp_from)) { + $this->SetError($this->Lang('from_failed') . $smtp_from . " : " . implode(",",$this->smtp->getError())) ; + throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); + } + + // Attempt to send attach all recipients + foreach($this->to as $to) { + if (!$this->smtp->Recipient($to[0])) { + $bad_rcpt[] = $to[0]; + // implement call back function if it exists + $isSent = 0; + $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body); + } else { + // implement call back function if it exists + $isSent = 1; + $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body); + } + } + foreach($this->cc as $cc) { + if (!$this->smtp->Recipient($cc[0])) { + $bad_rcpt[] = $cc[0]; + // implement call back function if it exists + $isSent = 0; + $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body); + } else { + // implement call back function if it exists + $isSent = 1; + $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body); + } + } + foreach($this->bcc as $bcc) { + if (!$this->smtp->Recipient($bcc[0])) { + $bad_rcpt[] = $bcc[0]; + // implement call back function if it exists + $isSent = 0; + $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body); + } else { + // implement call back function if it exists + $isSent = 1; + $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body); + } + } + + + if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses + $badaddresses = implode(', ', $bad_rcpt); + throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses); + } + if(!$this->smtp->Data($header . $body)) { + throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL); + } + if($this->SMTPKeepAlive == true) { + $this->smtp->Reset(); + } else { + $this->smtp->Quit(); + $this->smtp->Close(); + } + return true; + } + + /** + * Initiates a connection to an SMTP server. + * Returns false if the operation failed. + * @uses SMTP + * @access public + * @throws phpmailerException + * @return bool + */ + public function SmtpConnect() { + if(is_null($this->smtp)) { + $this->smtp = new SMTP; + } + + $this->smtp->Timeout = $this->Timeout; + $this->smtp->do_debug = $this->SMTPDebug; + $hosts = explode(';', $this->Host); + $index = 0; + $connection = $this->smtp->Connected(); + + // Retry while there is no connection + try { + while($index < count($hosts) && !$connection) { + $hostinfo = array(); + if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { + $host = $hostinfo[1]; + $port = $hostinfo[2]; + } else { + $host = $hosts[$index]; + $port = $this->Port; + } + + $tls = ($this->SMTPSecure == 'tls'); + $ssl = ($this->SMTPSecure == 'ssl'); + + if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { + + $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); + $this->smtp->Hello($hello); + + if ($tls) { + if (!$this->smtp->StartTLS()) { + throw new phpmailerException($this->Lang('connect_host')); + } + + //We must resend HELO after tls negotiation + $this->smtp->Hello($hello); + } + + $connection = true; + if ($this->SMTPAuth) { + if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, + $this->Realm, $this->Workstation)) { + throw new phpmailerException($this->Lang('authenticate')); + } + } + } + $index++; + if (!$connection) { + throw new phpmailerException($this->Lang('connect_host')); + } + } + } catch (phpmailerException $e) { + $this->smtp->Reset(); + if ($this->exceptions) { + throw $e; + } + } + return true; + } + + /** + * Closes the active SMTP session if one exists. + * @return void + */ + public function SmtpClose() { + if ($this->smtp !== null) { + if($this->smtp->Connected()) { + $this->smtp->Quit(); + $this->smtp->Close(); + } + } + } + + /** + * Sets the language for all class error messages. + * Returns false if it cannot load the language file. The default language is English. + * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") + * @param string $lang_path Path to the language file directory + * @return bool + * @access public + */ + function SetLanguage($langcode = 'en', $lang_path = 'language/') { + //Define full set of translatable strings + $PHPMAILER_LANG = array( + 'authenticate' => 'SMTP Error: Could not authenticate.', + 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', + 'data_not_accepted' => 'SMTP Error: Data not accepted.', + 'empty_message' => 'Message body empty', + 'encoding' => 'Unknown encoding: ', + 'execute' => 'Could not execute: ', + 'file_access' => 'Could not access file: ', + 'file_open' => 'File Error: Could not open file: ', + 'from_failed' => 'The following From address failed: ', + 'instantiate' => 'Could not instantiate mail function.', + 'invalid_address' => 'Invalid address', + 'mailer_not_supported' => ' mailer is not supported.', + 'provide_address' => 'You must provide at least one recipient email address.', + 'recipients_failed' => 'SMTP Error: The following recipients failed: ', + 'signing' => 'Signing Error: ', + 'smtp_connect_failed' => 'SMTP Connect() failed.', + 'smtp_error' => 'SMTP server error: ', + 'variable_set' => 'Cannot set or reset variable: ' + ); + //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"! + $l = true; + if ($langcode != 'en') { //There is no English translation file + $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php'; + } + $this->language = $PHPMAILER_LANG; + return ($l == true); //Returns false if language not found + } + + /** + * Return the current array of language strings + * @return array + */ + public function GetTranslations() { + return $this->language; + } + + ///////////////////////////////////////////////// + // METHODS, MESSAGE CREATION + ///////////////////////////////////////////////// + + /** + * Creates recipient headers. + * @access public + * @param string $type + * @param array $addr + * @return string + */ + public function AddrAppend($type, $addr) { + $addr_str = $type . ': '; + $addresses = array(); + foreach ($addr as $a) { + $addresses[] = $this->AddrFormat($a); + } + $addr_str .= implode(', ', $addresses); + $addr_str .= $this->LE; + + return $addr_str; + } + + /** + * Formats an address correctly. + * @access public + * @param string $addr + * @return string + */ + public function AddrFormat($addr) { + if (empty($addr[1])) { + return $this->SecureHeader($addr[0]); + } else { + return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; + } + } + + /** + * Wraps message for use with mailers that do not + * automatically perform wrapping and for quoted-printable. + * Original written by philippe. + * @param string $message The message to wrap + * @param integer $length The line length to wrap to + * @param boolean $qp_mode Whether to run in Quoted-Printable mode + * @access public + * @return string + */ + public function WrapText($message, $length, $qp_mode = false) { + $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; + // If utf-8 encoding is used, we will need to make sure we don't + // split multibyte characters when we wrap + $is_utf8 = (strtolower($this->CharSet) == "utf-8"); + $lelen = strlen($this->LE); + $crlflen = strlen(self::CRLF); + + $message = $this->FixEOL($message); + if (substr($message, -$lelen) == $this->LE) { + $message = substr($message, 0, -$lelen); + } + + $line = explode($this->LE, $message); // Magic. We know FixEOL uses $LE + $message = ''; + for ($i = 0 ;$i < count($line); $i++) { + $line_part = explode(' ', $line[$i]); + $buf = ''; + for ($e = 0; $e<count($line_part); $e++) { + $word = $line_part[$e]; + if ($qp_mode and (strlen($word) > $length)) { + $space_left = $length - strlen($buf) - $crlflen; + if ($e != 0) { + if ($space_left > 20) { + $len = $space_left; + if ($is_utf8) { + $len = $this->UTF8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == "=") { + $len--; + } elseif (substr($word, $len - 2, 1) == "=") { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + $buf .= ' ' . $part; + $message .= $buf . sprintf("=%s", self::CRLF); + } else { + $message .= $buf . $soft_break; + } + $buf = ''; + } + while (strlen($word) > 0) { + $len = $length; + if ($is_utf8) { + $len = $this->UTF8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == "=") { + $len--; + } elseif (substr($word, $len - 2, 1) == "=") { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + + if (strlen($word) > 0) { + $message .= $part . sprintf("=%s", self::CRLF); + } else { + $buf = $part; + } + } + } else { + $buf_o = $buf; + $buf .= ($e == 0) ? $word : (' ' . $word); + + if (strlen($buf) > $length and $buf_o != '') { + $message .= $buf_o . $soft_break; + $buf = $word; + } + } + } + $message .= $buf . self::CRLF; + } + + return $message; + } + + /** + * Finds last character boundary prior to maxLength in a utf-8 + * quoted (printable) encoded string. + * Original written by Colin Brown. + * @access public + * @param string $encodedText utf-8 QP text + * @param int $maxLength find last character boundary prior to this length + * @return int + */ + public function UTF8CharBoundary($encodedText, $maxLength) { + $foundSplitPos = false; + $lookBack = 3; + while (!$foundSplitPos) { + $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); + $encodedCharPos = strpos($lastChunk, "="); + if ($encodedCharPos !== false) { + // Found start of encoded character byte within $lookBack block. + // Check the encoded byte value (the 2 chars after the '=') + $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); + $dec = hexdec($hex); + if ($dec < 128) { // Single byte character. + // If the encoded char was found at pos 0, it will fit + // otherwise reduce maxLength to start of the encoded char + $maxLength = ($encodedCharPos == 0) ? $maxLength : + $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec >= 192) { // First byte of a multi byte character + // Reduce maxLength to split at start of character + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back + $lookBack += 3; + } + } else { + // No encoded character found + $foundSplitPos = true; + } + } + return $maxLength; + } + + + /** + * Set the body wrapping. + * @access public + * @return void + */ + public function SetWordWrap() { + if($this->WordWrap < 1) { + return; + } + + switch($this->message_type) { + case 'alt': + case 'alt_inline': + case 'alt_attach': + case 'alt_inline_attach': + $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); + break; + default: + $this->Body = $this->WrapText($this->Body, $this->WordWrap); + break; + } + } + + /** + * Assembles message header. + * @access public + * @return string The assembled header + */ + public function CreateHeader() { + $result = ''; + + // Set the boundaries + $uniq_id = md5(uniqid(time())); + $this->boundary[1] = 'b1_' . $uniq_id; + $this->boundary[2] = 'b2_' . $uniq_id; + $this->boundary[3] = 'b3_' . $uniq_id; + + if ($this->MessageDate == '') { + $result .= $this->HeaderLine('Date', self::RFCDate()); + } else { + $result .= $this->HeaderLine('Date', $this->MessageDate); + } + + if ($this->ReturnPath) { + $result .= $this->HeaderLine('Return-Path', trim($this->ReturnPath)); + } elseif ($this->Sender == '') { + $result .= $this->HeaderLine('Return-Path', trim($this->From)); + } else { + $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); + } + + // To be created automatically by mail() + if($this->Mailer != 'mail') { + if ($this->SingleTo === true) { + foreach($this->to as $t) { + $this->SingleToArray[] = $this->AddrFormat($t); + } + } else { + if(count($this->to) > 0) { + $result .= $this->AddrAppend('To', $this->to); + } elseif (count($this->cc) == 0) { + $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); + } + } + } + + $from = array(); + $from[0][0] = trim($this->From); + $from[0][1] = $this->FromName; + $result .= $this->AddrAppend('From', $from); + + // sendmail and mail() extract Cc from the header before sending + if(count($this->cc) > 0) { + $result .= $this->AddrAppend('Cc', $this->cc); + } + + // sendmail and mail() extract Bcc from the header before sending + if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { + $result .= $this->AddrAppend('Bcc', $this->bcc); + } + + if(count($this->ReplyTo) > 0) { + $result .= $this->AddrAppend('Reply-To', $this->ReplyTo); + } + + // mail() sets the subject itself + if($this->Mailer != 'mail') { + $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); + } + + if($this->MessageID != '') { + $result .= $this->HeaderLine('Message-ID', $this->MessageID); + } else { + $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); + } + $result .= $this->HeaderLine('X-Priority', $this->Priority); + if ($this->XMailer == '') { + $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)'); + } else { + $myXmailer = trim($this->XMailer); + if ($myXmailer) { + $result .= $this->HeaderLine('X-Mailer', $myXmailer); + } + } + + if($this->ConfirmReadingTo != '') { + $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); + } + + // Add custom headers + for($index = 0; $index < count($this->CustomHeader); $index++) { + $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); + } + if (!$this->sign_key_file) { + $result .= $this->HeaderLine('MIME-Version', '1.0'); + $result .= $this->GetMailMIME(); + } + + return $result; + } + + /** + * Returns the message MIME. + * @access public + * @return string + */ + public function GetMailMIME() { + $result = ''; + switch($this->message_type) { + case 'inline': + $result .= $this->HeaderLine('Content-Type', 'multipart/related;'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'attach': + case 'inline_attach': + case 'alt_attach': + case 'alt_inline_attach': + $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'alt': + case 'alt_inline': + $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + default: + // Catches case 'plain': and case '': + $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); + $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset='.$this->CharSet); + break; + } + + if($this->Mailer != 'mail') { + $result .= $this->LE; + } + + return $result; + } + + /** + * Returns the MIME message (headers and body). Only really valid post PreSend(). + * @access public + * @return string + */ + public function GetSentMIMEMessage() { + return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; + } + + + /** + * Assembles the message body. Returns an empty string on failure. + * @access public + * @throws phpmailerException + * @return string The assembled message body + */ + public function CreateBody() { + $body = ''; + + if ($this->sign_key_file) { + $body .= $this->GetMailMIME().$this->LE; + } + + $this->SetWordWrap(); + + switch($this->message_type) { + case 'inline': + $body .= $this->GetBoundary($this->boundary[1], '', '', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->AttachAll("inline", $this->boundary[1]); + break; + case 'attach': + $body .= $this->GetBoundary($this->boundary[1], '', '', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->AttachAll("attachment", $this->boundary[1]); + break; + case 'inline_attach': + $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->GetBoundary($this->boundary[2], '', '', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->AttachAll("inline", $this->boundary[2]); + $body .= $this->LE; + $body .= $this->AttachAll("attachment", $this->boundary[1]); + break; + case 'alt': + $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); + $body .= $this->EncodeString($this->AltBody, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->EndBoundary($this->boundary[1]); + break; + case 'alt_inline': + $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); + $body .= $this->EncodeString($this->AltBody, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->AttachAll("inline", $this->boundary[2]); + $body .= $this->LE; + $body .= $this->EndBoundary($this->boundary[1]); + break; + case 'alt_attach': + $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', ''); + $body .= $this->EncodeString($this->AltBody, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->EndBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->AttachAll("attachment", $this->boundary[1]); + break; + case 'alt_inline_attach': + $body .= $this->TextLine("--" . $this->boundary[1]); + $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', ''); + $body .= $this->EncodeString($this->AltBody, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->TextLine("--" . $this->boundary[2]); + $body .= $this->HeaderLine('Content-Type', 'multipart/related;'); + $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"'); + $body .= $this->LE; + $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', ''); + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->AttachAll("inline", $this->boundary[3]); + $body .= $this->LE; + $body .= $this->EndBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->AttachAll("attachment", $this->boundary[1]); + break; + default: + // catch case 'plain' and case '' + $body .= $this->EncodeString($this->Body, $this->Encoding); + break; + } + + if ($this->IsError()) { + $body = ''; + } elseif ($this->sign_key_file) { + try { + $file = tempnam('', 'mail'); + file_put_contents($file, $body); //TODO check this worked + $signed = tempnam("", "signed"); + if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) { + @unlink($file); + $body = file_get_contents($signed); + @unlink($signed); + } else { + @unlink($file); + @unlink($signed); + throw new phpmailerException($this->Lang("signing").openssl_error_string()); + } + } catch (phpmailerException $e) { + $body = ''; + if ($this->exceptions) { + throw $e; + } + } + } + + return $body; + } + + /** + * Returns the start of a message boundary. + * @access protected + * @param string $boundary + * @param string $charSet + * @param string $contentType + * @param string $encoding + * @return string + */ + protected function GetBoundary($boundary, $charSet, $contentType, $encoding) { + $result = ''; + if($charSet == '') { + $charSet = $this->CharSet; + } + if($contentType == '') { + $contentType = $this->ContentType; + } + if($encoding == '') { + $encoding = $this->Encoding; + } + $result .= $this->TextLine('--' . $boundary); + $result .= sprintf("Content-Type: %s; charset=%s", $contentType, $charSet); + $result .= $this->LE; + $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); + $result .= $this->LE; + + return $result; + } + + /** + * Returns the end of a message boundary. + * @access protected + * @param string $boundary + * @return string + */ + protected function EndBoundary($boundary) { + return $this->LE . '--' . $boundary . '--' . $this->LE; + } + + /** + * Sets the message type. + * @access protected + * @return void + */ + protected function SetMessageType() { + $this->message_type = array(); + if($this->AlternativeExists()) $this->message_type[] = "alt"; + if($this->InlineImageExists()) $this->message_type[] = "inline"; + if($this->AttachmentExists()) $this->message_type[] = "attach"; + $this->message_type = implode("_", $this->message_type); + if($this->message_type == "") $this->message_type = "plain"; + } + + /** + * Returns a formatted header line. + * @access public + * @param string $name + * @param string $value + * @return string + */ + public function HeaderLine($name, $value) { + return $name . ': ' . $value . $this->LE; + } + + /** + * Returns a formatted mail line. + * @access public + * @param string $value + * @return string + */ + public function TextLine($value) { + return $value . $this->LE; + } + + ///////////////////////////////////////////////// + // CLASS METHODS, ATTACHMENTS + ///////////////////////////////////////////////// + + /** + * Adds an attachment from a path on the filesystem. + * Returns false if the file could not be found + * or accessed. + * @param string $path Path to the attachment. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @throws phpmailerException + * @return bool + */ + public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { + try { + if ( !@is_file($path) ) { + throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE); + } + $filename = basename($path); + if ( $name == '' ) { + $name = $filename; + } + + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => 'attachment', + 7 => 0 + ); + + } catch (phpmailerException $e) { + $this->SetError($e->getMessage()); + if ($this->exceptions) { + throw $e; + } + if ($this->SMTPDebug) { + $this->edebug($e->getMessage()."\n"); + } + if ( $e->getCode() == self::STOP_CRITICAL ) { + return false; + } + } + return true; + } + + /** + * Return the current array of attachments + * @return array + */ + public function GetAttachments() { + return $this->attachment; + } + + /** + * Attaches all fs, string, and binary attachments to the message. + * Returns an empty string on failure. + * @access protected + * @param string $disposition_type + * @param string $boundary + * @return string + */ + protected function AttachAll($disposition_type, $boundary) { + // Return text of body + $mime = array(); + $cidUniq = array(); + $incl = array(); + + // Add all attachments + foreach ($this->attachment as $attachment) { + // CHECK IF IT IS A VALID DISPOSITION_FILTER + if($attachment[6] == $disposition_type) { + // Check for string attachment + $string = ''; + $path = ''; + $bString = $attachment[5]; + if ($bString) { + $string = $attachment[0]; + } else { + $path = $attachment[0]; + } + + $inclhash = md5(serialize($attachment)); + if (in_array($inclhash, $incl)) { continue; } + $incl[] = $inclhash; + $filename = $attachment[1]; + $name = $attachment[2]; + $encoding = $attachment[3]; + $type = $attachment[4]; + $disposition = $attachment[6]; + $cid = $attachment[7]; + if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; } + $cidUniq[$cid] = true; + + $mime[] = sprintf("--%s%s", $boundary, $this->LE); + $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); + $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); + + if($disposition == 'inline') { + $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); + } + + $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + + // Encode as string attachment + if($bString) { + $mime[] = $this->EncodeString($string, $encoding); + if($this->IsError()) { + return ''; + } + $mime[] = $this->LE.$this->LE; + } else { + $mime[] = $this->EncodeFile($path, $encoding); + if($this->IsError()) { + return ''; + } + $mime[] = $this->LE.$this->LE; + } + } + } + + $mime[] = sprintf("--%s--%s", $boundary, $this->LE); + + return implode("", $mime); + } + + /** + * Encodes attachment in requested format. + * Returns an empty string on failure. + * @param string $path The full path to the file + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @throws phpmailerException + * @see EncodeFile() + * @access protected + * @return string + */ + protected function EncodeFile($path, $encoding = 'base64') { + try { + if (!is_readable($path)) { + throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE); + } + // if (!function_exists('get_magic_quotes')) { + // function get_magic_quotes() { + // return false; + // } + // } + $magic_quotes = get_magic_quotes_runtime(); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime(0); + } else { + ini_set('magic_quotes_runtime', 0); + } + } + $file_buffer = file_get_contents($path); + $file_buffer = $this->EncodeString($file_buffer, $encoding); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime($magic_quotes); + } else { + ini_set('magic_quotes_runtime', $magic_quotes); + } + } + return $file_buffer; + } catch (Exception $e) { + $this->SetError($e->getMessage()); + return ''; + } + } + + /** + * Encodes string to requested format. + * Returns an empty string on failure. + * @param string $str The text to encode + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @access public + * @return string + */ + public function EncodeString($str, $encoding = 'base64') { + $encoded = ''; + switch(strtolower($encoding)) { + case 'base64': + $encoded = chunk_split(base64_encode($str), 76, $this->LE); + break; + case '7bit': + case '8bit': + $encoded = $this->FixEOL($str); + //Make sure it ends with a line break + if (substr($encoded, -(strlen($this->LE))) != $this->LE) + $encoded .= $this->LE; + break; + case 'binary': + $encoded = $str; + break; + case 'quoted-printable': + $encoded = $this->EncodeQP($str); + break; + default: + $this->SetError($this->Lang('encoding') . $encoding); + break; + } + return $encoded; + } + + /** + * Encode a header string to best (shortest) of Q, B, quoted or none. + * @access public + * @param string $str + * @param string $position + * @return string + */ + public function EncodeHeader($str, $position = 'text') { + $x = 0; + + switch (strtolower($position)) { + case 'phrase': + if (!preg_match('/[\200-\377]/', $str)) { + // Can't use addslashes as we don't know what value has magic_quotes_sybase + $encoded = addcslashes($str, "\0..\37\177\\\""); + if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { + return ($encoded); + } else { + return ("\"$encoded\""); + } + } + $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); + break; + case 'comment': + $x = preg_match_all('/[()"]/', $str, $matches); + // Fall-through + case 'text': + default: + $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); + break; + } + + if ($x == 0) { + return ($str); + } + + $maxlen = 75 - 7 - strlen($this->CharSet); + // Try to select the encoding which should produce the shortest output + if (strlen($str)/3 < $x) { + $encoding = 'B'; + if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { + // Use a custom function which correctly encodes and wraps long + // multibyte strings without breaking lines within a character + $encoded = $this->Base64EncodeWrapMB($str, "\n"); + } else { + $encoded = base64_encode($str); + $maxlen -= $maxlen % 4; + $encoded = trim(chunk_split($encoded, $maxlen, "\n")); + } + } else { + $encoding = 'Q'; + $encoded = $this->EncodeQ($str, $position); + $encoded = $this->WrapText($encoded, $maxlen, true); + $encoded = str_replace('='.self::CRLF, "\n", trim($encoded)); + } + + $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); + $encoded = trim(str_replace("\n", $this->LE, $encoded)); + + return $encoded; + } + + /** + * Checks if a string contains multibyte characters. + * @access public + * @param string $str multi-byte text to wrap encode + * @return bool + */ + public function HasMultiBytes($str) { + if (function_exists('mb_strlen')) { + return (strlen($str) > mb_strlen($str, $this->CharSet)); + } else { // Assume no multibytes (we can't handle without mbstring functions anyway) + return false; + } + } + + /** + * Correctly encodes and wraps long multibyte strings for mail headers + * without breaking lines within a character. + * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php + * @access public + * @param string $str multi-byte text to wrap encode + * @param string $lf string to use as linefeed/end-of-line + * @return string + */ + public function Base64EncodeWrapMB($str, $lf=null) { + $start = "=?".$this->CharSet."?B?"; + $end = "?="; + $encoded = ""; + if ($lf === null) { + $lf = $this->LE; + } + + $mb_length = mb_strlen($str, $this->CharSet); + // Each line must have length <= 75, including $start and $end + $length = 75 - strlen($start) - strlen($end); + // Average multi-byte ratio + $ratio = $mb_length / strlen($str); + // Base64 has a 4:3 ratio + $offset = $avgLength = floor($length * $ratio * .75); + + for ($i = 0; $i < $mb_length; $i += $offset) { + $lookBack = 0; + + do { + $offset = $avgLength - $lookBack; + $chunk = mb_substr($str, $i, $offset, $this->CharSet); + $chunk = base64_encode($chunk); + $lookBack++; + } + while (strlen($chunk) > $length); + + $encoded .= $chunk . $lf; + } + + // Chomp the last linefeed + $encoded = substr($encoded, 0, -strlen($lf)); + return $encoded; + } + + /** + * Encode string to quoted-printable. + * Only uses standard PHP, slow, but will always work + * @access public + * @param string $input + * @param integer $line_max Number of chars allowed on a line before wrapping + * @param bool $space_conv + * @internal param string $string the text to encode + * @return string + */ + public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) { + $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); + $lines = preg_split('/(?:\r\n|\r|\n)/', $input); + $eol = "\r\n"; + $escape = '='; + $output = ''; + while( list(, $line) = each($lines) ) { + $linlen = strlen($line); + $newline = ''; + for($i = 0; $i < $linlen; $i++) { + $c = substr( $line, $i, 1 ); + $dec = ord( $c ); + if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E + $c = '=2E'; + } + if ( $dec == 32 ) { + if ( $i == ( $linlen - 1 ) ) { // convert space at eol only + $c = '=20'; + } else if ( $space_conv ) { + $c = '=20'; + } + } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required + $h2 = (integer)floor($dec/16); + $h1 = (integer)floor($dec%16); + $c = $escape.$hex[$h2].$hex[$h1]; + } + if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted + $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay + $newline = ''; + // check if newline first character will be point or not + if ( $dec == 46 ) { + $c = '=2E'; + } + } + $newline .= $c; + } // end of for + $output .= $newline.$eol; + } // end of while + return $output; + } + + /** + * Encode string to RFC2045 (6.7) quoted-printable format + * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version + * Also results in same content as you started with after decoding + * @see EncodeQPphp() + * @access public + * @param string $string the text to encode + * @param integer $line_max Number of chars allowed on a line before wrapping + * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function + * @return string + * @author Marcus Bointon + */ + public function EncodeQP($string, $line_max = 76, $space_conv = false) { + if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) + return quoted_printable_encode($string); + } + $filters = stream_get_filters(); + if (!in_array('convert.*', $filters)) { //Got convert stream filter? + return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation + } + $fp = fopen('php://temp/', 'r+'); + $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks + $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); + $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); + fputs($fp, $string); + rewind($fp); + $out = stream_get_contents($fp); + stream_filter_remove($s); + $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange + fclose($fp); + return $out; + } + + /** + * Encode string to q encoding. + * @link http://tools.ietf.org/html/rfc2047 + * @param string $str the text to encode + * @param string $position Where the text is going to be used, see the RFC for what that means + * @access public + * @return string + */ + public function EncodeQ($str, $position = 'text') { + //There should not be any EOL in the string + $pattern=""; + $encoded = str_replace(array("\r", "\n"), '', $str); + switch (strtolower($position)) { + case 'phrase': + $pattern = '^A-Za-z0-9!*+\/ -'; + break; + + case 'comment': + $pattern = '\(\)"'; + //note that we dont break here! + //for this reason we build the $pattern withoud including delimiters and [] + + case 'text': + default: + //Replace every high ascii, control =, ? and _ characters + //We put \075 (=) as first value to make sure it's the first one in being converted, preventing double encode + $pattern = '\075\000-\011\013\014\016-\037\077\137\177-\377' . $pattern; + break; + } + + if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { + foreach (array_unique($matches[0]) as $char) { + $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); + } + } + + //Replace every spaces to _ (more readable than =20) + return str_replace(' ', '_', $encoded); +} + + + /** + * Adds a string or binary attachment (non-filesystem) to the list. + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return void + */ + public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $filename, + 2 => basename($filename), + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => 'attachment', + 7 => 0 + ); + } + + /** + * Adds an embedded attachment. This can include images, sounds, and + * just about any other document. Make sure to set the $type to an + * image type. For JPEG images use "image/jpeg" and for GIF images + * use "image/gif". + * @param string $path Path to the attachment. + * @param string $cid Content ID of the attachment. Use this to identify + * the Id for accessing the image in an HTML form. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return bool + */ + public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { + + if ( !@is_file($path) ) { + $this->SetError($this->Lang('file_access') . $path); + return false; + } + + $filename = basename($path); + if ( $name == '' ) { + $name = $filename; + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => 'inline', + 7 => $cid + ); + + return true; + } + + /** + * Adds an embedded stringified attachment. This can include images, sounds, and + * just about any other document. Make sure to set the $type to an + * image type. For JPEG images use "image/jpeg" and for GIF images + * use "image/gif". + * @param string $string The attachment. + * @param string $cid Content ID of the attachment. Use this to identify + * the Id for accessing the image in an HTML form. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return bool + */ + public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $name, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => 'inline', + 7 => $cid + ); + } + + /** + * Returns true if an inline attachment is present. + * @access public + * @return bool + */ + public function InlineImageExists() { + foreach($this->attachment as $attachment) { + if ($attachment[6] == 'inline') { + return true; + } + } + return false; + } + + /** + * Returns true if an attachment (non-inline) is present. + * @return bool + */ + public function AttachmentExists() { + foreach($this->attachment as $attachment) { + if ($attachment[6] == 'attachment') { + return true; + } + } + return false; + } + + /** + * Does this message have an alternative body set? + * @return bool + */ + public function AlternativeExists() { + return !empty($this->AltBody); + } + + ///////////////////////////////////////////////// + // CLASS METHODS, MESSAGE RESET + ///////////////////////////////////////////////// + + /** + * Clears all recipients assigned in the TO array. Returns void. + * @return void + */ + public function ClearAddresses() { + foreach($this->to as $to) { + unset($this->all_recipients[strtolower($to[0])]); + } + $this->to = array(); + } + + /** + * Clears all recipients assigned in the CC array. Returns void. + * @return void + */ + public function ClearCCs() { + foreach($this->cc as $cc) { + unset($this->all_recipients[strtolower($cc[0])]); + } + $this->cc = array(); + } + + /** + * Clears all recipients assigned in the BCC array. Returns void. + * @return void + */ + public function ClearBCCs() { + foreach($this->bcc as $bcc) { + unset($this->all_recipients[strtolower($bcc[0])]); + } + $this->bcc = array(); + } + + /** + * Clears all recipients assigned in the ReplyTo array. Returns void. + * @return void + */ + public function ClearReplyTos() { + $this->ReplyTo = array(); + } + + /** + * Clears all recipients assigned in the TO, CC and BCC + * array. Returns void. + * @return void + */ + public function ClearAllRecipients() { + $this->to = array(); + $this->cc = array(); + $this->bcc = array(); + $this->all_recipients = array(); + } + + /** + * Clears all previously set filesystem, string, and binary + * attachments. Returns void. + * @return void + */ + public function ClearAttachments() { + $this->attachment = array(); + } + + /** + * Clears all custom headers. Returns void. + * @return void + */ + public function ClearCustomHeaders() { + $this->CustomHeader = array(); + } + + ///////////////////////////////////////////////// + // CLASS METHODS, MISCELLANEOUS + ///////////////////////////////////////////////// + + /** + * Adds the error message to the error container. + * @access protected + * @param string $msg + * @return void + */ + protected function SetError($msg) { + $this->error_count++; + if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { + $lasterror = $this->smtp->getError(); + if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) { + $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n"; + } + } + $this->ErrorInfo = $msg; + } + + /** + * Returns the proper RFC 822 formatted date. + * @access public + * @return string + * @static + */ + public static function RFCDate() { + $tz = date('Z'); + $tzs = ($tz < 0) ? '-' : '+'; + $tz = abs($tz); + $tz = (int)($tz/3600)*100 + ($tz%3600)/60; + $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); + + return $result; + } + + /** + * Returns the server hostname or 'localhost.localdomain' if unknown. + * @access protected + * @return string + */ + protected function ServerHostname() { + if (!empty($this->Hostname)) { + $result = $this->Hostname; + } elseif (isset($_SERVER['SERVER_NAME'])) { + $result = $_SERVER['SERVER_NAME']; + } else { + $result = 'localhost.localdomain'; + } + + return $result; + } + + /** + * Returns a message in the appropriate language. + * @access protected + * @param string $key + * @return string + */ + protected function Lang($key) { + if(count($this->language) < 1) { + $this->SetLanguage('en'); // set the default language + } + + if(isset($this->language[$key])) { + return $this->language[$key]; + } else { + return 'Language string failed to load: ' . $key; + } + } + + /** + * Returns true if an error occurred. + * @access public + * @return bool + */ + public function IsError() { + return ($this->error_count > 0); + } + + /** + * Changes every end of line from CRLF, CR or LF to $this->LE. + * @access public + * @param string $str String to FixEOL + * @return string + */ + public function FixEOL($str) { + // condense down to \n + $nstr = str_replace(array("\r\n", "\r"), "\n", $str); + // Now convert LE as needed + if ($this->LE !== "\n") { + $nstr = str_replace("\n", $this->LE, $nstr); + } + return $nstr; + } + + /** + * Adds a custom header. $name value can be overloaded to contain + * both header name and value (name:value) + * @access public + * @param string $name custom header name + * @param string $value header value + * @return void + */ + public function AddCustomHeader($name, $value=null) { + if ($value === null) { + // Value passed in as name:value + $this->CustomHeader[] = explode(':', $name, 2); + } else { + $this->CustomHeader[] = array($name, $value); + } + } + + /** + * Evaluates the message and returns modifications for inline images and backgrounds + * @access public + * @param string $message Text to be HTML modified + * @param string $basedir baseline directory for path + * @return string $message + */ + public function MsgHTML($message, $basedir = '') { + preg_match_all("/(src|background)=[\"'](.*)[\"']/Ui", $message, $images); + if(isset($images[2])) { + foreach($images[2] as $i => $url) { + // do not change urls for absolute images (thanks to corvuscorax) + if (!preg_match('#^[A-z]+://#', $url)) { + $filename = basename($url); + $directory = dirname($url); + if ($directory == '.') { + $directory = ''; + } + $cid = 'cid:' . md5($url); + $ext = pathinfo($filename, PATHINFO_EXTENSION); + $mimeType = self::_mime_types($ext); + if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; } + if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; } + if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($url), $filename, 'base64', $mimeType) ) { + $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"".$cid."\"", $message); + } + } + } + } + $this->IsHTML(true); + $this->Body = $message; + if (empty($this->AltBody)) { + $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message))); + if (!empty($textMsg)) { + $this->AltBody = html_entity_decode($textMsg, ENT_QUOTES, $this->CharSet); + } + } + if (empty($this->AltBody)) { + $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; + } + return $message; + } + + /** + * Gets the MIME type of the embedded or inline image + * @param string $ext File extension + * @access public + * @return string MIME type of ext + * @static + */ + public static function _mime_types($ext = '') { + $mimes = array( + 'xl' => 'application/excel', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'bin' => 'application/macbinary', + 'doc' => 'application/msword', + 'word' => 'application/msword', + 'class' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'exe' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'psd' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'so' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'js' => 'application/x-javascript', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => 'application/x-tar', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'zip' => 'application/zip', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mpga' => 'audio/mpeg', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'wav' => 'audio/x-wav', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'png' => 'image/png', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'eml' => 'message/rfc822', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', + 'shtml' => 'text/html', + 'log' => 'text/plain', + 'text' => 'text/plain', + 'txt' => 'text/plain', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mov' => 'video/quicktime', + 'qt' => 'video/quicktime', + 'rv' => 'video/vnd.rn-realvideo', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie' + ); + return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; + } + + /** + * Set (or reset) Class Objects (variables) + * + * Usage Example: + * $page->set('X-Priority', '3'); + * + * @access public + * @param string $name Parameter Name + * @param mixed $value Parameter Value + * NOTE: will not work with arrays, there are no arrays to set/reset + * @throws phpmailerException + * @return bool + * @todo Should this not be using __set() magic function? + */ + public function set($name, $value = '') { + try { + if (isset($this->$name) ) { + $this->$name = $value; + } else { + throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL); + } + } catch (Exception $e) { + $this->SetError($e->getMessage()); + if ($e->getCode() == self::STOP_CRITICAL) { + return false; + } + } + return true; + } + + /** + * Strips newlines to prevent header injection. + * @access public + * @param string $str String + * @return string + */ + public function SecureHeader($str) { + return trim(str_replace(array("\r", "\n"), '', $str)); + } + + /** + * Set the private key file and password to sign the message. + * + * @access public + * @param $cert_filename + * @param string $key_filename Parameter File Name + * @param string $key_pass Password for private key + */ + public function Sign($cert_filename, $key_filename, $key_pass) { + $this->sign_cert_file = $cert_filename; + $this->sign_key_file = $key_filename; + $this->sign_key_pass = $key_pass; + } + + /** + * Set the private key file and password to sign the message. + * + * @access public + * @param string $txt + * @return string + */ + public function DKIM_QP($txt) { + $line = ''; + for ($i = 0; $i < strlen($txt); $i++) { + $ord = ord($txt[$i]); + if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) { + $line .= $txt[$i]; + } else { + $line .= "=".sprintf("%02X", $ord); + } + } + return $line; + } + + /** + * Generate DKIM signature + * + * @access public + * @param string $s Header + * @return string + */ + public function DKIM_Sign($s) { + $privKeyStr = file_get_contents($this->DKIM_private); + if ($this->DKIM_passphrase != '') { + $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); + } else { + $privKey = $privKeyStr; + } + if (openssl_sign($s, $signature, $privKey)) { + return base64_encode($signature); + } + return ''; + } + + /** + * Generate DKIM Canonicalization Header + * + * @access public + * @param string $s Header + * @return string + */ + public function DKIM_HeaderC($s) { + $s = preg_replace("/\r\n\s+/", " ", $s); + $lines = explode("\r\n", $s); + foreach ($lines as $key => $line) { + list($heading, $value) = explode(":", $line, 2); + $heading = strtolower($heading); + $value = preg_replace("/\s+/", " ", $value) ; // Compress useless spaces + $lines[$key] = $heading.":".trim($value) ; // Don't forget to remove WSP around the value + } + $s = implode("\r\n", $lines); + return $s; + } + + /** + * Generate DKIM Canonicalization Body + * + * @access public + * @param string $body Message Body + * @return string + */ + public function DKIM_BodyC($body) { + if ($body == '') return "\r\n"; + // stabilize line endings + $body = str_replace("\r\n", "\n", $body); + $body = str_replace("\n", "\r\n", $body); + // END stabilize line endings + while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") { + $body = substr($body, 0, strlen($body) - 2); + } + return $body; + } + + /** + * Create the DKIM header, body, as new header + * + * @access public + * @param string $headers_line Header lines + * @param string $subject Subject + * @param string $body Body + * @return string + */ + public function DKIM_Add($headers_line, $subject, $body) { + $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms + $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body + $DKIMquery = 'dns/txt'; // Query method + $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) + $subject_header = "Subject: $subject"; + $headers = explode($this->LE, $headers_line); + $from_header = ""; + $to_header = ""; + foreach($headers as $header) { + if (strpos($header, 'From:') === 0) { + $from_header = $header; + } elseif (strpos($header, 'To:') === 0) { + $to_header = $header; + } + } + $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); + $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); + $subject = str_replace('|', '=7C', $this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable + $body = $this->DKIM_BodyC($body); + $DKIMlen = strlen($body) ; // Length of body + $DKIMb64 = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body + $ident = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";"; + $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n". + "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n". + "\th=From:To:Subject;\r\n". + "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n". + "\tz=$from\r\n". + "\t|$to\r\n". + "\t|$subject;\r\n". + "\tbh=" . $DKIMb64 . ";\r\n". + "\tb="; + $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs); + $signed = $this->DKIM_Sign($toSign); + return "X-PHPMAILER-DKIM: code.google.com/a/apache-extras.org/p/phpmailer/\r\n".$dkimhdrs.$signed."\r\n"; + } + + /** + * Perform callback + * @param boolean $isSent + * @param string $to + * @param string $cc + * @param string $bcc + * @param string $subject + * @param string $body + * @param string $from + */ + protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from=null) { + if (!empty($this->action_function) && is_callable($this->action_function)) { + $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); + call_user_func_array($this->action_function, $params); + } + } +} + +/** + * Exception handler for PHPMailer + * @package PHPMailer + */ +class phpmailerException extends Exception { + /** + * Prettify error message output + * @return string + */ + public function errorMessage() { + $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n"; + return $errorMsg; + } +} +?> diff --git a/sources/wp-includes/class-pop3.php b/sources/wp-includes/class-pop3.php new file mode 100644 index 0000000..d0455d7 --- /dev/null +++ b/sources/wp-includes/class-pop3.php @@ -0,0 +1,652 @@ +<?php +/** + * mail_fetch/setup.php + * + * Copyright (c) 1999-2011 CDI (cdi@thewebmasters.net) All Rights Reserved + * Modified by Philippe Mingo 2001-2009 mingo@rotedic.com + * An RFC 1939 compliant wrapper class for the POP3 protocol. + * + * Licensed under the GNU GPL. For full terms see the file COPYING. + * + * POP3 class + * + * @copyright 1999-2011 The SquirrelMail Project Team + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + * @package plugins + * @subpackage mail_fetch + */ + +class POP3 { + var $ERROR = ''; // Error string. + + var $TIMEOUT = 60; // Default timeout before giving up on a + // network operation. + + var $COUNT = -1; // Mailbox msg count + + var $BUFFER = 512; // Socket buffer for socket fgets() calls. + // Per RFC 1939 the returned line a POP3 + // server can send is 512 bytes. + + var $FP = ''; // The connection to the server's + // file descriptor + + var $MAILSERVER = ''; // Set this to hard code the server name + + var $DEBUG = FALSE; // set to true to echo pop3 + // commands and responses to error_log + // this WILL log passwords! + + var $BANNER = ''; // Holds the banner returned by the + // pop server - used for apop() + + var $ALLOWAPOP = FALSE; // Allow or disallow apop() + // This must be set to true + // manually + + function POP3 ( $server = '', $timeout = '' ) { + settype($this->BUFFER,"integer"); + if( !empty($server) ) { + // Do not allow programs to alter MAILSERVER + // if it is already specified. They can get around + // this if they -really- want to, so don't count on it. + if(empty($this->MAILSERVER)) + $this->MAILSERVER = $server; + } + if(!empty($timeout)) { + settype($timeout,"integer"); + $this->TIMEOUT = $timeout; + if (!ini_get('safe_mode')) + set_time_limit($timeout); + } + return true; + } + + function update_timer () { + if (!ini_get('safe_mode')) + set_time_limit($this->TIMEOUT); + return true; + } + + function connect ($server, $port = 110) { + // Opens a socket to the specified server. Unless overridden, + // port defaults to 110. Returns true on success, false on fail + + // If MAILSERVER is set, override $server with it's value + + if (!isset($port) || !$port) {$port = 110;} + if(!empty($this->MAILSERVER)) + $server = $this->MAILSERVER; + + if(empty($server)){ + $this->ERROR = "POP3 connect: " . _("No server specified"); + unset($this->FP); + return false; + } + + $fp = @fsockopen("$server", $port, $errno, $errstr); + + if(!$fp) { + $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]"; + unset($this->FP); + return false; + } + + socket_set_blocking($fp,-1); + $this->update_timer(); + $reply = fgets($fp,$this->BUFFER); + $reply = $this->strip_clf($reply); + if($this->DEBUG) + error_log("POP3 SEND [connect: $server] GOT [$reply]",0); + if(!$this->is_ok($reply)) { + $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]"; + unset($this->FP); + return false; + } + $this->FP = $fp; + $this->BANNER = $this->parse_banner($reply); + return true; + } + + function user ($user = "") { + // Sends the USER command, returns true or false + + if( empty($user) ) { + $this->ERROR = "POP3 user: " . _("no login ID submitted"); + return false; + } elseif(!isset($this->FP)) { + $this->ERROR = "POP3 user: " . _("connection not established"); + return false; + } else { + $reply = $this->send_cmd("USER $user"); + if(!$this->is_ok($reply)) { + $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]"; + return false; + } else + return true; + } + } + + function pass ($pass = "") { + // Sends the PASS command, returns # of msgs in mailbox, + // returns false (undef) on Auth failure + + if(empty($pass)) { + $this->ERROR = "POP3 pass: " . _("No password submitted"); + return false; + } elseif(!isset($this->FP)) { + $this->ERROR = "POP3 pass: " . _("connection not established"); + return false; + } else { + $reply = $this->send_cmd("PASS $pass"); + if(!$this->is_ok($reply)) { + $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]"; + $this->quit(); + return false; + } else { + // Auth successful. + $count = $this->last("count"); + $this->COUNT = $count; + return $count; + } + } + } + + function apop ($login,$pass) { + // Attempts an APOP login. If this fails, it'll + // try a standard login. YOUR SERVER MUST SUPPORT + // THE USE OF THE APOP COMMAND! + // (apop is optional per rfc1939) + + if(!isset($this->FP)) { + $this->ERROR = "POP3 apop: " . _("No connection to server"); + return false; + } elseif(!$this->ALLOWAPOP) { + $retVal = $this->login($login,$pass); + return $retVal; + } elseif(empty($login)) { + $this->ERROR = "POP3 apop: " . _("No login ID submitted"); + return false; + } elseif(empty($pass)) { + $this->ERROR = "POP3 apop: " . _("No password submitted"); + return false; + } else { + $banner = $this->BANNER; + if( (!$banner) or (empty($banner)) ) { + $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort"); + $retVal = $this->login($login,$pass); + return $retVal; + } else { + $AuthString = $banner; + $AuthString .= $pass; + $APOPString = md5($AuthString); + $cmd = "APOP $login $APOPString"; + $reply = $this->send_cmd($cmd); + if(!$this->is_ok($reply)) { + $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort"); + $retVal = $this->login($login,$pass); + return $retVal; + } else { + // Auth successful. + $count = $this->last("count"); + $this->COUNT = $count; + return $count; + } + } + } + } + + function login ($login = "", $pass = "") { + // Sends both user and pass. Returns # of msgs in mailbox or + // false on failure (or -1, if the error occurs while getting + // the number of messages.) + + if( !isset($this->FP) ) { + $this->ERROR = "POP3 login: " . _("No connection to server"); + return false; + } else { + $fp = $this->FP; + if( !$this->user( $login ) ) { + // Preserve the error generated by user() + return false; + } else { + $count = $this->pass($pass); + if( (!$count) || ($count == -1) ) { + // Preserve the error generated by last() and pass() + return false; + } else + return $count; + } + } + } + + function top ($msgNum, $numLines = "0") { + // Gets the header and first $numLines of the msg body + // returns data in an array with each returned line being + // an array element. If $numLines is empty, returns + // only the header information, and none of the body. + + if(!isset($this->FP)) { + $this->ERROR = "POP3 top: " . _("No connection to server"); + return false; + } + $this->update_timer(); + + $fp = $this->FP; + $buffer = $this->BUFFER; + $cmd = "TOP $msgNum $numLines"; + fwrite($fp, "TOP $msgNum $numLines\r\n"); + $reply = fgets($fp, $buffer); + $reply = $this->strip_clf($reply); + if($this->DEBUG) { + @error_log("POP3 SEND [$cmd] GOT [$reply]",0); + } + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]"; + return false; + } + + $count = 0; + $MsgArray = array(); + + $line = fgets($fp,$buffer); + while ( !preg_match('/^\.\r\n/',$line)) + { + $MsgArray[$count] = $line; + $count++; + $line = fgets($fp,$buffer); + if(empty($line)) { break; } + } + + return $MsgArray; + } + + function pop_list ($msgNum = "") { + // If called with an argument, returns that msgs' size in octets + // No argument returns an associative array of undeleted + // msg numbers and their sizes in octets + + if(!isset($this->FP)) + { + $this->ERROR = "POP3 pop_list: " . _("No connection to server"); + return false; + } + $fp = $this->FP; + $Total = $this->COUNT; + if( (!$Total) or ($Total == -1) ) + { + return false; + } + if($Total == 0) + { + return array("0","0"); + // return -1; // mailbox empty + } + + $this->update_timer(); + + if(!empty($msgNum)) + { + $cmd = "LIST $msgNum"; + fwrite($fp,"$cmd\r\n"); + $reply = fgets($fp,$this->BUFFER); + $reply = $this->strip_clf($reply); + if($this->DEBUG) { + @error_log("POP3 SEND [$cmd] GOT [$reply]",0); + } + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; + return false; + } + list($junk,$num,$size) = preg_split('/\s+/',$reply); + return $size; + } + $cmd = "LIST"; + $reply = $this->send_cmd($cmd); + if(!$this->is_ok($reply)) + { + $reply = $this->strip_clf($reply); + $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]"; + return false; + } + $MsgArray = array(); + $MsgArray[0] = $Total; + for($msgC=1;$msgC <= $Total; $msgC++) + { + if($msgC > $Total) { break; } + $line = fgets($fp,$this->BUFFER); + $line = $this->strip_clf($line); + if(strpos($line, '.') === 0) + { + $this->ERROR = "POP3 pop_list: " . _("Premature end of list"); + return false; + } + list($thisMsg,$msgSize) = preg_split('/\s+/',$line); + settype($thisMsg,"integer"); + if($thisMsg != $msgC) + { + $MsgArray[$msgC] = "deleted"; + } + else + { + $MsgArray[$msgC] = $msgSize; + } + } + return $MsgArray; + } + + function get ($msgNum) { + // Retrieve the specified msg number. Returns an array + // where each line of the msg is an array element. + + if(!isset($this->FP)) + { + $this->ERROR = "POP3 get: " . _("No connection to server"); + return false; + } + + $this->update_timer(); + + $fp = $this->FP; + $buffer = $this->BUFFER; + $cmd = "RETR $msgNum"; + $reply = $this->send_cmd($cmd); + + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]"; + return false; + } + + $count = 0; + $MsgArray = array(); + + $line = fgets($fp,$buffer); + while ( !preg_match('/^\.\r\n/',$line)) + { + if ( $line{0} == '.' ) { $line = substr($line,1); } + $MsgArray[$count] = $line; + $count++; + $line = fgets($fp,$buffer); + if(empty($line)) { break; } + } + return $MsgArray; + } + + function last ( $type = "count" ) { + // Returns the highest msg number in the mailbox. + // returns -1 on error, 0+ on success, if type != count + // results in a popstat() call (2 element array returned) + + $last = -1; + if(!isset($this->FP)) + { + $this->ERROR = "POP3 last: " . _("No connection to server"); + return $last; + } + + $reply = $this->send_cmd("STAT"); + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]"; + return $last; + } + + $Vars = preg_split('/\s+/',$reply); + $count = $Vars[1]; + $size = $Vars[2]; + settype($count,"integer"); + settype($size,"integer"); + if($type != "count") + { + return array($count,$size); + } + return $count; + } + + function reset () { + // Resets the status of the remote server. This includes + // resetting the status of ALL msgs to not be deleted. + // This method automatically closes the connection to the server. + + if(!isset($this->FP)) + { + $this->ERROR = "POP3 reset: " . _("No connection to server"); + return false; + } + $reply = $this->send_cmd("RSET"); + if(!$this->is_ok($reply)) + { + // The POP3 RSET command -never- gives a -ERR + // response - if it ever does, something truely + // wild is going on. + + $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]"; + @error_log("POP3 reset: ERROR [$reply]",0); + } + $this->quit(); + return true; + } + + function send_cmd ( $cmd = "" ) + { + // Sends a user defined command string to the + // POP server and returns the results. Useful for + // non-compliant or custom POP servers. + // Do NOT includ the \r\n as part of your command + // string - it will be appended automatically. + + // The return value is a standard fgets() call, which + // will read up to $this->BUFFER bytes of data, until it + // encounters a new line, or EOF, whichever happens first. + + // This method works best if $cmd responds with only + // one line of data. + + if(!isset($this->FP)) + { + $this->ERROR = "POP3 send_cmd: " . _("No connection to server"); + return false; + } + + if(empty($cmd)) + { + $this->ERROR = "POP3 send_cmd: " . _("Empty command string"); + return ""; + } + + $fp = $this->FP; + $buffer = $this->BUFFER; + $this->update_timer(); + fwrite($fp,"$cmd\r\n"); + $reply = fgets($fp,$buffer); + $reply = $this->strip_clf($reply); + if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } + return $reply; + } + + function quit() { + // Closes the connection to the POP3 server, deleting + // any msgs marked as deleted. + + if(!isset($this->FP)) + { + $this->ERROR = "POP3 quit: " . _("connection does not exist"); + return false; + } + $fp = $this->FP; + $cmd = "QUIT"; + fwrite($fp,"$cmd\r\n"); + $reply = fgets($fp,$this->BUFFER); + $reply = $this->strip_clf($reply); + if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } + fclose($fp); + unset($this->FP); + return true; + } + + function popstat () { + // Returns an array of 2 elements. The number of undeleted + // msgs in the mailbox, and the size of the mbox in octets. + + $PopArray = $this->last("array"); + + if($PopArray == -1) { return false; } + + if( (!$PopArray) or (empty($PopArray)) ) + { + return false; + } + return $PopArray; + } + + function uidl ($msgNum = "") + { + // Returns the UIDL of the msg specified. If called with + // no arguments, returns an associative array where each + // undeleted msg num is a key, and the msg's uidl is the element + // Array element 0 will contain the total number of msgs + + if(!isset($this->FP)) { + $this->ERROR = "POP3 uidl: " . _("No connection to server"); + return false; + } + + $fp = $this->FP; + $buffer = $this->BUFFER; + + if(!empty($msgNum)) { + $cmd = "UIDL $msgNum"; + $reply = $this->send_cmd($cmd); + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; + return false; + } + list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply); + return $myUidl; + } else { + $this->update_timer(); + + $UIDLArray = array(); + $Total = $this->COUNT; + $UIDLArray[0] = $Total; + + if ($Total < 1) + { + return $UIDLArray; + } + $cmd = "UIDL"; + fwrite($fp, "UIDL\r\n"); + $reply = fgets($fp, $buffer); + $reply = $this->strip_clf($reply); + if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); } + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]"; + return false; + } + + $line = ""; + $count = 1; + $line = fgets($fp,$buffer); + while ( !preg_match('/^\.\r\n/',$line)) { + list ($msg,$msgUidl) = preg_split('/\s+/',$line); + $msgUidl = $this->strip_clf($msgUidl); + if($count == $msg) { + $UIDLArray[$msg] = $msgUidl; + } + else + { + $UIDLArray[$count] = 'deleted'; + } + $count++; + $line = fgets($fp,$buffer); + } + } + return $UIDLArray; + } + + function delete ($msgNum = "") { + // Flags a specified msg as deleted. The msg will not + // be deleted until a quit() method is called. + + if(!isset($this->FP)) + { + $this->ERROR = "POP3 delete: " . _("No connection to server"); + return false; + } + if(empty($msgNum)) + { + $this->ERROR = "POP3 delete: " . _("No msg number submitted"); + return false; + } + $reply = $this->send_cmd("DELE $msgNum"); + if(!$this->is_ok($reply)) + { + $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]"; + return false; + } + return true; + } + + // ********************************************************* + + // The following methods are internal to the class. + + function is_ok ($cmd = "") { + // Return true or false on +OK or -ERR + + if( empty($cmd) ) + return false; + else + return( stripos($cmd, '+OK') !== false ); + } + + function strip_clf ($text = "") { + // Strips \r\n from server responses + + if(empty($text)) + return $text; + else { + $stripped = str_replace(array("\r","\n"),'',$text); + return $stripped; + } + } + + function parse_banner ( $server_text ) { + $outside = true; + $banner = ""; + $length = strlen($server_text); + for($count =0; $count < $length; $count++) + { + $digit = substr($server_text,$count,1); + if(!empty($digit)) { + if( (!$outside) && ($digit != '<') && ($digit != '>') ) + { + $banner .= $digit; + } + if ($digit == '<') + { + $outside = false; + } + if($digit == '>') + { + $outside = true; + } + } + } + $banner = $this->strip_clf($banner); // Just in case + return "<$banner>"; + } + +} // End class + +// For php4 compatibility +if (!function_exists("stripos")) { + function stripos($haystack, $needle){ + return strpos($haystack, stristr( $haystack, $needle )); + } +} diff --git a/sources/wp-includes/class-simplepie.php b/sources/wp-includes/class-simplepie.php new file mode 100644 index 0000000..ba6f28d --- /dev/null +++ b/sources/wp-includes/class-simplepie.php @@ -0,0 +1,3119 @@ +<?php +if ( ! class_exists( 'SimplePie' ) ) : + +// Load classes we will need. +require ABSPATH . WPINC . '/SimplePie/Misc.php'; +require ABSPATH . WPINC . '/SimplePie/Cache.php'; +require ABSPATH . WPINC . '/SimplePie/File.php'; +require ABSPATH . WPINC . '/SimplePie/Sanitize.php'; +require ABSPATH . WPINC . '/SimplePie/Registry.php'; +require ABSPATH . WPINC . '/SimplePie/IRI.php'; +require ABSPATH . WPINC . '/SimplePie/Locator.php'; +require ABSPATH . WPINC . '/SimplePie/Content/Type/Sniffer.php'; +require ABSPATH . WPINC . '/SimplePie/XML/Declaration/Parser.php'; +require ABSPATH . WPINC . '/SimplePie/Parser.php'; +require ABSPATH . WPINC . '/SimplePie/Item.php'; +require ABSPATH . WPINC . '/SimplePie/Parse/Date.php'; +require ABSPATH . WPINC . '/SimplePie/Author.php'; + +/** + * WordPress autoloader for SimplePie. + * + * @since 3.5.0 + */ +function wp_simplepie_autoload( $class ) { + if ( 0 !== strpos( $class, 'SimplePie_' ) ) + return; + + $file = ABSPATH . WPINC . '/' . str_replace( '_', '/', $class ) . '.php'; + include $file; +} + +if ( function_exists( 'spl_autoload_register' ) ) { + /** + * We autoload classes we may not need. + * + * If SPL is disabled, we load all of SimplePie manually. + * + * Core.php is not loaded manually, because SimplePie_Core (a deprecated class) + * was never included in WordPress core. + */ + spl_autoload_register( 'wp_simplepie_autoload' ); +} else { + require ABSPATH . WPINC . '/SimplePie/Cache/Base.php'; + require ABSPATH . WPINC . '/SimplePie/Cache/DB.php'; + require ABSPATH . WPINC . '/SimplePie/Cache/File.php'; + require ABSPATH . WPINC . '/SimplePie/Cache/Memcache.php'; + require ABSPATH . WPINC . '/SimplePie/Cache/MySQL.php'; + require ABSPATH . WPINC . '/SimplePie/Caption.php'; + require ABSPATH . WPINC . '/SimplePie/Category.php'; + require ABSPATH . WPINC . '/SimplePie/Copyright.php'; + require ABSPATH . WPINC . '/SimplePie/Credit.php'; + require ABSPATH . WPINC . '/SimplePie/Decode/HTML/Entities.php'; + require ABSPATH . WPINC . '/SimplePie/Enclosure.php'; + require ABSPATH . WPINC . '/SimplePie/gzdecode.php'; + require ABSPATH . WPINC . '/SimplePie/HTTP/Parser.php'; + require ABSPATH . WPINC . '/SimplePie/Net/IPv6.php'; + require ABSPATH . WPINC . '/SimplePie/Rating.php'; + require ABSPATH . WPINC . '/SimplePie/Restriction.php'; + require ABSPATH . WPINC . '/SimplePie/Source.php'; +} + +/** + * SimplePie + * + * A PHP-Based RSS and Atom Feed Framework. + * Takes the hard work out of managing a complete RSS/Atom solution. + * + * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * * Neither the name of the SimplePie Team nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS + * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package SimplePie + * @version 1.3.1 + * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue + * @author Ryan Parman + * @author Geoffrey Sneddon + * @author Ryan McCue + * @link http://simplepie.org/ SimplePie + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + */ + +/** + * SimplePie Name + */ +define('SIMPLEPIE_NAME', 'SimplePie'); + +/** + * SimplePie Version + */ +define('SIMPLEPIE_VERSION', '1.3.1'); + +/** + * SimplePie Build + * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc) + */ +define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build())); + +/** + * SimplePie Website URL + */ +define('SIMPLEPIE_URL', 'http://simplepie.org'); + +/** + * SimplePie Useragent + * @see SimplePie::set_useragent() + */ +define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD); + +/** + * SimplePie Linkback + */ +define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>'); + +/** + * No Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_NONE', 0); + +/** + * Feed Link Element Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1); + +/** + * Local Feed Extension Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2); + +/** + * Local Feed Body Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4); + +/** + * Remote Feed Extension Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8); + +/** + * Remote Feed Body Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16); + +/** + * All Feed Autodiscovery + * @see SimplePie::set_autodiscovery_level() + */ +define('SIMPLEPIE_LOCATOR_ALL', 31); + +/** + * No known feed type + */ +define('SIMPLEPIE_TYPE_NONE', 0); + +/** + * RSS 0.90 + */ +define('SIMPLEPIE_TYPE_RSS_090', 1); + +/** + * RSS 0.91 (Netscape) + */ +define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2); + +/** + * RSS 0.91 (Userland) + */ +define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4); + +/** + * RSS 0.91 (both Netscape and Userland) + */ +define('SIMPLEPIE_TYPE_RSS_091', 6); + +/** + * RSS 0.92 + */ +define('SIMPLEPIE_TYPE_RSS_092', 8); + +/** + * RSS 0.93 + */ +define('SIMPLEPIE_TYPE_RSS_093', 16); + +/** + * RSS 0.94 + */ +define('SIMPLEPIE_TYPE_RSS_094', 32); + +/** + * RSS 1.0 + */ +define('SIMPLEPIE_TYPE_RSS_10', 64); + +/** + * RSS 2.0 + */ +define('SIMPLEPIE_TYPE_RSS_20', 128); + +/** + * RDF-based RSS + */ +define('SIMPLEPIE_TYPE_RSS_RDF', 65); + +/** + * Non-RDF-based RSS (truly intended as syndication format) + */ +define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190); + +/** + * All RSS + */ +define('SIMPLEPIE_TYPE_RSS_ALL', 255); + +/** + * Atom 0.3 + */ +define('SIMPLEPIE_TYPE_ATOM_03', 256); + +/** + * Atom 1.0 + */ +define('SIMPLEPIE_TYPE_ATOM_10', 512); + +/** + * All Atom + */ +define('SIMPLEPIE_TYPE_ATOM_ALL', 768); + +/** + * All feed types + */ +define('SIMPLEPIE_TYPE_ALL', 1023); + +/** + * No construct + */ +define('SIMPLEPIE_CONSTRUCT_NONE', 0); + +/** + * Text construct + */ +define('SIMPLEPIE_CONSTRUCT_TEXT', 1); + +/** + * HTML construct + */ +define('SIMPLEPIE_CONSTRUCT_HTML', 2); + +/** + * XHTML construct + */ +define('SIMPLEPIE_CONSTRUCT_XHTML', 4); + +/** + * base64-encoded construct + */ +define('SIMPLEPIE_CONSTRUCT_BASE64', 8); + +/** + * IRI construct + */ +define('SIMPLEPIE_CONSTRUCT_IRI', 16); + +/** + * A construct that might be HTML + */ +define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32); + +/** + * All constructs + */ +define('SIMPLEPIE_CONSTRUCT_ALL', 63); + +/** + * Don't change case + */ +define('SIMPLEPIE_SAME_CASE', 1); + +/** + * Change to lowercase + */ +define('SIMPLEPIE_LOWERCASE', 2); + +/** + * Change to uppercase + */ +define('SIMPLEPIE_UPPERCASE', 4); + +/** + * PCRE for HTML attributes + */ +define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*'); + +/** + * PCRE for XML attributes + */ +define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*'); + +/** + * XML Namespace + */ +define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace'); + +/** + * Atom 1.0 Namespace + */ +define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom'); + +/** + * Atom 0.3 Namespace + */ +define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#'); + +/** + * RDF Namespace + */ +define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); + +/** + * RSS 0.90 Namespace + */ +define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/'); + +/** + * RSS 1.0 Namespace + */ +define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/'); + +/** + * RSS 1.0 Content Module Namespace + */ +define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/'); + +/** + * RSS 2.0 Namespace + * (Stupid, I know, but I'm certain it will confuse people less with support.) + */ +define('SIMPLEPIE_NAMESPACE_RSS_20', ''); + +/** + * DC 1.0 Namespace + */ +define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/'); + +/** + * DC 1.1 Namespace + */ +define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/'); + +/** + * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace + */ +define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#'); + +/** + * GeoRSS Namespace + */ +define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss'); + +/** + * Media RSS Namespace + */ +define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/'); + +/** + * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec. + */ +define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss'); + +/** + * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5. + */ +define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss'); + +/** + * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace. + */ +define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/'); + +/** + * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace. + */ +define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss'); + +/** + * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL. + */ +define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/'); + +/** + * iTunes RSS Namespace + */ +define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd'); + +/** + * XHTML Namespace + */ +define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml'); + +/** + * IANA Link Relations Registry + */ +define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/'); + +/** + * No file source + */ +define('SIMPLEPIE_FILE_SOURCE_NONE', 0); + +/** + * Remote file source + */ +define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1); + +/** + * Local file source + */ +define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2); + +/** + * fsockopen() file source + */ +define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4); + +/** + * cURL file source + */ +define('SIMPLEPIE_FILE_SOURCE_CURL', 8); + +/** + * file_get_contents() file source + */ +define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16); + + + +/** + * SimplePie + * + * @package SimplePie + * @subpackage API + */ +class SimplePie +{ + /** + * @var array Raw data + * @access private + */ + public $data = array(); + + /** + * @var mixed Error string + * @access private + */ + public $error; + + /** + * @var object Instance of SimplePie_Sanitize (or other class) + * @see SimplePie::set_sanitize_class() + * @access private + */ + public $sanitize; + + /** + * @var string SimplePie Useragent + * @see SimplePie::set_useragent() + * @access private + */ + public $useragent = SIMPLEPIE_USERAGENT; + + /** + * @var string Feed URL + * @see SimplePie::set_feed_url() + * @access private + */ + public $feed_url; + + /** + * @var object Instance of SimplePie_File to use as a feed + * @see SimplePie::set_file() + * @access private + */ + public $file; + + /** + * @var string Raw feed data + * @see SimplePie::set_raw_data() + * @access private + */ + public $raw_data; + + /** + * @var int Timeout for fetching remote files + * @see SimplePie::set_timeout() + * @access private + */ + public $timeout = 10; + + /** + * @var bool Forces fsockopen() to be used for remote files instead + * of cURL, even if a new enough version is installed + * @see SimplePie::force_fsockopen() + * @access private + */ + public $force_fsockopen = false; + + /** + * @var bool Force the given data/URL to be treated as a feed no matter what + * it appears like + * @see SimplePie::force_feed() + * @access private + */ + public $force_feed = false; + + /** + * @var bool Enable/Disable Caching + * @see SimplePie::enable_cache() + * @access private + */ + public $cache = true; + + /** + * @var int Cache duration (in seconds) + * @see SimplePie::set_cache_duration() + * @access private + */ + public $cache_duration = 3600; + + /** + * @var int Auto-discovery cache duration (in seconds) + * @see SimplePie::set_autodiscovery_cache_duration() + * @access private + */ + public $autodiscovery_cache_duration = 604800; // 7 Days. + + /** + * @var string Cache location (relative to executing script) + * @see SimplePie::set_cache_location() + * @access private + */ + public $cache_location = './cache'; + + /** + * @var string Function that creates the cache filename + * @see SimplePie::set_cache_name_function() + * @access private + */ + public $cache_name_function = 'md5'; + + /** + * @var bool Reorder feed by date descending + * @see SimplePie::enable_order_by_date() + * @access private + */ + public $order_by_date = true; + + /** + * @var mixed Force input encoding to be set to the follow value + * (false, or anything type-cast to false, disables this feature) + * @see SimplePie::set_input_encoding() + * @access private + */ + public $input_encoding = false; + + /** + * @var int Feed Autodiscovery Level + * @see SimplePie::set_autodiscovery_level() + * @access private + */ + public $autodiscovery = SIMPLEPIE_LOCATOR_ALL; + + /** + * Class registry object + * + * @var SimplePie_Registry + */ + public $registry; + + /** + * @var int Maximum number of feeds to check with autodiscovery + * @see SimplePie::set_max_checked_feeds() + * @access private + */ + public $max_checked_feeds = 10; + + /** + * @var array All the feeds found during the autodiscovery process + * @see SimplePie::get_all_discovered_feeds() + * @access private + */ + public $all_discovered_feeds = array(); + + /** + * @var string Web-accessible path to the handler_image.php file. + * @see SimplePie::set_image_handler() + * @access private + */ + public $image_handler = ''; + + /** + * @var array Stores the URLs when multiple feeds are being initialized. + * @see SimplePie::set_feed_url() + * @access private + */ + public $multifeed_url = array(); + + /** + * @var array Stores SimplePie objects when multiple feeds initialized. + * @access private + */ + public $multifeed_objects = array(); + + /** + * @var array Stores the get_object_vars() array for use with multifeeds. + * @see SimplePie::set_feed_url() + * @access private + */ + public $config_settings = null; + + /** + * @var integer Stores the number of items to return per-feed with multifeeds. + * @see SimplePie::set_item_limit() + * @access private + */ + public $item_limit = 0; + + /** + * @var array Stores the default attributes to be stripped by strip_attributes(). + * @see SimplePie::strip_attributes() + * @access private + */ + public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'); + + /** + * @var array Stores the default tags to be stripped by strip_htmltags(). + * @see SimplePie::strip_htmltags() + * @access private + */ + public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'); + + /** + * The SimplePie class contains feed level data and options + * + * To use SimplePie, create the SimplePie object with no parameters. You can + * then set configuration options using the provided methods. After setting + * them, you must initialise the feed using $feed->init(). At that point the + * object's methods and properties will be available to you. + * + * Previously, it was possible to pass in the feed URL along with cache + * options directly into the constructor. This has been removed as of 1.3 as + * it caused a lot of confusion. + * + * @since 1.0 Preview Release + */ + public function __construct() + { + if (version_compare(PHP_VERSION, '5.2', '<')) + { + trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.'); + die(); + } + + // Other objects, instances created here so we can set options on them + $this->sanitize = new SimplePie_Sanitize(); + $this->registry = new SimplePie_Registry(); + + if (func_num_args() > 0) + { + $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING; + trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level); + + $args = func_get_args(); + switch (count($args)) { + case 3: + $this->set_cache_duration($args[2]); + case 2: + $this->set_cache_location($args[1]); + case 1: + $this->set_feed_url($args[0]); + $this->init(); + } + } + } + + /** + * Used for converting object to a string + */ + public function __toString() + { + return md5(serialize($this->data)); + } + + /** + * Remove items that link back to this before destroying this object + */ + public function __destruct() + { + if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode')) + { + if (!empty($this->data['items'])) + { + foreach ($this->data['items'] as $item) + { + $item->__destruct(); + } + unset($item, $this->data['items']); + } + if (!empty($this->data['ordered_items'])) + { + foreach ($this->data['ordered_items'] as $item) + { + $item->__destruct(); + } + unset($item, $this->data['ordered_items']); + } + } + } + + /** + * Force the given data/URL to be treated as a feed + * + * This tells SimplePie to ignore the content-type provided by the server. + * Be careful when using this option, as it will also disable autodiscovery. + * + * @since 1.1 + * @param bool $enable Force the given data/URL to be treated as a feed + */ + public function force_feed($enable = false) + { + $this->force_feed = (bool) $enable; + } + + /** + * Set the URL of the feed you want to parse + * + * This allows you to enter the URL of the feed you want to parse, or the + * website you want to try to use auto-discovery on. This takes priority + * over any set raw data. + * + * You can set multiple feeds to mash together by passing an array instead + * of a string for the $url. Remember that with each additional feed comes + * additional processing and resources. + * + * @since 1.0 Preview Release + * @see set_raw_data() + * @param string|array $url This is the URL (or array of URLs) that you want to parse. + */ + public function set_feed_url($url) + { + $this->multifeed_url = array(); + if (is_array($url)) + { + foreach ($url as $value) + { + $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1)); + } + } + else + { + $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1)); + } + } + + /** + * Set an instance of {@see SimplePie_File} to use as a feed + * + * @param SimplePie_File &$file + * @return bool True on success, false on failure + */ + public function set_file(&$file) + { + if ($file instanceof SimplePie_File) + { + $this->feed_url = $file->url; + $this->file =& $file; + return true; + } + return false; + } + + /** + * Set the raw XML data to parse + * + * Allows you to use a string of RSS/Atom data instead of a remote feed. + * + * If you have a feed available as a string in PHP, you can tell SimplePie + * to parse that data string instead of a remote feed. Any set feed URL + * takes precedence. + * + * @since 1.0 Beta 3 + * @param string $data RSS or Atom data as a string. + * @see set_feed_url() + */ + public function set_raw_data($data) + { + $this->raw_data = $data; + } + + /** + * Set the the default timeout for fetching remote feeds + * + * This allows you to change the maximum time the feed's server to respond + * and send the feed back. + * + * @since 1.0 Beta 3 + * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed. + */ + public function set_timeout($timeout = 10) + { + $this->timeout = (int) $timeout; + } + + /** + * Force SimplePie to use fsockopen() instead of cURL + * + * @since 1.0 Beta 3 + * @param bool $enable Force fsockopen() to be used + */ + public function force_fsockopen($enable = false) + { + $this->force_fsockopen = (bool) $enable; + } + + /** + * Enable/disable caching in SimplePie. + * + * This option allows you to disable caching all-together in SimplePie. + * However, disabling the cache can lead to longer load times. + * + * @since 1.0 Preview Release + * @param bool $enable Enable caching + */ + public function enable_cache($enable = true) + { + $this->cache = (bool) $enable; + } + + /** + * Set the length of time (in seconds) that the contents of a feed will be + * cached + * + * @param int $seconds The feed content cache duration + */ + public function set_cache_duration($seconds = 3600) + { + $this->cache_duration = (int) $seconds; + } + + /** + * Set the length of time (in seconds) that the autodiscovered feed URL will + * be cached + * + * @param int $seconds The autodiscovered feed URL cache duration. + */ + public function set_autodiscovery_cache_duration($seconds = 604800) + { + $this->autodiscovery_cache_duration = (int) $seconds; + } + + /** + * Set the file system location where the cached files should be stored + * + * @param string $location The file system location. + */ + public function set_cache_location($location = './cache') + { + $this->cache_location = (string) $location; + } + + /** + * Set whether feed items should be sorted into reverse chronological order + * + * @param bool $enable Sort as reverse chronological order. + */ + public function enable_order_by_date($enable = true) + { + $this->order_by_date = (bool) $enable; + } + + /** + * Set the character encoding used to parse the feed + * + * This overrides the encoding reported by the feed, however it will fall + * back to the normal encoding detection if the override fails + * + * @param string $encoding Character encoding + */ + public function set_input_encoding($encoding = false) + { + if ($encoding) + { + $this->input_encoding = (string) $encoding; + } + else + { + $this->input_encoding = false; + } + } + + /** + * Set how much feed autodiscovery to do + * + * @see SIMPLEPIE_LOCATOR_NONE + * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY + * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION + * @see SIMPLEPIE_LOCATOR_LOCAL_BODY + * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION + * @see SIMPLEPIE_LOCATOR_REMOTE_BODY + * @see SIMPLEPIE_LOCATOR_ALL + * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator) + */ + public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL) + { + $this->autodiscovery = (int) $level; + } + + /** + * Get the class registry + * + * Use this to override SimplePie's default classes + * @see SimplePie_Registry + * @return SimplePie_Registry + */ + public function &get_registry() + { + return $this->registry; + } + + /**#@+ + * Useful when you are overloading or extending SimplePie's default classes. + * + * @deprecated Use {@see get_registry()} instead + * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation + * @param string $class Name of custom class + * @return boolean True on success, false otherwise + */ + /** + * Set which class SimplePie uses for caching + */ + public function set_cache_class($class = 'SimplePie_Cache') + { + return $this->registry->register('Cache', $class, true); + } + + /** + * Set which class SimplePie uses for auto-discovery + */ + public function set_locator_class($class = 'SimplePie_Locator') + { + return $this->registry->register('Locator', $class, true); + } + + /** + * Set which class SimplePie uses for XML parsing + */ + public function set_parser_class($class = 'SimplePie_Parser') + { + return $this->registry->register('Parser', $class, true); + } + + /** + * Set which class SimplePie uses for remote file fetching + */ + public function set_file_class($class = 'SimplePie_File') + { + return $this->registry->register('File', $class, true); + } + + /** + * Set which class SimplePie uses for data sanitization + */ + public function set_sanitize_class($class = 'SimplePie_Sanitize') + { + return $this->registry->register('Sanitize', $class, true); + } + + /** + * Set which class SimplePie uses for handling feed items + */ + public function set_item_class($class = 'SimplePie_Item') + { + return $this->registry->register('Item', $class, true); + } + + /** + * Set which class SimplePie uses for handling author data + */ + public function set_author_class($class = 'SimplePie_Author') + { + return $this->registry->register('Author', $class, true); + } + + /** + * Set which class SimplePie uses for handling category data + */ + public function set_category_class($class = 'SimplePie_Category') + { + return $this->registry->register('Category', $class, true); + } + + /** + * Set which class SimplePie uses for feed enclosures + */ + public function set_enclosure_class($class = 'SimplePie_Enclosure') + { + return $this->registry->register('Enclosure', $class, true); + } + + /** + * Set which class SimplePie uses for `<media:text>` captions + */ + public function set_caption_class($class = 'SimplePie_Caption') + { + return $this->registry->register('Caption', $class, true); + } + + /** + * Set which class SimplePie uses for `<media:copyright>` + */ + public function set_copyright_class($class = 'SimplePie_Copyright') + { + return $this->registry->register('Copyright', $class, true); + } + + /** + * Set which class SimplePie uses for `<media:credit>` + */ + public function set_credit_class($class = 'SimplePie_Credit') + { + return $this->registry->register('Credit', $class, true); + } + + /** + * Set which class SimplePie uses for `<media:rating>` + */ + public function set_rating_class($class = 'SimplePie_Rating') + { + return $this->registry->register('Rating', $class, true); + } + + /** + * Set which class SimplePie uses for `<media:restriction>` + */ + public function set_restriction_class($class = 'SimplePie_Restriction') + { + return $this->registry->register('Restriction', $class, true); + } + + /** + * Set which class SimplePie uses for content-type sniffing + */ + public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer') + { + return $this->registry->register('Content_Type_Sniffer', $class, true); + } + + /** + * Set which class SimplePie uses item sources + */ + public function set_source_class($class = 'SimplePie_Source') + { + return $this->registry->register('Source', $class, true); + } + /**#@-*/ + + /** + * Set the user agent string + * + * @param string $ua New user agent string. + */ + public function set_useragent($ua = SIMPLEPIE_USERAGENT) + { + $this->useragent = (string) $ua; + } + + /** + * Set callback function to create cache filename with + * + * @param mixed $function Callback function + */ + public function set_cache_name_function($function = 'md5') + { + if (is_callable($function)) + { + $this->cache_name_function = $function; + } + } + + /** + * Set options to make SP as fast as possible + * + * Forgoes a substantial amount of data sanitization in favor of speed. This + * turns SimplePie into a dumb parser of feeds. + * + * @param bool $set Whether to set them or not + */ + public function set_stupidly_fast($set = false) + { + if ($set) + { + $this->enable_order_by_date(false); + $this->remove_div(false); + $this->strip_comments(false); + $this->strip_htmltags(false); + $this->strip_attributes(false); + $this->set_image_handler(false); + } + } + + /** + * Set maximum number of feeds to check with autodiscovery + * + * @param int $max Maximum number of feeds to check + */ + public function set_max_checked_feeds($max = 10) + { + $this->max_checked_feeds = (int) $max; + } + + public function remove_div($enable = true) + { + $this->sanitize->remove_div($enable); + } + + public function strip_htmltags($tags = '', $encode = null) + { + if ($tags === '') + { + $tags = $this->strip_htmltags; + } + $this->sanitize->strip_htmltags($tags); + if ($encode !== null) + { + $this->sanitize->encode_instead_of_strip($tags); + } + } + + public function encode_instead_of_strip($enable = true) + { + $this->sanitize->encode_instead_of_strip($enable); + } + + public function strip_attributes($attribs = '') + { + if ($attribs === '') + { + $attribs = $this->strip_attributes; + } + $this->sanitize->strip_attributes($attribs); + } + + /** + * Set the output encoding + * + * Allows you to override SimplePie's output to match that of your webpage. + * This is useful for times when your webpages are not being served as + * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and + * is similar to {@see set_input_encoding()}. + * + * It should be noted, however, that not all character encodings can support + * all characters. If your page is being served as ISO-8859-1 and you try + * to display a Japanese feed, you'll likely see garbled characters. + * Because of this, it is highly recommended to ensure that your webpages + * are served as UTF-8. + * + * The number of supported character encodings depends on whether your web + * host supports {@link http://php.net/mbstring mbstring}, + * {@link http://php.net/iconv iconv}, or both. See + * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for + * more information. + * + * @param string $encoding + */ + public function set_output_encoding($encoding = 'UTF-8') + { + $this->sanitize->set_output_encoding($encoding); + } + + public function strip_comments($strip = false) + { + $this->sanitize->strip_comments($strip); + } + + /** + * Set element/attribute key/value pairs of HTML attributes + * containing URLs that need to be resolved relative to the feed + * + * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite, + * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite, + * |q|@cite + * + * @since 1.0 + * @param array|null $element_attribute Element/attribute key/value pairs, null for default + */ + public function set_url_replacements($element_attribute = null) + { + $this->sanitize->set_url_replacements($element_attribute); + } + + /** + * Set the handler to enable the display of cached images. + * + * @param str $page Web-accessible path to the handler_image.php file. + * @param str $qs The query string that the value should be passed to. + */ + public function set_image_handler($page = false, $qs = 'i') + { + if ($page !== false) + { + $this->sanitize->set_image_handler($page . '?' . $qs . '='); + } + else + { + $this->image_handler = ''; + } + } + + /** + * Set the limit for items returned per-feed with multifeeds + * + * @param integer $limit The maximum number of items to return. + */ + public function set_item_limit($limit = 0) + { + $this->item_limit = (int) $limit; + } + + /** + * Initialize the feed object + * + * This is what makes everything happen. Period. This is where all of the + * configuration options get processed, feeds are fetched, cached, and + * parsed, and all of that other good stuff. + * + * @return boolean True if successful, false otherwise + */ + public function init() + { + // Check absolute bare minimum requirements. + if (!extension_loaded('xml') || !extension_loaded('pcre')) + { + return false; + } + // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader. + elseif (!extension_loaded('xmlreader')) + { + static $xml_is_sane = null; + if ($xml_is_sane === null) + { + $parser_check = xml_parser_create(); + xml_parse_into_struct($parser_check, '<foo>&</foo>', $values); + xml_parser_free($parser_check); + $xml_is_sane = isset($values[0]['value']); + } + if (!$xml_is_sane) + { + return false; + } + } + + if (method_exists($this->sanitize, 'set_registry')) + { + $this->sanitize->set_registry($this->registry); + } + + // Pass whatever was set with config options over to the sanitizer. + // Pass the classes in for legacy support; new classes should use the registry instead + $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache')); + $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen); + + if (!empty($this->multifeed_url)) + { + $i = 0; + $success = 0; + $this->multifeed_objects = array(); + $this->error = array(); + foreach ($this->multifeed_url as $url) + { + $this->multifeed_objects[$i] = clone $this; + $this->multifeed_objects[$i]->set_feed_url($url); + $single_success = $this->multifeed_objects[$i]->init(); + $success |= $single_success; + if (!$single_success) + { + $this->error[$i] = $this->multifeed_objects[$i]->error(); + } + $i++; + } + return (bool) $success; + } + elseif ($this->feed_url === null && $this->raw_data === null) + { + return false; + } + + $this->error = null; + $this->data = array(); + $this->multifeed_objects = array(); + $cache = false; + + if ($this->feed_url !== null) + { + $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url)); + + // Decide whether to enable caching + if ($this->cache && $parsed_feed_url['scheme'] !== '') + { + $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc')); + } + + // Fetch the data via SimplePie_File into $this->raw_data + if (($fetched = $this->fetch_data($cache)) === true) + { + return true; + } + elseif ($fetched === false) { + return false; + } + + list($headers, $sniffed) = $fetched; + } + + // Set up array of possible encodings + $encodings = array(); + + // First check to see if input has been overridden. + if ($this->input_encoding !== false) + { + $encodings[] = $this->input_encoding; + } + + $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity'); + $text_types = array('text/xml', 'text/xml-external-parsed-entity'); + + // RFC 3023 (only applies to sniffed content) + if (isset($sniffed)) + { + if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml') + { + if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) + { + $encodings[] = strtoupper($charset[1]); + } + $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry))); + $encodings[] = 'UTF-8'; + } + elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml') + { + if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) + { + $encodings[] = $charset[1]; + } + $encodings[] = 'US-ASCII'; + } + // Text MIME-type default + elseif (substr($sniffed, 0, 5) === 'text/') + { + $encodings[] = 'US-ASCII'; + } + } + + // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1 + $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry))); + $encodings[] = 'UTF-8'; + $encodings[] = 'ISO-8859-1'; + + // There's no point in trying an encoding twice + $encodings = array_unique($encodings); + + // Loop through each possible encoding, till we return something, or run out of possibilities + foreach ($encodings as $encoding) + { + // Change the encoding to UTF-8 (as we always use UTF-8 internally) + if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8'))) + { + // Create new parser + $parser = $this->registry->create('Parser'); + + // If it's parsed fine + if ($parser->parse($utf8_data, 'UTF-8')) + { + $this->data = $parser->get_data(); + if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE)) + { + $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed."; + $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); + return false; + } + + if (isset($headers)) + { + $this->data['headers'] = $headers; + } + $this->data['build'] = SIMPLEPIE_BUILD; + + // Cache the file if caching is enabled + if ($cache && !$cache->save($this)) + { + trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); + } + return true; + } + } + } + + if (isset($parser)) + { + // We have an error, just set SimplePie_Misc::error to it and quit + $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column()); + } + else + { + $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.'; + } + + $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); + + return false; + } + + /** + * Fetch the data via SimplePie_File + * + * If the data is already cached, attempt to fetch it from there instead + * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache + * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type + */ + protected function fetch_data(&$cache) + { + // If it's enabled, use the cache + if ($cache) + { + // Load the Cache + $this->data = $cache->load(); + if (!empty($this->data)) + { + // If the cache is for an outdated build of SimplePie + if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD) + { + $cache->unlink(); + $this->data = array(); + } + // If we've hit a collision just rerun it with caching disabled + elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) + { + $cache = false; + $this->data = array(); + } + // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL. + elseif (isset($this->data['feed_url'])) + { + // If the autodiscovery cache is still valid use it. + if ($cache->mtime() + $this->autodiscovery_cache_duration > time()) + { + // Do not need to do feed autodiscovery yet. + if ($this->data['feed_url'] !== $this->data['url']) + { + $this->set_feed_url($this->data['feed_url']); + return $this->init(); + } + + $cache->unlink(); + $this->data = array(); + } + } + // Check if the cache has been updated + elseif ($cache->mtime() + $this->cache_duration < time()) + { + // If we have last-modified and/or etag set + if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) + { + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + if (isset($this->data['headers']['last-modified'])) + { + $headers['if-modified-since'] = $this->data['headers']['last-modified']; + } + if (isset($this->data['headers']['etag'])) + { + $headers['if-none-match'] = $this->data['headers']['etag']; + } + + $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen)); + + if ($file->success) + { + if ($file->status_code === 304) + { + $cache->touch(); + return true; + } + } + else + { + unset($file); + } + } + } + // If the cache is still valid, just return true + else + { + $this->raw_data = false; + return true; + } + } + // If the cache is empty, delete it + else + { + $cache->unlink(); + $this->data = array(); + } + } + // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it. + if (!isset($file)) + { + if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url) + { + $file =& $this->file; + } + else + { + $headers = array( + 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1', + ); + $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen)); + } + } + // If the file connection has an error, set SimplePie::error to that and quit + if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) + { + $this->error = $file->error; + return !empty($this->data); + } + + if (!$this->force_feed) + { + // Check if the supplied URL is a feed, if it isn't, look for it. + $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds)); + + if (!$locate->is_feed($file)) + { + // We need to unset this so that if SimplePie::set_file() has been called that object is untouched + unset($file); + try + { + if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))) + { + $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed."; + $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__)); + return false; + } + } + catch (SimplePie_Exception $e) + { + // This is usually because DOMDocument doesn't exist + $this->error = $e->getMessage(); + $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine())); + return false; + } + if ($cache) + { + $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD); + if (!$cache->save($this)) + { + trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING); + } + $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc')); + } + $this->feed_url = $file->url; + } + $locate = null; + } + + $this->raw_data = $file->body; + + $headers = $file->headers; + $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file)); + $sniffed = $sniffer->get_type(); + + return array($headers, $sniffed); + } + + /** + * Get the error message for the occured error + * + * @return string|array Error message, or array of messages for multifeeds + */ + public function error() + { + return $this->error; + } + + /** + * Get the raw XML + * + * This is the same as the old `$feed->enable_xml_dump(true)`, but returns + * the data instead of printing it. + * + * @return string|boolean Raw XML data, false if the cache is used + */ + public function get_raw_data() + { + return $this->raw_data; + } + + /** + * Get the character encoding used for output + * + * @since Preview Release + * @return string + */ + public function get_encoding() + { + return $this->sanitize->output_encoding; + } + + /** + * Send the content-type header with correct encoding + * + * This method ensures that the SimplePie-enabled page is being served with + * the correct {@link http://www.iana.org/assignments/media-types/ mime-type} + * and character encoding HTTP headers (character encoding determined by the + * {@see set_output_encoding} config option). + * + * This won't work properly if any content or whitespace has already been + * sent to the browser, because it relies on PHP's + * {@link http://php.net/header header()} function, and these are the + * circumstances under which the function works. + * + * Because it's setting these settings for the entire page (as is the nature + * of HTTP headers), this should only be used once per page (again, at the + * top). + * + * @param string $mime MIME type to serve the page as + */ + public function handle_content_type($mime = 'text/html') + { + if (!headers_sent()) + { + $header = "Content-type: $mime;"; + if ($this->get_encoding()) + { + $header .= ' charset=' . $this->get_encoding(); + } + else + { + $header .= ' charset=UTF-8'; + } + header($header); + } + } + + /** + * Get the type of the feed + * + * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against + * using {@link http://php.net/language.operators.bitwise bitwise operators} + * + * @since 0.8 (usage changed to using constants in 1.0) + * @see SIMPLEPIE_TYPE_NONE Unknown. + * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90. + * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape). + * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland). + * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91. + * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92. + * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93. + * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94. + * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0. + * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x. + * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS. + * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format). + * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS. + * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3. + * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0. + * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom. + * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type. + * @return int SIMPLEPIE_TYPE_* constant + */ + public function get_type() + { + if (!isset($this->data['type'])) + { + $this->data['type'] = SIMPLEPIE_TYPE_ALL; + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'])) + { + $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10; + } + elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'])) + { + $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03; + } + elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'])) + { + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel']) + || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image']) + || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']) + || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput'])) + { + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10; + } + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel']) + || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image']) + || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']) + || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput'])) + { + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090; + } + } + elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'])) + { + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL; + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) + { + switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) + { + case '0.91': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091; + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) + { + switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) + { + case '0': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE; + break; + + case '24': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND; + break; + } + } + break; + + case '0.92': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092; + break; + + case '0.93': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093; + break; + + case '0.94': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094; + break; + + case '2.0': + $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20; + break; + } + } + } + else + { + $this->data['type'] = SIMPLEPIE_TYPE_NONE; + } + } + return $this->data['type']; + } + + /** + * Get the URL for the feed + * + * May or may not be different from the URL passed to {@see set_feed_url()}, + * depending on whether auto-discovery was used. + * + * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.) + * @todo If we have a perm redirect we should return the new URL + * @todo When we make the above change, let's support <itunes:new-feed-url> as well + * @todo Also, |atom:link|@rel=self + * @return string|null + */ + public function subscribe_url() + { + if ($this->feed_url !== null) + { + return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI); + } + else + { + return null; + } + } + + /** + * Get data for an feed-level element + * + * This method allows you to get access to ANY element/attribute that is a + * sub-element of the opening feed tag. + * + * The return value is an indexed array of elements matching the given + * namespace and tag name. Each element has `attribs`, `data` and `child` + * subkeys. For `attribs` and `child`, these contain namespace subkeys. + * `attribs` then has one level of associative name => value data (where + * `value` is a string) after the namespace. `child` has tag-indexed keys + * after the namespace, each member of which is an indexed array matching + * this same format. + * + * For example: + * <pre> + * // This is probably a bad example because we already support + * // <media:content> natively, but it shows you how to parse through + * // the nodes. + * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group'); + * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']; + * $file = $content[0]['attribs']['']['url']; + * echo $file; + * </pre> + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_feed_tags($namespace, $tag) + { + $type = $this->get_type(); + if ($type & SIMPLEPIE_TYPE_ATOM_10) + { + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag])) + { + return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]; + } + } + if ($type & SIMPLEPIE_TYPE_ATOM_03) + { + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag])) + { + return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]; + } + } + if ($type & SIMPLEPIE_TYPE_RSS_RDF) + { + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag])) + { + return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]; + } + } + if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION) + { + if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag])) + { + return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]; + } + } + return null; + } + + /** + * Get data for an channel-level element + * + * This method allows you to get access to ANY element/attribute in the + * channel/header section of the feed. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_channel_tags($namespace, $tag) + { + $type = $this->get_type(); + if ($type & SIMPLEPIE_TYPE_ATOM_ALL) + { + if ($return = $this->get_feed_tags($namespace, $tag)) + { + return $return; + } + } + if ($type & SIMPLEPIE_TYPE_RSS_10) + { + if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel')) + { + if (isset($channel[0]['child'][$namespace][$tag])) + { + return $channel[0]['child'][$namespace][$tag]; + } + } + } + if ($type & SIMPLEPIE_TYPE_RSS_090) + { + if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel')) + { + if (isset($channel[0]['child'][$namespace][$tag])) + { + return $channel[0]['child'][$namespace][$tag]; + } + } + } + if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION) + { + if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel')) + { + if (isset($channel[0]['child'][$namespace][$tag])) + { + return $channel[0]['child'][$namespace][$tag]; + } + } + } + return null; + } + + /** + * Get data for an channel-level element + * + * This method allows you to get access to ANY element/attribute in the + * image/logo section of the feed. + * + * See {@see SimplePie::get_feed_tags()} for a description of the return value + * + * @since 1.0 + * @see http://simplepie.org/wiki/faq/supported_xml_namespaces + * @param string $namespace The URL of the XML namespace of the elements you're trying to access + * @param string $tag Tag name + * @return array + */ + public function get_image_tags($namespace, $tag) + { + $type = $this->get_type(); + if ($type & SIMPLEPIE_TYPE_RSS_10) + { + if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image')) + { + if (isset($image[0]['child'][$namespace][$tag])) + { + return $image[0]['child'][$namespace][$tag]; + } + } + } + if ($type & SIMPLEPIE_TYPE_RSS_090) + { + if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image')) + { + if (isset($image[0]['child'][$namespace][$tag])) + { + return $image[0]['child'][$namespace][$tag]; + } + } + } + if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION) + { + if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image')) + { + if (isset($image[0]['child'][$namespace][$tag])) + { + return $image[0]['child'][$namespace][$tag]; + } + } + } + return null; + } + + /** + * Get the base URL value from the feed + * + * Uses `<xml:base>` if available, otherwise uses the first link in the + * feed, or failing that, the URL of the feed itself. + * + * @see get_link + * @see subscribe_url + * + * @param array $element + * @return string + */ + public function get_base($element = array()) + { + if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base'])) + { + return $element['xml_base']; + } + elseif ($this->get_link() !== null) + { + return $this->get_link(); + } + else + { + return $this->subscribe_url(); + } + } + + /** + * Sanitize feed data + * + * @access private + * @see SimplePie_Sanitize::sanitize() + * @param string $data Data to sanitize + * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants + * @param string $base Base URL to resolve URLs against + * @return string Sanitized data + */ + public function sanitize($data, $type, $base = '') + { + return $this->sanitize->sanitize($data, $type, $base); + } + + /** + * Get the title of the feed + * + * Uses `<atom:title>`, `<title>` or `<dc:title>` + * + * @since 1.0 (previously called `get_feed_title` since 0.8) + * @return string|null + */ + public function get_title() + { + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + /** + * Get a category for the feed + * + * @since Unknown + * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Category|null + */ + public function get_category($key = 0) + { + $categories = $this->get_categories(); + if (isset($categories[$key])) + { + return $categories[$key]; + } + else + { + return null; + } + } + + /** + * Get all categories for the feed + * + * Uses `<atom:category>`, `<category>` or `<dc:subject>` + * + * @since Unknown + * @return array|null List of {@see SimplePie_Category} objects + */ + public function get_categories() + { + $categories = array(); + + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category) + { + $term = null; + $scheme = null; + $label = null; + if (isset($category['attribs']['']['term'])) + { + $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['scheme'])) + { + $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($category['attribs']['']['label'])) + { + $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT); + } + $categories[] = $this->registry->create('Category', array($term, $scheme, $label)); + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category) + { + // This is really the label, but keep this as the term also for BC. + // Label will also work on retrieving because that falls back to term. + $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT); + if (isset($category['attribs']['']['domain'])) + { + $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + $scheme = null; + } + $categories[] = $this->registry->create('Category', array($term, $scheme, null)); + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category) + { + $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($categories)) + { + return array_unique($categories); + } + else + { + return null; + } + } + + /** + * Get an author for the feed + * + * @since 1.1 + * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_author($key = 0) + { + $authors = $this->get_authors(); + if (isset($authors[$key])) + { + return $authors[$key]; + } + else + { + return null; + } + } + + /** + * Get all authors for the feed + * + * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>` + * + * @since 1.1 + * @return array|null List of {@see SimplePie_Author} objects + */ + public function get_authors() + { + $authors = array(); + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author) + { + $name = null; + $uri = null; + $email = null; + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $authors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author')) + { + $name = null; + $url = null; + $email = null; + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $authors[] = $this->registry->create('Author', array($name, $url, $email)); + } + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author) + { + $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null)); + } + + if (!empty($authors)) + { + return array_unique($authors); + } + else + { + return null; + } + } + + /** + * Get a contributor for the feed + * + * @since 1.1 + * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Author|null + */ + public function get_contributor($key = 0) + { + $contributors = $this->get_contributors(); + if (isset($contributors[$key])) + { + return $contributors[$key]; + } + else + { + return null; + } + } + + /** + * Get all contributors for the feed + * + * Uses `<atom:contributor>` + * + * @since 1.1 + * @return array|null List of {@see SimplePie_Author} objects + */ + public function get_contributors() + { + $contributors = array(); + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor) + { + $name = null; + $uri = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])) + { + $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $uri !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $uri, $email)); + } + } + foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor) + { + $name = null; + $url = null; + $email = null; + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'])) + { + $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'])) + { + $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0])); + } + if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'])) + { + $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + if ($name !== null || $email !== null || $url !== null) + { + $contributors[] = $this->registry->create('Author', array($name, $url, $email)); + } + } + + if (!empty($contributors)) + { + return array_unique($contributors); + } + else + { + return null; + } + } + + /** + * Get a single link for the feed + * + * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) + * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1 + * @param string $rel The relationship of the link to return + * @return string|null Link URL + */ + public function get_link($key = 0, $rel = 'alternate') + { + $links = $this->get_links($rel); + if (isset($links[$key])) + { + return $links[$key]; + } + else + { + return null; + } + } + + /** + * Get the permalink for the item + * + * Returns the first link available with a relationship of "alternate". + * Identical to {@see get_link()} with key 0 + * + * @see get_link + * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8) + * @internal Added for parity between the parent-level and the item/entry-level. + * @return string|null Link URL + */ + public function get_permalink() + { + return $this->get_link(0); + } + + /** + * Get all links for the feed + * + * Uses `<atom:link>` or `<link>` + * + * @since Beta 2 + * @param string $rel The relationship of links to return + * @return array|null Links found for the feed (strings) + */ + public function get_links($rel = 'alternate') + { + if (!isset($this->data['links'])) + { + $this->data['links'] = array(); + if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link')) + { + foreach ($links as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + } + } + } + if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link')) + { + foreach ($links as $link) + { + if (isset($link['attribs']['']['href'])) + { + $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate'; + $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link)); + + } + } + } + if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0])); + } + + $keys = array_keys($this->data['links']); + foreach ($keys as $key) + { + if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key))) + { + if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key])) + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]); + $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]; + } + else + { + $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key]; + } + } + elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY) + { + $this->data['links'][substr($key, 41)] =& $this->data['links'][$key]; + } + $this->data['links'][$key] = array_unique($this->data['links'][$key]); + } + } + + if (isset($this->data['links'][$rel])) + { + return $this->data['links'][$rel]; + } + else + { + return null; + } + } + + public function get_all_discovered_feeds() + { + return $this->all_discovered_feeds; + } + + /** + * Get the content for the item + * + * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`, + * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>` + * + * @since 1.0 (previously called `get_feed_description()` since 0.8) + * @return string|null + */ + public function get_description() + { + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0])); + } + else + { + return null; + } + } + + /** + * Get the copyright info for the feed + * + * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>` + * + * @since 1.0 (previously called `get_feed_copyright()` since 0.8) + * @return string|null + */ + public function get_copyright() + { + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright')) + { + return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + /** + * Get the language for the feed + * + * Uses `<language>`, `<dc:language>`, or @xml_lang + * + * @since 1.0 (previously called `get_feed_language()` since 0.8) + * @return string|null + */ + public function get_language() + { + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'])) + { + return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'])) + { + return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'])) + { + return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif (isset($this->data['headers']['content-language'])) + { + return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + /** + * Get the latitude coordinates for the item + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:lat>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_latitude() + { + + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[1]; + } + else + { + return null; + } + } + + /** + * Get the longitude coordinates for the feed + * + * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications + * + * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>` + * + * @since 1.0 + * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo + * @link http://www.georss.org/ GeoRSS + * @return string|null + */ + public function get_longitude() + { + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long')) + { + return (float) $return[0]['data']; + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon')) + { + return (float) $return[0]['data']; + } + elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) + { + return (float) $match[2]; + } + else + { + return null; + } + } + + /** + * Get the feed logo's title + * + * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title. + * + * Uses `<image><title>` or `<image><dc:title>` + * + * @return string|null + */ + public function get_image_title() + { + if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT); + } + else + { + return null; + } + } + + /** + * Get the feed logo's URL + * + * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to + * have a "feed logo" URL. This points directly to the image itself. + * + * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`, + * `<image><title>` or `<image><dc:title>` + * + * @return string|null + */ + public function get_image_url() + { + if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image')) + { + return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + else + { + return null; + } + } + + + /** + * Get the feed logo's link + * + * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This + * points to a human-readable page that the image should link to. + * + * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`, + * `<image><title>` or `<image><dc:title>` + * + * @return string|null + */ + public function get_image_link() + { + if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link')) + { + return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + } + else + { + return null; + } + } + + /** + * Get the feed logo's link + * + * RSS 2.0 feeds are allowed to have a "feed logo" width. + * + * Uses `<image><width>` or defaults to 88.0 if no width is specified and + * the feed is an RSS 2.0 feed. + * + * @return int|float|null + */ + public function get_image_width() + { + if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width')) + { + return round($return[0]['data']); + } + elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url')) + { + return 88.0; + } + else + { + return null; + } + } + + /** + * Get the feed logo's height + * + * RSS 2.0 feeds are allowed to have a "feed logo" height. + * + * Uses `<image><height>` or defaults to 31.0 if no height is specified and + * the feed is an RSS 2.0 feed. + * + * @return int|float|null + */ + public function get_image_height() + { + if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height')) + { + return round($return[0]['data']); + } + elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url')) + { + return 31.0; + } + else + { + return null; + } + } + + /** + * Get the number of items in the feed + * + * This is well-suited for {@link http://php.net/for for()} loops with + * {@see get_item()} + * + * @param int $max Maximum value to return. 0 for no limit + * @return int Number of items in the feed + */ + public function get_item_quantity($max = 0) + { + $max = (int) $max; + $qty = count($this->get_items()); + if ($max === 0) + { + return $qty; + } + else + { + return ($qty > $max) ? $max : $qty; + } + } + + /** + * Get a single item from the feed + * + * This is better suited for {@link http://php.net/for for()} loops, whereas + * {@see get_items()} is better suited for + * {@link http://php.net/foreach foreach()} loops. + * + * @see get_item_quantity() + * @since Beta 2 + * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1 + * @return SimplePie_Item|null + */ + public function get_item($key = 0) + { + $items = $this->get_items(); + if (isset($items[$key])) + { + return $items[$key]; + } + else + { + return null; + } + } + + /** + * Get all items from the feed + * + * This is better suited for {@link http://php.net/for for()} loops, whereas + * {@see get_items()} is better suited for + * {@link http://php.net/foreach foreach()} loops. + * + * @see get_item_quantity + * @since Beta 2 + * @param int $start Index to start at + * @param int $end Number of items to return. 0 for all items after `$start` + * @return array|null List of {@see SimplePie_Item} objects + */ + public function get_items($start = 0, $end = 0) + { + if (!isset($this->data['items'])) + { + if (!empty($this->multifeed_objects)) + { + $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit); + } + else + { + $this->data['items'] = array(); + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry')) + { + $keys = array_keys($items); + foreach ($keys as $key) + { + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); + } + } + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry')) + { + $keys = array_keys($items); + foreach ($keys as $key) + { + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); + } + } + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item')) + { + $keys = array_keys($items); + foreach ($keys as $key) + { + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); + } + } + if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item')) + { + $keys = array_keys($items); + foreach ($keys as $key) + { + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); + } + } + if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item')) + { + $keys = array_keys($items); + foreach ($keys as $key) + { + $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key])); + } + } + } + } + + if (!empty($this->data['items'])) + { + // If we want to order it by date, check if all items have a date, and then sort it + if ($this->order_by_date && empty($this->multifeed_objects)) + { + if (!isset($this->data['ordered_items'])) + { + $do_sort = true; + foreach ($this->data['items'] as $item) + { + if (!$item->get_date('U')) + { + $do_sort = false; + break; + } + } + $item = null; + $this->data['ordered_items'] = $this->data['items']; + if ($do_sort) + { + usort($this->data['ordered_items'], array(get_class($this), 'sort_items')); + } + } + $items = $this->data['ordered_items']; + } + else + { + $items = $this->data['items']; + } + + // Slice the data as desired + if ($end === 0) + { + return array_slice($items, $start); + } + else + { + return array_slice($items, $start, $end); + } + } + else + { + return array(); + } + } + + /** + * Set the favicon handler + * + * @deprecated Use your own favicon handling instead + */ + public function set_favicon_handler($page = false, $qs = 'i') + { + $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING; + trigger_error('Favicon handling has been removed, please use your own handling', $level); + return false; + } + + /** + * Get the favicon for the current feed + * + * @deprecated Use your own favicon handling instead + */ + public function get_favicon() + { + $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING; + trigger_error('Favicon handling has been removed, please use your own handling', $level); + + if (($url = $this->get_link()) !== null) + { + return 'http://g.etfv.co/' . urlencode($url); + } + + return false; + } + + /** + * Magic method handler + * + * @param string $method Method name + * @param array $args Arguments to the method + * @return mixed + */ + public function __call($method, $args) + { + if (strpos($method, 'subscribe_') === 0) + { + $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING; + trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level); + return ''; + } + if ($method === 'enable_xml_dump') + { + $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING; + trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level); + return false; + } + + $class = get_class($this); + $trace = debug_backtrace(); + $file = $trace[0]['file']; + $line = $trace[0]['line']; + trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR); + } + + /** + * Sorting callback for items + * + * @access private + * @param SimplePie $a + * @param SimplePie $b + * @return boolean + */ + public static function sort_items($a, $b) + { + return $a->get_date('U') <= $b->get_date('U'); + } + + /** + * Merge items from several feeds into one + * + * If you're merging multiple feeds together, they need to all have dates + * for the items or else SimplePie will refuse to sort them. + * + * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings + * @param array $urls List of SimplePie feed objects to merge + * @param int $start Starting item + * @param int $end Number of items to return + * @param int $limit Maximum number of items per feed + * @return array + */ + public static function merge_items($urls, $start = 0, $end = 0, $limit = 0) + { + if (is_array($urls) && sizeof($urls) > 0) + { + $items = array(); + foreach ($urls as $arg) + { + if ($arg instanceof SimplePie) + { + $items = array_merge($items, $arg->get_items(0, $limit)); + } + else + { + trigger_error('Arguments must be SimplePie objects', E_USER_WARNING); + } + } + + $do_sort = true; + foreach ($items as $item) + { + if (!$item->get_date('U')) + { + $do_sort = false; + break; + } + } + $item = null; + if ($do_sort) + { + usort($items, array(get_class($urls[0]), 'sort_items')); + } + + if ($end === 0) + { + return array_slice($items, $start); + } + else + { + return array_slice($items, $start, $end); + } + } + else + { + trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING); + return array(); + } + } +} +endif; \ No newline at end of file diff --git a/sources/wp-includes/class-smtp.php b/sources/wp-includes/class-smtp.php new file mode 100644 index 0000000..72361bb --- /dev/null +++ b/sources/wp-includes/class-smtp.php @@ -0,0 +1,1003 @@ +<?php +/*~ class.smtp.php +.---------------------------------------------------------------------------. +| Software: PHPMailer - PHP email class | +| Version: 5.2.4 | +| Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ | +| ------------------------------------------------------------------------- | +| Admin: Jim Jagielski (project admininistrator) | +| Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net | +| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net | +| : Jim Jagielski (jimjag) jimjag@gmail.com | +| Founder: Brent R. Matzelle (original founder) | +| Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. | +| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. | +| Copyright (c) 2001-2003, Brent R. Matzelle | +| ------------------------------------------------------------------------- | +| License: Distributed under the Lesser General Public License (LGPL) | +| http://www.gnu.org/copyleft/lesser.html | +| This program is distributed in the hope that it will be useful - WITHOUT | +| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | +| FITNESS FOR A PARTICULAR PURPOSE. | +'---------------------------------------------------------------------------' +*/ + +/** + * PHPMailer - PHP SMTP email transport class + * NOTE: Designed for use with PHP version 5 and up + * @package PHPMailer + * @author Andy Prevost + * @author Marcus Bointon + * @copyright 2004 - 2008 Andy Prevost + * @author Jim Jagielski + * @copyright 2010 - 2012 Jim Jagielski + * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) + */ + +/** + * PHP RFC821 SMTP client + * + * Implements all the RFC 821 SMTP commands except TURN which will always return a not implemented error. + * SMTP also provides some utility methods for sending mail to an SMTP server. + * @author Chris Ryan + * @package PHPMailer + */ + +class SMTP { + /** + * SMTP server port + * @var int + */ + public $SMTP_PORT = 25; + + /** + * SMTP reply line ending (don't change) + * @var string + */ + public $CRLF = "\r\n"; + + /** + * Sets whether debugging is turned on + * @var bool + */ + public $do_debug; // the level of debug to perform + + /** + * Sets the function/method to use for debugging output. + * Right now we only honor "echo" or "error_log" + * @var string + */ + public $Debugoutput = "echo"; + + /** + * Sets VERP use on/off (default is off) + * @var bool + */ + public $do_verp = false; + + /** + * Sets the SMTP timeout value for reads, in seconds + * @var int + */ + public $Timeout = 15; + + /** + * Sets the SMTP timelimit value for reads, in seconds + * @var int + */ + public $Timelimit = 30; + + /** + * Sets the SMTP PHPMailer Version number + * @var string + */ + public $Version = '5.2.4'; + + ///////////////////////////////////////////////// + // PROPERTIES, PRIVATE AND PROTECTED + ///////////////////////////////////////////////// + + /** + * @var resource The socket to the server + */ + private $smtp_conn; + /** + * @var string Error message, if any, for the last call + */ + private $error; + /** + * @var string The reply the server sent to us for HELO + */ + private $helo_rply; + + /** + * Outputs debugging info via user-defined method + * @param string $str + */ + private function edebug($str) { + if ($this->Debugoutput == "error_log") { + error_log($str); + } else { + echo $str; + } + } + + /** + * Initialize the class so that the data is in a known state. + * @access public + * @return SMTP + */ + public function __construct() { + $this->smtp_conn = 0; + $this->error = null; + $this->helo_rply = null; + + $this->do_debug = 0; + } + + ///////////////////////////////////////////////// + // CONNECTION FUNCTIONS + ///////////////////////////////////////////////// + + /** + * Connect to the server specified on the port specified. + * If the port is not specified use the default SMTP_PORT. + * If tval is specified then a connection will try and be + * established with the server for that number of seconds. + * If tval is not specified the default is 30 seconds to + * try on the connection. + * + * SMTP CODE SUCCESS: 220 + * SMTP CODE FAILURE: 421 + * @access public + * @param string $host + * @param int $port + * @param int $tval + * @return bool + */ + public function Connect($host, $port = 0, $tval = 30) { + // set the error val to null so there is no confusion + $this->error = null; + + // make sure we are __not__ connected + if($this->connected()) { + // already connected, generate error + $this->error = array("error" => "Already connected to a server"); + return false; + } + + if(empty($port)) { + $port = $this->SMTP_PORT; + } + + // connect to the smtp server + $this->smtp_conn = @fsockopen($host, // the host of the server + $port, // the port to use + $errno, // error number if any + $errstr, // error message if any + $tval); // give up after ? secs + // verify we connected properly + if(empty($this->smtp_conn)) { + $this->error = array("error" => "Failed to connect to server", + "errno" => $errno, + "errstr" => $errstr); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />'); + } + return false; + } + + // SMTP server can take longer to respond, give longer timeout for first read + // Windows does not have support for this timeout function + if(substr(PHP_OS, 0, 3) != "WIN") { + $max = ini_get('max_execution_time'); + if ($max != 0 && $tval > $max) { // don't bother if unlimited + @set_time_limit($tval); + } + stream_set_timeout($this->smtp_conn, $tval, 0); + } + + // get any announcement + $announce = $this->get_lines(); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />'); + } + + return true; + } + + /** + * Initiate a TLS communication with the server. + * + * SMTP CODE 220 Ready to start TLS + * SMTP CODE 501 Syntax error (no parameters allowed) + * SMTP CODE 454 TLS not available due to temporary reason + * @access public + * @return bool success + */ + public function StartTLS() { + $this->error = null; # to avoid confusion + + if(!$this->connected()) { + $this->error = array("error" => "Called StartTLS() without being connected"); + return false; + } + + fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 220) { + $this->error = + array("error" => "STARTTLS not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + + // Begin encrypted connection + if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { + return false; + } + + return true; + } + + /** + * Performs SMTP authentication. Must be run after running the + * Hello() method. Returns true if successfully authenticated. + * @access public + * @param string $username + * @param string $password + * @param string $authtype + * @param string $realm + * @param string $workstation + * @return bool + */ + public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') { + if (empty($authtype)) { + $authtype = 'LOGIN'; + } + + switch ($authtype) { + case 'PLAIN': + // Start authentication + fputs($this->smtp_conn,"AUTH PLAIN" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "AUTH not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + // Send encoded username and password + fputs($this->smtp_conn, base64_encode("\0".$username."\0".$password) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 235) { + $this->error = + array("error" => "Authentication not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + break; + case 'LOGIN': + // Start authentication + fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "AUTH not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + + // Send encoded username + fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "Username not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + + // Send encoded password + fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 235) { + $this->error = + array("error" => "Password not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + break; + case 'NTLM': + /* + * ntlm_sasl_client.php + ** Bundled with Permission + ** + ** How to telnet in windows: http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx + ** PROTOCOL Documentation http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication + */ + require_once('ntlm_sasl_client.php'); + $temp = new stdClass(); + $ntlm_client = new ntlm_sasl_client_class; + if(! $ntlm_client->Initialize($temp)){//let's test if every function its available + $this->error = array("error" => $temp->error); + if($this->do_debug >= 1) { + $this->edebug("You need to enable some modules in your php.ini file: " . $this->error["error"] . $this->CRLF); + } + return false; + } + $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1 + + fputs($this->smtp_conn,"AUTH NTLM " . base64_encode($msg1) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + + if($code != 334) { + $this->error = + array("error" => "AUTH not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF); + } + return false; + } + + $challange = substr($rply,3);//though 0 based, there is a white space after the 3 digit number....//msg2 + $challange = base64_decode($challange); + $ntlm_res = $ntlm_client->NTLMResponse(substr($challange,24,8),$password); + $msg3 = $ntlm_client->TypeMsg3($ntlm_res,$username,$realm,$workstation);//msg3 + // Send encoded username + fputs($this->smtp_conn, base64_encode($msg3) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 235) { + $this->error = + array("error" => "Could not authenticate", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF); + } + return false; + } + break; + } + return true; + } + + /** + * Returns true if connected to a server otherwise false + * @access public + * @return bool + */ + public function Connected() { + if(!empty($this->smtp_conn)) { + $sock_status = socket_get_status($this->smtp_conn); + if($sock_status["eof"]) { + // the socket is valid but we are not connected + if($this->do_debug >= 1) { + $this->edebug("SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"); + } + $this->Close(); + return false; + } + return true; // everything looks good + } + return false; + } + + /** + * Closes the socket and cleans up the state of the class. + * It is not considered good to use this function without + * first trying to use QUIT. + * @access public + * @return void + */ + public function Close() { + $this->error = null; // so there is no confusion + $this->helo_rply = null; + if(!empty($this->smtp_conn)) { + // close the connection and cleanup + fclose($this->smtp_conn); + $this->smtp_conn = 0; + } + } + + ///////////////////////////////////////////////// + // SMTP COMMANDS + ///////////////////////////////////////////////// + + /** + * Issues a data command and sends the msg_data to the server + * finializing the mail transaction. $msg_data is the message + * that is to be send with the headers. Each header needs to be + * on a single line followed by a <CRLF> with the message headers + * and the message body being seperated by and additional <CRLF>. + * + * Implements rfc 821: DATA <CRLF> + * + * SMTP CODE INTERMEDIATE: 354 + * [data] + * <CRLF>.<CRLF> + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 552,554,451,452 + * SMTP CODE FAILURE: 451,554 + * SMTP CODE ERROR : 500,501,503,421 + * @access public + * @param string $msg_data + * @return bool + */ + public function Data($msg_data) { + $this->error = null; // so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Data() without being connected"); + return false; + } + + fputs($this->smtp_conn,"DATA" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 354) { + $this->error = + array("error" => "DATA command not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + + /* the server is ready to accept data! + * according to rfc 821 we should not send more than 1000 + * including the CRLF + * characters on a single line so we will break the data up + * into lines by \r and/or \n then if needed we will break + * each of those into smaller lines to fit within the limit. + * in addition we will be looking for lines that start with + * a period '.' and append and additional period '.' to that + * line. NOTE: this does not count towards limit. + */ + + // normalize the line breaks so we know the explode works + $msg_data = str_replace("\r\n","\n",$msg_data); + $msg_data = str_replace("\r","\n",$msg_data); + $lines = explode("\n",$msg_data); + + /* we need to find a good way to determine is headers are + * in the msg_data or if it is a straight msg body + * currently I am assuming rfc 822 definitions of msg headers + * and if the first field of the first line (':' sperated) + * does not contain a space then it _should_ be a header + * and we can process all lines before a blank "" line as + * headers. + */ + + $field = substr($lines[0],0,strpos($lines[0],":")); + $in_headers = false; + if(!empty($field) && !strstr($field," ")) { + $in_headers = true; + } + + $max_line_length = 998; // used below; set here for ease in change + + while(list(,$line) = @each($lines)) { + $lines_out = null; + if($line == "" && $in_headers) { + $in_headers = false; + } + // ok we need to break this line up into several smaller lines + while(strlen($line) > $max_line_length) { + $pos = strrpos(substr($line,0,$max_line_length)," "); + + // Patch to fix DOS attack + if(!$pos) { + $pos = $max_line_length - 1; + $lines_out[] = substr($line,0,$pos); + $line = substr($line,$pos); + } else { + $lines_out[] = substr($line,0,$pos); + $line = substr($line,$pos + 1); + } + + /* if processing headers add a LWSP-char to the front of new line + * rfc 822 on long msg headers + */ + if($in_headers) { + $line = "\t" . $line; + } + } + $lines_out[] = $line; + + // send the lines to the server + while(list(,$line_out) = @each($lines_out)) { + if(strlen($line_out) > 0) + { + if(substr($line_out, 0, 1) == ".") { + $line_out = "." . $line_out; + } + } + fputs($this->smtp_conn,$line_out . $this->CRLF); + } + } + + // message data has been sent + fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 250) { + $this->error = + array("error" => "DATA not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + return true; + } + + /** + * Sends the HELO command to the smtp server. + * This makes sure that we and the server are in + * the same known state. + * + * Implements from rfc 821: HELO <SP> <domain> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500, 501, 504, 421 + * @access public + * @param string $host + * @return bool + */ + public function Hello($host = '') { + $this->error = null; // so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Hello() without being connected"); + return false; + } + + // if hostname for HELO was not specified send default + if(empty($host)) { + // determine appropriate default to send to server + $host = "localhost"; + } + + // Send extended hello first (RFC 2821) + if(!$this->SendHello("EHLO", $host)) { + if(!$this->SendHello("HELO", $host)) { + return false; + } + } + + return true; + } + + /** + * Sends a HELO/EHLO command. + * @access private + * @param string $hello + * @param string $host + * @return bool + */ + private function SendHello($hello, $host) { + fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />'); + } + + if($code != 250) { + $this->error = + array("error" => $hello . " not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + + $this->helo_rply = $rply; + + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. + * + * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,421 + * @access public + * @param string $from + * @return bool + */ + public function Mail($from) { + $this->error = null; // so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Mail() without being connected"); + return false; + } + + $useVerp = ($this->do_verp ? " XVERP" : ""); + fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 250) { + $this->error = + array("error" => "MAIL not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + return true; + } + + /** + * Sends the quit command to the server and then closes the socket + * if there is no error or the $close_on_error argument is true. + * + * Implements from rfc 821: QUIT <CRLF> + * + * SMTP CODE SUCCESS: 221 + * SMTP CODE ERROR : 500 + * @access public + * @param bool $close_on_error + * @return bool + */ + public function Quit($close_on_error = true) { + $this->error = null; // so there is no confusion + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Quit() without being connected"); + return false; + } + + // send the quit command to the server + fputs($this->smtp_conn,"quit" . $this->CRLF); + + // get any good-bye messages + $byemsg = $this->get_lines(); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />'); + } + + $rval = true; + $e = null; + + $code = substr($byemsg,0,3); + if($code != 221) { + // use e as a tmp var cause Close will overwrite $this->error + $e = array("error" => "SMTP server rejected quit command", + "smtp_code" => $code, + "smtp_rply" => substr($byemsg,4)); + $rval = false; + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />'); + } + } + + if(empty($e) || $close_on_error) { + $this->Close(); + } + + return $rval; + } + + /** + * Sends the command RCPT to the SMTP server with the TO: argument of $to. + * Returns true if the recipient was accepted false if it was rejected. + * + * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> + * + * SMTP CODE SUCCESS: 250,251 + * SMTP CODE FAILURE: 550,551,552,553,450,451,452 + * SMTP CODE ERROR : 500,501,503,421 + * @access public + * @param string $to + * @return bool + */ + public function Recipient($to) { + $this->error = null; // so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Recipient() without being connected"); + return false; + } + + fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 250 && $code != 251) { + $this->error = + array("error" => "RCPT not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + return true; + } + + /** + * Sends the RSET command to abort and transaction that is + * currently in progress. Returns true if successful false + * otherwise. + * + * Implements rfc 821: RSET <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500,501,504,421 + * @access public + * @return bool + */ + public function Reset() { + $this->error = null; // so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Reset() without being connected"); + return false; + } + + fputs($this->smtp_conn,"RSET" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 250) { + $this->error = + array("error" => "RSET failed", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * + * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @param string $from + * @return bool + */ + public function SendAndMail($from) { + $this->error = null; // so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called SendAndMail() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + $this->edebug("SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />'); + } + + if($code != 250) { + $this->error = + array("error" => "SAML not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />'); + } + return false; + } + return true; + } + + /** + * This is an optional command for SMTP that this class does not + * support. This method is here to make the RFC821 Definition + * complete for this class and __may__ be implimented in the future + * + * Implements from rfc 821: TURN <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 502 + * SMTP CODE ERROR : 500, 503 + * @access public + * @return bool + */ + public function Turn() { + $this->error = array("error" => "This method, TURN, of the SMTP ". + "is not implemented"); + if($this->do_debug >= 1) { + $this->edebug("SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />'); + } + return false; + } + + /** + * Get the current error + * @access public + * @return array + */ + public function getError() { + return $this->error; + } + + ///////////////////////////////////////////////// + // INTERNAL FUNCTIONS + ///////////////////////////////////////////////// + + /** + * Read in as many lines as possible + * either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * @access private + * @return string + */ + private function get_lines() { + $data = ""; + $endtime = 0; + /* If for some reason the fp is bad, don't inf loop */ + if (!is_resource($this->smtp_conn)) { + return $data; + } + stream_set_timeout($this->smtp_conn, $this->Timeout); + if ($this->Timelimit > 0) { + $endtime = time() + $this->Timelimit; + } + while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { + $str = @fgets($this->smtp_conn,515); + if($this->do_debug >= 4) { + $this->edebug("SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />'); + $this->edebug("SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />'); + } + $data .= $str; + if($this->do_debug >= 4) { + $this->edebug("SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />'); + } + // if 4th character is a space, we are done reading, break the loop + if(substr($str,3,1) == " ") { break; } + // Timed-out? Log and break + $info = stream_get_meta_data($this->smtp_conn); + if ($info['timed_out']) { + if($this->do_debug >= 4) { + $this->edebug("SMTP -> get_lines(): timed-out (" . $this->Timeout . " seconds) <br />"); + } + break; + } + // Now check if reads took too long + if ($endtime) { + if (time() > $endtime) { + if($this->do_debug >= 4) { + $this->edebug("SMTP -> get_lines(): timelimit reached (" . $this->Timelimit . " seconds) <br />"); + } + break; + } + } + } + return $data; + } + +} +?> diff --git a/sources/wp-includes/class-snoopy.php b/sources/wp-includes/class-snoopy.php new file mode 100644 index 0000000..2c59c48 --- /dev/null +++ b/sources/wp-includes/class-snoopy.php @@ -0,0 +1,1256 @@ +<?php + +/** + * Deprecated. Use WP_HTTP (http.php, class-http.php) instead. + */ +_deprecated_file( basename( __FILE__ ), '3.0', WPINC . '/http.php' ); + +if ( !class_exists( 'Snoopy' ) ) : +/************************************************* + +Snoopy - the PHP net client +Author: Monte Ohrt <monte@ispi.net> +Copyright (c): 1999-2008 New Digital Group, all rights reserved +Version: 1.2.4 + + * This library 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. + * + * This library 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You may contact the author of Snoopy by e-mail at: +monte@ohrt.com + +The latest version of Snoopy can be obtained from: +http://snoopy.sourceforge.net/ + +*************************************************/ + +class Snoopy +{ + /**** Public variables ****/ + + /* user definable vars */ + + var $host = "www.php.net"; // host name we are connecting to + var $port = 80; // port we are connecting to + var $proxy_host = ""; // proxy host to use + var $proxy_port = ""; // proxy port to use + var $proxy_user = ""; // proxy user to use + var $proxy_pass = ""; // proxy password to use + + var $agent = "Snoopy v1.2.4"; // agent we masquerade as + var $referer = ""; // referer info to pass + var $cookies = array(); // array of cookies to pass + // $cookies["username"]="joe"; + var $rawheaders = array(); // array of raw headers to send + // $rawheaders["Content-type"]="text/html"; + + var $maxredirs = 5; // http redirection depth maximum. 0 = disallow + var $lastredirectaddr = ""; // contains address of last redirected address + var $offsiteok = true; // allows redirection off-site + var $maxframes = 0; // frame content depth maximum. 0 = disallow + var $expandlinks = true; // expand links to fully qualified URLs. + // this only applies to fetchlinks() + // submitlinks(), and submittext() + var $passcookies = true; // pass set cookies back through redirects + // NOTE: this currently does not respect + // dates, domains or paths. + + var $user = ""; // user for http authentication + var $pass = ""; // password for http authentication + + // http accept types + var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + + var $results = ""; // where the content is put + + var $error = ""; // error messages sent here + var $response_code = ""; // response code returned from server + var $headers = array(); // headers returned from server sent here + var $maxlength = 500000; // max return data length (body) + var $read_timeout = 0; // timeout on read operations, in seconds + // supported only since PHP 4 Beta 4 + // set to 0 to disallow timeouts + var $timed_out = false; // if a read operation timed out + var $status = 0; // http request status + + var $temp_dir = "/tmp"; // temporary directory that the webserver + // has permission to write to. + // under Windows, this should be C:\temp + + var $curl_path = "/usr/local/bin/curl"; + // Snoopy will use cURL for fetching + // SSL content if a full system path to + // the cURL binary is supplied here. + // set to false if you do not have + // cURL installed. See http://curl.haxx.se + // for details on installing cURL. + // Snoopy does *not* use the cURL + // library functions built into php, + // as these functions are not stable + // as of this Snoopy release. + + /**** Private variables ****/ + + var $_maxlinelen = 4096; // max line length (headers) + + var $_httpmethod = "GET"; // default http request method + var $_httpversion = "HTTP/1.0"; // default http request version + var $_submit_method = "POST"; // default submit method + var $_submit_type = "application/x-www-form-urlencoded"; // default submit type + var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type + var $_redirectaddr = false; // will be set if page fetched is a redirect + var $_redirectdepth = 0; // increments on an http redirect + var $_frameurls = array(); // frame src urls + var $_framedepth = 0; // increments on frame depth + + var $_isproxy = false; // set if using a proxy server + var $_fp_timeout = 30; // timeout for socket connection + +/*======================================================================*\ + Function: fetch + Purpose: fetch the contents of a web page + (and possibly other protocols in the + future like ftp, nntp, gopher, etc.) + Input: $URI the location of the page to fetch + Output: $this->results the output text from the fetch +\*======================================================================*/ + + function fetch($URI) + { + + //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS); + $URI_PARTS = parse_url($URI); + if (!empty($URI_PARTS["user"])) + $this->user = $URI_PARTS["user"]; + if (!empty($URI_PARTS["pass"])) + $this->pass = $URI_PARTS["pass"]; + if (empty($URI_PARTS["query"])) + $URI_PARTS["query"] = ''; + if (empty($URI_PARTS["path"])) + $URI_PARTS["path"] = ''; + + switch(strtolower($URI_PARTS["scheme"])) + { + case "http": + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_connect($fp)) + { + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httprequest($URI,$fp,$URI,$this->_httpmethod); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httprequest($path, $fp, $URI, $this->_httpmethod); + } + + $this->_disconnect($fp); + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + $this->fetch($this->_redirectaddr); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + } + else + { + return false; + } + return true; + break; + case "https": + if(!$this->curl_path) + return false; + if(function_exists("is_executable")) + if (!is_executable($this->curl_path)) + return false; + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httpsrequest($URI,$URI,$this->_httpmethod); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httpsrequest($path, $URI, $this->_httpmethod); + } + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + $this->fetch($this->_redirectaddr); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + return true; + break; + default: + // not a valid protocol + $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; + return false; + break; + } + return true; + } + +/*======================================================================*\ + Function: submit + Purpose: submit an http form + Input: $URI the location to post the data + $formvars the formvars to use. + format: $formvars["var"] = "val"; + $formfiles an array of files to submit + format: $formfiles["var"] = "/dir/filename.ext"; + Output: $this->results the text output from the post +\*======================================================================*/ + + function submit($URI, $formvars="", $formfiles="") + { + unset($postdata); + + $postdata = $this->_prepare_post_body($formvars, $formfiles); + + $URI_PARTS = parse_url($URI); + if (!empty($URI_PARTS["user"])) + $this->user = $URI_PARTS["user"]; + if (!empty($URI_PARTS["pass"])) + $this->pass = $URI_PARTS["pass"]; + if (empty($URI_PARTS["query"])) + $URI_PARTS["query"] = ''; + if (empty($URI_PARTS["path"])) + $URI_PARTS["path"] = ''; + + switch(strtolower($URI_PARTS["scheme"])) + { + case "http": + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_connect($fp)) + { + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata); + } + + $this->_disconnect($fp); + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr)) + $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]); + + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + if( strpos( $this->_redirectaddr, "?" ) > 0 ) + $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get + else + $this->submit($this->_redirectaddr,$formvars, $formfiles); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + + } + else + { + return false; + } + return true; + break; + case "https": + if(!$this->curl_path) + return false; + if(function_exists("is_executable")) + if (!is_executable($this->curl_path)) + return false; + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata); + } + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr)) + $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]); + + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + if( strpos( $this->_redirectaddr, "?" ) > 0 ) + $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get + else + $this->submit($this->_redirectaddr,$formvars, $formfiles); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + return true; + break; + + default: + // not a valid protocol + $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; + return false; + break; + } + return true; + } + +/*======================================================================*\ + Function: fetchlinks + Purpose: fetch the links from a web page + Input: $URI where you are fetching from + Output: $this->results an array of the URLs +\*======================================================================*/ + + function fetchlinks($URI) + { + if ($this->fetch($URI)) + { + if($this->lastredirectaddr) + $URI = $this->lastredirectaddr; + if(is_array($this->results)) + { + for($x=0;$x<count($this->results);$x++) + $this->results[$x] = $this->_striplinks($this->results[$x]); + } + else + $this->results = $this->_striplinks($this->results); + + if($this->expandlinks) + $this->results = $this->_expandlinks($this->results, $URI); + return true; + } + else + return false; + } + +/*======================================================================*\ + Function: fetchform + Purpose: fetch the form elements from a web page + Input: $URI where you are fetching from + Output: $this->results the resulting html form +\*======================================================================*/ + + function fetchform($URI) + { + + if ($this->fetch($URI)) + { + + if(is_array($this->results)) + { + for($x=0;$x<count($this->results);$x++) + $this->results[$x] = $this->_stripform($this->results[$x]); + } + else + $this->results = $this->_stripform($this->results); + + return true; + } + else + return false; + } + + +/*======================================================================*\ + Function: fetchtext + Purpose: fetch the text from a web page, stripping the links + Input: $URI where you are fetching from + Output: $this->results the text from the web page +\*======================================================================*/ + + function fetchtext($URI) + { + if($this->fetch($URI)) + { + if(is_array($this->results)) + { + for($x=0;$x<count($this->results);$x++) + $this->results[$x] = $this->_striptext($this->results[$x]); + } + else + $this->results = $this->_striptext($this->results); + return true; + } + else + return false; + } + +/*======================================================================*\ + Function: submitlinks + Purpose: grab links from a form submission + Input: $URI where you are submitting from + Output: $this->results an array of the links from the post +\*======================================================================*/ + + function submitlinks($URI, $formvars="", $formfiles="") + { + if($this->submit($URI,$formvars, $formfiles)) + { + if($this->lastredirectaddr) + $URI = $this->lastredirectaddr; + if(is_array($this->results)) + { + for($x=0;$x<count($this->results);$x++) + { + $this->results[$x] = $this->_striplinks($this->results[$x]); + if($this->expandlinks) + $this->results[$x] = $this->_expandlinks($this->results[$x],$URI); + } + } + else + { + $this->results = $this->_striplinks($this->results); + if($this->expandlinks) + $this->results = $this->_expandlinks($this->results,$URI); + } + return true; + } + else + return false; + } + +/*======================================================================*\ + Function: submittext + Purpose: grab text from a form submission + Input: $URI where you are submitting from + Output: $this->results the text from the web page +\*======================================================================*/ + + function submittext($URI, $formvars = "", $formfiles = "") + { + if($this->submit($URI,$formvars, $formfiles)) + { + if($this->lastredirectaddr) + $URI = $this->lastredirectaddr; + if(is_array($this->results)) + { + for($x=0;$x<count($this->results);$x++) + { + $this->results[$x] = $this->_striptext($this->results[$x]); + if($this->expandlinks) + $this->results[$x] = $this->_expandlinks($this->results[$x],$URI); + } + } + else + { + $this->results = $this->_striptext($this->results); + if($this->expandlinks) + $this->results = $this->_expandlinks($this->results,$URI); + } + return true; + } + else + return false; + } + + + +/*======================================================================*\ + Function: set_submit_multipart + Purpose: Set the form submission content type to + multipart/form-data +\*======================================================================*/ + function set_submit_multipart() + { + $this->_submit_type = "multipart/form-data"; + } + + +/*======================================================================*\ + Function: set_submit_normal + Purpose: Set the form submission content type to + application/x-www-form-urlencoded +\*======================================================================*/ + function set_submit_normal() + { + $this->_submit_type = "application/x-www-form-urlencoded"; + } + + + + +/*======================================================================*\ + Private functions +\*======================================================================*/ + + +/*======================================================================*\ + Function: _striplinks + Purpose: strip the hyperlinks from an html document + Input: $document document to strip. + Output: $match an array of the links +\*======================================================================*/ + + function _striplinks($document) + { + preg_match_all("'<\s*a\s.*?href\s*=\s* # find <a href= + ([\"\'])? # find single or double quote + (?(1) (.*?)\\1 | ([^\s\>]+)) # if quote found, match up to next matching + # quote, otherwise match up to next space + 'isx",$document,$links); + + + // catenate the non-empty matches from the conditional subpattern + + while(list($key,$val) = each($links[2])) + { + if(!empty($val)) + $match[] = $val; + } + + while(list($key,$val) = each($links[3])) + { + if(!empty($val)) + $match[] = $val; + } + + // return the links + return $match; + } + +/*======================================================================*\ + Function: _stripform + Purpose: strip the form elements from an html document + Input: $document document to strip. + Output: $match an array of the links +\*======================================================================*/ + + function _stripform($document) + { + preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements); + + // catenate the matches + $match = implode("\r\n",$elements[0]); + + // return the links + return $match; + } + + + +/*======================================================================*\ + Function: _striptext + Purpose: strip the text from an html document + Input: $document document to strip. + Output: $text the resulting text +\*======================================================================*/ + + function _striptext($document) + { + + // I didn't use preg eval (//e) since that is only available in PHP 4.0. + // so, list your entities one by one here. I included some of the + // more common ones. + + $search = array("'<script[^>]*?>.*?</script>'si", // strip out javascript + "'<[\/\!]*?[^<>]*?>'si", // strip out html tags + "'([\r\n])[\s]+'", // strip out white space + "'&(quot|#34|#034|#x22);'i", // replace html entities + "'&(amp|#38|#038|#x26);'i", // added hexadecimal values + "'&(lt|#60|#060|#x3c);'i", + "'&(gt|#62|#062|#x3e);'i", + "'&(nbsp|#160|#xa0);'i", + "'&(iexcl|#161);'i", + "'&(cent|#162);'i", + "'&(pound|#163);'i", + "'&(copy|#169);'i", + "'&(reg|#174);'i", + "'&(deg|#176);'i", + "'&(#39|#039|#x27);'", + "'&(euro|#8364);'i", // europe + "'&a(uml|UML);'", // german + "'&o(uml|UML);'", + "'&u(uml|UML);'", + "'&A(uml|UML);'", + "'&O(uml|UML);'", + "'&U(uml|UML);'", + "'ß'i", + ); + $replace = array( "", + "", + "\\1", + "\"", + "&", + "<", + ">", + " ", + chr(161), + chr(162), + chr(163), + chr(169), + chr(174), + chr(176), + chr(39), + chr(128), + chr(0xE4), // ANSI ä + chr(0xF6), // ANSI ö + chr(0xFC), // ANSI ü + chr(0xC4), // ANSI Ä + chr(0xD6), // ANSI Ö + chr(0xDC), // ANSI Ü + chr(0xDF), // ANSI ß + ); + + $text = preg_replace($search,$replace,$document); + + return $text; + } + +/*======================================================================*\ + Function: _expandlinks + Purpose: expand each link into a fully qualified URL + Input: $links the links to qualify + $URI the full URI to get the base from + Output: $expandedLinks the expanded links +\*======================================================================*/ + + function _expandlinks($links,$URI) + { + + preg_match("/^[^\?]+/",$URI,$match); + + $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]); + $match = preg_replace("|/$|","",$match); + $match_part = parse_url($match); + $match_root = + $match_part["scheme"]."://".$match_part["host"]; + + $search = array( "|^http://".preg_quote($this->host)."|i", + "|^(\/)|i", + "|^(?!http://)(?!mailto:)|i", + "|/\./|", + "|/[^\/]+/\.\./|" + ); + + $replace = array( "", + $match_root."/", + $match."/", + "/", + "/" + ); + + $expandedLinks = preg_replace($search,$replace,$links); + + return $expandedLinks; + } + +/*======================================================================*\ + Function: _httprequest + Purpose: go get the http data from the server + Input: $url the url to fetch + $fp the current open file pointer + $URI the full URI + $body body contents to send if any (POST) + Output: +\*======================================================================*/ + + function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="") + { + $cookie_headers = ''; + if($this->passcookies && $this->_redirectaddr) + $this->setcookies(); + + $URI_PARTS = parse_url($URI); + if(empty($url)) + $url = "/"; + $headers = $http_method." ".$url." ".$this->_httpversion."\r\n"; + if(!empty($this->agent)) + $headers .= "User-Agent: ".$this->agent."\r\n"; + if(!empty($this->host) && !isset($this->rawheaders['Host'])) { + $headers .= "Host: ".$this->host; + if(!empty($this->port) && $this->port != 80) + $headers .= ":".$this->port; + $headers .= "\r\n"; + } + if(!empty($this->accept)) + $headers .= "Accept: ".$this->accept."\r\n"; + if(!empty($this->referer)) + $headers .= "Referer: ".$this->referer."\r\n"; + if(!empty($this->cookies)) + { + if(!is_array($this->cookies)) + $this->cookies = (array)$this->cookies; + + reset($this->cookies); + if ( count($this->cookies) > 0 ) { + $cookie_headers .= 'Cookie: '; + foreach ( $this->cookies as $cookieKey => $cookieVal ) { + $cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; "; + } + $headers .= substr($cookie_headers,0,-2) . "\r\n"; + } + } + if(!empty($this->rawheaders)) + { + if(!is_array($this->rawheaders)) + $this->rawheaders = (array)$this->rawheaders; + while(list($headerKey,$headerVal) = each($this->rawheaders)) + $headers .= $headerKey.": ".$headerVal."\r\n"; + } + if(!empty($content_type)) { + $headers .= "Content-type: $content_type"; + if ($content_type == "multipart/form-data") + $headers .= "; boundary=".$this->_mime_boundary; + $headers .= "\r\n"; + } + if(!empty($body)) + $headers .= "Content-length: ".strlen($body)."\r\n"; + if(!empty($this->user) || !empty($this->pass)) + $headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n"; + + //add proxy auth headers + if(!empty($this->proxy_user)) + $headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n"; + + + $headers .= "\r\n"; + + // set the read timeout if needed + if ($this->read_timeout > 0) + socket_set_timeout($fp, $this->read_timeout); + $this->timed_out = false; + + fwrite($fp,$headers.$body,strlen($headers.$body)); + + $this->_redirectaddr = false; + unset($this->headers); + + while($currentHeader = fgets($fp,$this->_maxlinelen)) + { + if ($this->read_timeout > 0 && $this->_check_timeout($fp)) + { + $this->status=-100; + return false; + } + + if($currentHeader == "\r\n") + break; + + // if a header begins with Location: or URI:, set the redirect + if(preg_match("/^(Location:|URI:)/i",$currentHeader)) + { + // get URL portion of the redirect + preg_match("/^(Location:|URI:)[ ]+(.*)/i",chop($currentHeader),$matches); + // look for :// in the Location header to see if hostname is included + if(!preg_match("|\:\/\/|",$matches[2])) + { + // no host in the path, so prepend + $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; + // eliminate double slash + if(!preg_match("|^/|",$matches[2])) + $this->_redirectaddr .= "/".$matches[2]; + else + $this->_redirectaddr .= $matches[2]; + } + else + $this->_redirectaddr = $matches[2]; + } + + if(preg_match("|^HTTP/|",$currentHeader)) + { + if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status)) + { + $this->status= $status[1]; + } + $this->response_code = $currentHeader; + } + + $this->headers[] = $currentHeader; + } + + $results = ''; + do { + $_data = fread($fp, $this->maxlength); + if (strlen($_data) == 0) { + break; + } + $results .= $_data; + } while(true); + + if ($this->read_timeout > 0 && $this->_check_timeout($fp)) + { + $this->status=-100; + return false; + } + + // check if there is a redirect meta tag + + if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) + + { + $this->_redirectaddr = $this->_expandlinks($match[1],$URI); + } + + // have we hit our frame depth and is there frame src to fetch? + if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match)) + { + $this->results[] = $results; + for($x=0; $x<count($match[1]); $x++) + $this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); + } + // have we already fetched framed content? + elseif(is_array($this->results)) + $this->results[] = $results; + // no framed content + else + $this->results = $results; + + return true; + } + +/*======================================================================*\ + Function: _httpsrequest + Purpose: go get the https data from the server using curl + Input: $url the url to fetch + $URI the full URI + $body body contents to send if any (POST) + Output: +\*======================================================================*/ + + function _httpsrequest($url,$URI,$http_method,$content_type="",$body="") + { + if($this->passcookies && $this->_redirectaddr) + $this->setcookies(); + + $headers = array(); + + $URI_PARTS = parse_url($URI); + if(empty($url)) + $url = "/"; + // GET ... header not needed for curl + //$headers[] = $http_method." ".$url." ".$this->_httpversion; + if(!empty($this->agent)) + $headers[] = "User-Agent: ".$this->agent; + if(!empty($this->host)) + if(!empty($this->port)) + $headers[] = "Host: ".$this->host.":".$this->port; + else + $headers[] = "Host: ".$this->host; + if(!empty($this->accept)) + $headers[] = "Accept: ".$this->accept; + if(!empty($this->referer)) + $headers[] = "Referer: ".$this->referer; + if(!empty($this->cookies)) + { + if(!is_array($this->cookies)) + $this->cookies = (array)$this->cookies; + + reset($this->cookies); + if ( count($this->cookies) > 0 ) { + $cookie_str = 'Cookie: '; + foreach ( $this->cookies as $cookieKey => $cookieVal ) { + $cookie_str .= $cookieKey."=".urlencode($cookieVal)."; "; + } + $headers[] = substr($cookie_str,0,-2); + } + } + if(!empty($this->rawheaders)) + { + if(!is_array($this->rawheaders)) + $this->rawheaders = (array)$this->rawheaders; + while(list($headerKey,$headerVal) = each($this->rawheaders)) + $headers[] = $headerKey.": ".$headerVal; + } + if(!empty($content_type)) { + if ($content_type == "multipart/form-data") + $headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary; + else + $headers[] = "Content-type: $content_type"; + } + if(!empty($body)) + $headers[] = "Content-length: ".strlen($body); + if(!empty($this->user) || !empty($this->pass)) + $headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass); + + for($curr_header = 0; $curr_header < count($headers); $curr_header++) { + $safer_header = strtr( $headers[$curr_header], "\"", " " ); + $cmdline_params .= " -H \"".$safer_header."\""; + } + + if(!empty($body)) + $cmdline_params .= " -d \"$body\""; + + if($this->read_timeout > 0) + $cmdline_params .= " -m ".$this->read_timeout; + + $headerfile = tempnam($this->temp_dir, "sno"); + + exec($this->curl_path." -k -D \"$headerfile\"".$cmdline_params." \"".escapeshellcmd($URI)."\"",$results,$return); + + if($return) + { + $this->error = "Error: cURL could not retrieve the document, error $return."; + return false; + } + + + $results = implode("\r\n",$results); + + $result_headers = file("$headerfile"); + + $this->_redirectaddr = false; + unset($this->headers); + + for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++) + { + + // if a header begins with Location: or URI:, set the redirect + if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader])) + { + // get URL portion of the redirect + preg_match("/^(Location: |URI:)\s+(.*)/",chop($result_headers[$currentHeader]),$matches); + // look for :// in the Location header to see if hostname is included + if(!preg_match("|\:\/\/|",$matches[2])) + { + // no host in the path, so prepend + $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; + // eliminate double slash + if(!preg_match("|^/|",$matches[2])) + $this->_redirectaddr .= "/".$matches[2]; + else + $this->_redirectaddr .= $matches[2]; + } + else + $this->_redirectaddr = $matches[2]; + } + + if(preg_match("|^HTTP/|",$result_headers[$currentHeader])) + $this->response_code = $result_headers[$currentHeader]; + + $this->headers[] = $result_headers[$currentHeader]; + } + + // check if there is a redirect meta tag + + if(preg_match("'<meta[\s]*http-equiv[^>]*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) + { + $this->_redirectaddr = $this->_expandlinks($match[1],$URI); + } + + // have we hit our frame depth and is there frame src to fetch? + if(($this->_framedepth < $this->maxframes) && preg_match_all("'<frame\s+.*src[\s]*=[\'\"]?([^\'\"\>]+)'i",$results,$match)) + { + $this->results[] = $results; + for($x=0; $x<count($match[1]); $x++) + $this->_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); + } + // have we already fetched framed content? + elseif(is_array($this->results)) + $this->results[] = $results; + // no framed content + else + $this->results = $results; + + unlink("$headerfile"); + + return true; + } + +/*======================================================================*\ + Function: setcookies() + Purpose: set cookies for a redirection +\*======================================================================*/ + + function setcookies() + { + for($x=0; $x<count($this->headers); $x++) + { + if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x],$match)) + $this->cookies[$match[1]] = urldecode($match[2]); + } + } + + +/*======================================================================*\ + Function: _check_timeout + Purpose: checks whether timeout has occurred + Input: $fp file pointer +\*======================================================================*/ + + function _check_timeout($fp) + { + if ($this->read_timeout > 0) { + $fp_status = socket_get_status($fp); + if ($fp_status["timed_out"]) { + $this->timed_out = true; + return true; + } + } + return false; + } + +/*======================================================================*\ + Function: _connect + Purpose: make a socket connection + Input: $fp file pointer +\*======================================================================*/ + + function _connect(&$fp) + { + if(!empty($this->proxy_host) && !empty($this->proxy_port)) + { + $this->_isproxy = true; + + $host = $this->proxy_host; + $port = $this->proxy_port; + } + else + { + $host = $this->host; + $port = $this->port; + } + + $this->status = 0; + + if($fp = fsockopen( + $host, + $port, + $errno, + $errstr, + $this->_fp_timeout + )) + { + // socket connection succeeded + + return true; + } + else + { + // socket connection failed + $this->status = $errno; + switch($errno) + { + case -3: + $this->error="socket creation failed (-3)"; + case -4: + $this->error="dns lookup failure (-4)"; + case -5: + $this->error="connection refused or timed out (-5)"; + default: + $this->error="connection failed (".$errno.")"; + } + return false; + } + } +/*======================================================================*\ + Function: _disconnect + Purpose: disconnect a socket connection + Input: $fp file pointer +\*======================================================================*/ + + function _disconnect($fp) + { + return(fclose($fp)); + } + + +/*======================================================================*\ + Function: _prepare_post_body + Purpose: Prepare post body according to encoding type + Input: $formvars - form variables + $formfiles - form upload files + Output: post body +\*======================================================================*/ + + function _prepare_post_body($formvars, $formfiles) + { + settype($formvars, "array"); + settype($formfiles, "array"); + $postdata = ''; + + if (count($formvars) == 0 && count($formfiles) == 0) + return; + + switch ($this->_submit_type) { + case "application/x-www-form-urlencoded": + reset($formvars); + while(list($key,$val) = each($formvars)) { + if (is_array($val) || is_object($val)) { + while (list($cur_key, $cur_val) = each($val)) { + $postdata .= urlencode($key)."[]=".urlencode($cur_val)."&"; + } + } else + $postdata .= urlencode($key)."=".urlencode($val)."&"; + } + break; + + case "multipart/form-data": + $this->_mime_boundary = "Snoopy".md5(uniqid(microtime())); + + reset($formvars); + while(list($key,$val) = each($formvars)) { + if (is_array($val) || is_object($val)) { + while (list($cur_key, $cur_val) = each($val)) { + $postdata .= "--".$this->_mime_boundary."\r\n"; + $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n"; + $postdata .= "$cur_val\r\n"; + } + } else { + $postdata .= "--".$this->_mime_boundary."\r\n"; + $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n"; + $postdata .= "$val\r\n"; + } + } + + reset($formfiles); + while (list($field_name, $file_names) = each($formfiles)) { + settype($file_names, "array"); + while (list(, $file_name) = each($file_names)) { + if (!is_readable($file_name)) continue; + + $fp = fopen($file_name, "r"); + $file_content = fread($fp, filesize($file_name)); + fclose($fp); + $base_name = basename($file_name); + + $postdata .= "--".$this->_mime_boundary."\r\n"; + $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n"; + $postdata .= "$file_content\r\n"; + } + } + $postdata .= "--".$this->_mime_boundary."--\r\n"; + break; + } + + return $postdata; + } +} +endif; +?> diff --git a/sources/wp-includes/class-wp-admin-bar.php b/sources/wp-includes/class-wp-admin-bar.php new file mode 100644 index 0000000..d35886d --- /dev/null +++ b/sources/wp-includes/class-wp-admin-bar.php @@ -0,0 +1,506 @@ +<?php +/** + * The WordPress Toolbar + * + * @since 3.1.0 + * + * @package WordPress + * @subpackage Toolbar + */ +class WP_Admin_Bar { + private $nodes = array(); + private $bound = false; + public $user; + + public function __get( $name ) { + switch ( $name ) { + case 'proto' : + return is_ssl() ? 'https://' : 'http://'; + break; + case 'menu' : + _deprecated_argument( 'WP_Admin_Bar', '3.3', 'Modify admin bar nodes with WP_Admin_Bar::get_node(), WP_Admin_Bar::add_node(), and WP_Admin_Bar::remove_node(), not the <code>menu</code> property.' ); + return array(); // Sorry, folks. + break; + } + } + + public function initialize() { + $this->user = new stdClass; + + if ( is_user_logged_in() ) { + /* Populate settings we need for the menu based on the current user. */ + $this->user->blogs = get_blogs_of_user( get_current_user_id() ); + if ( is_multisite() ) { + $this->user->active_blog = get_active_blog_for_user( get_current_user_id() ); + $this->user->domain = empty( $this->user->active_blog ) ? user_admin_url() : trailingslashit( get_home_url( $this->user->active_blog->blog_id ) ); + $this->user->account_domain = $this->user->domain; + } else { + $this->user->active_blog = $this->user->blogs[get_current_blog_id()]; + $this->user->domain = trailingslashit( home_url() ); + $this->user->account_domain = $this->user->domain; + } + } + + add_action( 'wp_head', 'wp_admin_bar_header' ); + + add_action( 'admin_head', 'wp_admin_bar_header' ); + + if ( current_theme_supports( 'admin-bar' ) ) { + /** + * To remove the default padding styles from WordPress for the Toolbar, use the following code: + * add_theme_support( 'admin-bar', array( 'callback' => '__return_false' ) ); + */ + $admin_bar_args = get_theme_support( 'admin-bar' ); + $header_callback = $admin_bar_args[0]['callback']; + } + + if ( empty($header_callback) ) + $header_callback = '_admin_bar_bump_cb'; + + add_action('wp_head', $header_callback); + + wp_enqueue_script( 'admin-bar' ); + wp_enqueue_style( 'admin-bar' ); + + /** + * Fires after WP_Admin_Bar is initialized. + * + * @since 3.1.0 + */ + do_action( 'admin_bar_init' ); + } + + public function add_menu( $node ) { + $this->add_node( $node ); + } + + public function remove_menu( $id ) { + $this->remove_node( $id ); + } + + /** + * Add a node to the menu. + * + * @param array $args - The arguments for each node. + * - id - string - The ID of the item. + * - title - string - The title of the node. + * - parent - string - The ID of the parent node. Optional. + * - href - string - The link for the item. Optional. + * - group - boolean - If the node is a group. Optional. Default false. + * - meta - array - Meta data including the following keys: html, class, onclick, target, title, tabindex. + */ + public function add_node( $args ) { + // Shim for old method signature: add_node( $parent_id, $menu_obj, $args ) + if ( func_num_args() >= 3 && is_string( func_get_arg(0) ) ) + $args = array_merge( array( 'parent' => func_get_arg(0) ), func_get_arg(2) ); + + if ( is_object( $args ) ) + $args = get_object_vars( $args ); + + // Ensure we have a valid title. + if ( empty( $args['id'] ) ) { + if ( empty( $args['title'] ) ) + return; + + _doing_it_wrong( __METHOD__, __( 'The menu ID should not be empty.' ), '3.3' ); + // Deprecated: Generate an ID from the title. + $args['id'] = esc_attr( sanitize_title( trim( $args['title'] ) ) ); + } + + $defaults = array( + 'id' => false, + 'title' => false, + 'parent' => false, + 'href' => false, + 'group' => false, + 'meta' => array(), + ); + + // If the node already exists, keep any data that isn't provided. + if ( $maybe_defaults = $this->get_node( $args['id'] ) ) + $defaults = get_object_vars( $maybe_defaults ); + + // Do the same for 'meta' items. + if ( ! empty( $defaults['meta'] ) && ! empty( $args['meta'] ) ) + $args['meta'] = wp_parse_args( $args['meta'], $defaults['meta'] ); + + $args = wp_parse_args( $args, $defaults ); + + $back_compat_parents = array( + 'my-account-with-avatar' => array( 'my-account', '3.3' ), + 'my-blogs' => array( 'my-sites', '3.3' ), + ); + + if ( isset( $back_compat_parents[ $args['parent'] ] ) ) { + list( $new_parent, $version ) = $back_compat_parents[ $args['parent'] ]; + _deprecated_argument( __METHOD__, $version, sprintf( 'Use <code>%s</code> as the parent for the <code>%s</code> admin bar node instead of <code>%s</code>.', $new_parent, $args['id'], $args['parent'] ) ); + $args['parent'] = $new_parent; + } + + $this->_set_node( $args ); + } + + final protected function _set_node( $args ) { + $this->nodes[ $args['id'] ] = (object) $args; + } + + /** + * Gets a node. + * + * @return object Node. + */ + final public function get_node( $id ) { + if ( $node = $this->_get_node( $id ) ) + return clone $node; + } + + final protected function _get_node( $id ) { + if ( $this->bound ) + return; + + if ( empty( $id ) ) + $id = 'root'; + + if ( isset( $this->nodes[ $id ] ) ) + return $this->nodes[ $id ]; + } + + final public function get_nodes() { + if ( ! $nodes = $this->_get_nodes() ) + return; + + foreach ( $nodes as &$node ) { + $node = clone $node; + } + return $nodes; + } + + final protected function _get_nodes() { + if ( $this->bound ) + return; + + return $this->nodes; + } + + /** + * Add a group to a menu node. + * + * @since 3.3.0 + * + * @param array $args - The arguments for each node. + * - id - string - The ID of the item. + * - parent - string - The ID of the parent node. Optional. Default root. + * - meta - array - Meta data including the following keys: class, onclick, target, title. + */ + final public function add_group( $args ) { + $args['group'] = true; + + $this->add_node( $args ); + } + + /** + * Remove a node. + * + * @param string The ID of the item. + */ + public function remove_node( $id ) { + $this->_unset_node( $id ); + } + + final protected function _unset_node( $id ) { + unset( $this->nodes[ $id ] ); + } + + public function render() { + $root = $this->_bind(); + if ( $root ) + $this->_render( $root ); + } + + final protected function _bind() { + if ( $this->bound ) + return; + + // Add the root node. + // Clear it first, just in case. Don't mess with The Root. + $this->remove_node( 'root' ); + $this->add_node( array( + 'id' => 'root', + 'group' => false, + ) ); + + // Normalize nodes: define internal 'children' and 'type' properties. + foreach ( $this->_get_nodes() as $node ) { + $node->children = array(); + $node->type = ( $node->group ) ? 'group' : 'item'; + unset( $node->group ); + + // The Root wants your orphans. No lonely items allowed. + if ( ! $node->parent ) + $node->parent = 'root'; + } + + foreach ( $this->_get_nodes() as $node ) { + if ( 'root' == $node->id ) + continue; + + // Fetch the parent node. If it isn't registered, ignore the node. + if ( ! $parent = $this->_get_node( $node->parent ) ) { + continue; + } + + // Generate the group class (we distinguish between top level and other level groups). + $group_class = ( $node->parent == 'root' ) ? 'ab-top-menu' : 'ab-submenu'; + + if ( $node->type == 'group' ) { + if ( empty( $node->meta['class'] ) ) + $node->meta['class'] = $group_class; + else + $node->meta['class'] .= ' ' . $group_class; + } + + // Items in items aren't allowed. Wrap nested items in 'default' groups. + if ( $parent->type == 'item' && $node->type == 'item' ) { + $default_id = $parent->id . '-default'; + $default = $this->_get_node( $default_id ); + + // The default group is added here to allow groups that are + // added before standard menu items to render first. + if ( ! $default ) { + // Use _set_node because add_node can be overloaded. + // Make sure to specify default settings for all properties. + $this->_set_node( array( + 'id' => $default_id, + 'parent' => $parent->id, + 'type' => 'group', + 'children' => array(), + 'meta' => array( + 'class' => $group_class, + ), + 'title' => false, + 'href' => false, + ) ); + $default = $this->_get_node( $default_id ); + $parent->children[] = $default; + } + $parent = $default; + + // Groups in groups aren't allowed. Add a special 'container' node. + // The container will invisibly wrap both groups. + } elseif ( $parent->type == 'group' && $node->type == 'group' ) { + $container_id = $parent->id . '-container'; + $container = $this->_get_node( $container_id ); + + // We need to create a container for this group, life is sad. + if ( ! $container ) { + // Use _set_node because add_node can be overloaded. + // Make sure to specify default settings for all properties. + $this->_set_node( array( + 'id' => $container_id, + 'type' => 'container', + 'children' => array( $parent ), + 'parent' => false, + 'title' => false, + 'href' => false, + 'meta' => array(), + ) ); + + $container = $this->_get_node( $container_id ); + + // Link the container node if a grandparent node exists. + $grandparent = $this->_get_node( $parent->parent ); + + if ( $grandparent ) { + $container->parent = $grandparent->id; + + $index = array_search( $parent, $grandparent->children, true ); + if ( $index === false ) + $grandparent->children[] = $container; + else + array_splice( $grandparent->children, $index, 1, array( $container ) ); + } + + $parent->parent = $container->id; + } + + $parent = $container; + } + + // Update the parent ID (it might have changed). + $node->parent = $parent->id; + + // Add the node to the tree. + $parent->children[] = $node; + } + + $root = $this->_get_node( 'root' ); + $this->bound = true; + return $root; + } + + final protected function _render( $root ) { + global $is_IE; + + // Add browser classes. + // We have to do this here since admin bar shows on the front end. + $class = 'nojq nojs'; + if ( $is_IE ) { + if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 7' ) ) + $class .= ' ie7'; + elseif ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 8' ) ) + $class .= ' ie8'; + elseif ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 9' ) ) + $class .= ' ie9'; + } elseif ( wp_is_mobile() ) { + $class .= ' mobile'; + } + + ?> + <div id="wpadminbar" class="<?php echo $class; ?>" role="navigation"> + <a class="screen-reader-shortcut" href="#wp-toolbar" tabindex="1"><?php _e('Skip to toolbar'); ?></a> + <div class="quicklinks" id="wp-toolbar" role="navigation" aria-label="<?php esc_attr_e('Top navigation toolbar.'); ?>" tabindex="0"> + <?php foreach ( $root->children as $group ) { + $this->_render_group( $group ); + } ?> + </div> + <?php if ( is_user_logged_in() ) : ?> + <a class="screen-reader-shortcut" href="<?php echo esc_url( wp_logout_url() ); ?>"><?php _e('Log Out'); ?></a> + <?php endif; ?> + </div> + + <?php + } + + final protected function _render_container( $node ) { + if ( $node->type != 'container' || empty( $node->children ) ) + return; + + ?><div id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>" class="ab-group-container"><?php + foreach ( $node->children as $group ) { + $this->_render_group( $group ); + } + ?></div><?php + } + + final protected function _render_group( $node ) { + if ( $node->type == 'container' ) + return $this->_render_container( $node ); + + if ( $node->type != 'group' || empty( $node->children ) ) + return; + + if ( ! empty( $node->meta['class'] ) ) + $class = ' class="' . esc_attr( trim( $node->meta['class'] ) ) . '"'; + else + $class = ''; + + ?><ul id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>"<?php echo $class; ?>><?php + foreach ( $node->children as $item ) { + $this->_render_item( $item ); + } + ?></ul><?php + } + + final protected function _render_item( $node ) { + if ( $node->type != 'item' ) + return; + + $is_parent = ! empty( $node->children ); + $has_link = ! empty( $node->href ); + + $tabindex = isset( $node->meta['tabindex'] ) ? (int) $node->meta['tabindex'] : ''; + $aria_attributes = $tabindex ? 'tabindex="' . $tabindex . '"' : ''; + + $menuclass = ''; + + if ( $is_parent ) { + $menuclass = 'menupop '; + $aria_attributes .= ' aria-haspopup="true"'; + } + + if ( ! empty( $node->meta['class'] ) ) + $menuclass .= $node->meta['class']; + + if ( $menuclass ) + $menuclass = ' class="' . esc_attr( trim( $menuclass ) ) . '"'; + + ?> + + <li id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>"<?php echo $menuclass; ?>><?php + if ( $has_link ): + ?><a class="ab-item" <?php echo $aria_attributes; ?> href="<?php echo esc_url( $node->href ) ?>"<?php + if ( ! empty( $node->meta['onclick'] ) ) : + ?> onclick="<?php echo esc_js( $node->meta['onclick'] ); ?>"<?php + endif; + if ( ! empty( $node->meta['target'] ) ) : + ?> target="<?php echo esc_attr( $node->meta['target'] ); ?>"<?php + endif; + if ( ! empty( $node->meta['title'] ) ) : + ?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php + endif; + ?>><?php + else: + ?><div class="ab-item ab-empty-item" <?php echo $aria_attributes; + if ( ! empty( $node->meta['title'] ) ) : + ?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php + endif; + ?>><?php + endif; + + echo $node->title; + + if ( $has_link ) : + ?></a><?php + else: + ?></div><?php + endif; + + if ( $is_parent ) : + ?><div class="ab-sub-wrapper"><?php + foreach ( $node->children as $group ) { + $this->_render_group( $group ); + } + ?></div><?php + endif; + + if ( ! empty( $node->meta['html'] ) ) + echo $node->meta['html']; + + ?> + </li><?php + } + + public function recursive_render( $id, $node ) { + _deprecated_function( __METHOD__, '3.3', 'WP_Admin_bar::render(), WP_Admin_Bar::_render_item()' ); + $this->_render_item( $node ); + } + + public function add_menus() { + // User related, aligned right. + add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_menu', 0 ); + add_action( 'admin_bar_menu', 'wp_admin_bar_search_menu', 4 ); + add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_item', 7 ); + + // Site related. + add_action( 'admin_bar_menu', 'wp_admin_bar_wp_menu', 10 ); + add_action( 'admin_bar_menu', 'wp_admin_bar_my_sites_menu', 20 ); + add_action( 'admin_bar_menu', 'wp_admin_bar_site_menu', 30 ); + add_action( 'admin_bar_menu', 'wp_admin_bar_updates_menu', 40 ); + + // Content related. + if ( ! is_network_admin() && ! is_user_admin() ) { + add_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 ); + add_action( 'admin_bar_menu', 'wp_admin_bar_new_content_menu', 70 ); + } + add_action( 'admin_bar_menu', 'wp_admin_bar_edit_menu', 80 ); + + add_action( 'admin_bar_menu', 'wp_admin_bar_add_secondary_groups', 200 ); + + /** + * Fires after menus are added to the menu bar. + * + * @since 3.1.0 + */ + do_action( 'add_admin_bar_menus' ); + } +} diff --git a/sources/wp-includes/class-wp-ajax-response.php b/sources/wp-includes/class-wp-ajax-response.php new file mode 100644 index 0000000..24eb687 --- /dev/null +++ b/sources/wp-includes/class-wp-ajax-response.php @@ -0,0 +1,139 @@ +<?php +/** + * Send XML response back to AJAX request. + * + * @package WordPress + * @since 2.1.0 + */ +class WP_Ajax_Response { + /** + * Store XML responses to send. + * + * @since 2.1.0 + * @var array + * @access private + */ + var $responses = array(); + + /** + * Constructor - Passes args to {@link WP_Ajax_Response::add()}. + * + * @since 2.1.0 + * @see WP_Ajax_Response::add() + * + * @param string|array $args Optional. Will be passed to add() method. + * @return WP_Ajax_Response + */ + function __construct( $args = '' ) { + if ( !empty($args) ) + $this->add($args); + } + + /** + * Append to XML response based on given arguments. + * + * The arguments that can be passed in the $args parameter are below. It is + * also possible to pass a WP_Error object in either the 'id' or 'data' + * argument. The parameter isn't actually optional, content should be given + * in order to send the correct response. + * + * 'what' argument is a string that is the XMLRPC response type. + * 'action' argument is a boolean or string that acts like a nonce. + * 'id' argument can be WP_Error or an integer. + * 'old_id' argument is false by default or an integer of the previous ID. + * 'position' argument is an integer or a string with -1 = top, 1 = bottom, + * html ID = after, -html ID = before. + * 'data' argument is a string with the content or message. + * 'supplemental' argument is an array of strings that will be children of + * the supplemental element. + * + * @since 2.1.0 + * + * @param string|array $args Override defaults. + * @return string XML response. + */ + function add( $args = '' ) { + $defaults = array( + 'what' => 'object', 'action' => false, + 'id' => '0', 'old_id' => false, + 'position' => 1, + 'data' => '', 'supplemental' => array() + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + $position = preg_replace( '/[^a-z0-9:_-]/i', '', $position ); + + if ( is_wp_error($id) ) { + $data = $id; + $id = 0; + } + + $response = ''; + if ( is_wp_error($data) ) { + foreach ( (array) $data->get_error_codes() as $code ) { + $response .= "<wp_error code='$code'><![CDATA[" . $data->get_error_message($code) . "]]></wp_error>"; + if ( !$error_data = $data->get_error_data($code) ) + continue; + $class = ''; + if ( is_object($error_data) ) { + $class = ' class="' . get_class($error_data) . '"'; + $error_data = get_object_vars($error_data); + } + + $response .= "<wp_error_data code='$code'$class>"; + + if ( is_scalar($error_data) ) { + $response .= "<![CDATA[$error_data]]>"; + } elseif ( is_array($error_data) ) { + foreach ( $error_data as $k => $v ) + $response .= "<$k><![CDATA[$v]]></$k>"; + } + + $response .= "</wp_error_data>"; + } + } else { + $response = "<response_data><![CDATA[$data]]></response_data>"; + } + + $s = ''; + if ( is_array($supplemental) ) { + foreach ( $supplemental as $k => $v ) + $s .= "<$k><![CDATA[$v]]></$k>"; + $s = "<supplemental>$s</supplemental>"; + } + + if ( false === $action ) + $action = $_POST['action']; + + $x = ''; + $x .= "<response action='{$action}_$id'>"; // The action attribute in the xml output is formatted like a nonce action + $x .= "<$what id='$id' " . ( false === $old_id ? '' : "old_id='$old_id' " ) . "position='$position'>"; + $x .= $response; + $x .= $s; + $x .= "</$what>"; + $x .= "</response>"; + + $this->responses[] = $x; + return $x; + } + + /** + * Display XML formatted responses. + * + * Sets the content type header to text/xml. + * + * @since 2.1.0 + */ + function send() { + header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) ); + echo "<?xml version='1.0' encoding='" . get_option( 'blog_charset' ) . "' standalone='yes'?><wp_ajax>"; + foreach ( (array) $this->responses as $response ) + echo $response; + echo '</wp_ajax>'; + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + wp_die(); + else + die(); + } +} diff --git a/sources/wp-includes/class-wp-customize-control.php b/sources/wp-includes/class-wp-customize-control.php new file mode 100644 index 0000000..fde8561 --- /dev/null +++ b/sources/wp-includes/class-wp-customize-control.php @@ -0,0 +1,817 @@ +<?php +/** + * Customize Control Class + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Control { + /** + * @access public + * @var WP_Customize_Manager + */ + public $manager; + + /** + * @access public + * @var string + */ + public $id; + + /** + * All settings tied to the control. + * + * @access public + * @var array + */ + public $settings; + + /** + * The primary setting for the control (if there is one). + * + * @access public + * @var string + */ + public $setting = 'default'; + + /** + * @access public + * @var int + */ + public $priority = 10; + + /** + * @access public + * @var string + */ + public $section = ''; + + /** + * @access public + * @var string + */ + public $label = ''; + + /** + * @todo: Remove choices + * + * @access public + * @var array + */ + public $choices = array(); + + /** + * @access public + * @var array + */ + public $json = array(); + + /** + * @access public + * @var string + */ + public $type = 'text'; + + + /** + * Constructor. + * + * If $args['settings'] is not defined, use the $id as the setting ID. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager + * @param string $id + * @param array $args + */ + function __construct( $manager, $id, $args = array() ) { + $keys = array_keys( get_object_vars( $this ) ); + foreach ( $keys as $key ) { + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } + + $this->manager = $manager; + $this->id = $id; + + + // Process settings. + if ( empty( $this->settings ) ) + $this->settings = $id; + + $settings = array(); + if ( is_array( $this->settings ) ) { + foreach ( $this->settings as $key => $setting ) { + $settings[ $key ] = $this->manager->get_setting( $setting ); + } + } else { + $this->setting = $this->manager->get_setting( $this->settings ); + $settings['default'] = $this->setting; + } + $this->settings = $settings; + } + + /** + * Enqueue control related scripts/styles. + * + * @since 3.4.0 + */ + public function enqueue() {} + + + /** + * Fetch a setting's value. + * Grabs the main setting by default. + * + * @since 3.4.0 + * + * @param string $setting_key + * @return mixed The requested setting's value, if the setting exists. + */ + public final function value( $setting_key = 'default' ) { + if ( isset( $this->settings[ $setting_key ] ) ) + return $this->settings[ $setting_key ]->value(); + } + + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + */ + public function to_json() { + $this->json['settings'] = array(); + foreach ( $this->settings as $key => $setting ) { + $this->json['settings'][ $key ] = $setting->id; + } + + $this->json['type'] = $this->type; + } + + /** + * Check if the theme supports the control and check user capabilities. + * + * @since 3.4.0 + * + * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true. + */ + public final function check_capabilities() { + foreach ( $this->settings as $setting ) { + if ( ! $setting->check_capabilities() ) + return false; + } + + $section = $this->manager->get_section( $this->section ); + if ( isset( $section ) && ! $section->check_capabilities() ) + return false; + + return true; + } + + /** + * Check capabilities and render the control. + * + * @since 3.4.0 + * @uses WP_Customize_Control::render() + */ + public final function maybe_render() { + if ( ! $this->check_capabilities() ) + return; + + do_action( 'customize_render_control', $this ); + do_action( 'customize_render_control_' . $this->id, $this ); + + $this->render(); + } + + /** + * Render the control. Renders the control wrapper, then calls $this->render_content(). + * + * @since 3.4.0 + */ + protected function render() { + $id = 'customize-control-' . str_replace( '[', '-', str_replace( ']', '', $this->id ) ); + $class = 'customize-control customize-control-' . $this->type; + + ?><li id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $class ); ?>"> + <?php $this->render_content(); ?> + </li><?php + } + + /** + * Get the data link parameter for a setting. + * + * @since 3.4.0 + * + * @param string $setting_key + * @return string Data link parameter, if $setting_key is a valid setting, empty string otherwise. + */ + public function get_link( $setting_key = 'default' ) { + if ( ! isset( $this->settings[ $setting_key ] ) ) + return ''; + + return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"'; + } + + /** + * Render the data link parameter for a setting + * + * @since 3.4.0 + * @uses WP_Customize_Control::get_link() + * + * @param string $setting_key + */ + public function link( $setting_key = 'default' ) { + echo $this->get_link( $setting_key ); + } + + /** + * Render the control's content. + * + * Allows the content to be overriden without having to rewrite the wrapper. + * + * @since 3.4.0 + */ + protected function render_content() { + switch( $this->type ) { + case 'text': + ?> + <label> + <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> + <input type="text" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); ?> /> + </label> + <?php + break; + case 'checkbox': + ?> + <label> + <input type="checkbox" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); checked( $this->value() ); ?> /> + <?php echo esc_html( $this->label ); ?> + </label> + <?php + break; + case 'radio': + if ( empty( $this->choices ) ) + return; + + $name = '_customize-radio-' . $this->id; + + ?> + <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> + <?php + foreach ( $this->choices as $value => $label ) : + ?> + <label> + <input type="radio" value="<?php echo esc_attr( $value ); ?>" name="<?php echo esc_attr( $name ); ?>" <?php $this->link(); checked( $this->value(), $value ); ?> /> + <?php echo esc_html( $label ); ?><br/> + </label> + <?php + endforeach; + break; + case 'select': + if ( empty( $this->choices ) ) + return; + + ?> + <label> + <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> + <select <?php $this->link(); ?>> + <?php + foreach ( $this->choices as $value => $label ) + echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->value(), $value, false ) . '>' . $label . '</option>'; + ?> + </select> + </label> + <?php + break; + case 'dropdown-pages': + $dropdown = wp_dropdown_pages( + array( + 'name' => '_customize-dropdown-pages-' . $this->id, + 'echo' => 0, + 'show_option_none' => __( '— Select —' ), + 'option_none_value' => '0', + 'selected' => $this->value(), + ) + ); + + // Hackily add in the data link parameter. + $dropdown = str_replace( '<select', '<select ' . $this->get_link(), $dropdown ); + + printf( + '<label class="customize-control-select"><span class="customize-control-title">%s</span> %s</label>', + $this->label, + $dropdown + ); + break; + } + } +} + +/** + * Customize Color Control Class + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Color_Control extends WP_Customize_Control { + /** + * @access public + * @var string + */ + public $type = 'color'; + + /** + * @access public + * @var array + */ + public $statuses; + + /** + * Constructor. + * + * If $args['settings'] is not defined, use the $id as the setting ID. + * + * @since 3.4.0 + * @uses WP_Customize_Control::__construct() + * + * @param WP_Customize_Manager $manager + * @param string $id + * @param array $args + */ + public function __construct( $manager, $id, $args = array() ) { + $this->statuses = array( '' => __('Default') ); + parent::__construct( $manager, $id, $args ); + } + + /** + * Enqueue control related scripts/styles. + * + * @since 3.4.0 + */ + public function enqueue() { + wp_enqueue_script( 'wp-color-picker' ); + wp_enqueue_style( 'wp-color-picker' ); + } + + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + * @uses WP_Customize_Control::to_json() + */ + public function to_json() { + parent::to_json(); + $this->json['statuses'] = $this->statuses; + } + + /** + * Render the control's content. + * + * @since 3.4.0 + */ + public function render_content() { + $this_default = $this->setting->default; + $default_attr = ''; + if ( $this_default ) { + if ( false === strpos( $this_default, '#' ) ) + $this_default = '#' . $this_default; + $default_attr = ' data-default-color="' . esc_attr( $this_default ) . '"'; + } + // The input's value gets set by JS. Don't fill it. + ?> + <label> + <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> + <div class="customize-control-content"> + <input class="color-picker-hex" type="text" maxlength="7" placeholder="<?php esc_attr_e( 'Hex Value' ); ?>"<?php echo $default_attr; ?> /> + </div> + </label> + <?php + } +} + +/** + * Customize Upload Control Class + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Upload_Control extends WP_Customize_Control { + public $type = 'upload'; + public $removed = ''; + public $context; + public $extensions = array(); + + /** + * Enqueue control related scripts/styles. + * + * @since 3.4.0 + */ + public function enqueue() { + wp_enqueue_script( 'wp-plupload' ); + } + + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + * @uses WP_Customize_Control::to_json() + */ + public function to_json() { + parent::to_json(); + + $this->json['removed'] = $this->removed; + + if ( $this->context ) + $this->json['context'] = $this->context; + + if ( $this->extensions ) + $this->json['extensions'] = implode( ',', $this->extensions ); + } + + /** + * Render the control's content. + * + * @since 3.4.0 + */ + public function render_content() { + ?> + <label> + <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> + <div> + <a href="#" class="button-secondary upload"><?php _e( 'Upload' ); ?></a> + <a href="#" class="remove"><?php _e( 'Remove' ); ?></a> + </div> + </label> + <?php + } +} + +/** + * Customize Image Control Class + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Image_Control extends WP_Customize_Upload_Control { + public $type = 'image'; + public $get_url; + public $statuses; + public $extensions = array( 'jpg', 'jpeg', 'gif', 'png' ); + + protected $tabs = array(); + + /** + * Constructor. + * + * If $args['settings'] is not defined, use the $id as the setting ID. + * + * @since 3.4.0 + * @uses WP_Customize_Upload_Control::__construct() + * + * @param WP_Customize_Manager $manager + * @param string $id + * @param array $args + */ + public function __construct( $manager, $id, $args ) { + $this->statuses = array( '' => __('No Image') ); + + parent::__construct( $manager, $id, $args ); + + $this->add_tab( 'upload-new', __('Upload New'), array( $this, 'tab_upload_new' ) ); + $this->add_tab( 'uploaded', __('Uploaded'), array( $this, 'tab_uploaded' ) ); + + // Early priority to occur before $this->manager->prepare_controls(); + add_action( 'customize_controls_init', array( $this, 'prepare_control' ), 5 ); + } + + /** + * Prepares the control. + * + * If no tabs exist, removes the control from the manager. + * + * @since 3.4.2 + */ + public function prepare_control() { + if ( ! $this->tabs ) + $this->manager->remove_control( $this->id ); + } + + /** + * Refresh the parameters passed to the JavaScript via JSON. + * + * @since 3.4.0 + * @uses WP_Customize_Upload_Control::to_json() + */ + public function to_json() { + parent::to_json(); + $this->json['statuses'] = $this->statuses; + } + + /** + * Render the control's content. + * + * @since 3.4.0 + */ + public function render_content() { + $src = $this->value(); + if ( isset( $this->get_url ) ) + $src = call_user_func( $this->get_url, $src ); + + ?> + <div class="customize-image-picker"> + <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> + + <div class="customize-control-content"> + <div class="dropdown preview-thumbnail" tabindex="0"> + <div class="dropdown-content"> + <?php if ( empty( $src ) ): ?> + <img style="display:none;" /> + <?php else: ?> + <img src="<?php echo esc_url( set_url_scheme( $src ) ); ?>" /> + <?php endif; ?> + <div class="dropdown-status"></div> + </div> + <div class="dropdown-arrow"></div> + </div> + </div> + + <div class="library"> + <ul> + <?php foreach ( $this->tabs as $id => $tab ): ?> + <li data-customize-tab='<?php echo esc_attr( $id ); ?>' tabindex='0'> + <?php echo esc_html( $tab['label'] ); ?> + </li> + <?php endforeach; ?> + </ul> + <?php foreach ( $this->tabs as $id => $tab ): ?> + <div class="library-content" data-customize-tab='<?php echo esc_attr( $id ); ?>'> + <?php call_user_func( $tab['callback'] ); ?> + </div> + <?php endforeach; ?> + </div> + + <div class="actions"> + <a href="#" class="remove"><?php _e( 'Remove Image' ); ?></a> + </div> + </div> + <?php + } + + /** + * Add a tab to the control. + * + * @since 3.4.0 + * + * @param string $id + * @param string $label + * @param mixed $callback + */ + public function add_tab( $id, $label, $callback ) { + $this->tabs[ $id ] = array( + 'label' => $label, + 'callback' => $callback, + ); + } + + /** + * Remove a tab from the control. + * + * @since 3.4.0 + * + * @param string $id + */ + public function remove_tab( $id ) { + unset( $this->tabs[ $id ] ); + } + + /** + * @since 3.4.0 + */ + public function tab_upload_new() { + if ( ! _device_can_upload() ) { + echo '<p>' . sprintf( __('The web browser on your device cannot be used to upload files. You may be able to use the <a href="%s">native app for your device</a> instead.'), 'http://wordpress.org/mobile/' ) . '</p>'; + } else { + ?> + <div class="upload-dropzone"> + <?php _e('Drop a file here or <a href="#" class="upload">select a file</a>.'); ?> + </div> + <div class="upload-fallback"> + <span class="button-secondary"><?php _e('Select File'); ?></span> + </div> + <?php + } + } + + /** + * @since 3.4.0 + */ + public function tab_uploaded() { + ?> + <div class="uploaded-target"></div> + <?php + } + + /** + * @since 3.4.0 + * + * @param string $url + * @param string $thumbnail_url + */ + public function print_tab_image( $url, $thumbnail_url = null ) { + $url = set_url_scheme( $url ); + $thumbnail_url = ( $thumbnail_url ) ? set_url_scheme( $thumbnail_url ) : $url; + ?> + <a href="#" class="thumbnail" data-customize-image-value="<?php echo esc_url( $url ); ?>"> + <img src="<?php echo esc_url( $thumbnail_url ); ?>" /> + </a> + <?php + } +} + +/** + * Customize Background Image Control Class + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Background_Image_Control extends WP_Customize_Image_Control { + + /** + * Constructor. + * + * @since 3.4.0 + * @uses WP_Customize_Image_Control::__construct() + * + * @param WP_Customize_Manager $manager + */ + public function __construct( $manager ) { + parent::__construct( $manager, 'background_image', array( + 'label' => __( 'Background Image' ), + 'section' => 'background_image', + 'context' => 'custom-background', + 'get_url' => 'get_background_image', + ) ); + + if ( $this->setting->default ) + $this->add_tab( 'default', __('Default'), array( $this, 'tab_default_background' ) ); + } + + /** + * @since 3.4.0 + */ + public function tab_uploaded() { + $backgrounds = get_posts( array( + 'post_type' => 'attachment', + 'meta_key' => '_wp_attachment_is_custom_background', + 'meta_value' => $this->manager->get_stylesheet(), + 'orderby' => 'none', + 'nopaging' => true, + ) ); + + ?><div class="uploaded-target"></div><?php + + if ( empty( $backgrounds ) ) + return; + + foreach ( (array) $backgrounds as $background ) + $this->print_tab_image( esc_url_raw( $background->guid ) ); + } + + /** + * @since 3.4.0 + * @uses WP_Customize_Image_Control::print_tab_image() + */ + public function tab_default_background() { + $this->print_tab_image( $this->setting->default ); + } +} + +/** + * Customize Header Image Control Class + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Header_Image_Control extends WP_Customize_Image_Control { + /** + * The processed default headers. + * @since 3.4.2 + * @var array + */ + protected $default_headers; + + /** + * The uploaded headers. + * @since 3.4.2 + * @var array + */ + protected $uploaded_headers; + + /** + * Constructor. + * + * @since 3.4.0 + * @uses WP_Customize_Image_Control::__construct() + * @uses WP_Customize_Image_Control::add_tab() + * + * @param WP_Customize_Manager $manager + */ + public function __construct( $manager ) { + parent::__construct( $manager, 'header_image', array( + 'label' => __( 'Header Image' ), + 'settings' => array( + 'default' => 'header_image', + 'data' => 'header_image_data', + ), + 'section' => 'header_image', + 'context' => 'custom-header', + 'removed' => 'remove-header', + 'get_url' => 'get_header_image', + 'statuses' => array( + '' => __('Default'), + 'remove-header' => __('No Image'), + 'random-default-image' => __('Random Default Image'), + 'random-uploaded-image' => __('Random Uploaded Image'), + ) + ) ); + + // Remove the upload tab. + $this->remove_tab( 'upload-new' ); + } + + /** + * Prepares the control. + * + * If no tabs exist, removes the control from the manager. + * + * @since 3.4.2 + */ + public function prepare_control() { + global $custom_image_header; + if ( empty( $custom_image_header ) ) + return parent::prepare_control(); + + // Process default headers and uploaded headers. + $custom_image_header->process_default_headers(); + $this->default_headers = $custom_image_header->default_headers; + $this->uploaded_headers = get_uploaded_header_images(); + + if ( $this->default_headers ) + $this->add_tab( 'default', __('Default'), array( $this, 'tab_default_headers' ) ); + + if ( ! $this->uploaded_headers ) + $this->remove_tab( 'uploaded' ); + + return parent::prepare_control(); + } + + /** + * @since 3.4.0 + * + * @param mixed $choice Which header image to select. (@see Custom_Image_Header::get_header_image() ) + * @param array $header + */ + public function print_header_image( $choice, $header ) { + $header['url'] = set_url_scheme( $header['url'] ); + $header['thumbnail_url'] = set_url_scheme( $header['thumbnail_url'] ); + + $header_image_data = array( 'choice' => $choice ); + foreach ( array( 'attachment_id', 'width', 'height', 'url', 'thumbnail_url' ) as $key ) { + if ( isset( $header[ $key ] ) ) + $header_image_data[ $key ] = $header[ $key ]; + } + + + ?> + <a href="#" class="thumbnail" + data-customize-image-value="<?php echo esc_url( $header['url'] ); ?>" + data-customize-header-image-data="<?php echo esc_attr( json_encode( $header_image_data ) ); ?>"> + <img src="<?php echo esc_url( $header['thumbnail_url'] ); ?>" /> + </a> + <?php + } + + /** + * @since 3.4.0 + */ + public function tab_uploaded() { + ?><div class="uploaded-target"></div><?php + + foreach ( $this->uploaded_headers as $choice => $header ) + $this->print_header_image( $choice, $header ); + } + + /** + * @since 3.4.0 + */ + public function tab_default_headers() { + foreach ( $this->default_headers as $choice => $header ) + $this->print_header_image( $choice, $header ); + } +} \ No newline at end of file diff --git a/sources/wp-includes/class-wp-customize-manager.php b/sources/wp-includes/class-wp-customize-manager.php new file mode 100644 index 0000000..cad9f13 --- /dev/null +++ b/sources/wp-includes/class-wp-customize-manager.php @@ -0,0 +1,1059 @@ +<?php +/** + * Customize Manager. + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +final class WP_Customize_Manager { + protected $theme; + protected $original_stylesheet; + + protected $previewing = false; + + protected $settings = array(); + protected $sections = array(); + protected $controls = array(); + + protected $nonce_tick; + + protected $customized; + + private $_post_values; + + /** + * Constructor. + * + * @since 3.4.0 + */ + public function __construct() { + require( ABSPATH . WPINC . '/class-wp-customize-setting.php' ); + require( ABSPATH . WPINC . '/class-wp-customize-section.php' ); + require( ABSPATH . WPINC . '/class-wp-customize-control.php' ); + + add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) ); + + add_action( 'setup_theme', array( $this, 'setup_theme' ) ); + add_action( 'wp_loaded', array( $this, 'wp_loaded' ) ); + + // Run wp_redirect_status late to make sure we override the status last. + add_action( 'wp_redirect_status', array( $this, 'wp_redirect_status' ), 1000 ); + + // Do not spawn cron (especially the alternate cron) while running the customizer. + remove_action( 'init', 'wp_cron' ); + + // Do not run update checks when rendering the controls. + remove_action( 'admin_init', '_maybe_update_core' ); + remove_action( 'admin_init', '_maybe_update_plugins' ); + remove_action( 'admin_init', '_maybe_update_themes' ); + + add_action( 'wp_ajax_customize_save', array( $this, 'save' ) ); + + add_action( 'customize_register', array( $this, 'register_controls' ) ); + add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) ); + add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) ); + } + + /** + * Return true if it's an AJAX request. + * + * @since 3.4.0 + * + * @return bool + */ + public function doing_ajax() { + return isset( $_POST['customized'] ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ); + } + + /** + * Custom wp_die wrapper. Returns either the standard message for UI + * or the AJAX message. + * + * @since 3.4.0 + * + * @param mixed $ajax_message AJAX return + * @param mixed $message UI message + */ + protected function wp_die( $ajax_message, $message = null ) { + if ( $this->doing_ajax() ) + wp_die( $ajax_message ); + + if ( ! $message ) + $message = __( 'Cheatin’ uh?' ); + + wp_die( $message ); + } + + /** + * Return the AJAX wp_die() handler if it's a customized request. + * + * @since 3.4.0 + * + * @return string + */ + public function wp_die_handler() { + if ( $this->doing_ajax() ) + return '_ajax_wp_die_handler'; + + return '_default_wp_die_handler'; + } + + /** + * Start preview and customize theme. + * + * Check if customize query variable exist. Init filters to filter the current theme. + * + * @since 3.4.0 + */ + public function setup_theme() { + send_origin_headers(); + + if ( is_admin() && ! $this->doing_ajax() ) + auth_redirect(); + elseif ( $this->doing_ajax() && ! is_user_logged_in() ) + $this->wp_die( 0 ); + + show_admin_bar( false ); + + if ( ! current_user_can( 'edit_theme_options' ) ) + $this->wp_die( -1 ); + + $this->original_stylesheet = get_stylesheet(); + + $this->theme = wp_get_theme( isset( $_REQUEST['theme'] ) ? $_REQUEST['theme'] : null ); + + if ( $this->is_theme_active() ) { + // Once the theme is loaded, we'll validate it. + add_action( 'after_setup_theme', array( $this, 'after_setup_theme' ) ); + } else { + if ( ! current_user_can( 'switch_themes' ) ) + $this->wp_die( -1 ); + + // If the theme isn't active, you can't preview it if it is not allowed or has errors. + if ( $this->theme()->errors() ) + $this->wp_die( -1 ); + + if ( ! $this->theme()->is_allowed() ) + $this->wp_die( -1 ); + } + + $this->start_previewing_theme(); + } + + /** + * Callback to validate a theme once it is loaded + * + * @since 3.4.0 + */ + function after_setup_theme() { + if ( ! $this->doing_ajax() && ! validate_current_theme() ) { + wp_redirect( 'themes.php?broken=true' ); + exit; + } + } + + /** + * Start previewing the selected theme. + * + * Adds filters to change the current theme. + * + * @since 3.4.0 + */ + public function start_previewing_theme() { + // Bail if we're already previewing. + if ( $this->is_preview() ) + return; + + $this->previewing = true; + + if ( ! $this->is_theme_active() ) { + add_filter( 'template', array( $this, 'get_template' ) ); + add_filter( 'stylesheet', array( $this, 'get_stylesheet' ) ); + add_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) ); + + // @link: http://core.trac.wordpress.org/ticket/20027 + add_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) ); + add_filter( 'pre_option_template', array( $this, 'get_template' ) ); + + // Handle custom theme roots. + add_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) ); + add_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) ); + } + + do_action( 'start_previewing_theme', $this ); + } + + /** + * Stop previewing the selected theme. + * + * Removes filters to change the current theme. + * + * @since 3.4.0 + */ + public function stop_previewing_theme() { + if ( ! $this->is_preview() ) + return; + + $this->previewing = false; + + if ( ! $this->is_theme_active() ) { + remove_filter( 'template', array( $this, 'get_template' ) ); + remove_filter( 'stylesheet', array( $this, 'get_stylesheet' ) ); + remove_filter( 'pre_option_current_theme', array( $this, 'current_theme' ) ); + + // @link: http://core.trac.wordpress.org/ticket/20027 + remove_filter( 'pre_option_stylesheet', array( $this, 'get_stylesheet' ) ); + remove_filter( 'pre_option_template', array( $this, 'get_template' ) ); + + // Handle custom theme roots. + remove_filter( 'pre_option_stylesheet_root', array( $this, 'get_stylesheet_root' ) ); + remove_filter( 'pre_option_template_root', array( $this, 'get_template_root' ) ); + } + + do_action( 'stop_previewing_theme', $this ); + } + + /** + * Get the theme being customized. + * + * @since 3.4.0 + * + * @return WP_Theme + */ + public function theme() { + return $this->theme; + } + + /** + * Get the registered settings. + * + * @since 3.4.0 + * + * @return array + */ + public function settings() { + return $this->settings; + } + + /** + * Get the registered controls. + * + * @since 3.4.0 + * + * @return array + */ + public function controls() { + return $this->controls; + } + + /** + * Get the registered sections. + * + * @since 3.4.0 + * + * @return array + */ + public function sections() { + return $this->sections; + } + + /** + * Checks if the current theme is active. + * + * @since 3.4.0 + * + * @return bool + */ + public function is_theme_active() { + return $this->get_stylesheet() == $this->original_stylesheet; + } + + /** + * Register styles/scripts and initialize the preview of each setting + * + * @since 3.4.0 + */ + public function wp_loaded() { + do_action( 'customize_register', $this ); + + if ( $this->is_preview() && ! is_admin() ) + $this->customize_preview_init(); + } + + /** + * Prevents AJAX requests from following redirects when previewing a theme + * by issuing a 200 response instead of a 30x. + * + * Instead, the JS will sniff out the location header. + * + * @since 3.4.0 + * + * @param $status + * @return int + */ + public function wp_redirect_status( $status ) { + if ( $this->is_preview() && ! is_admin() ) + return 200; + + return $status; + } + + /** + * Decode the $_POST attribute used to override the WP_Customize_Setting values. + * + * @since 3.4.0 + * + * @param mixed $setting A WP_Customize_Setting derived object + * @return string Sanitized attribute + */ + public function post_value( $setting ) { + if ( ! isset( $this->_post_values ) ) { + if ( isset( $_POST['customized'] ) ) + $this->_post_values = json_decode( wp_unslash( $_POST['customized'] ), true ); + else + $this->_post_values = false; + } + + if ( isset( $this->_post_values[ $setting->id ] ) ) + return $setting->sanitize( $this->_post_values[ $setting->id ] ); + } + + /** + * Print javascript settings. + * + * @since 3.4.0 + */ + public function customize_preview_init() { + $this->nonce_tick = check_ajax_referer( 'preview-customize_' . $this->get_stylesheet(), 'nonce' ); + + $this->prepare_controls(); + + wp_enqueue_script( 'customize-preview' ); + add_action( 'wp_head', array( $this, 'customize_preview_base' ) ); + add_action( 'wp_head', array( $this, 'customize_preview_html5' ) ); + add_action( 'wp_footer', array( $this, 'customize_preview_settings' ), 20 ); + add_action( 'shutdown', array( $this, 'customize_preview_signature' ), 1000 ); + add_filter( 'wp_die_handler', array( $this, 'remove_preview_signature' ) ); + + foreach ( $this->settings as $setting ) { + $setting->preview(); + } + + do_action( 'customize_preview_init', $this ); + } + + /** + * Print base element for preview frame. + * + * @since 3.4.0 + */ + public function customize_preview_base() { + ?><base href="<?php echo home_url( '/' ); ?>" /><?php + } + + /** + * Print a workaround to handle HTML5 tags in IE < 9 + * + * @since 3.4.0 + */ + public function customize_preview_html5() { ?> + <!--[if lt IE 9]> + <script type="text/javascript"> + var e = [ 'abbr', 'article', 'aside', 'audio', 'canvas', 'datalist', 'details', + 'figure', 'footer', 'header', 'hgroup', 'mark', 'menu', 'meter', 'nav', + 'output', 'progress', 'section', 'time', 'video' ]; + for ( var i = 0; i < e.length; i++ ) { + document.createElement( e[i] ); + } + </script> + <![endif]--><?php + } + + /** + * Print javascript settings for preview frame. + * + * @since 3.4.0 + */ + public function customize_preview_settings() { + $settings = array( + 'values' => array(), + 'channel' => esc_js( $_POST['customize_messenger_channel'] ), + ); + + if ( 2 == $this->nonce_tick ) { + $settings['nonce'] = array( + 'save' => wp_create_nonce( 'save-customize_' . $this->get_stylesheet() ), + 'preview' => wp_create_nonce( 'preview-customize_' . $this->get_stylesheet() ) + ); + } + + foreach ( $this->settings as $id => $setting ) { + $settings['values'][ $id ] = $setting->js_value(); + } + + ?> + <script type="text/javascript"> + var _wpCustomizeSettings = <?php echo json_encode( $settings ); ?>; + </script> + <?php + } + + /** + * Prints a signature so we can ensure the customizer was properly executed. + * + * @since 3.4.0 + */ + public function customize_preview_signature() { + echo 'WP_CUSTOMIZER_SIGNATURE'; + } + + /** + * Removes the signature in case we experience a case where the customizer was not properly executed. + * + * @since 3.4.0 + */ + public function remove_preview_signature( $return = null ) { + remove_action( 'shutdown', array( $this, 'customize_preview_signature' ), 1000 ); + + return $return; + } + + /** + * Is it a theme preview? + * + * @since 3.4.0 + * + * @return bool True if it's a preview, false if not. + */ + public function is_preview() { + return (bool) $this->previewing; + } + + /** + * Retrieve the template name of the previewed theme. + * + * @since 3.4.0 + * + * @return string Template name. + */ + public function get_template() { + return $this->theme()->get_template(); + } + + /** + * Retrieve the stylesheet name of the previewed theme. + * + * @since 3.4.0 + * + * @return string Stylesheet name. + */ + public function get_stylesheet() { + return $this->theme()->get_stylesheet(); + } + + /** + * Retrieve the template root of the previewed theme. + * + * @since 3.4.0 + * + * @return string Theme root. + */ + public function get_template_root() { + return get_raw_theme_root( $this->get_template(), true ); + } + + /** + * Retrieve the stylesheet root of the previewed theme. + * + * @since 3.4.0 + * + * @return string Theme root. + */ + public function get_stylesheet_root() { + return get_raw_theme_root( $this->get_stylesheet(), true ); + } + + /** + * Filter the current theme and return the name of the previewed theme. + * + * @since 3.4.0 + * + * @param $current_theme {@internal Parameter is not used} + * @return string Theme name. + */ + public function current_theme( $current_theme ) { + return $this->theme()->display('Name'); + } + + /** + * Switch the theme and trigger the save action of each setting. + * + * @since 3.4.0 + */ + public function save() { + if ( ! $this->is_preview() ) + die; + + check_ajax_referer( 'save-customize_' . $this->get_stylesheet(), 'nonce' ); + + // Do we have to switch themes? + if ( ! $this->is_theme_active() ) { + // Temporarily stop previewing the theme to allow switch_themes() + // to operate properly. + $this->stop_previewing_theme(); + switch_theme( $this->get_stylesheet() ); + $this->start_previewing_theme(); + } + + do_action( 'customize_save', $this ); + + foreach ( $this->settings as $setting ) { + $setting->save(); + } + + do_action( 'customize_save_after', $this ); + + die; + } + + /** + * Add a customize setting. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the setting. Can be a + * theme mod or option name. + * @param array $args Setting arguments. + */ + public function add_setting( $id, $args = array() ) { + if ( is_a( $id, 'WP_Customize_Setting' ) ) + $setting = $id; + else + $setting = new WP_Customize_Setting( $this, $id, $args ); + + $this->settings[ $setting->id ] = $setting; + } + + /** + * Retrieve a customize setting. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the setting. + * @return object The settings object. + */ + public function get_setting( $id ) { + if ( isset( $this->settings[ $id ] ) ) + return $this->settings[ $id ]; + } + + /** + * Remove a customize setting. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the setting. + */ + public function remove_setting( $id ) { + unset( $this->settings[ $id ] ); + } + + /** + * Add a customize section. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the section. + * @param array $args Section arguments. + */ + public function add_section( $id, $args = array() ) { + if ( is_a( $id, 'WP_Customize_Section' ) ) + $section = $id; + else + $section = new WP_Customize_Section( $this, $id, $args ); + + $this->sections[ $section->id ] = $section; + } + + /** + * Retrieve a customize section. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the section. + * @return object The section object. + */ + public function get_section( $id ) { + if ( isset( $this->sections[ $id ] ) ) + return $this->sections[ $id ]; + } + + /** + * Remove a customize section. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the section. + */ + public function remove_section( $id ) { + unset( $this->sections[ $id ] ); + } + + /** + * Add a customize control. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the control. + * @param array $args Setting arguments. + */ + public function add_control( $id, $args = array() ) { + if ( is_a( $id, 'WP_Customize_Control' ) ) + $control = $id; + else + $control = new WP_Customize_Control( $this, $id, $args ); + + $this->controls[ $control->id ] = $control; + } + + /** + * Retrieve a customize control. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the control. + * @return object The settings object. + */ + public function get_control( $id ) { + if ( isset( $this->controls[ $id ] ) ) + return $this->controls[ $id ]; + } + + /** + * Remove a customize setting. + * + * @since 3.4.0 + * + * @param string $id A specific ID of the control. + */ + public function remove_control( $id ) { + unset( $this->controls[ $id ] ); + } + + /** + * Helper function to compare two objects by priority. + * + * @since 3.4.0 + * + * @param object $a Object A. + * @param object $b Object B. + * @return int + */ + protected final function _cmp_priority( $a, $b ) { + $ap = $a->priority; + $bp = $b->priority; + + if ( $ap == $bp ) + return 0; + return ( $ap > $bp ) ? 1 : -1; + } + + /** + * Prepare settings and sections. + * + * @since 3.4.0 + */ + public function prepare_controls() { + // Prepare controls + // Reversing makes uasort sort by time added when conflicts occur. + + $this->controls = array_reverse( $this->controls ); + $controls = array(); + + foreach ( $this->controls as $id => $control ) { + if ( ! isset( $this->sections[ $control->section ] ) || ! $control->check_capabilities() ) + continue; + + $this->sections[ $control->section ]->controls[] = $control; + $controls[ $id ] = $control; + } + $this->controls = $controls; + + // Prepare sections + $this->sections = array_reverse( $this->sections ); + uasort( $this->sections, array( $this, '_cmp_priority' ) ); + $sections = array(); + + foreach ( $this->sections as $section ) { + if ( ! $section->check_capabilities() || ! $section->controls ) + continue; + + usort( $section->controls, array( $this, '_cmp_priority' ) ); + $sections[] = $section; + } + $this->sections = $sections; + } + + /** + * Enqueue scripts for customize controls. + * + * @since 3.4.0 + */ + public function enqueue_control_scripts() { + foreach ( $this->controls as $control ) { + $control->enqueue(); + } + } + + /** + * Register some default controls. + * + * @since 3.4.0 + */ + public function register_controls() { + + /* Site Title & Tagline */ + + $this->add_section( 'title_tagline', array( + 'title' => __( 'Site Title & Tagline' ), + 'priority' => 20, + ) ); + + $this->add_setting( 'blogname', array( + 'default' => get_option( 'blogname' ), + 'type' => 'option', + 'capability' => 'manage_options', + ) ); + + $this->add_control( 'blogname', array( + 'label' => __( 'Site Title' ), + 'section' => 'title_tagline', + ) ); + + $this->add_setting( 'blogdescription', array( + 'default' => get_option( 'blogdescription' ), + 'type' => 'option', + 'capability' => 'manage_options', + ) ); + + $this->add_control( 'blogdescription', array( + 'label' => __( 'Tagline' ), + 'section' => 'title_tagline', + ) ); + + /* Colors */ + + $this->add_section( 'colors', array( + 'title' => __( 'Colors' ), + 'priority' => 40, + ) ); + + $this->add_setting( 'header_textcolor', array( + 'theme_supports' => array( 'custom-header', 'header-text' ), + 'default' => get_theme_support( 'custom-header', 'default-text-color' ), + + 'sanitize_callback' => array( $this, '_sanitize_header_textcolor' ), + 'sanitize_js_callback' => 'maybe_hash_hex_color', + ) ); + + // Input type: checkbox + // With custom value + $this->add_control( 'display_header_text', array( + 'settings' => 'header_textcolor', + 'label' => __( 'Display Header Text' ), + 'section' => 'title_tagline', + 'type' => 'checkbox', + ) ); + + $this->add_control( new WP_Customize_Color_Control( $this, 'header_textcolor', array( + 'label' => __( 'Header Text Color' ), + 'section' => 'colors', + ) ) ); + + // Input type: Color + // With sanitize_callback + $this->add_setting( 'background_color', array( + 'default' => get_theme_support( 'custom-background', 'default-color' ), + 'theme_supports' => 'custom-background', + + 'sanitize_callback' => 'sanitize_hex_color_no_hash', + 'sanitize_js_callback' => 'maybe_hash_hex_color', + ) ); + + $this->add_control( new WP_Customize_Color_Control( $this, 'background_color', array( + 'label' => __( 'Background Color' ), + 'section' => 'colors', + ) ) ); + + + /* Custom Header */ + + $this->add_section( 'header_image', array( + 'title' => __( 'Header Image' ), + 'theme_supports' => 'custom-header', + 'priority' => 60, + ) ); + + $this->add_setting( new WP_Customize_Filter_Setting( $this, 'header_image', array( + 'default' => get_theme_support( 'custom-header', 'default-image' ), + 'theme_supports' => 'custom-header', + ) ) ); + + $this->add_setting( new WP_Customize_Header_Image_Setting( $this, 'header_image_data', array( + // 'default' => get_theme_support( 'custom-header', 'default-image' ), + 'theme_supports' => 'custom-header', + ) ) ); + + $this->add_control( new WP_Customize_Header_Image_Control( $this ) ); + + /* Custom Background */ + + $this->add_section( 'background_image', array( + 'title' => __( 'Background Image' ), + 'theme_supports' => 'custom-background', + 'priority' => 80, + ) ); + + $this->add_setting( 'background_image', array( + 'default' => get_theme_support( 'custom-background', 'default-image' ), + 'theme_supports' => 'custom-background', + ) ); + + $this->add_setting( new WP_Customize_Background_Image_Setting( $this, 'background_image_thumb', array( + 'theme_supports' => 'custom-background', + ) ) ); + + $this->add_control( new WP_Customize_Background_Image_Control( $this ) ); + + $this->add_setting( 'background_repeat', array( + 'default' => 'repeat', + 'theme_supports' => 'custom-background', + ) ); + + $this->add_control( 'background_repeat', array( + 'label' => __( 'Background Repeat' ), + 'section' => 'background_image', + 'type' => 'radio', + 'choices' => array( + 'no-repeat' => __('No Repeat'), + 'repeat' => __('Tile'), + 'repeat-x' => __('Tile Horizontally'), + 'repeat-y' => __('Tile Vertically'), + ), + ) ); + + $this->add_setting( 'background_position_x', array( + 'default' => 'left', + 'theme_supports' => 'custom-background', + ) ); + + $this->add_control( 'background_position_x', array( + 'label' => __( 'Background Position' ), + 'section' => 'background_image', + 'type' => 'radio', + 'choices' => array( + 'left' => __('Left'), + 'center' => __('Center'), + 'right' => __('Right'), + ), + ) ); + + $this->add_setting( 'background_attachment', array( + 'default' => 'fixed', + 'theme_supports' => 'custom-background', + ) ); + + $this->add_control( 'background_attachment', array( + 'label' => __( 'Background Attachment' ), + 'section' => 'background_image', + 'type' => 'radio', + 'choices' => array( + 'fixed' => __('Fixed'), + 'scroll' => __('Scroll'), + ), + ) ); + + // If the theme is using the default background callback, we can update + // the background CSS using postMessage. + if ( get_theme_support( 'custom-background', 'wp-head-callback' ) === '_custom_background_cb' ) { + foreach ( array( 'color', 'image', 'position_x', 'repeat', 'attachment' ) as $prop ) { + $this->get_setting( 'background_' . $prop )->transport = 'postMessage'; + } + } + + /* Nav Menus */ + + $locations = get_registered_nav_menus(); + $menus = wp_get_nav_menus(); + $menu_locations = get_nav_menu_locations(); + $num_locations = count( array_keys( $locations ) ); + + $this->add_section( 'nav', array( + 'title' => __( 'Navigation' ), + 'theme_supports' => 'menus', + 'priority' => 100, + 'description' => sprintf( _n('Your theme supports %s menu. Select which menu you would like to use.', 'Your theme supports %s menus. Select which menu appears in each location.', $num_locations ), number_format_i18n( $num_locations ) ) . "\n\n" . __('You can edit your menu content on the Menus screen in the Appearance section.'), + ) ); + + if ( $menus ) { + $choices = array( 0 => __( '— Select —' ) ); + foreach ( $menus as $menu ) { + $choices[ $menu->term_id ] = wp_html_excerpt( $menu->name, 40, '…' ); + } + + foreach ( $locations as $location => $description ) { + $menu_setting_id = "nav_menu_locations[{$location}]"; + + $this->add_setting( $menu_setting_id, array( + 'sanitize_callback' => 'absint', + 'theme_supports' => 'menus', + ) ); + + $this->add_control( $menu_setting_id, array( + 'label' => $description, + 'section' => 'nav', + 'type' => 'select', + 'choices' => $choices, + ) ); + } + } + + /* Static Front Page */ + // #WP19627 + + $this->add_section( 'static_front_page', array( + 'title' => __( 'Static Front Page' ), + // 'theme_supports' => 'static-front-page', + 'priority' => 120, + 'description' => __( 'Your theme supports a static front page.' ), + ) ); + + $this->add_setting( 'show_on_front', array( + 'default' => get_option( 'show_on_front' ), + 'capability' => 'manage_options', + 'type' => 'option', + // 'theme_supports' => 'static-front-page', + ) ); + + $this->add_control( 'show_on_front', array( + 'label' => __( 'Front page displays' ), + 'section' => 'static_front_page', + 'type' => 'radio', + 'choices' => array( + 'posts' => __( 'Your latest posts' ), + 'page' => __( 'A static page' ), + ), + ) ); + + $this->add_setting( 'page_on_front', array( + 'type' => 'option', + 'capability' => 'manage_options', + // 'theme_supports' => 'static-front-page', + ) ); + + $this->add_control( 'page_on_front', array( + 'label' => __( 'Front page' ), + 'section' => 'static_front_page', + 'type' => 'dropdown-pages', + ) ); + + $this->add_setting( 'page_for_posts', array( + 'type' => 'option', + 'capability' => 'manage_options', + // 'theme_supports' => 'static-front-page', + ) ); + + $this->add_control( 'page_for_posts', array( + 'label' => __( 'Posts page' ), + 'section' => 'static_front_page', + 'type' => 'dropdown-pages', + ) ); + } + + /** + * Callback for validating the header_textcolor value. + * + * Accepts 'blank', and otherwise uses sanitize_hex_color_no_hash(). + * Returns default text color if hex color is empty. + * + * @since 3.4.0 + * + * @param string $color + * @return string + */ + public function _sanitize_header_textcolor( $color ) { + if ( 'blank' === $color ) + return 'blank'; + + $color = sanitize_hex_color_no_hash( $color ); + if ( empty( $color ) ) + $color = get_theme_support( 'custom-header', 'default-text-color' ); + + return $color; + } +}; + +/** + * Validates a hex color. + * + * Returns either '', a 3 or 6 digit hex color (with #), or null. + * For validating values without a #, see sanitize_hex_color_no_hash(). + * + * @since 3.4.0 + * + * @param string $color + * @return string|null + */ +function sanitize_hex_color( $color ) { + if ( '' === $color ) + return ''; + + // 3 or 6 hex digits, or the empty string. + if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) + return $color; + + return null; +} + +/** + * Sanitizes a hex color without a hash. Use sanitize_hex_color() when possible. + * + * Saving hex colors without a hash puts the burden of adding the hash on the + * UI, which makes it difficult to use or upgrade to other color types such as + * rgba, hsl, rgb, and html color names. + * + * Returns either '', a 3 or 6 digit hex color (without a #), or null. + * + * @since 3.4.0 + * @uses sanitize_hex_color() + * + * @param string $color + * @return string|null + */ +function sanitize_hex_color_no_hash( $color ) { + $color = ltrim( $color, '#' ); + + if ( '' === $color ) + return ''; + + return sanitize_hex_color( '#' . $color ) ? $color : null; +} + +/** + * Ensures that any hex color is properly hashed. + * Otherwise, returns value untouched. + * + * This method should only be necessary if using sanitize_hex_color_no_hash(). + * + * @since 3.4.0 + * + * @param string $color + * @return string + */ +function maybe_hash_hex_color( $color ) { + if ( $unhashed = sanitize_hex_color_no_hash( $color ) ) + return '#' . $unhashed; + + return $color; +} diff --git a/sources/wp-includes/class-wp-customize-section.php b/sources/wp-includes/class-wp-customize-section.php new file mode 100644 index 0000000..ab24dab --- /dev/null +++ b/sources/wp-includes/class-wp-customize-section.php @@ -0,0 +1,96 @@ +<?php +/** + * Customize Section Class. + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Section { + public $manager; + public $id; + public $priority = 10; + public $capability = 'edit_theme_options'; + public $theme_supports = ''; + public $title = ''; + public $description = ''; + public $controls; + + /** + * Constructor. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager + * @param string $id An specific ID of the section. + * @param array $args Section arguments. + */ + function __construct( $manager, $id, $args = array() ) { + $keys = array_keys( get_class_vars( __CLASS__ ) ); + foreach ( $keys as $key ) { + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } + + $this->manager = $manager; + $this->id = $id; + + $this->controls = array(); // Users cannot customize the $controls array. + + return $this; + } + + /** + * Check if the theme supports the section and check user capabilities. + * + * @since 3.4.0 + * + * @return bool False if theme doesn't support the section or user doesn't have the capability. + */ + public final function check_capabilities() { + if ( $this->capability && ! call_user_func_array( 'current_user_can', (array) $this->capability ) ) + return false; + + if ( $this->theme_supports && ! call_user_func_array( 'current_theme_supports', (array) $this->theme_supports ) ) + return false; + + return true; + } + + /** + * Check capabilities and render the section. + * + * @since 3.4.0 + */ + public final function maybe_render() { + if ( ! $this->check_capabilities() ) + return; + + do_action( 'customize_render_section', $this ); + do_action( 'customize_render_section_' . $this->id ); + + $this->render(); + } + + /** + * Render the section. + * + * @since 3.4.0 + */ + protected function render() { + ?> + <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="control-section accordion-section"> + <h3 class="accordion-section-title" tabindex="0"><?php echo esc_html( $this->title ); ?></h3> + <ul class="accordion-section-content"> + <?php if ( ! empty( $this->description ) ) : ?> + <li><p class="description"><?php echo $this->description; ?></p></li> + <?php endif; ?> + <?php + foreach ( $this->controls as $control ) + $control->maybe_render(); + ?> + </ul> + </li> + <?php + } +} diff --git a/sources/wp-includes/class-wp-customize-setting.php b/sources/wp-includes/class-wp-customize-setting.php new file mode 100644 index 0000000..c8542ef --- /dev/null +++ b/sources/wp-includes/class-wp-customize-setting.php @@ -0,0 +1,439 @@ +<?php +/** + * Customize Setting Class. + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Setting { + public $manager; + public $id; + + public $type = 'theme_mod'; + public $capability = 'edit_theme_options'; + public $theme_supports = ''; + public $default = ''; + public $transport = 'refresh'; + + public $sanitize_callback = ''; + public $sanitize_js_callback = ''; + + protected $id_data = array(); + private $_post_value; // Cached, sanitized $_POST value. + + /** + * Constructor. + * + * @since 3.4.0 + * + * @param WP_Customize_Manager $manager + * @param string $id An specific ID of the setting. Can be a + * theme mod or option name. + * @param array $args Setting arguments. + * @return WP_Customize_Setting + */ + function __construct( $manager, $id, $args = array() ) { + $keys = array_keys( get_class_vars( __CLASS__ ) ); + foreach ( $keys as $key ) { + if ( isset( $args[ $key ] ) ) + $this->$key = $args[ $key ]; + } + + $this->manager = $manager; + $this->id = $id; + + // Parse the ID for array keys. + $this->id_data[ 'keys' ] = preg_split( '/\[/', str_replace( ']', '', $this->id ) ); + $this->id_data[ 'base' ] = array_shift( $this->id_data[ 'keys' ] ); + + // Rebuild the ID. + $this->id = $this->id_data[ 'base' ]; + if ( ! empty( $this->id_data[ 'keys' ] ) ) + $this->id .= '[' . implode( '][', $this->id_data[ 'keys' ] ) . ']'; + + if ( $this->sanitize_callback ) + add_filter( "customize_sanitize_{$this->id}", $this->sanitize_callback, 10, 2 ); + + if ( $this->sanitize_js_callback ) + add_filter( "customize_sanitize_js_{$this->id}", $this->sanitize_js_callback, 10, 2 ); + + return $this; + } + + /** + * Handle previewing the setting. + * + * @since 3.4.0 + */ + public function preview() { + switch( $this->type ) { + case 'theme_mod' : + add_filter( 'theme_mod_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) ); + break; + case 'option' : + if ( empty( $this->id_data[ 'keys' ] ) ) + add_filter( 'pre_option_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) ); + else { + add_filter( 'option_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) ); + add_filter( 'default_option_' . $this->id_data[ 'base' ], array( $this, '_preview_filter' ) ); + } + break; + default : + do_action( 'customize_preview_' . $this->id ); + } + } + + /** + * Callback function to filter the theme mods and options. + * + * @since 3.4.0 + * @uses WP_Customize_Setting::multidimensional_replace() + * + * @param mixed $original Old value. + * @return mixed New or old value. + */ + public function _preview_filter( $original ) { + return $this->multidimensional_replace( $original, $this->id_data[ 'keys' ], $this->post_value() ); + } + + /** + * Set the value of the parameter for a specific theme. + * + * @since 3.4.0 + * + * @return bool False if cap check fails or value isn't set. + */ + public final function save() { + $value = $this->post_value(); + + if ( ! $this->check_capabilities() || ! isset( $value ) ) + return false; + + do_action( 'customize_save_' . $this->id_data[ 'base' ] ); + + $this->update( $value ); + } + + /** + * Fetches, validates, and sanitizes the $_POST value. + * + * @since 3.4.0 + * + * @param mixed $default A default value which is used as a fallback. Default is null. + * @return mixed The default value on failure, otherwise the sanitized value. + */ + public final function post_value( $default = null ) { + if ( isset( $this->_post_value ) ) + return $this->_post_value; + + $result = $this->manager->post_value( $this ); + + if ( isset( $result ) ) + return $this->_post_value = $result; + else + return $default; + } + + /** + * Sanitize an input. + * + * @since 3.4.0 + * + * @param mixed $value The value to sanitize. + * @return mixed Null if an input isn't valid, otherwise the sanitized value. + */ + public function sanitize( $value ) { + $value = wp_unslash( $value ); + return apply_filters( "customize_sanitize_{$this->id}", $value, $this ); + } + + /** + * Set the value of the parameter for a specific theme. + * + * @since 3.4.0 + * + * @param mixed $value The value to update. + * @return mixed The result of saving the value. + */ + protected function update( $value ) { + switch( $this->type ) { + case 'theme_mod' : + return $this->_update_theme_mod( $value ); + break; + case 'option' : + return $this->_update_option( $value ); + break; + default : + return do_action( 'customize_update_' . $this->type, $value ); + } + } + + /** + * Update the theme mod from the value of the parameter. + * + * @since 3.4.0 + * + * @param mixed $value The value to update. + * @return mixed The result of saving the value. + */ + protected function _update_theme_mod( $value ) { + // Handle non-array theme mod. + if ( empty( $this->id_data[ 'keys' ] ) ) + return set_theme_mod( $this->id_data[ 'base' ], $value ); + + // Handle array-based theme mod. + $mods = get_theme_mod( $this->id_data[ 'base' ] ); + $mods = $this->multidimensional_replace( $mods, $this->id_data[ 'keys' ], $value ); + if ( isset( $mods ) ) + return set_theme_mod( $this->id_data[ 'base' ], $mods ); + } + + /** + * Update the theme mod from the value of the parameter. + * + * @since 3.4.0 + * + * @param mixed $value The value to update. + * @return mixed The result of saving the value. + */ + protected function _update_option( $value ) { + // Handle non-array option. + if ( empty( $this->id_data[ 'keys' ] ) ) + return update_option( $this->id_data[ 'base' ], $value ); + + // Handle array-based options. + $options = get_option( $this->id_data[ 'base' ] ); + $options = $this->multidimensional_replace( $options, $this->id_data[ 'keys' ], $value ); + if ( isset( $options ) ) + return update_option( $this->id_data[ 'base' ], $options ); + } + + /** + * Fetch the value of the parameter for a specific theme. + * + * @since 3.4.0 + * + * @return mixed The requested value. + */ + public function value() { + switch( $this->type ) { + case 'theme_mod' : + $function = 'get_theme_mod'; + break; + case 'option' : + $function = 'get_option'; + break; + default : + return apply_filters( 'customize_value_' . $this->id_data[ 'base' ], $this->default ); + } + + // Handle non-array value + if ( empty( $this->id_data[ 'keys' ] ) ) + return $function( $this->id_data[ 'base' ], $this->default ); + + // Handle array-based value + $values = $function( $this->id_data[ 'base' ] ); + return $this->multidimensional_get( $values, $this->id_data[ 'keys' ], $this->default ); + } + + /** + * Escape the parameter's value for use in JavaScript. + * + * @since 3.4.0 + * + * @return mixed The requested escaped value. + */ + public function js_value() { + $value = apply_filters( "customize_sanitize_js_{$this->id}", $this->value(), $this ); + + if ( is_string( $value ) ) + return html_entity_decode( $value, ENT_QUOTES, 'UTF-8'); + + return $value; + } + + /** + * Check if the theme supports the setting and check user capabilities. + * + * @since 3.4.0 + * + * @return bool False if theme doesn't support the setting or user can't change setting, otherwise true. + */ + public final function check_capabilities() { + if ( $this->capability && ! call_user_func_array( 'current_user_can', (array) $this->capability ) ) + return false; + + if ( $this->theme_supports && ! call_user_func_array( 'current_theme_supports', (array) $this->theme_supports ) ) + return false; + + return true; + } + + /** + * Multidimensional helper function. + * + * @since 3.4.0 + * + * @param $root + * @param $keys + * @param bool $create Default is false. + * @return null|array Keys are 'root', 'node', and 'key'. + */ + final protected function multidimensional( &$root, $keys, $create = false ) { + if ( $create && empty( $root ) ) + $root = array(); + + if ( ! isset( $root ) || empty( $keys ) ) + return; + + $last = array_pop( $keys ); + $node = &$root; + + foreach ( $keys as $key ) { + if ( $create && ! isset( $node[ $key ] ) ) + $node[ $key ] = array(); + + if ( ! is_array( $node ) || ! isset( $node[ $key ] ) ) + return; + + $node = &$node[ $key ]; + } + + if ( $create && ! isset( $node[ $last ] ) ) + $node[ $last ] = array(); + + if ( ! isset( $node[ $last ] ) ) + return; + + return array( + 'root' => &$root, + 'node' => &$node, + 'key' => $last, + ); + } + + /** + * Will attempt to replace a specific value in a multidimensional array. + * + * @since 3.4.0 + * + * @param $root + * @param $keys + * @param mixed $value The value to update. + * @return + */ + final protected function multidimensional_replace( $root, $keys, $value ) { + if ( ! isset( $value ) ) + return $root; + elseif ( empty( $keys ) ) // If there are no keys, we're replacing the root. + return $value; + + $result = $this->multidimensional( $root, $keys, true ); + + if ( isset( $result ) ) + $result['node'][ $result['key'] ] = $value; + + return $root; + } + + /** + * Will attempt to fetch a specific value from a multidimensional array. + * + * @since 3.4.0 + * + * @param $root + * @param $keys + * @param $default A default value which is used as a fallback. Default is null. + * @return mixed The requested value or the default value. + */ + final protected function multidimensional_get( $root, $keys, $default = null ) { + if ( empty( $keys ) ) // If there are no keys, test the root. + return isset( $root ) ? $root : $default; + + $result = $this->multidimensional( $root, $keys ); + return isset( $result ) ? $result['node'][ $result['key'] ] : $default; + } + + /** + * Will attempt to check if a specific value in a multidimensional array is set. + * + * @since 3.4.0 + * + * @param $root + * @param $keys + * @return bool True if value is set, false if not. + */ + final protected function multidimensional_isset( $root, $keys ) { + $result = $this->multidimensional_get( $root, $keys ); + return isset( $result ); + } +} + +/** + * A setting that is used to filter a value, but will not save the results. + * + * Results should be properly handled using another setting or callback. + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +class WP_Customize_Filter_Setting extends WP_Customize_Setting { + + /** + * @since 3.4.0 + */ + public function update( $value ) {} +} + +/** + * A setting that is used to filter a value, but will not save the results. + * + * Results should be properly handled using another setting or callback. + * + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +final class WP_Customize_Header_Image_Setting extends WP_Customize_Setting { + public $id = 'header_image_data'; + + /** + * @since 3.4.0 + * + * @param $value + */ + public function update( $value ) { + global $custom_image_header; + + // If the value doesn't exist (removed or random), + // use the header_image value. + if ( ! $value ) + $value = $this->manager->get_setting('header_image')->post_value(); + + if ( is_array( $value ) && isset( $value['choice'] ) ) + $custom_image_header->set_header_image( $value['choice'] ); + else + $custom_image_header->set_header_image( $value ); + } +} + +/** + * @package WordPress + * @subpackage Customize + * @since 3.4.0 + */ +final class WP_Customize_Background_Image_Setting extends WP_Customize_Setting { + public $id = 'background_image_thumb'; + + /** + * @since 3.4.0 + * @uses remove_theme_mod() + * + * @param $value + */ + public function update( $value ) { + remove_theme_mod( 'background_image_thumb' ); + } +} diff --git a/sources/wp-includes/class-wp-editor.php b/sources/wp-includes/class-wp-editor.php new file mode 100644 index 0000000..7581288 --- /dev/null +++ b/sources/wp-includes/class-wp-editor.php @@ -0,0 +1,919 @@ +<?php +/** + * Facilitates adding of the WordPress editor as used on the Write and Edit screens. + * + * @package WordPress + * @since 3.3.0 + * + * Private, not included by default. See wp_editor() in wp-includes/general-template.php. + */ + +final class _WP_Editors { + public static $mce_locale; + + private static $mce_settings = array(); + private static $qt_settings = array(); + private static $plugins = array(); + private static $qt_buttons = array(); + private static $ext_plugins; + private static $baseurl; + private static $first_init; + private static $this_tinymce = false; + private static $this_quicktags = false; + private static $has_tinymce = false; + private static $has_quicktags = false; + private static $has_medialib = false; + private static $editor_buttons_css = true; + + private function __construct() {} + + public static function parse_settings($editor_id, $settings) { + $set = wp_parse_args( $settings, array( + 'wpautop' => true, // use wpautop? + 'media_buttons' => true, // show insert/upload button(s) + 'textarea_name' => $editor_id, // set the textarea name to something different, square brackets [] can be used here + 'textarea_rows' => 20, + 'tabindex' => '', + 'tabfocus_elements' => ':prev,:next', // the previous and next element ID to move the focus to when pressing the Tab key in TinyMCE + 'editor_css' => '', // intended for extra styles for both visual and Text editors buttons, needs to include the <style> tags, can use "scoped". + 'editor_class' => '', // add extra class(es) to the editor textarea + 'teeny' => false, // output the minimal editor config used in Press This + 'dfw' => false, // replace the default fullscreen with DFW (needs specific DOM elements and css) + 'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array() + 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array() + ) ); + + self::$this_tinymce = ( $set['tinymce'] && user_can_richedit() ); + self::$this_quicktags = (bool) $set['quicktags']; + + if ( self::$this_tinymce ) + self::$has_tinymce = true; + + if ( self::$this_quicktags ) + self::$has_quicktags = true; + + if ( empty( $set['editor_height'] ) ) + return $set; + + if ( 'content' === $editor_id ) { + // A cookie (set when a user resizes the editor) overrides the height. + $cookie = (int) get_user_setting( 'ed_size' ); + + // Upgrade an old TinyMCE cookie if it is still around, and the new one isn't. + if ( ! $cookie && isset( $_COOKIE['TinyMCE_content_size'] ) ) { + parse_str( $_COOKIE['TinyMCE_content_size'], $cookie ); + $cookie = $cookie['ch']; + } + + if ( $cookie ) + $set['editor_height'] = $cookie; + } + + if ( $set['editor_height'] < 50 ) + $set['editor_height'] = 50; + elseif ( $set['editor_height'] > 5000 ) + $set['editor_height'] = 5000; + + return $set; + } + + /** + * Outputs the HTML for a single instance of the editor. + * + * @param string $content The initial content of the editor. + * @param string $editor_id ID for the textarea and TinyMCE and Quicktags instances (can contain only ASCII letters and numbers). + * @param array $settings See the _parse_settings() method for description. + */ + public static function editor( $content, $editor_id, $settings = array() ) { + + $set = self::parse_settings($editor_id, $settings); + $editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"'; + $tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : ''; + $switch_class = 'html-active'; + $toolbar = $buttons = ''; + + if ( ! empty( $set['editor_height'] ) ) + $height = ' style="height: ' . $set['editor_height'] . 'px"'; + else + $height = ' rows="' . $set['textarea_rows'] . '"'; + + if ( !current_user_can( 'upload_files' ) ) + $set['media_buttons'] = false; + + if ( self::$this_quicktags && self::$this_tinymce ) { + $switch_class = 'html-active'; + + // 'html' and 'switch-html' are used for the "Text" editor tab. + if ( 'html' == wp_default_editor() ) { + add_filter('the_editor_content', 'wp_htmledit_pre'); + } else { + add_filter('the_editor_content', 'wp_richedit_pre'); + $switch_class = 'tmce-active'; + } + + $buttons .= '<a id="' . $editor_id . '-html" class="wp-switch-editor switch-html" onclick="switchEditors.switchto(this);">' . _x( 'Text', 'Name for the Text editor tab (formerly HTML)' ) . "</a>\n"; + $buttons .= '<a id="' . $editor_id . '-tmce" class="wp-switch-editor switch-tmce" onclick="switchEditors.switchto(this);">' . __('Visual') . "</a>\n"; + } + + echo '<div id="wp-' . $editor_id . '-wrap" class="wp-core-ui wp-editor-wrap ' . $switch_class . '">'; + + if ( self::$editor_buttons_css ) { + wp_print_styles('editor-buttons'); + self::$editor_buttons_css = false; + } + + if ( !empty($set['editor_css']) ) + echo $set['editor_css'] . "\n"; + + if ( !empty($buttons) || $set['media_buttons'] ) { + echo '<div id="wp-' . $editor_id . '-editor-tools" class="wp-editor-tools hide-if-no-js">'; + echo $buttons; + + if ( $set['media_buttons'] ) { + self::$has_medialib = true; + + if ( !function_exists('media_buttons') ) + include(ABSPATH . 'wp-admin/includes/media.php'); + + echo '<div id="wp-' . $editor_id . '-media-buttons" class="wp-media-buttons">'; + do_action('media_buttons', $editor_id); + echo "</div>\n"; + } + echo "</div>\n"; + } + + $the_editor = apply_filters('the_editor', '<div id="wp-' . $editor_id . '-editor-container" class="wp-editor-container"><textarea' . $editor_class . $height . $tabindex . ' cols="40" name="' . $set['textarea_name'] . '" id="' . $editor_id . '">%s</textarea></div>'); + $content = apply_filters('the_editor_content', $content); + + printf($the_editor, $content); + echo "\n</div>\n\n"; + + self::editor_settings($editor_id, $set); + } + + public static function editor_settings($editor_id, $set) { + $first_run = false; + + if ( empty(self::$first_init) ) { + if ( is_admin() ) { + add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_js'), 50 ); + add_action( 'admin_footer', array( __CLASS__, 'enqueue_scripts'), 1 ); + } else { + add_action( 'wp_print_footer_scripts', array( __CLASS__, 'editor_js'), 50 ); + add_action( 'wp_footer', array( __CLASS__, 'enqueue_scripts'), 1 ); + } + } + + if ( self::$this_quicktags ) { + + $qtInit = array( + 'id' => $editor_id, + 'buttons' => '' + ); + + if ( is_array($set['quicktags']) ) + $qtInit = array_merge($qtInit, $set['quicktags']); + + if ( empty($qtInit['buttons']) ) + $qtInit['buttons'] = 'strong,em,link,block,del,ins,img,ul,ol,li,code,more,close'; + + if ( $set['dfw'] ) + $qtInit['buttons'] .= ',fullscreen'; + + $qtInit = apply_filters('quicktags_settings', $qtInit, $editor_id); + self::$qt_settings[$editor_id] = $qtInit; + + self::$qt_buttons = array_merge( self::$qt_buttons, explode(',', $qtInit['buttons']) ); + } + + if ( self::$this_tinymce ) { + + if ( empty(self::$first_init) ) { + self::$baseurl = includes_url('js/tinymce'); + self::$mce_locale = $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1 + $no_captions = (bool) apply_filters( 'disable_captions', '' ); + $plugins = array( 'inlinepopups', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs' ); + $first_run = true; + $ext_plugins = ''; + + if ( $set['teeny'] ) { + self::$plugins = $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs' ), $editor_id ); + } else { + /* + The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'. + It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin. + The url should be absolute and should include the js file name to be loaded. Example: + array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' ) + If the plugin uses a button, it should be added with one of the "$mce_buttons" filters. + */ + $mce_external_plugins = apply_filters('mce_external_plugins', array()); + + if ( ! empty($mce_external_plugins) ) { + + /* + The following filter loads external language files for TinyMCE plugins. + It takes an associative array 'plugin_name' => 'path', where path is the + include path to the file. The language file should follow the same format as + /tinymce/langs/wp-langs.php and should define a variable $strings that + holds all translated strings. + When this filter is not used, the function will try to load {mce_locale}.js. + If that is not found, en.js will be tried next. + */ + $mce_external_languages = apply_filters('mce_external_languages', array()); + + $loaded_langs = array(); + $strings = ''; + + if ( ! empty($mce_external_languages) ) { + foreach ( $mce_external_languages as $name => $path ) { + if ( @is_file($path) && @is_readable($path) ) { + include_once($path); + $ext_plugins .= $strings . "\n"; + $loaded_langs[] = $name; + } + } + } + + foreach ( $mce_external_plugins as $name => $url ) { + + $url = set_url_scheme( $url ); + + $plugins[] = '-' . $name; + + $plugurl = dirname($url); + $strings = $str1 = $str2 = ''; + if ( ! in_array($name, $loaded_langs) ) { + $path = str_replace( content_url(), '', $plugurl ); + $path = WP_CONTENT_DIR . $path . '/langs/'; + + if ( function_exists('realpath') ) + $path = trailingslashit( realpath($path) ); + + if ( @is_file($path . $mce_locale . '.js') ) + $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n"; + + if ( @is_file($path . $mce_locale . '_dlg.js') ) + $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n"; + + if ( 'en' != $mce_locale && empty($strings) ) { + if ( @is_file($path . 'en.js') ) { + $str1 = @file_get_contents($path . 'en.js'); + $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n"; + } + + if ( @is_file($path . 'en_dlg.js') ) { + $str2 = @file_get_contents($path . 'en_dlg.js'); + $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n"; + } + } + + if ( ! empty($strings) ) + $ext_plugins .= "\n" . $strings . "\n"; + } + + $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n"; + $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n"; + } + } + + $plugins = array_unique( apply_filters('tiny_mce_plugins', $plugins) ); + } + + if ( $set['dfw'] ) + $plugins[] = 'wpfullscreen'; + + self::$plugins = $plugins; + self::$ext_plugins = $ext_plugins; + + if ( in_array( 'spellchecker', $plugins ) ) { + /* + translators: These languages show up in the spellchecker drop-down menu, in the order specified, and with the first + language listed being the default language. They must be comma-separated and take the format of name=code, where name + is the language name (which you may internationalize), and code is a valid ISO 639 language code. Please test the + spellchecker with your values. + */ + $mce_spellchecker_languages = __( 'English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv' ); + + /* + The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu. + By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server. + The + sign marks the default language. More: http://www.tinymce.com/wiki.php/Plugin:spellchecker. + */ + $mce_spellchecker_languages = apply_filters( 'mce_spellchecker_languages', '+' . $mce_spellchecker_languages ); + } + + self::$first_init = array( + 'mode' => 'exact', + 'width' => '100%', + 'theme' => 'advanced', + 'skin' => 'wp_theme', + 'language' => self::$mce_locale, + 'theme_advanced_toolbar_location' => 'top', + 'theme_advanced_toolbar_align' => 'left', + 'theme_advanced_statusbar_location' => 'bottom', + 'theme_advanced_resizing' => true, + 'theme_advanced_resize_horizontal' => false, + 'dialog_type' => 'modal', + 'formats' => "{ + alignleft : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}}, + {selector : 'img,table', classes : 'alignleft'} + ], + aligncenter : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}}, + {selector : 'img,table', classes : 'aligncenter'} + ], + alignright : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}}, + {selector : 'img,table', classes : 'alignright'} + ], + strikethrough : {inline : 'del'} + }", + 'relative_urls' => false, + 'remove_script_host' => false, + 'convert_urls' => false, + 'remove_linebreaks' => true, + 'gecko_spellcheck' => true, + 'fix_list_elements' => true, + 'keep_styles' => false, + 'entities' => '38,amp,60,lt,62,gt', + 'accessibility_focus' => true, + 'media_strict' => false, + 'paste_remove_styles' => true, + 'paste_remove_spans' => true, + 'paste_strip_class_attributes' => 'all', + 'paste_text_use_dialog' => true, + 'webkit_fake_resize' => false, + 'preview_styles' => 'font-family font-weight text-decoration text-transform', + 'schema' => 'html5', + 'wpeditimage_disable_captions' => $no_captions, + 'wp_fullscreen_content_css' => self::$baseurl . '/plugins/wpfullscreen/css/wp-fullscreen.css', + 'plugins' => implode( ',', $plugins ) + ); + + if ( in_array( 'spellchecker', $plugins ) ) { + self::$first_init['spellchecker_rpc_url'] = self::$baseurl . '/plugins/spellchecker/rpc.php'; + self::$first_init['spellchecker_languages'] = $mce_spellchecker_languages; + } + + // load editor_style.css if the current theme supports it + if ( ! empty( $GLOBALS['editor_styles'] ) && is_array( $GLOBALS['editor_styles'] ) ) { + $editor_styles = $GLOBALS['editor_styles']; + + $mce_css = array(); + $editor_styles = array_unique( array_filter( $editor_styles ) ); + $style_uri = get_stylesheet_directory_uri(); + $style_dir = get_stylesheet_directory(); + + // Support externally referenced styles (like, say, fonts). + foreach ( $editor_styles as $key => $file ) { + if ( preg_match( '~^(https?:)?//~', $file ) ) { + $mce_css[] = esc_url_raw( $file ); + unset( $editor_styles[ $key ] ); + } + } + + // Look in a parent theme first, that way child theme CSS overrides. + if ( is_child_theme() ) { + $template_uri = get_template_directory_uri(); + $template_dir = get_template_directory(); + + foreach ( $editor_styles as $key => $file ) { + if ( $file && file_exists( "$template_dir/$file" ) ) + $mce_css[] = "$template_uri/$file"; + } + } + + foreach ( $editor_styles as $file ) { + if ( $file && file_exists( "$style_dir/$file" ) ) + $mce_css[] = "$style_uri/$file"; + } + + $mce_css = implode( ',', $mce_css ); + } else { + $mce_css = ''; + } + + $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' ); + + if ( ! empty($mce_css) ) + self::$first_init['content_css'] = $mce_css; + } + + if ( $set['teeny'] ) { + $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold', 'italic', 'underline', 'blockquote', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'undo', 'redo', 'link', 'unlink', 'fullscreen'), $editor_id ); + $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = array(); + } else { + $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'bullist', 'numlist', 'blockquote', 'justifyleft', 'justifycenter', 'justifyright', 'link', 'unlink', 'wp_more', 'spellchecker', 'fullscreen', 'wp_adv' ), $editor_id); + $mce_buttons_2 = apply_filters('mce_buttons_2', array( 'formatselect', 'underline', 'justifyfull', 'forecolor', 'pastetext', 'pasteword', 'removeformat', 'charmap', 'outdent', 'indent', 'undo', 'redo', 'wp_help' ), $editor_id); + $mce_buttons_3 = apply_filters('mce_buttons_3', array(), $editor_id); + $mce_buttons_4 = apply_filters('mce_buttons_4', array(), $editor_id); + } + + $body_class = $editor_id; + + if ( $post = get_post() ) { + $body_class .= ' post-type-' . sanitize_html_class( $post->post_type ) . ' post-status-' . sanitize_html_class( $post->post_status ); + if ( post_type_supports( $post->post_type, 'post-formats' ) ) { + $post_format = get_post_format( $post ); + if ( $post_format && ! is_wp_error( $post_format ) ) + $body_class .= ' post-format-' . sanitize_html_class( $post_format ); + else + $body_class .= ' post-format-standard'; + } + } + + if ( !empty($set['tinymce']['body_class']) ) { + $body_class .= ' ' . $set['tinymce']['body_class']; + unset($set['tinymce']['body_class']); + } + + if ( $set['dfw'] ) { + // replace the first 'fullscreen' with 'wp_fullscreen' + if ( ($key = array_search('fullscreen', $mce_buttons)) !== false ) + $mce_buttons[$key] = 'wp_fullscreen'; + elseif ( ($key = array_search('fullscreen', $mce_buttons_2)) !== false ) + $mce_buttons_2[$key] = 'wp_fullscreen'; + elseif ( ($key = array_search('fullscreen', $mce_buttons_3)) !== false ) + $mce_buttons_3[$key] = 'wp_fullscreen'; + elseif ( ($key = array_search('fullscreen', $mce_buttons_4)) !== false ) + $mce_buttons_4[$key] = 'wp_fullscreen'; + } + + $mceInit = array ( + 'elements' => $editor_id, + 'wpautop' => (bool) $set['wpautop'], + 'remove_linebreaks' => (bool) $set['wpautop'], + 'apply_source_formatting' => (bool) !$set['wpautop'], + 'theme_advanced_buttons1' => implode($mce_buttons, ','), + 'theme_advanced_buttons2' => implode($mce_buttons_2, ','), + 'theme_advanced_buttons3' => implode($mce_buttons_3, ','), + 'theme_advanced_buttons4' => implode($mce_buttons_4, ','), + 'tabfocus_elements' => $set['tabfocus_elements'], + 'body_class' => $body_class + ); + + // The main editor doesn't use the TinyMCE resizing cookie. + $mceInit['theme_advanced_resizing_use_cookie'] = 'content' !== $editor_id || empty( $set['editor_height'] ); + + if ( $first_run ) + $mceInit = array_merge(self::$first_init, $mceInit); + + if ( is_array($set['tinymce']) ) + $mceInit = array_merge($mceInit, $set['tinymce']); + + // For people who really REALLY know what they're doing with TinyMCE + // You can modify $mceInit to add, remove, change elements of the config before tinyMCE.init + // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through this filter. + // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0. + if ( $set['teeny'] ) { + $mceInit = apply_filters('teeny_mce_before_init', $mceInit, $editor_id); + } else { + $mceInit = apply_filters('tiny_mce_before_init', $mceInit, $editor_id); + } + + if ( empty($mceInit['theme_advanced_buttons3']) && !empty($mceInit['theme_advanced_buttons4']) ) { + $mceInit['theme_advanced_buttons3'] = $mceInit['theme_advanced_buttons4']; + $mceInit['theme_advanced_buttons4'] = ''; + } + + self::$mce_settings[$editor_id] = $mceInit; + } // end if self::$this_tinymce + } + + private static function _parse_init($init) { + $options = ''; + + foreach ( $init as $k => $v ) { + if ( is_bool($v) ) { + $val = $v ? 'true' : 'false'; + $options .= $k . ':' . $val . ','; + continue; + } elseif ( !empty($v) && is_string($v) && ( ('{' == $v{0} && '}' == $v{strlen($v) - 1}) || ('[' == $v{0} && ']' == $v{strlen($v) - 1}) || preg_match('/^\(?function ?\(/', $v) ) ) { + $options .= $k . ':' . $v . ','; + continue; + } + $options .= $k . ':"' . $v . '",'; + } + + return '{' . trim( $options, ' ,' ) . '}'; + } + + public static function enqueue_scripts() { + wp_enqueue_script('word-count'); + + if ( self::$has_tinymce ) + wp_enqueue_script('editor'); + + if ( self::$has_quicktags ) + wp_enqueue_script('quicktags'); + + if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) ) { + wp_enqueue_script('wplink'); + wp_enqueue_script('wpdialogs-popup'); + wp_enqueue_style('wp-jquery-ui-dialog'); + } + + if ( in_array('wpfullscreen', self::$plugins, true) || in_array('fullscreen', self::$qt_buttons, true) ) + wp_enqueue_script('wp-fullscreen'); + + if ( self::$has_medialib ) { + add_thickbox(); + wp_enqueue_script('media-upload'); + } + } + + public static function editor_js() { + global $tinymce_version, $concatenate_scripts, $compress_scripts; + + /** + * Filter "tiny_mce_version" is deprecated + * + * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE. + * These plugins can be refreshed by appending query string to the URL passed to "mce_external_plugins" filter. + * If the plugin has a popup dialog, a query string can be added to the button action that opens it (in the plugin's code). + */ + $version = 'ver=' . $tinymce_version; + $tmce_on = !empty(self::$mce_settings); + + if ( ! isset($concatenate_scripts) ) + script_concat_settings(); + + $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING']) + && false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'); + + if ( $tmce_on && 'en' != self::$mce_locale ) + include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php'); + + $mceInit = $qtInit = ''; + if ( $tmce_on ) { + foreach ( self::$mce_settings as $editor_id => $init ) { + $options = self::_parse_init( $init ); + $mceInit .= "'$editor_id':{$options},"; + } + $mceInit = '{' . trim($mceInit, ',') . '}'; + } else { + $mceInit = '{}'; + } + + if ( !empty(self::$qt_settings) ) { + foreach ( self::$qt_settings as $editor_id => $init ) { + $options = self::_parse_init( $init ); + $qtInit .= "'$editor_id':{$options},"; + } + $qtInit = '{' . trim($qtInit, ',') . '}'; + } else { + $qtInit = '{}'; + } + + $ref = array( + 'plugins' => implode( ',', self::$plugins ), + 'theme' => 'advanced', + 'language' => self::$mce_locale + ); + + $suffix = ( defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ) ? '_src' : ''; + + do_action('before_wp_tiny_mce', self::$mce_settings); +?> + + <script type="text/javascript"> + tinyMCEPreInit = { + base : "<?php echo self::$baseurl; ?>", + suffix : "<?php echo $suffix; ?>", + query : "<?php echo $version; ?>", + mceInit : <?php echo $mceInit; ?>, + qtInit : <?php echo $qtInit; ?>, + ref : <?php echo self::_parse_init( $ref ); ?>, + load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');} + }; + </script> +<?php + + $baseurl = self::$baseurl; + + if ( $tmce_on ) { + if ( $compressed ) { + echo "<script type='text/javascript' src='{$baseurl}/wp-tinymce.php?c=1&$version'></script>\n"; + } else { + echo "<script type='text/javascript' src='{$baseurl}/tiny_mce.js?$version'></script>\n"; + echo "<script type='text/javascript' src='{$baseurl}/wp-tinymce-schema.js?$version'></script>\n"; + } + + if ( 'en' != self::$mce_locale && isset($lang) ) + echo "<script type='text/javascript'>\n$lang\n</script>\n"; + else + echo "<script type='text/javascript' src='{$baseurl}/langs/wp-langs-en.js?$version'></script>\n"; + } + + $mce = ( self::$has_tinymce && wp_default_editor() == 'tinymce' ) || ! self::$has_quicktags; +?> + + <script type="text/javascript"> + var wpActiveEditor; + + (function(){ + var init, ed, qt, first_init, DOM, el, i, mce = <?php echo (int) $mce; ?>; + + if ( typeof(tinymce) == 'object' ) { + DOM = tinymce.DOM; + // mark wp_theme/ui.css as loaded + DOM.files[tinymce.baseURI.getURI() + '/themes/advanced/skins/wp_theme/ui.css'] = true; + + DOM.events.add( DOM.select('.wp-editor-wrap'), 'mousedown', function(e){ + if ( this.id ) + wpActiveEditor = this.id.slice(3, -5); + }); + + for ( ed in tinyMCEPreInit.mceInit ) { + if ( first_init ) { + init = tinyMCEPreInit.mceInit[ed] = tinymce.extend( {}, first_init, tinyMCEPreInit.mceInit[ed] ); + } else { + init = first_init = tinyMCEPreInit.mceInit[ed]; + } + + if ( mce ) + try { tinymce.init(init); } catch(e){} + } + } else { + if ( tinyMCEPreInit.qtInit ) { + for ( i in tinyMCEPreInit.qtInit ) { + el = tinyMCEPreInit.qtInit[i].id; + if ( el ) + document.getElementById('wp-'+el+'-wrap').onmousedown = function(){ wpActiveEditor = this.id.slice(3, -5); } + } + } + } + + if ( typeof(QTags) == 'function' ) { + for ( qt in tinyMCEPreInit.qtInit ) { + try { quicktags( tinyMCEPreInit.qtInit[qt] ); } catch(e){} + } + } + })(); + <?php + + if ( self::$ext_plugins ) + echo self::$ext_plugins . "\n"; + + if ( ! $compressed && $tmce_on ) { + ?> + (function(){var t=tinyMCEPreInit,sl=tinymce.ScriptLoader,ln=t.ref.language,th=t.ref.theme,pl=t.ref.plugins;sl.markDone(t.base+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'_dlg.js');sl.markDone(t.base+'/themes/advanced/skins/wp_theme/ui.css');tinymce.each(pl.split(','),function(n){if(n&&n.charAt(0)!='-'){sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'.js');sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'_dlg.js');}});})(); + <?php + } + + if ( !is_admin() ) + echo 'var ajaxurl = "' . admin_url( 'admin-ajax.php', 'relative' ) . '";'; + + ?> + </script> + <?php + + if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) ) + self::wp_link_dialog(); + + if ( in_array('wpfullscreen', self::$plugins, true) || in_array('fullscreen', self::$qt_buttons, true) ) + self::wp_fullscreen_html(); + + do_action('after_wp_tiny_mce', self::$mce_settings); + } + + public static function wp_fullscreen_html() { + global $content_width; + $post = get_post(); + + $width = isset($content_width) && 800 > $content_width ? $content_width : 800; + $width = $width + 22; // compensate for the padding and border + $dfw_width = get_user_setting( 'dfw_width', $width ); + $save = isset($post->post_status) && $post->post_status == 'publish' ? __('Update') : __('Save'); + ?> + <div id="wp-fullscreen-body"<?php if ( is_rtl() ) echo ' class="rtl"'; ?>> + <div id="fullscreen-topbar"> + <div id="wp-fullscreen-toolbar"> + <div id="wp-fullscreen-close"><a href="#" onclick="fullscreen.off();return false;"><?php _e('Exit fullscreen'); ?></a></div> + <div id="wp-fullscreen-central-toolbar" style="width:<?php echo $width; ?>px;"> + + <div id="wp-fullscreen-mode-bar"><div id="wp-fullscreen-modes"> + <a href="#" onclick="fullscreen.switchmode('tinymce');return false;"><?php _e( 'Visual' ); ?></a> + <a href="#" onclick="fullscreen.switchmode('html');return false;"><?php _ex( 'Text', 'Name for the Text editor tab (formerly HTML)' ); ?></a> + </div></div> + + <div id="wp-fullscreen-button-bar"><div id="wp-fullscreen-buttons" class="wp_themeSkin"> + <?php + + $buttons = array( + // format: title, onclick, show in both editors + 'bold' => array( 'title' => __('Bold (Ctrl + B)'), 'onclick' => 'fullscreen.b();', 'both' => false ), + 'italic' => array( 'title' => __('Italic (Ctrl + I)'), 'onclick' => 'fullscreen.i();', 'both' => false ), + '0' => 'separator', + 'bullist' => array( 'title' => __('Unordered list (Alt + Shift + U)'), 'onclick' => 'fullscreen.ul();', 'both' => false ), + 'numlist' => array( 'title' => __('Ordered list (Alt + Shift + O)'), 'onclick' => 'fullscreen.ol();', 'both' => false ), + '1' => 'separator', + 'blockquote' => array( 'title' => __('Blockquote (Alt + Shift + Q)'), 'onclick' => 'fullscreen.blockquote();', 'both' => false ), + 'image' => array( 'title' => __('Insert/edit image (Alt + Shift + M)'), 'onclick' => "fullscreen.medialib();", 'both' => true ), + '2' => 'separator', + 'link' => array( 'title' => __('Insert/edit link (Alt + Shift + A)'), 'onclick' => 'fullscreen.link();', 'both' => true ), + 'unlink' => array( 'title' => __('Unlink (Alt + Shift + S)'), 'onclick' => 'fullscreen.unlink();', 'both' => false ), + '3' => 'separator', + 'help' => array( 'title' => __('Help (Alt + Shift + H)'), 'onclick' => 'fullscreen.help();', 'both' => false ) + ); + + $buttons = apply_filters( 'wp_fullscreen_buttons', $buttons ); + + foreach ( $buttons as $button => $args ) { + if ( 'separator' == $args ) { ?> + <div><span aria-orientation="vertical" role="separator" class="mceSeparator"></span></div> + <?php continue; + } ?> + + <div<?php if ( $args['both'] ) { ?> class="wp-fullscreen-both"<?php } ?>> + <a title="<?php echo $args['title']; ?>" onclick="<?php echo $args['onclick']; ?>return false;" class="mceButton mceButtonEnabled mce_<?php echo $button; ?>" href="#" id="wp_fs_<?php echo $button; ?>" role="button" aria-pressed="false"> + <span class="mceIcon mce_<?php echo $button; ?>"></span> + </a> + </div> + <?php + } ?> + + </div></div> + + <div id="wp-fullscreen-save"> + <input type="button" class="button-primary right" value="<?php echo $save; ?>" onclick="fullscreen.save();" /> + <span class="spinner"></span> + <span class="fs-saved"><?php if ( $post->post_status == 'publish' ) _e('Updated.'); else _e('Saved.'); ?></span> + </div> + + </div> + </div> + </div> + + <div id="wp-fullscreen-wrap" style="width:<?php echo $dfw_width; ?>px;"> + <?php if ( post_type_supports($post->post_type, 'title') ) { ?> + <label id="wp-fullscreen-title-prompt-text" for="wp-fullscreen-title"><?php echo apply_filters( 'enter_title_here', __( 'Enter title here' ), $post ); ?></label> + <input type="text" id="wp-fullscreen-title" value="" autocomplete="off" /> + <?php } ?> + + <div id="wp-fullscreen-container"> + <textarea id="wp_mce_fullscreen"></textarea> + </div> + + <div id="wp-fullscreen-status"> + <div id="wp-fullscreen-count"><?php printf( __( 'Word count: %s' ), '<span class="word-count">0</span>' ); ?></div> + <div id="wp-fullscreen-tagline"><?php _e('Just write.'); ?></div> + </div> + </div> + </div> + + <div class="fullscreen-overlay" id="fullscreen-overlay"></div> + <div class="fullscreen-overlay fullscreen-fader fade-600" id="fullscreen-fader"></div> + <?php + } + + /** + * Performs post queries for internal linking. + * + * @since 3.1.0 + * + * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments. + * @return array Results. + */ + public static function wp_link_query( $args = array() ) { + $pts = get_post_types( array( 'public' => true ), 'objects' ); + $pt_names = array_keys( $pts ); + + $query = array( + 'post_type' => $pt_names, + 'suppress_filters' => true, + 'update_post_term_cache' => false, + 'update_post_meta_cache' => false, + 'post_status' => 'publish', + 'order' => 'DESC', + 'orderby' => 'post_date', + 'posts_per_page' => 20, + ); + + $args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1; + + if ( isset( $args['s'] ) ) + $query['s'] = $args['s']; + + $query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0; + + /** + * Filter the link query arguments. + * + * Allows modification of the link query arguments before querying. + * + * @see WP_Query for a full list of arguments + * + * @since 3.7.0 + * + * @param array $query An array of WP_Query arguments. + */ + $query = apply_filters( 'wp_link_query_args', $query ); + + // Do main query. + $get_posts = new WP_Query; + $posts = $get_posts->query( $query ); + // Check if any posts were found. + if ( ! $get_posts->post_count ) + return false; + + // Build results. + $results = array(); + foreach ( $posts as $post ) { + if ( 'post' == $post->post_type ) + $info = mysql2date( __( 'Y/m/d' ), $post->post_date ); + else + $info = $pts[ $post->post_type ]->labels->singular_name; + + $results[] = array( + 'ID' => $post->ID, + 'title' => trim( esc_html( strip_tags( get_the_title( $post ) ) ) ), + 'permalink' => get_permalink( $post->ID ), + 'info' => $info, + ); + } + + /** + * Filter the link query results. + * + * Allows modification of the returned link query results. + * + * @since 3.7.0 + * + * @param array $results { + * An associative array of query results. + * + * @type array { + * @type int 'ID' The post ID. + * @type string 'title' The trimmed, escaped post title. + * @type string 'permalink' The post permalink. + * @type string 'info' A 'Y/m/d'-formatted date for 'post' post type, the 'singular_name' post type label otherwise. + * } + * } + * @param array $query An array of WP_Query arguments. @see 'wp_link_query_args' filter + */ + return apply_filters( 'wp_link_query', $results, $query ); + } + + /** + * Dialog for internal linking. + * + * @since 3.1.0 + */ + public static function wp_link_dialog() { + ?> + <div style="display:none;"> + <form id="wp-link" tabindex="-1"> + <?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?> + <div id="link-selector"> + <div id="link-options"> + <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p> + <div> + <label><span><?php _e( 'URL' ); ?></span><input id="url-field" type="text" name="href" /></label> + </div> + <div> + <label><span><?php _e( 'Title' ); ?></span><input id="link-title-field" type="text" name="linktitle" /></label> + </div> + <div class="link-target"> + <label><input type="checkbox" id="link-target-checkbox" /> <?php _e( 'Open link in a new window/tab' ); ?></label> + </div> + </div> + <?php $show_internal = '1' == get_user_setting( 'wplink', '0' ); ?> + <p class="howto toggle-arrow <?php if ( $show_internal ) echo 'toggle-arrow-active'; ?>" id="internal-toggle"><?php _e( 'Or link to existing content' ); ?></p> + <div id="search-panel"<?php if ( ! $show_internal ) echo ' style="display:none"'; ?>> + <div class="link-search-wrapper"> + <label> + <span class="search-label"><?php _e( 'Search' ); ?></span> + <input type="search" id="search-field" class="link-search-field" autocomplete="off" /> + <span class="spinner"></span> + </label> + </div> + <div id="search-results" class="query-results"> + <ul></ul> + <div class="river-waiting"> + <span class="spinner"></span> + </div> + </div> + <div id="most-recent-results" class="query-results"> + <div class="query-notice"><em><?php _e( 'No search term specified. Showing recent items.' ); ?></em></div> + <ul></ul> + <div class="river-waiting"> + <span class="spinner"></span> + </div> + </div> + </div> + </div> + <div class="submitbox"> + <div id="wp-link-update"> + <input type="submit" value="<?php esc_attr_e( 'Add Link' ); ?>" class="button-primary" id="wp-link-submit" name="wp-link-submit"> + </div> + <div id="wp-link-cancel"> + <a class="submitdelete deletion" href="#"><?php _e( 'Cancel' ); ?></a> + </div> + </div> + </form> + </div> + <?php + } +} diff --git a/sources/wp-includes/class-wp-embed.php b/sources/wp-includes/class-wp-embed.php new file mode 100644 index 0000000..575066c --- /dev/null +++ b/sources/wp-includes/class-wp-embed.php @@ -0,0 +1,323 @@ +<?php +/** + * API for easily embedding rich media such as videos and images into content. + * + * @package WordPress + * @subpackage Embed + * @since 2.9.0 + */ +class WP_Embed { + var $handlers = array(); + var $post_ID; + var $usecache = true; + var $linkifunknown = true; + + /** + * Constructor + */ + function __construct() { + // Hack to get the [embed] shortcode to run before wpautop() + add_filter( 'the_content', array( $this, 'run_shortcode' ), 8 ); + + // Shortcode placeholder for strip_shortcodes() + add_shortcode( 'embed', '__return_false' ); + + // Attempts to embed all URLs in a post + add_filter( 'the_content', array( $this, 'autoembed' ), 8 ); + + // When a post is saved, invalidate the oEmbed cache + add_action( 'pre_post_update', array( $this, 'delete_oembed_caches' ) ); + + // After a post is saved, cache oEmbed items via AJAX + add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) ); + } + + /** + * Process the [embed] shortcode. + * + * Since the [embed] shortcode needs to be run earlier than other shortcodes, + * this function removes all existing shortcodes, registers the [embed] shortcode, + * calls {@link do_shortcode()}, and then re-registers the old shortcodes. + * + * @uses $shortcode_tags + * @uses remove_all_shortcodes() + * @uses add_shortcode() + * @uses do_shortcode() + * + * @param string $content Content to parse + * @return string Content with shortcode parsed + */ + function run_shortcode( $content ) { + global $shortcode_tags; + + // Back up current registered shortcodes and clear them all out + $orig_shortcode_tags = $shortcode_tags; + remove_all_shortcodes(); + + add_shortcode( 'embed', array( $this, 'shortcode' ) ); + + // Do the shortcode (only the [embed] one is registered) + $content = do_shortcode( $content ); + + // Put the original shortcodes back + $shortcode_tags = $orig_shortcode_tags; + + return $content; + } + + /** + * If a post/page was saved, then output JavaScript to make + * an AJAX request that will call WP_Embed::cache_oembed(). + */ + function maybe_run_ajax_cache() { + $post = get_post(); + + if ( ! $post || empty($_GET['message']) || 1 != $_GET['message'] ) + return; + +?> +<script type="text/javascript"> +/* <![CDATA[ */ + jQuery(document).ready(function($){ + $.get("<?php echo admin_url( 'admin-ajax.php?action=oembed-cache&post=' . $post->ID, 'relative' ); ?>"); + }); +/* ]]> */ +</script> +<?php + } + + /** + * Register an embed handler. Do not use this function directly, use {@link wp_embed_register_handler()} instead. + * This function should probably also only be used for sites that do not support oEmbed. + * + * @param string $id An internal ID/name for the handler. Needs to be unique. + * @param string $regex The regex that will be used to see if this handler should be used for a URL. + * @param callback $callback The callback function that will be called if the regex is matched. + * @param int $priority Optional. Used to specify the order in which the registered handlers will be tested (default: 10). Lower numbers correspond with earlier testing, and handlers with the same priority are tested in the order in which they were added to the action. + */ + function register_handler( $id, $regex, $callback, $priority = 10 ) { + $this->handlers[$priority][$id] = array( + 'regex' => $regex, + 'callback' => $callback, + ); + } + + /** + * Unregister a previously registered embed handler. Do not use this function directly, use {@link wp_embed_unregister_handler()} instead. + * + * @param string $id The handler ID that should be removed. + * @param int $priority Optional. The priority of the handler to be removed (default: 10). + */ + function unregister_handler( $id, $priority = 10 ) { + if ( isset($this->handlers[$priority][$id]) ) + unset($this->handlers[$priority][$id]); + } + + /** + * The {@link do_shortcode()} callback function. + * + * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers. + * If none of the regex matches and it's enabled, then the URL will be given to the {@link WP_oEmbed} class. + * + * @uses wp_oembed_get() + * @uses wp_parse_args() + * @uses wp_embed_defaults() + * @uses WP_Embed::maybe_make_link() + * @uses get_option() + * @uses author_can() + * @uses wp_cache_get() + * @uses wp_cache_set() + * @uses get_post_meta() + * @uses update_post_meta() + * + * @param array $attr Shortcode attributes. + * @param string $url The URL attempting to be embedded. + * @return string The embed HTML on success, otherwise the original URL. + */ + function shortcode( $attr, $url = '' ) { + $post = get_post(); + + if ( empty( $url ) ) + return ''; + + $rawattr = $attr; + $attr = wp_parse_args( $attr, wp_embed_defaults() ); + + // kses converts & into & and we need to undo this + // See http://core.trac.wordpress.org/ticket/11311 + $url = str_replace( '&', '&', $url ); + + // Look for known internal handlers + ksort( $this->handlers ); + foreach ( $this->handlers as $priority => $handlers ) { + foreach ( $handlers as $id => $handler ) { + if ( preg_match( $handler['regex'], $url, $matches ) && is_callable( $handler['callback'] ) ) { + if ( false !== $return = call_user_func( $handler['callback'], $matches, $attr, $url, $rawattr ) ) + /** + * Filter the returned embed handler. + * + * @since 2.9.0 + * + * @param mixed $return The shortcode callback function to call. + * @param string $url The attempted embed URL. + * @param array $attr An array of shortcode attributes. + */ + return apply_filters( 'embed_handler_html', $return, $url, $attr ); + } + } + } + + $post_ID = ( ! empty( $post->ID ) ) ? $post->ID : null; + if ( ! empty( $this->post_ID ) ) // Potentially set by WP_Embed::cache_oembed() + $post_ID = $this->post_ID; + + // Unknown URL format. Let oEmbed have a go. + if ( $post_ID ) { + + // Check for a cached result (stored in the post meta) + $cachekey = '_oembed_' . md5( $url . serialize( $attr ) ); + if ( $this->usecache ) { + $cache = get_post_meta( $post_ID, $cachekey, true ); + + // Failures are cached + if ( '{{unknown}}' === $cache ) + return $this->maybe_make_link( $url ); + + if ( ! empty( $cache ) ) + /** + * Filter the cached oEmbed HTML. + * + * @since 2.9.0 + * + * @param mixed $cache The cached HTML result, stored in post meta. + * @param string $url The attempted embed URL. + * @param array $attr An array of shortcode attributes. + * @param int $post_ID Post ID. + */ + return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID ); + } + + /** + * Filter whether to inspect the given URL for discoverable <link> tags. + * + * @see WP_oEmbed::discover() + * + * @param bool false Whether to enable <link> tag discovery. Default false. + */ + $attr['discover'] = ( apply_filters( 'embed_oembed_discover', false ) && author_can( $post_ID, 'unfiltered_html' ) ); + + // Use oEmbed to get the HTML + $html = wp_oembed_get( $url, $attr ); + + // Cache the result + $cache = ( $html ) ? $html : '{{unknown}}'; + update_post_meta( $post_ID, $cachekey, $cache ); + + // If there was a result, return it + if ( $html ) { + /** This filter is documented in wp-includes/class-wp-embed.php */ + return apply_filters( 'embed_oembed_html', $html, $url, $attr, $post_ID ); + } + } + + // Still unknown + return $this->maybe_make_link( $url ); + } + + /** + * Delete all oEmbed caches. + * + * @param int $post_ID Post ID to delete the caches for. + */ + function delete_oembed_caches( $post_ID ) { + $post_metas = get_post_custom_keys( $post_ID ); + if ( empty($post_metas) ) + return; + + foreach( $post_metas as $post_meta_key ) { + if ( '_oembed_' == substr( $post_meta_key, 0, 8 ) ) + delete_post_meta( $post_ID, $post_meta_key ); + } + } + + /** + * Triggers a caching of all oEmbed results. + * + * @param int $post_ID Post ID to do the caching for. + */ + function cache_oembed( $post_ID ) { + $post = get_post( $post_ID ); + + $post_types = array( 'post', 'page' ); + /** + * Filter the array of post types to cache oEmbed results for. + * + * @since 2.9.0 + * + * @param array $post_types Array of post types to cache oEmbed results for. Default 'post', 'page'. + */ + if ( empty($post->ID) || !in_array( $post->post_type, apply_filters( 'embed_cache_oembed_types', $post_types ) ) ) + return; + + // Trigger a caching + if ( !empty($post->post_content) ) { + $this->post_ID = $post->ID; + $this->usecache = false; + + $content = $this->run_shortcode( $post->post_content ); + $this->autoembed( $content ); + + $this->usecache = true; + } + } + + /** + * Passes any unlinked URLs that are on their own line to {@link WP_Embed::shortcode()} for potential embedding. + * + * @uses WP_Embed::autoembed_callback() + * + * @param string $content The content to be searched. + * @return string Potentially modified $content. + */ + function autoembed( $content ) { + return preg_replace_callback( '|^\s*(https?://[^\s"]+)\s*$|im', array( $this, 'autoembed_callback' ), $content ); + } + + /** + * Callback function for {@link WP_Embed::autoembed()}. + * + * @uses WP_Embed::shortcode() + * + * @param array $match A regex match array. + * @return string The embed HTML on success, otherwise the original URL. + */ + function autoembed_callback( $match ) { + $oldval = $this->linkifunknown; + $this->linkifunknown = false; + $return = $this->shortcode( array(), $match[1] ); + $this->linkifunknown = $oldval; + + return "\n$return\n"; + } + + /** + * Conditionally makes a hyperlink based on an internal class variable. + * + * @param string $url URL to potentially be linked. + * @return string Linked URL or the original URL. + */ + function maybe_make_link( $url ) { + $output = ( $this->linkifunknown ) ? '<a href="' . esc_url($url) . '">' . esc_html($url) . '</a>' : $url; + + /** + * Filter the returned, maybe-linked embed URL. + * + * @since 2.9.0 + * + * @param string $output The linked or original URL. + * @param string $url The original URL. + */ + return apply_filters( 'embed_maybe_make_link', $output, $url ); + } +} +$GLOBALS['wp_embed'] = new WP_Embed(); diff --git a/sources/wp-includes/class-wp-error.php b/sources/wp-includes/class-wp-error.php new file mode 100644 index 0000000..bbfcebc --- /dev/null +++ b/sources/wp-includes/class-wp-error.php @@ -0,0 +1,208 @@ +<?php +/** + * WordPress Error API. + * + * Contains the WP_Error class and the is_wp_error() function. + * + * @package WordPress + */ + +/** + * WordPress Error class. + * + * Container for checking for WordPress errors and error messages. Return + * WP_Error and use {@link is_wp_error()} to check if this class is returned. + * Many core WordPress functions pass this class in the event of an error and + * if not handled properly will result in code errors. + * + * @package WordPress + * @since 2.1.0 + */ +class WP_Error { + /** + * Stores the list of errors. + * + * @since 2.1.0 + * @var array + * @access private + */ + var $errors = array(); + + /** + * Stores the list of data for error codes. + * + * @since 2.1.0 + * @var array + * @access private + */ + var $error_data = array(); + + /** + * Constructor - Sets up error message. + * + * If code parameter is empty then nothing will be done. It is possible to + * add multiple messages to the same code, but with other methods in the + * class. + * + * All parameters are optional, but if the code parameter is set, then the + * data parameter is optional. + * + * @since 2.1.0 + * + * @param string|int $code Error code + * @param string $message Error message + * @param mixed $data Optional. Error data. + * @return WP_Error + */ + function __construct($code = '', $message = '', $data = '') { + if ( empty($code) ) + return; + + $this->errors[$code][] = $message; + + if ( ! empty($data) ) + $this->error_data[$code] = $data; + } + + /** + * Retrieve all error codes. + * + * @since 2.1.0 + * @access public + * + * @return array List of error codes, if available. + */ + function get_error_codes() { + if ( empty($this->errors) ) + return array(); + + return array_keys($this->errors); + } + + /** + * Retrieve first error code available. + * + * @since 2.1.0 + * @access public + * + * @return string|int Empty string, if no error codes. + */ + function get_error_code() { + $codes = $this->get_error_codes(); + + if ( empty($codes) ) + return ''; + + return $codes[0]; + } + + /** + * Retrieve all error messages or error messages matching code. + * + * @since 2.1.0 + * + * @param string|int $code Optional. Retrieve messages matching code, if exists. + * @return array Error strings on success, or empty array on failure (if using code parameter). + */ + function get_error_messages($code = '') { + // Return all messages if no code specified. + if ( empty($code) ) { + $all_messages = array(); + foreach ( (array) $this->errors as $code => $messages ) + $all_messages = array_merge($all_messages, $messages); + + return $all_messages; + } + + if ( isset($this->errors[$code]) ) + return $this->errors[$code]; + else + return array(); + } + + /** + * Get single error message. + * + * This will get the first message available for the code. If no code is + * given then the first code available will be used. + * + * @since 2.1.0 + * + * @param string|int $code Optional. Error code to retrieve message. + * @return string + */ + function get_error_message($code = '') { + if ( empty($code) ) + $code = $this->get_error_code(); + $messages = $this->get_error_messages($code); + if ( empty($messages) ) + return ''; + return $messages[0]; + } + + /** + * Retrieve error data for error code. + * + * @since 2.1.0 + * + * @param string|int $code Optional. Error code. + * @return mixed Null, if no errors. + */ + function get_error_data($code = '') { + if ( empty($code) ) + $code = $this->get_error_code(); + + if ( isset($this->error_data[$code]) ) + return $this->error_data[$code]; + return null; + } + + /** + * Append more error messages to list of error messages. + * + * @since 2.1.0 + * @access public + * + * @param string|int $code Error code. + * @param string $message Error message. + * @param mixed $data Optional. Error data. + */ + function add($code, $message, $data = '') { + $this->errors[$code][] = $message; + if ( ! empty($data) ) + $this->error_data[$code] = $data; + } + + /** + * Add data for error code. + * + * The error code can only contain one error data. + * + * @since 2.1.0 + * + * @param mixed $data Error data. + * @param string|int $code Error code. + */ + function add_data($data, $code = '') { + if ( empty($code) ) + $code = $this->get_error_code(); + + $this->error_data[$code] = $data; + } +} + +/** + * Check whether variable is a WordPress Error. + * + * Returns true if $thing is an object of the WP_Error class. + * + * @since 2.1.0 + * + * @param mixed $thing Check if unknown variable is a WP_Error object. + * @return bool True, if WP_Error. False, if not WP_Error. + */ +function is_wp_error($thing) { + if ( is_object($thing) && is_a($thing, 'WP_Error') ) + return true; + return false; +} diff --git a/sources/wp-includes/class-wp-http-ixr-client.php b/sources/wp-includes/class-wp-http-ixr-client.php new file mode 100644 index 0000000..736fc5a --- /dev/null +++ b/sources/wp-includes/class-wp-http-ixr-client.php @@ -0,0 +1,92 @@ +<?php +/** + * WP_HTTP_IXR_Client + * + * @package WordPress + * @since 3.1.0 + * + */ +class WP_HTTP_IXR_Client extends IXR_Client { + + function __construct($server, $path = false, $port = false, $timeout = 15) { + if ( ! $path ) { + // Assume we have been given a URL instead + $bits = parse_url($server); + $this->scheme = $bits['scheme']; + $this->server = $bits['host']; + $this->port = isset($bits['port']) ? $bits['port'] : $port; + $this->path = !empty($bits['path']) ? $bits['path'] : '/'; + + // Make absolutely sure we have a path + if ( ! $this->path ) + $this->path = '/'; + } else { + $this->scheme = 'http'; + $this->server = $server; + $this->path = $path; + $this->port = $port; + } + $this->useragent = 'The Incutio XML-RPC PHP Library'; + $this->timeout = $timeout; + } + + function query() { + $args = func_get_args(); + $method = array_shift($args); + $request = new IXR_Request($method, $args); + $xml = $request->getXml(); + + $port = $this->port ? ":$this->port" : ''; + $url = $this->scheme . '://' . $this->server . $port . $this->path; + $args = array( + 'headers' => array('Content-Type' => 'text/xml'), + 'user-agent' => $this->useragent, + 'body' => $xml, + ); + + // Merge Custom headers ala #8145 + foreach ( $this->headers as $header => $value ) + $args['headers'][$header] = $value; + + if ( $this->timeout !== false ) + $args['timeout'] = $this->timeout; + + // Now send the request + if ( $this->debug ) + echo '<pre class="ixr_request">' . htmlspecialchars($xml) . "\n</pre>\n\n"; + + $response = wp_remote_post($url, $args); + + if ( is_wp_error($response) ) { + $errno = $response->get_error_code(); + $errorstr = $response->get_error_message(); + $this->error = new IXR_Error(-32300, "transport error: $errno $errorstr"); + return false; + } + + if ( 200 != wp_remote_retrieve_response_code( $response ) ) { + $this->error = new IXR_Error(-32301, 'transport error - HTTP status code was not 200 (' . wp_remote_retrieve_response_code( $response ) . ')'); + return false; + } + + if ( $this->debug ) + echo '<pre class="ixr_response">' . htmlspecialchars( wp_remote_retrieve_body( $response ) ) . "\n</pre>\n\n"; + + // Now parse what we've got back + $this->message = new IXR_Message( wp_remote_retrieve_body( $response ) ); + if ( ! $this->message->parse() ) { + // XML error + $this->error = new IXR_Error(-32700, 'parse error. not well formed'); + return false; + } + + // Is the message a fault? + if ( $this->message->messageType == 'fault' ) { + $this->error = new IXR_Error($this->message->faultCode, $this->message->faultString); + return false; + } + + // Message must be OK + return true; + } +} diff --git a/sources/wp-includes/class-wp-image-editor-gd.php b/sources/wp-includes/class-wp-image-editor-gd.php new file mode 100644 index 0000000..a8235c2 --- /dev/null +++ b/sources/wp-includes/class-wp-image-editor-gd.php @@ -0,0 +1,426 @@ +<?php +/** + * WordPress GD Image Editor + * + * @package WordPress + * @subpackage Image_Editor + */ + +/** + * WordPress Image Editor Class for Image Manipulation through GD + * + * @since 3.5.0 + * @package WordPress + * @subpackage Image_Editor + * @uses WP_Image_Editor Extends class + */ +class WP_Image_Editor_GD extends WP_Image_Editor { + + protected $image = false; // GD Resource + + function __destruct() { + if ( $this->image ) { + // we don't need the original in memory anymore + imagedestroy( $this->image ); + } + } + + /** + * Checks to see if current environment supports GD. + * + * @since 3.5.0 + * @access public + * + * @return boolean + */ + public static function test( $args = array() ) { + if ( ! extension_loaded('gd') || ! function_exists('gd_info') ) + return false; + + // On some setups GD library does not provide imagerotate() - Ticket #11536 + if ( isset( $args['methods'] ) && + in_array( 'rotate', $args['methods'] ) && + ! function_exists('imagerotate') ){ + + return false; + } + + return true; + } + + /** + * Checks to see if editor supports the mime-type specified. + * + * @since 3.5.0 + * @access public + * + * @param string $mime_type + * @return boolean + */ + public static function supports_mime_type( $mime_type ) { + $image_types = imagetypes(); + switch( $mime_type ) { + case 'image/jpeg': + return ($image_types & IMG_JPG) != 0; + case 'image/png': + return ($image_types & IMG_PNG) != 0; + case 'image/gif': + return ($image_types & IMG_GIF) != 0; + } + + return false; + } + + /** + * Loads image from $this->file into new GD Resource. + * + * @since 3.5.0 + * @access protected + * + * @return boolean|\WP_Error + */ + public function load() { + if ( $this->image ) + return true; + + if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) + return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); + + // Set artificially high because GD uses uncompressed images in memory + @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); + + if ( ! is_resource( $this->image ) ) + return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file ); + + $size = @getimagesize( $this->file ); + if ( ! $size ) + return new WP_Error( 'invalid_image', __('Could not read image size.'), $this->file ); + + if ( function_exists( 'imagealphablending' ) && function_exists( 'imagesavealpha' ) ) { + imagealphablending( $this->image, false ); + imagesavealpha( $this->image, true ); + } + + $this->update_size( $size[0], $size[1] ); + $this->mime_type = $size['mime']; + + return true; + } + + /** + * Sets or updates current image size. + * + * @since 3.5.0 + * @access protected + * + * @param int $width + * @param int $height + */ + protected function update_size( $width = false, $height = false ) { + if ( ! $width ) + $width = imagesx( $this->image ); + + if ( ! $height ) + $height = imagesy( $this->image ); + + return parent::update_size( $width, $height ); + } + + /** + * Resizes current image. + * Wraps _resize, since _resize returns a GD Resource. + * + * @since 3.5.0 + * @access public + * + * @param int $max_w + * @param int $max_h + * @param boolean $crop + * @return boolean|WP_Error + */ + public function resize( $max_w, $max_h, $crop = false ) { + if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) + return true; + + $resized = $this->_resize( $max_w, $max_h, $crop ); + + if ( is_resource( $resized ) ) { + imagedestroy( $this->image ); + $this->image = $resized; + return true; + + } elseif ( is_wp_error( $resized ) ) + return $resized; + + return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file ); + } + + protected function _resize( $max_w, $max_h, $crop = false ) { + $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); + if ( ! $dims ) { + return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions'), $this->file ); + } + list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; + + $resized = wp_imagecreatetruecolor( $dst_w, $dst_h ); + imagecopyresampled( $resized, $this->image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); + + if ( is_resource( $resized ) ) { + $this->update_size( $dst_w, $dst_h ); + return $resized; + } + + return new WP_Error( 'image_resize_error', __('Image resize failed.'), $this->file ); + } + + /** + * Resize multiple images from a single source. + * + * @since 3.5.0 + * @access public + * + * @param array $sizes { + * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. + * + * @type array $size { + * @type int $width Image width. + * @type int $height Image height. + * @type bool $crop Optional. Whether to crop the image. Default false. + * } + * } + * @return array An array of resized images metadata by size. + */ + public function multi_resize( $sizes ) { + $metadata = array(); + $orig_size = $this->size; + + foreach ( $sizes as $size => $size_data ) { + if ( ! ( isset( $size_data['width'] ) && isset( $size_data['height'] ) ) ) + continue; + + if ( ! isset( $size_data['crop'] ) ) + $size_data['crop'] = false; + + $image = $this->_resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); + + if( ! is_wp_error( $image ) ) { + $resized = $this->_save( $image ); + + imagedestroy( $image ); + + if ( ! is_wp_error( $resized ) && $resized ) { + unset( $resized['path'] ); + $metadata[$size] = $resized; + } + } + + $this->size = $orig_size; + } + + return $metadata; + } + + /** + * Crops Image. + * + * @since 3.5.0 + * @access public + * + * @param string|int $src The source file or Attachment ID. + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w Optional. The destination width. + * @param int $dst_h Optional. The destination height. + * @param boolean $src_abs Optional. If the source crop points are absolute. + * @return boolean|WP_Error + */ + public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { + // If destination width/height isn't specified, use same as + // width/height from source. + if ( ! $dst_w ) + $dst_w = $src_w; + if ( ! $dst_h ) + $dst_h = $src_h; + + $dst = wp_imagecreatetruecolor( $dst_w, $dst_h ); + + if ( $src_abs ) { + $src_w -= $src_x; + $src_h -= $src_y; + } + + if ( function_exists( 'imageantialias' ) ) + imageantialias( $dst, true ); + + imagecopyresampled( $dst, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ); + + if ( is_resource( $dst ) ) { + imagedestroy( $this->image ); + $this->image = $dst; + $this->update_size(); + return true; + } + + return new WP_Error( 'image_crop_error', __('Image crop failed.'), $this->file ); + } + + /** + * Rotates current image counter-clockwise by $angle. + * Ported from image-edit.php + * + * @since 3.5.0 + * @access public + * + * @param float $angle + * @return boolean|WP_Error + */ + public function rotate( $angle ) { + if ( function_exists('imagerotate') ) { + $rotated = imagerotate( $this->image, $angle, 0 ); + + if ( is_resource( $rotated ) ) { + imagedestroy( $this->image ); + $this->image = $rotated; + $this->update_size(); + return true; + } + } + return new WP_Error( 'image_rotate_error', __('Image rotate failed.'), $this->file ); + } + + /** + * Flips current image. + * + * @since 3.5.0 + * @access public + * + * @param boolean $horz Flip along Horizontal Axis + * @param boolean $vert Flip along Vertical Axis + * @returns boolean|WP_Error + */ + public function flip( $horz, $vert ) { + $w = $this->size['width']; + $h = $this->size['height']; + $dst = wp_imagecreatetruecolor( $w, $h ); + + if ( is_resource( $dst ) ) { + $sx = $vert ? ($w - 1) : 0; + $sy = $horz ? ($h - 1) : 0; + $sw = $vert ? -$w : $w; + $sh = $horz ? -$h : $h; + + if ( imagecopyresampled( $dst, $this->image, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) { + imagedestroy( $this->image ); + $this->image = $dst; + return true; + } + } + return new WP_Error( 'image_flip_error', __('Image flip failed.'), $this->file ); + } + + /** + * Saves current in-memory image to file. + * + * @since 3.5.0 + * @access public + * + * @param string $destfilename + * @param string $mime_type + * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} + */ + public function save( $filename = null, $mime_type = null ) { + $saved = $this->_save( $this->image, $filename, $mime_type ); + + if ( ! is_wp_error( $saved ) ) { + $this->file = $saved['path']; + $this->mime_type = $saved['mime-type']; + } + + return $saved; + } + + protected function _save( $image, $filename = null, $mime_type = null ) { + list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); + + if ( ! $filename ) + $filename = $this->generate_filename( null, null, $extension ); + + if ( 'image/gif' == $mime_type ) { + if ( ! $this->make_image( $filename, 'imagegif', array( $image, $filename ) ) ) + return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); + } + elseif ( 'image/png' == $mime_type ) { + // convert from full colors to index colors, like original PNG. + if ( function_exists('imageistruecolor') && ! imageistruecolor( $image ) ) + imagetruecolortopalette( $image, false, imagecolorstotal( $image ) ); + + if ( ! $this->make_image( $filename, 'imagepng', array( $image, $filename ) ) ) + return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); + } + elseif ( 'image/jpeg' == $mime_type ) { + if ( ! $this->make_image( $filename, 'imagejpeg', array( $image, $filename, apply_filters( 'jpeg_quality', $this->quality, 'image_resize' ) ) ) ) + return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); + } + else { + return new WP_Error( 'image_save_error', __('Image Editor Save Failed') ); + } + + // Set correct file permissions + $stat = stat( dirname( $filename ) ); + $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits + @ chmod( $filename, $perms ); + + return array( + 'path' => $filename, + 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), + 'width' => $this->size['width'], + 'height' => $this->size['height'], + 'mime-type'=> $mime_type, + ); + } + + /** + * Returns stream of current image. + * + * @since 3.5.0 + * @access public + * + * @param string $mime_type + */ + public function stream( $mime_type = null ) { + list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type ); + + switch ( $mime_type ) { + case 'image/png': + header( 'Content-Type: image/png' ); + return imagepng( $this->image ); + case 'image/gif': + header( 'Content-Type: image/gif' ); + return imagegif( $this->image ); + default: + header( 'Content-Type: image/jpeg' ); + return imagejpeg( $this->image, null, $this->quality ); + } + } + + /** + * Either calls editor's save function or handles file as a stream. + * + * @since 3.5.0 + * @access protected + * + * @param string|stream $filename + * @param callable $function + * @param array $arguments + * @return boolean + */ + protected function make_image( $filename, $function, $arguments ) { + if ( wp_is_stream( $filename ) ) + $arguments[1] = null; + + return parent::make_image( $filename, $function, $arguments ); + } +} diff --git a/sources/wp-includes/class-wp-image-editor-imagick.php b/sources/wp-includes/class-wp-image-editor-imagick.php new file mode 100644 index 0000000..2e1bebc --- /dev/null +++ b/sources/wp-includes/class-wp-image-editor-imagick.php @@ -0,0 +1,488 @@ +<?php +/** + * WordPress Imagick Image Editor + * + * @package WordPress + * @subpackage Image_Editor + */ + +/** + * WordPress Image Editor Class for Image Manipulation through Imagick PHP Module + * + * @since 3.5.0 + * @package WordPress + * @subpackage Image_Editor + * @uses WP_Image_Editor Extends class + */ +class WP_Image_Editor_Imagick extends WP_Image_Editor { + + protected $image = null; // Imagick Object + + function __destruct() { + if ( $this->image instanceof Imagick ) { + // we don't need the original in memory anymore + $this->image->clear(); + $this->image->destroy(); + } + } + + /** + * Checks to see if current environment supports Imagick. + * + * We require Imagick 2.2.0 or greater, based on whether the queryFormats() + * method can be called statically. + * + * @since 3.5.0 + * @access public + * + * @return boolean + */ + public static function test( $args = array() ) { + + // First, test Imagick's extension and classes. + if ( ! extension_loaded( 'imagick' ) || ! class_exists( 'Imagick' ) || ! class_exists( 'ImagickPixel' ) ) + return false; + + if ( version_compare( phpversion( 'imagick' ), '2.2.0', '<' ) ) + return false; + + $required_methods = array( + 'clear', + 'destroy', + 'valid', + 'getimage', + 'writeimage', + 'getimageblob', + 'getimagegeometry', + 'getimageformat', + 'setimageformat', + 'setimagecompression', + 'setimagecompressionquality', + 'setimagepage', + 'scaleimage', + 'cropimage', + 'rotateimage', + 'flipimage', + 'flopimage', + ); + + // Now, test for deep requirements within Imagick. + if ( ! defined( 'imagick::COMPRESSION_JPEG' ) ) + return false; + + if ( array_diff( $required_methods, get_class_methods( 'Imagick' ) ) ) + return false; + + return true; + } + + /** + * Checks to see if editor supports the mime-type specified. + * + * @since 3.5.0 + * @access public + * + * @param string $mime_type + * @return boolean + */ + public static function supports_mime_type( $mime_type ) { + $imagick_extension = strtoupper( self::get_extension( $mime_type ) ); + + if ( ! $imagick_extension ) + return false; + + // setIteratorIndex is optional unless mime is an animated format. + // Here, we just say no if you are missing it and aren't loading a jpeg. + if ( ! method_exists( 'Imagick', 'setIteratorIndex' ) && $mime_type != 'image/jpeg' ) + return false; + + try { + return ( (bool) @Imagick::queryFormats( $imagick_extension ) ); + } + catch ( Exception $e ) { + return false; + } + } + + /** + * Loads image from $this->file into new Imagick Object. + * + * @since 3.5.0 + * @access protected + * + * @return boolean|WP_Error True if loaded; WP_Error on failure. + */ + public function load() { + if ( $this->image instanceof Imagick ) + return true; + + if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) + return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); + + // Even though Imagick uses less PHP memory than GD, set higher limit for users that have low PHP.ini limits + @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + + try { + $this->image = new Imagick( $this->file ); + + if( ! $this->image->valid() ) + return new WP_Error( 'invalid_image', __('File is not an image.'), $this->file); + + // Select the first frame to handle animated images properly + if ( is_callable( array( $this->image, 'setIteratorIndex' ) ) ) + $this->image->setIteratorIndex(0); + + $this->mime_type = $this->get_mime_type( $this->image->getImageFormat() ); + } + catch ( Exception $e ) { + return new WP_Error( 'invalid_image', $e->getMessage(), $this->file ); + } + + $updated_size = $this->update_size(); + if ( is_wp_error( $updated_size ) ) + return $updated_size; + + return $this->set_quality(); + } + + /** + * Sets Image Compression quality on a 1-100% scale. + * + * @since 3.5.0 + * @access public + * + * @param int $quality Compression Quality. Range: [1,100] + * @return boolean|WP_Error + */ + public function set_quality( $quality = null ) { + if ( !$quality ) + $quality = $this->quality; + + try { + if( 'image/jpeg' == $this->mime_type ) { + $this->image->setImageCompressionQuality( apply_filters( 'jpeg_quality', $quality, 'image_resize' ) ); + $this->image->setImageCompression( imagick::COMPRESSION_JPEG ); + } + else { + $this->image->setImageCompressionQuality( $quality ); + } + } + catch ( Exception $e ) { + return new WP_Error( 'image_quality_error', $e->getMessage() ); + } + + return parent::set_quality( $quality ); + } + + /** + * Sets or updates current image size. + * + * @since 3.5.0 + * @access protected + * + * @param int $width + * @param int $height + */ + protected function update_size( $width = null, $height = null ) { + $size = null; + if ( !$width || !$height ) { + try { + $size = $this->image->getImageGeometry(); + } + catch ( Exception $e ) { + return new WP_Error( 'invalid_image', __('Could not read image size'), $this->file ); + } + } + + if ( ! $width ) + $width = $size['width']; + + if ( ! $height ) + $height = $size['height']; + + return parent::update_size( $width, $height ); + } + + /** + * Resizes current image. + * + * @since 3.5.0 + * @access public + * + * @param int $max_w + * @param int $max_h + * @param boolean $crop + * @return boolean|WP_Error + */ + public function resize( $max_w, $max_h, $crop = false ) { + if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) + return true; + + $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); + if ( ! $dims ) + return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') ); + list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; + + if ( $crop ) { + return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h ); + } + + try { + /** + * @TODO: Thumbnail is more efficient, given a newer version of Imagemagick. + * $this->image->thumbnailImage( $dst_w, $dst_h ); + */ + $this->image->scaleImage( $dst_w, $dst_h ); + } + catch ( Exception $e ) { + return new WP_Error( 'image_resize_error', $e->getMessage() ); + } + + return $this->update_size( $dst_w, $dst_h ); + } + + /** + * Resize multiple images from a single source. + * + * @since 3.5.0 + * @access public + * + * @param array $sizes { + * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. + * + * @type array $size { + * @type int $width Image width. + * @type int $height Image height. + * @type bool $crop Optional. Whether to crop the image. Default false. + * } + * } + * @return array An array of resized images metadata by size. + */ + public function multi_resize( $sizes ) { + $metadata = array(); + $orig_size = $this->size; + $orig_image = $this->image->getImage(); + + foreach ( $sizes as $size => $size_data ) { + if ( ! $this->image ) + $this->image = $orig_image->getImage(); + + if ( ! ( isset( $size_data['width'] ) && isset( $size_data['height'] ) ) ) + continue; + + if ( ! isset( $size_data['crop'] ) ) + $size_data['crop'] = false; + + $resize_result = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); + + if( ! is_wp_error( $resize_result ) ) { + $resized = $this->_save( $this->image ); + + $this->image->clear(); + $this->image->destroy(); + $this->image = null; + + if ( ! is_wp_error( $resized ) && $resized ) { + unset( $resized['path'] ); + $metadata[$size] = $resized; + } + } + + $this->size = $orig_size; + } + + $this->image = $orig_image; + + return $metadata; + } + + /** + * Crops Image. + * + * @since 3.5.0 + * @access public + * + * @param string|int $src The source file or Attachment ID. + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w Optional. The destination width. + * @param int $dst_h Optional. The destination height. + * @param boolean $src_abs Optional. If the source crop points are absolute. + * @return boolean|WP_Error + */ + public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { + if ( $src_abs ) { + $src_w -= $src_x; + $src_h -= $src_y; + } + + try { + $this->image->cropImage( $src_w, $src_h, $src_x, $src_y ); + $this->image->setImagePage( $src_w, $src_h, 0, 0); + + if ( $dst_w || $dst_h ) { + // If destination width/height isn't specified, use same as + // width/height from source. + if ( ! $dst_w ) + $dst_w = $src_w; + if ( ! $dst_h ) + $dst_h = $src_h; + + $this->image->scaleImage( $dst_w, $dst_h ); + return $this->update_size(); + } + } + catch ( Exception $e ) { + return new WP_Error( 'image_crop_error', $e->getMessage() ); + } + return $this->update_size(); + } + + /** + * Rotates current image counter-clockwise by $angle. + * + * @since 3.5.0 + * @access public + * + * @param float $angle + * @return boolean|WP_Error + */ + public function rotate( $angle ) { + /** + * $angle is 360-$angle because Imagick rotates clockwise + * (GD rotates counter-clockwise) + */ + try { + $this->image->rotateImage( new ImagickPixel('none'), 360-$angle ); + + // Since this changes the dimensions of the image, update the size. + $result = $this->update_size(); + if ( is_wp_error( $result ) ) + return $result; + + $this->image->setImagePage( $this->size['width'], $this->size['height'], 0, 0 ); + } + catch ( Exception $e ) { + return new WP_Error( 'image_rotate_error', $e->getMessage() ); + } + return true; + } + + /** + * Flips current image. + * + * @since 3.5.0 + * @access public + * + * @param boolean $horz Flip along Horizontal Axis + * @param boolean $vert Flip along Vertical Axis + * @returns boolean|WP_Error + */ + public function flip( $horz, $vert ) { + try { + if ( $horz ) + $this->image->flipImage(); + + if ( $vert ) + $this->image->flopImage(); + } + catch ( Exception $e ) { + return new WP_Error( 'image_flip_error', $e->getMessage() ); + } + return true; + } + + /** + * Saves current image to file. + * + * @since 3.5.0 + * @access public + * + * @param string $destfilename + * @param string $mime_type + * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} + */ + public function save( $destfilename = null, $mime_type = null ) { + $saved = $this->_save( $this->image, $destfilename, $mime_type ); + + if ( ! is_wp_error( $saved ) ) { + $this->file = $saved['path']; + $this->mime_type = $saved['mime-type']; + + try { + $this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) ); + } + catch ( Exception $e ) { + return new WP_Error( 'image_save_error', $e->getMessage(), $this->file ); + } + } + + return $saved; + } + + protected function _save( $image, $filename = null, $mime_type = null ) { + list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); + + if ( ! $filename ) + $filename = $this->generate_filename( null, null, $extension ); + + try { + // Store initial Format + $orig_format = $this->image->getImageFormat(); + + $this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) ); + $this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) ); + + // Reset original Format + $this->image->setImageFormat( $orig_format ); + } + catch ( Exception $e ) { + return new WP_Error( 'image_save_error', $e->getMessage(), $filename ); + } + + // Set correct file permissions + $stat = stat( dirname( $filename ) ); + $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits + @ chmod( $filename, $perms ); + + return array( + 'path' => $filename, + 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), + 'width' => $this->size['width'], + 'height' => $this->size['height'], + 'mime-type' => $mime_type, + ); + } + + /** + * Streams current image to browser. + * + * @since 3.5.0 + * @access public + * + * @param string $mime_type + * @return boolean|WP_Error + */ + public function stream( $mime_type = null ) { + list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type ); + + try { + // Temporarily change format for stream + $this->image->setImageFormat( strtoupper( $extension ) ); + + // Output stream of image content + header( "Content-Type: $mime_type" ); + print $this->image->getImageBlob(); + + // Reset Image to original Format + $this->image->setImageFormat( $this->get_extension( $this->mime_type ) ); + } + catch ( Exception $e ) { + return new WP_Error( 'image_stream_error', $e->getMessage() ); + } + + return true; + } +} diff --git a/sources/wp-includes/class-wp-image-editor.php b/sources/wp-includes/class-wp-image-editor.php new file mode 100644 index 0000000..81909f8 --- /dev/null +++ b/sources/wp-includes/class-wp-image-editor.php @@ -0,0 +1,423 @@ +<?php +/** + * Base WordPress Image Editor + * + * @package WordPress + * @subpackage Image_Editor + */ + +/** + * Base image editor class from which implementations extend + * + * @since 3.5.0 + */ +abstract class WP_Image_Editor { + protected $file = null; + protected $size = null; + protected $mime_type = null; + protected $default_mime_type = 'image/jpeg'; + protected $quality = 90; + + /** + * Each instance handles a single file. + */ + public function __construct( $file ) { + $this->file = $file; + } + + /** + * Checks to see if current environment supports the editor chosen. + * Must be overridden in a sub-class. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param array $args + * @return boolean + */ + public static function test( $args = array() ) { + return false; + } + + /** + * Checks to see if editor supports the mime-type specified. + * Must be overridden in a sub-class. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param string $mime_type + * @return boolean + */ + public static function supports_mime_type( $mime_type ) { + return false; + } + + /** + * Loads image from $this->file into editor. + * + * @since 3.5.0 + * @access protected + * @abstract + * + * @return boolean|WP_Error True if loaded; WP_Error on failure. + */ + abstract public function load(); + + /** + * Saves current image to file. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param string $destfilename + * @param string $mime_type + * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} + */ + abstract public function save( $destfilename = null, $mime_type = null ); + + /** + * Resizes current image. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param int $max_w + * @param int $max_h + * @param boolean $crop + * @return boolean|WP_Error + */ + abstract public function resize( $max_w, $max_h, $crop = false ); + + /** + * Resize multiple images from a single source. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param array $sizes { + * An array of image size arrays. Default sizes are 'small', 'medium', 'large'. + * + * @type array $size { + * @type int $width Image width. + * @type int $height Image height. + * @type bool $crop Optional. Whether to crop the image. Default false. + * } + * } + * @return array An array of resized images metadata by size. + */ + abstract public function multi_resize( $sizes ); + + /** + * Crops Image. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param string|int $src The source file or Attachment ID. + * @param int $src_x The start x position to crop from. + * @param int $src_y The start y position to crop from. + * @param int $src_w The width to crop. + * @param int $src_h The height to crop. + * @param int $dst_w Optional. The destination width. + * @param int $dst_h Optional. The destination height. + * @param boolean $src_abs Optional. If the source crop points are absolute. + * @return boolean|WP_Error + */ + abstract public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ); + + /** + * Rotates current image counter-clockwise by $angle. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param float $angle + * @return boolean|WP_Error + */ + abstract public function rotate( $angle ); + + /** + * Flips current image. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param boolean $horz Flip along Horizontal Axis + * @param boolean $vert Flip along Vertical Axis + * @return boolean|WP_Error + */ + abstract public function flip( $horz, $vert ); + + /** + * Streams current image to browser. + * + * @since 3.5.0 + * @access public + * @abstract + * + * @param string $mime_type + * @return boolean|WP_Error + */ + abstract public function stream( $mime_type = null ); + + /** + * Gets dimensions of image. + * + * @since 3.5.0 + * @access public + * + * @return array {'width'=>int, 'height'=>int} + */ + public function get_size() { + return $this->size; + } + + /** + * Sets current image size. + * + * @since 3.5.0 + * @access protected + * + * @param int $width + * @param int $height + */ + protected function update_size( $width = null, $height = null ) { + $this->size = array( + 'width' => (int) $width, + 'height' => (int) $height + ); + return true; + } + + /** + * Sets Image Compression quality on a 1-100% scale. + * + * @since 3.5.0 + * @access public + * + * @param int $quality Compression Quality. Range: [1,100] + * @return boolean + */ + public function set_quality( $quality ) { + /** + * Filter the default quality setting. + * + * @since 3.5.0 + * + * @param int $quality Quality level between 0 (low) and 100 (high). + */ + $this->quality = apply_filters( 'wp_editor_set_quality', $quality ); + + return ( (bool) $this->quality ); + } + + /** + * Returns preferred mime-type and extension based on provided + * file's extension and mime, or current file's extension and mime. + * + * Will default to $this->default_mime_type if requested is not supported. + * + * Provides corrected filename only if filename is provided. + * + * @since 3.5.0 + * @access protected + * + * @param string $filename + * @param string $mime_type + * @return array { filename|null, extension, mime-type } + */ + protected function get_output_format( $filename = null, $mime_type = null ) { + $new_ext = $file_ext = null; + $file_mime = null; + + // By default, assume specified type takes priority + if ( $mime_type ) { + $new_ext = $this->get_extension( $mime_type ); + } + + if ( $filename ) { + $file_ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) ); + $file_mime = $this->get_mime_type( $file_ext ); + } + else { + // If no file specified, grab editor's current extension and mime-type. + $file_ext = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) ); + $file_mime = $this->mime_type; + } + + // Check to see if specified mime-type is the same as type implied by + // file extension. If so, prefer extension from file. + if ( ! $mime_type || ( $file_mime == $mime_type ) ) { + $mime_type = $file_mime; + $new_ext = $file_ext; + } + + // Double-check that the mime-type selected is supported by the editor. + // If not, choose a default instead. + if ( ! $this->supports_mime_type( $mime_type ) ) { + /** + * Filter default mime type prior to getting the file extension. + * + * @see wp_get_mime_types() + * + * @since 3.5.0 + * + * @param string $mime_type Mime type string. + */ + $mime_type = apply_filters( 'image_editor_default_mime_type', $this->default_mime_type ); + $new_ext = $this->get_extension( $mime_type ); + } + + if ( $filename ) { + $ext = ''; + $info = pathinfo( $filename ); + $dir = $info['dirname']; + + if( isset( $info['extension'] ) ) + $ext = $info['extension']; + + $filename = trailingslashit( $dir ) . wp_basename( $filename, ".$ext" ) . ".{$new_ext}"; + } + + return array( $filename, $new_ext, $mime_type ); + } + + /** + * Builds an output filename based on current file, and adding proper suffix + * + * @since 3.5.0 + * @access public + * + * @param string $suffix + * @param string $dest_path + * @param string $extension + * @return string filename + */ + public function generate_filename( $suffix = null, $dest_path = null, $extension = null ) { + // $suffix will be appended to the destination filename, just before the extension + if ( ! $suffix ) + $suffix = $this->get_suffix(); + + $info = pathinfo( $this->file ); + $dir = $info['dirname']; + $ext = $info['extension']; + + $name = wp_basename( $this->file, ".$ext" ); + $new_ext = strtolower( $extension ? $extension : $ext ); + + if ( ! is_null( $dest_path ) && $_dest_path = realpath( $dest_path ) ) + $dir = $_dest_path; + + return trailingslashit( $dir ) . "{$name}-{$suffix}.{$new_ext}"; + } + + /** + * Builds and returns proper suffix for file based on height and width. + * + * @since 3.5.0 + * @access public + * + * @return string suffix + */ + public function get_suffix() { + if ( ! $this->get_size() ) + return false; + + return "{$this->size['width']}x{$this->size['height']}"; + } + + /** + * Either calls editor's save function or handles file as a stream. + * + * @since 3.5.0 + * @access protected + * + * @param string|stream $filename + * @param callable $function + * @param array $arguments + * @return boolean + */ + protected function make_image( $filename, $function, $arguments ) { + if ( $stream = wp_is_stream( $filename ) ) { + ob_start(); + } else { + // The directory containing the original file may no longer exist when using a replication plugin. + wp_mkdir_p( dirname( $filename ) ); + } + + $result = call_user_func_array( $function, $arguments ); + + if ( $result && $stream ) { + $contents = ob_get_contents(); + + $fp = fopen( $filename, 'w' ); + + if ( ! $fp ) + return false; + + fwrite( $fp, $contents ); + fclose( $fp ); + } + + if ( $stream ) { + ob_end_clean(); + } + + return $result; + } + + /** + * Returns first matched mime-type from extension, + * as mapped from wp_get_mime_types() + * + * @since 3.5.0 + * @access protected + * + * @param string $extension + * @return string|boolean + */ + protected static function get_mime_type( $extension = null ) { + if ( ! $extension ) + return false; + + $mime_types = wp_get_mime_types(); + $extensions = array_keys( $mime_types ); + + foreach( $extensions as $_extension ) { + if ( preg_match( "/{$extension}/i", $_extension ) ) { + return $mime_types[$_extension]; + } + } + + return false; + } + + /** + * Returns first matched extension from Mime-type, + * as mapped from wp_get_mime_types() + * + * @since 3.5.0 + * @access protected + * + * @param string $mime_type + * @return string|boolean + */ + protected static function get_extension( $mime_type = null ) { + $extensions = explode( '|', array_search( $mime_type, wp_get_mime_types() ) ); + + if ( empty( $extensions[0] ) ) + return false; + + return $extensions[0]; + } +} + diff --git a/sources/wp-includes/class-wp-theme.php b/sources/wp-includes/class-wp-theme.php new file mode 100644 index 0000000..cd4ef4e --- /dev/null +++ b/sources/wp-includes/class-wp-theme.php @@ -0,0 +1,1200 @@ +<?php +/** + * WP_Theme Class + * + * @package WordPress + * @subpackage Theme + */ + +final class WP_Theme implements ArrayAccess { + + /** + * Headers for style.css files. + * + * @static + * @access private + * @var array + */ + private static $file_headers = array( + 'Name' => 'Theme Name', + 'ThemeURI' => 'Theme URI', + 'Description' => 'Description', + 'Author' => 'Author', + 'AuthorURI' => 'Author URI', + 'Version' => 'Version', + 'Template' => 'Template', + 'Status' => 'Status', + 'Tags' => 'Tags', + 'TextDomain' => 'Text Domain', + 'DomainPath' => 'Domain Path', + ); + + /** + * Default themes. + * + * @static + * @access private + * @var array + */ + private static $default_themes = array( + 'classic' => 'WordPress Classic', + 'default' => 'WordPress Default', + 'twentyten' => 'Twenty Ten', + 'twentyeleven' => 'Twenty Eleven', + 'twentytwelve' => 'Twenty Twelve', + 'twentythirteen' => 'Twenty Thirteen', + ); + + /** + * Absolute path to the theme root, usually wp-content/themes + * + * @access private + * @var string + */ + private $theme_root; + + /** + * Header data from the theme's style.css file. + * + * @access private + * @var array + */ + private $headers = array(); + + /** + * Header data from the theme's style.css file after being sanitized. + * + * @access private + * @var array + */ + private $headers_sanitized; + + /** + * Header name from the theme's style.css after being translated. + * + * Cached due to sorting functions running over the translated name. + */ + private $name_translated; + + /** + * Errors encountered when initializing the theme. + * + * @access private + * @var WP_Error + */ + private $errors; + + /** + * The directory name of the theme's files, inside the theme root. + * + * In the case of a child theme, this is directory name of the child theme. + * Otherwise, 'stylesheet' is the same as 'template'. + * + * @access private + * @var string + */ + private $stylesheet; + + /** + * The directory name of the theme's files, inside the theme root. + * + * In the case of a child theme, this is the directory name of the parent theme. + * Otherwise, 'template' is the same as 'stylesheet'. + * + * @access private + * @var string + */ + private $template; + + /** + * A reference to the parent theme, in the case of a child theme. + * + * @access private + * @var WP_Theme + */ + private $parent; + + /** + * URL to the theme root, usually an absolute URL to wp-content/themes + * + * @access private + * var string + */ + private $theme_root_uri; + + /** + * Flag for whether the theme's textdomain is loaded. + * + * @access private + * @var bool + */ + private $textdomain_loaded; + + /** + * Stores an md5 hash of the theme root, to function as the cache key. + * + * @access private + * @var string + */ + private $cache_hash; + + /** + * Flag for whether the themes cache bucket should be persistently cached. + * + * Default is false. Can be set with the wp_cache_themes_persistently filter. + * + * @access private + * @var bool + */ + private static $persistently_cache; + + /** + * Expiration time for the themes cache bucket. + * + * By default the bucket is not cached, so this value is useless. + * + * @access private + * @var bool + */ + private static $cache_expiration = 1800; + + /** + * Constructor for WP_Theme. + * + * @param string $theme_dir Directory of the theme within the theme_root. + * @param string $theme_root Theme root. + * @param WP_Error|null $_child If this theme is a parent theme, the child may be passed for validation purposes. + */ + public function __construct( $theme_dir, $theme_root, $_child = null ) { + global $wp_theme_directories; + + // Initialize caching on first run. + if ( ! isset( self::$persistently_cache ) ) { + self::$persistently_cache = apply_filters( 'wp_cache_themes_persistently', false, 'WP_Theme' ); + if ( self::$persistently_cache ) { + wp_cache_add_global_groups( 'themes' ); + if ( is_int( self::$persistently_cache ) ) + self::$cache_expiration = self::$persistently_cache; + } else { + wp_cache_add_non_persistent_groups( 'themes' ); + } + } + + $this->theme_root = $theme_root; + $this->stylesheet = $theme_dir; + + // Correct a situation where the theme is 'some-directory/some-theme' but 'some-directory' was passed in as part of the theme root instead. + if ( ! in_array( $theme_root, (array) $wp_theme_directories ) && in_array( dirname( $theme_root ), (array) $wp_theme_directories ) ) { + $this->stylesheet = basename( $this->theme_root ) . '/' . $this->stylesheet; + $this->theme_root = dirname( $theme_root ); + } + + $this->cache_hash = md5( $this->theme_root . '/' . $this->stylesheet ); + $theme_file = $this->stylesheet . '/style.css'; + + $cache = $this->cache_get( 'theme' ); + + if ( is_array( $cache ) ) { + foreach ( array( 'errors', 'headers', 'template' ) as $key ) { + if ( isset( $cache[ $key ] ) ) + $this->$key = $cache[ $key ]; + } + if ( $this->errors ) + return; + if ( isset( $cache['theme_root_template'] ) ) + $theme_root_template = $cache['theme_root_template']; + } elseif ( ! file_exists( $this->theme_root . '/' . $theme_file ) ) { + $this->headers['Name'] = $this->stylesheet; + if ( ! file_exists( $this->theme_root . '/' . $this->stylesheet ) ) + $this->errors = new WP_Error( 'theme_not_found', sprintf( __( 'The theme directory "%s" does not exist.' ), $this->stylesheet ) ); + else + $this->errors = new WP_Error( 'theme_no_stylesheet', __( 'Stylesheet is missing.' ) ); + $this->template = $this->stylesheet; + $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); + if ( ! file_exists( $this->theme_root ) ) // Don't cache this one. + $this->errors->add( 'theme_root_missing', __( 'ERROR: The themes directory is either empty or doesn’t exist. Please check your installation.' ) ); + return; + } elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) { + $this->headers['Name'] = $this->stylesheet; + $this->errors = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) ); + $this->template = $this->stylesheet; + $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); + return; + } else { + $this->headers = get_file_data( $this->theme_root . '/' . $theme_file, self::$file_headers, 'theme' ); + // Default themes always trump their pretenders. + // Properly identify default themes that are inside a directory within wp-content/themes. + if ( $default_theme_slug = array_search( $this->headers['Name'], self::$default_themes ) ) { + if ( basename( $this->stylesheet ) != $default_theme_slug ) + $this->headers['Name'] .= '/' . $this->stylesheet; + } + } + + // (If template is set from cache [and there are no errors], we know it's good.) + if ( ! $this->template && ! ( $this->template = $this->headers['Template'] ) ) { + $this->template = $this->stylesheet; + if ( ! file_exists( $this->theme_root . '/' . $this->stylesheet . '/index.php' ) ) { + $this->errors = new WP_Error( 'theme_no_index', __( 'Template is missing.' ) ); + $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); + return; + } + } + + // If we got our data from cache, we can assume that 'template' is pointing to the right place. + if ( ! is_array( $cache ) && $this->template != $this->stylesheet && ! file_exists( $this->theme_root . '/' . $this->template . '/index.php' ) ) { + // If we're in a directory of themes inside /themes, look for the parent nearby. + // wp-content/themes/directory-of-themes/* + $parent_dir = dirname( $this->stylesheet ); + if ( '.' != $parent_dir && file_exists( $this->theme_root . '/' . $parent_dir . '/' . $this->template . '/index.php' ) ) { + $this->template = $parent_dir . '/' . $this->template; + } elseif ( ( $directories = search_theme_directories() ) && isset( $directories[ $this->template ] ) ) { + // Look for the template in the search_theme_directories() results, in case it is in another theme root. + // We don't look into directories of themes, just the theme root. + $theme_root_template = $directories[ $this->template ]['theme_root']; + } else { + // Parent theme is missing. + $this->errors = new WP_Error( 'theme_no_parent', sprintf( __( 'The parent theme is missing. Please install the "%s" parent theme.' ), $this->template ) ); + $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); + $this->parent = new WP_Theme( $this->template, $this->theme_root, $this ); + return; + } + } + + // Set the parent, if we're a child theme. + if ( $this->template != $this->stylesheet ) { + // If we are a parent, then there is a problem. Only two generations allowed! Cancel things out. + if ( is_a( $_child, 'WP_Theme' ) && $_child->template == $this->stylesheet ) { + $_child->parent = null; + $_child->errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The "%s" theme is not a valid parent theme.' ), $_child->template ) ); + $_child->cache_add( 'theme', array( 'headers' => $_child->headers, 'errors' => $_child->errors, 'stylesheet' => $_child->stylesheet, 'template' => $_child->template ) ); + // The two themes actually reference each other with the Template header. + if ( $_child->stylesheet == $this->template ) { + $this->errors = new WP_Error( 'theme_parent_invalid', sprintf( __( 'The "%s" theme is not a valid parent theme.' ), $this->template ) ); + $this->cache_add( 'theme', array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ) ); + } + return; + } + // Set the parent. Pass the current instance so we can do the crazy checks above and assess errors. + $this->parent = new WP_Theme( $this->template, isset( $theme_root_template ) ? $theme_root_template : $this->theme_root, $this ); + } + + // We're good. If we didn't retrieve from cache, set it. + if ( ! is_array( $cache ) ) { + $cache = array( 'headers' => $this->headers, 'errors' => $this->errors, 'stylesheet' => $this->stylesheet, 'template' => $this->template ); + // If the parent theme is in another root, we'll want to cache this. Avoids an entire branch of filesystem calls above. + if ( isset( $theme_root_template ) ) + $cache['theme_root_template'] = $theme_root_template; + $this->cache_add( 'theme', $cache ); + } + } + + /** + * When converting the object to a string, the theme name is returned. + * + * @return string Theme name, ready for display (translated) + */ + public function __toString() { + return (string) $this->display('Name'); + } + + /** + * __isset() magic method for properties formerly returned by current_theme_info() + */ + public function __isset( $offset ) { + static $properties = array( + 'name', 'title', 'version', 'parent_theme', 'template_dir', 'stylesheet_dir', 'template', 'stylesheet', + 'screenshot', 'description', 'author', 'tags', 'theme_root', 'theme_root_uri', + ); + + return in_array( $offset, $properties ); + } + + /** + * __get() magic method for properties formerly returned by current_theme_info() + */ + public function __get( $offset ) { + switch ( $offset ) { + case 'name' : + case 'title' : + return $this->get('Name'); + case 'version' : + return $this->get('Version'); + case 'parent_theme' : + return $this->parent() ? $this->parent()->get('Name') : ''; + case 'template_dir' : + return $this->get_template_directory(); + case 'stylesheet_dir' : + return $this->get_stylesheet_directory(); + case 'template' : + return $this->get_template(); + case 'stylesheet' : + return $this->get_stylesheet(); + case 'screenshot' : + return $this->get_screenshot( 'relative' ); + // 'author' and 'description' did not previously return translated data. + case 'description' : + return $this->display('Description'); + case 'author' : + return $this->display('Author'); + case 'tags' : + return $this->get( 'Tags' ); + case 'theme_root' : + return $this->get_theme_root(); + case 'theme_root_uri' : + return $this->get_theme_root_uri(); + // For cases where the array was converted to an object. + default : + return $this->offsetGet( $offset ); + } + } + + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes() + */ + public function offsetSet( $offset, $value ) {} + + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes() + */ + public function offsetUnset( $offset ) {} + + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes() + */ + public function offsetExists( $offset ) { + static $keys = array( + 'Name', 'Version', 'Status', 'Title', 'Author', 'Author Name', 'Author URI', 'Description', + 'Template', 'Stylesheet', 'Template Files', 'Stylesheet Files', 'Template Dir', 'Stylesheet Dir', + 'Screenshot', 'Tags', 'Theme Root', 'Theme Root URI', 'Parent Theme', + ); + + return in_array( $offset, $keys ); + } + + /** + * Method to implement ArrayAccess for keys formerly returned by get_themes(). + * + * Author, Author Name, Author URI, and Description did not previously return + * translated data. We are doing so now as it is safe to do. However, as + * Name and Title could have been used as the key for get_themes(), both remain + * untranslated for back compatibility. This means that ['Name'] is not ideal, + * and care should be taken to use $theme->display('Name') to get a properly + * translated header. + */ + public function offsetGet( $offset ) { + switch ( $offset ) { + case 'Name' : + case 'Title' : + // See note above about using translated data. get() is not ideal. + // It is only for backwards compatibility. Use display(). + return $this->get('Name'); + case 'Author' : + return $this->display( 'Author'); + case 'Author Name' : + return $this->display( 'Author', false); + case 'Author URI' : + return $this->display('AuthorURI'); + case 'Description' : + return $this->display( 'Description'); + case 'Version' : + case 'Status' : + return $this->get( $offset ); + case 'Template' : + return $this->get_template(); + case 'Stylesheet' : + return $this->get_stylesheet(); + case 'Template Files' : + return $this->get_files( 'php', 1, true ); + case 'Stylesheet Files' : + return $this->get_files( 'css', 0, false ); + case 'Template Dir' : + return $this->get_template_directory(); + case 'Stylesheet Dir' : + return $this->get_stylesheet_directory(); + case 'Screenshot' : + return $this->get_screenshot( 'relative' ); + case 'Tags' : + return $this->get('Tags'); + case 'Theme Root' : + return $this->get_theme_root(); + case 'Theme Root URI' : + return $this->get_theme_root_uri(); + case 'Parent Theme' : + return $this->parent() ? $this->parent()->get('Name') : ''; + default : + return null; + } + } + + /** + * Returns errors property. + * + * @since 3.4.0 + * @access public + * + * @return WP_Error|bool WP_Error if there are errors, or false. + */ + public function errors() { + return is_wp_error( $this->errors ) ? $this->errors : false; + } + + /** + * Whether the theme exists. + * + * A theme with errors exists. A theme with the error of 'theme_not_found', + * meaning that the theme's directory was not found, does not exist. + * + * @since 3.4.0 + * @access public + * + * @return bool Whether the theme exists. + */ + public function exists() { + return ! ( $this->errors() && in_array( 'theme_not_found', $this->errors()->get_error_codes() ) ); + } + + /** + * Returns reference to the parent theme. + * + * @since 3.4.0 + * @access public + * + * @return WP_Theme|bool Parent theme, or false if the current theme is not a child theme. + */ + public function parent() { + return isset( $this->parent ) ? $this->parent : false; + } + + /** + * Adds theme data to cache. + * + * Cache entries keyed by the theme and the type of data. + * + * @access private + * @since 3.4.0 + * + * @param string $key Type of data to store (theme, screenshot, headers, page_templates) + * @param string $data Data to store + * @return bool Return value from wp_cache_add() + */ + private function cache_add( $key, $data ) { + return wp_cache_add( $key . '-' . $this->cache_hash, $data, 'themes', self::$cache_expiration ); + } + + /** + * Gets theme data from cache. + * + * Cache entries are keyed by the theme and the type of data. + * + * @access private + * @since 3.4.0 + * + * @param string $key Type of data to retrieve (theme, screenshot, headers, page_templates) + * @return mixed Retrieved data + */ + private function cache_get( $key ) { + return wp_cache_get( $key . '-' . $this->cache_hash, 'themes' ); + } + + /** + * Clears the cache for the theme. + * + * @access public + * @since 3.4.0 + */ + public function cache_delete() { + foreach ( array( 'theme', 'screenshot', 'headers', 'page_templates' ) as $key ) + wp_cache_delete( $key . '-' . $this->cache_hash, 'themes' ); + $this->template = $this->textdomain_loaded = $this->theme_root_uri = $this->parent = $this->errors = $this->headers_sanitized = $this->name_translated = null; + $this->headers = array(); + $this->__construct( $this->stylesheet, $this->theme_root ); + } + + /** + * Get a raw, unformatted theme header. + * + * The header is sanitized, but is not translated, and is not marked up for display. + * To get a theme header for display, use the display() method. + * + * Use the get_template() method, not the 'Template' header, for finding the template. + * The 'Template' header is only good for what was written in the style.css, while + * get_template() takes into account where WordPress actually located the theme and + * whether it is actually valid. + * + * @access public + * @since 3.4.0 + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @return string String on success, false on failure. + */ + public function get( $header ) { + if ( ! isset( $this->headers[ $header ] ) ) + return false; + + if ( ! isset( $this->headers_sanitized ) ) { + $this->headers_sanitized = $this->cache_get( 'headers' ); + if ( ! is_array( $this->headers_sanitized ) ) + $this->headers_sanitized = array(); + } + + if ( isset( $this->headers_sanitized[ $header ] ) ) + return $this->headers_sanitized[ $header ]; + + // If themes are a persistent group, sanitize everything and cache it. One cache add is better than many cache sets. + if ( self::$persistently_cache ) { + foreach ( array_keys( $this->headers ) as $_header ) + $this->headers_sanitized[ $_header ] = $this->sanitize_header( $_header, $this->headers[ $_header ] ); + $this->cache_add( 'headers', $this->headers_sanitized ); + } else { + $this->headers_sanitized[ $header ] = $this->sanitize_header( $header, $this->headers[ $header ] ); + } + + return $this->headers_sanitized[ $header ]; + } + + /** + * Gets a theme header, formatted and translated for display. + * + * @access public + * @since 3.4.0 + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @param bool $markup Optional. Whether to mark up the header. Defaults to true. + * @param bool $translate Optional. Whether to translate the header. Defaults to true. + * @return string Processed header, false on failure. + */ + public function display( $header, $markup = true, $translate = true ) { + $value = $this->get( $header ); + + if ( $translate && ( empty( $value ) || ! $this->load_textdomain() ) ) + $translate = false; + + if ( $translate ) + $value = $this->translate_header( $header, $value ); + + if ( $markup ) + $value = $this->markup_header( $header, $value, $translate ); + + return $value; + } + + /** + * Sanitize a theme header. + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @param string $value Value to sanitize. + */ + private function sanitize_header( $header, $value ) { + switch ( $header ) { + case 'Status' : + if ( ! $value ) { + $value = 'publish'; + break; + } + // Fall through otherwise. + case 'Name' : + static $header_tags = array( + 'abbr' => array( 'title' => true ), + 'acronym' => array( 'title' => true ), + 'code' => true, + 'em' => true, + 'strong' => true, + ); + $value = wp_kses( $value, $header_tags ); + break; + case 'Author' : + // There shouldn't be anchor tags in Author, but some themes like to be challenging. + case 'Description' : + static $header_tags_with_a = array( + 'a' => array( 'href' => true, 'title' => true ), + 'abbr' => array( 'title' => true ), + 'acronym' => array( 'title' => true ), + 'code' => true, + 'em' => true, + 'strong' => true, + ); + $value = wp_kses( $value, $header_tags_with_a ); + break; + case 'ThemeURI' : + case 'AuthorURI' : + $value = esc_url_raw( $value ); + break; + case 'Tags' : + $value = array_filter( array_map( 'trim', explode( ',', strip_tags( $value ) ) ) ); + break; + } + + return $value; + } + + /** + * Mark up a theme header. + * + * @access private + * @since 3.4.0 + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @param string $value Value to mark up. + * @param string $translate Whether the header has been translated. + * @return string Value, marked up. + */ + private function markup_header( $header, $value, $translate ) { + switch ( $header ) { + case 'Name' : + if ( empty( $value ) ) + $value = $this->get_stylesheet(); + break; + case 'Description' : + $value = wptexturize( $value ); + break; + case 'Author' : + if ( $this->get('AuthorURI') ) { + static $attr = null; + if ( ! isset( $attr ) ) + $attr = esc_attr__( 'Visit author homepage' ); + $value = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $this->display( 'AuthorURI', true, $translate ), $attr, $value ); + } elseif ( ! $value ) { + $value = __( 'Anonymous' ); + } + break; + case 'Tags' : + static $comma = null; + if ( ! isset( $comma ) ) { + /* translators: used between list items, there is a space after the comma */ + $comma = __( ', ' ); + } + $value = implode( $comma, $value ); + break; + case 'ThemeURI' : + case 'AuthorURI' : + $value = esc_url( $value ); + break; + } + + return $value; + } + + /** + * Translate a theme header. + * + * @access private + * @since 3.4.0 + * + * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags. + * @param string $value Value to translate. + * @return string Translated value. + */ + private function translate_header( $header, $value ) { + switch ( $header ) { + case 'Name' : + // Cached for sorting reasons. + if ( isset( $this->name_translated ) ) + return $this->name_translated; + $this->name_translated = translate( $value, $this->get('TextDomain' ) ); + return $this->name_translated; + case 'Tags' : + if ( empty( $value ) || ! function_exists( 'get_theme_feature_list' ) ) + return $value; + + static $tags_list; + if ( ! isset( $tags_list ) ) { + $tags_list = array(); + $feature_list = get_theme_feature_list( false ); // No API + foreach ( $feature_list as $tags ) + $tags_list += $tags; + } + + foreach ( $value as &$tag ) { + if ( isset( $tags_list[ $tag ] ) ) + $tag = $tags_list[ $tag ]; + } + + return $value; + break; + default : + $value = translate( $value, $this->get('TextDomain') ); + } + return $value; + } + + /** + * The directory name of the theme's "stylesheet" files, inside the theme root. + * + * In the case of a child theme, this is directory name of the child theme. + * Otherwise, get_stylesheet() is the same as get_template(). + * + * @since 3.4.0 + * @access public + * + * @return string Stylesheet + */ + public function get_stylesheet() { + return $this->stylesheet; + } + + /** + * The directory name of the theme's "template" files, inside the theme root. + * + * In the case of a child theme, this is the directory name of the parent theme. + * Otherwise, the get_template() is the same as get_stylesheet(). + * + * @since 3.4.0 + * @access public + * + * @return string Template + */ + public function get_template() { + return $this->template; + } + + /** + * Returns the absolute path to the directory of a theme's "stylesheet" files. + * + * In the case of a child theme, this is the absolute path to the directory + * of the child theme's files. + * + * @since 3.4.0 + * @access public + * + * @return string Absolute path of the stylesheet directory. + */ + public function get_stylesheet_directory() { + if ( $this->errors() && in_array( 'theme_root_missing', $this->errors()->get_error_codes() ) ) + return ''; + + return $this->theme_root . '/' . $this->stylesheet; + } + + /** + * Returns the absolute path to the directory of a theme's "template" files. + * + * In the case of a child theme, this is the absolute path to the directory + * of the parent theme's files. + * + * @since 3.4.0 + * @access public + * + * @return string Absolute path of the template directory. + */ + public function get_template_directory() { + if ( $this->parent() ) + $theme_root = $this->parent()->theme_root; + else + $theme_root = $this->theme_root; + + return $theme_root . '/' . $this->template; + } + + /** + * Returns the URL to the directory of a theme's "stylesheet" files. + * + * In the case of a child theme, this is the URL to the directory of the + * child theme's files. + * + * @since 3.4.0 + * @access public + * + * @return string URL to the stylesheet directory. + */ + public function get_stylesheet_directory_uri() { + return $this->get_theme_root_uri() . '/' . str_replace( '%2F', '/', rawurlencode( $this->stylesheet ) ); + } + + /** + * Returns the URL to the directory of a theme's "template" files. + * + * In the case of a child theme, this is the URL to the directory of the + * parent theme's files. + * + * @since 3.4.0 + * @access public + * + * @return string URL to the template directory. + */ + public function get_template_directory_uri() { + if ( $this->parent() ) + $theme_root_uri = $this->parent()->get_theme_root_uri(); + else + $theme_root_uri = $this->get_theme_root_uri(); + + return $theme_root_uri . '/' . str_replace( '%2F', '/', rawurlencode( $this->template ) ); + } + + /** + * The absolute path to the directory of the theme root. + * + * This is typically the absolute path to wp-content/themes. + * + * @since 3.4.0 + * @access public + * + * @return string Theme root. + */ + public function get_theme_root() { + return $this->theme_root; + } + + /** + * Returns the URL to the directory of the theme root. + * + * This is typically the absolute URL to wp-content/themes. This forms the basis + * for all other URLs returned by WP_Theme, so we pass it to the public function + * get_theme_root_uri() and allow it to run the theme_root_uri filter. + * + * @uses get_theme_root_uri() + * + * @since 3.4.0 + * @access public + * + * @return string Theme root URI. + */ + public function get_theme_root_uri() { + if ( ! isset( $this->theme_root_uri ) ) + $this->theme_root_uri = get_theme_root_uri( $this->stylesheet, $this->theme_root ); + return $this->theme_root_uri; + } + + /** + * Returns the main screenshot file for the theme. + * + * The main screenshot is called screenshot.png. gif and jpg extensions are also allowed. + * + * Screenshots for a theme must be in the stylesheet directory. (In the case of child + * themes, parent theme screenshots are not inherited.) + * + * @since 3.4.0 + * @access public + * + * @param string $uri Type of URL to return, either 'relative' or an absolute URI. Defaults to absolute URI. + * @return mixed Screenshot file. False if the theme does not have a screenshot. + */ + public function get_screenshot( $uri = 'uri' ) { + $screenshot = $this->cache_get( 'screenshot' ); + if ( $screenshot ) { + if ( 'relative' == $uri ) + return $screenshot; + return $this->get_stylesheet_directory_uri() . '/' . $screenshot; + } elseif ( 0 === $screenshot ) { + return false; + } + + foreach ( array( 'png', 'gif', 'jpg', 'jpeg' ) as $ext ) { + if ( file_exists( $this->get_stylesheet_directory() . "/screenshot.$ext" ) ) { + $this->cache_add( 'screenshot', 'screenshot.' . $ext ); + if ( 'relative' == $uri ) + return 'screenshot.' . $ext; + return $this->get_stylesheet_directory_uri() . '/' . 'screenshot.' . $ext; + } + } + + $this->cache_add( 'screenshot', 0 ); + return false; + } + + /** + * Return files in the theme's directory. + * + * @since 3.4.0 + * @access public + * + * @param mixed $type Optional. Array of extensions to return. Defaults to all files (null). + * @param int $depth Optional. How deep to search for files. Defaults to a flat scan (0 depth). -1 depth is infinite. + * @param bool $search_parent Optional. Whether to return parent files. Defaults to false. + * @return array Array of files, keyed by the path to the file relative to the theme's directory, with the values + * being absolute paths. + */ + public function get_files( $type = null, $depth = 0, $search_parent = false ) { + $files = (array) self::scandir( $this->get_stylesheet_directory(), $type, $depth ); + + if ( $search_parent && $this->parent() ) + $files += (array) self::scandir( $this->get_template_directory(), $type, $depth ); + + return $files; + } + + /** + * Returns the theme's page templates. + * + * @since 3.4.0 + * @access public + * + * @return array Array of page templates, keyed by filename, with the value of the translated header name. + */ + public function get_page_templates() { + // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide. + if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) + return array(); + + $page_templates = $this->cache_get( 'page_templates' ); + + if ( ! is_array( $page_templates ) ) { + $page_templates = array(); + + $files = (array) $this->get_files( 'php', 1 ); + + foreach ( $files as $file => $full_path ) { + if ( ! preg_match( '|Template Name:(.*)$|mi', file_get_contents( $full_path ), $header ) ) + continue; + $page_templates[ $file ] = _cleanup_header_comment( $header[1] ); + } + + $this->cache_add( 'page_templates', $page_templates ); + } + + if ( $this->load_textdomain() ) { + foreach ( $page_templates as &$page_template ) { + $page_template = $this->translate_header( 'Template Name', $page_template ); + } + } + + if ( $this->parent() ) + $page_templates += $this->parent()->get_page_templates(); + + return $page_templates; + } + + /** + * Scans a directory for files of a certain extension. + * + * @since 3.4.0 + * @access private + * + * @param string $path Absolute path to search. + * @param mixed Array of extensions to find, string of a single extension, or null for all extensions. + * @param int $depth How deep to search for files. Optional, defaults to a flat scan (0 depth). -1 depth is infinite. + * @param string $relative_path The basename of the absolute path. Used to control the returned path + * for the found files, particularly when this function recurses to lower depths. + */ + private static function scandir( $path, $extensions = null, $depth = 0, $relative_path = '' ) { + if ( ! is_dir( $path ) ) + return false; + + if ( $extensions ) { + $extensions = (array) $extensions; + $_extensions = implode( '|', $extensions ); + } + + $relative_path = trailingslashit( $relative_path ); + if ( '/' == $relative_path ) + $relative_path = ''; + + $results = scandir( $path ); + $files = array(); + + foreach ( $results as $result ) { + if ( '.' == $result[0] ) + continue; + if ( is_dir( $path . '/' . $result ) ) { + if ( ! $depth || 'CVS' == $result ) + continue; + $found = self::scandir( $path . '/' . $result, $extensions, $depth - 1 , $relative_path . $result ); + $files = array_merge_recursive( $files, $found ); + } elseif ( ! $extensions || preg_match( '~\.(' . $_extensions . ')$~', $result ) ) { + $files[ $relative_path . $result ] = $path . '/' . $result; + } + } + + return $files; + } + + /** + * Loads the theme's textdomain. + * + * Translation files are not inherited from the parent theme. Todo: if this fails for the + * child theme, it should probably try to load the parent theme's translations. + * + * @since 3.4.0 + * @access public + * + * @return True if the textdomain was successfully loaded or has already been loaded. False if + * no textdomain was specified in the file headers, or if the domain could not be loaded. + */ + public function load_textdomain() { + if ( isset( $this->textdomain_loaded ) ) + return $this->textdomain_loaded; + + $textdomain = $this->get('TextDomain'); + if ( ! $textdomain ) { + $this->textdomain_loaded = false; + return false; + } + + if ( is_textdomain_loaded( $textdomain ) ) { + $this->textdomain_loaded = true; + return true; + } + + $path = $this->get_stylesheet_directory(); + if ( $domainpath = $this->get('DomainPath') ) + $path .= $domainpath; + else + $path .= '/languages'; + + $this->textdomain_loaded = load_theme_textdomain( $textdomain, $path ); + return $this->textdomain_loaded; + } + + /** + * Whether the theme is allowed (multisite only). + * + * @since 3.4.0 + * @access public + * + * @param string $check Optional. Whether to check only the 'network'-wide settings, the 'site' + * settings, or 'both'. Defaults to 'both'. + * @param int $blog_id Optional. Ignored if only network-wide settings are checked. Defaults to current blog. + * @return bool Whether the theme is allowed for the network. Returns true in single-site. + */ + public function is_allowed( $check = 'both', $blog_id = null ) { + if ( ! is_multisite() ) + return true; + + if ( 'both' == $check || 'network' == $check ) { + $allowed = self::get_allowed_on_network(); + if ( ! empty( $allowed[ $this->get_stylesheet() ] ) ) + return true; + } + + if ( 'both' == $check || 'site' == $check ) { + $allowed = self::get_allowed_on_site( $blog_id ); + if ( ! empty( $allowed[ $this->get_stylesheet() ] ) ) + return true; + } + + return false; + } + + /** + * Returns array of stylesheet names of themes allowed on the site or network. + * + * @since 3.4.0 + * @access public + * + * @param int $blog_id Optional. Defaults to current blog. + * @return array Array of stylesheet names. + */ + public static function get_allowed( $blog_id = null ) { + $network = (array) apply_filters( 'allowed_themes', self::get_allowed_on_network() ); + return $network + self::get_allowed_on_site( $blog_id ); + } + + /** + * Returns array of stylesheet names of themes allowed on the network. + * + * @since 3.4.0 + * @access public + * + * @return array Array of stylesheet names. + */ + public static function get_allowed_on_network() { + static $allowed_themes; + if ( ! isset( $allowed_themes ) ) + $allowed_themes = (array) get_site_option( 'allowedthemes' ); + return $allowed_themes; + } + + /** + * Returns array of stylesheet names of themes allowed on the site. + * + * @since 3.4.0 + * @access public + * + * @param int $blog_id Optional. Defaults to current blog. + * @return array Array of stylesheet names. + */ + public static function get_allowed_on_site( $blog_id = null ) { + static $allowed_themes = array(); + + if ( ! $blog_id || ! is_multisite() ) + $blog_id = get_current_blog_id(); + + if ( isset( $allowed_themes[ $blog_id ] ) ) + return $allowed_themes[ $blog_id ]; + + $current = $blog_id == get_current_blog_id(); + + if ( $current ) { + $allowed_themes[ $blog_id ] = get_option( 'allowedthemes' ); + } else { + switch_to_blog( $blog_id ); + $allowed_themes[ $blog_id ] = get_option( 'allowedthemes' ); + restore_current_blog(); + } + + // This is all super old MU back compat joy. + // 'allowedthemes' keys things by stylesheet. 'allowed_themes' keyed things by name. + if ( false === $allowed_themes[ $blog_id ] ) { + if ( $current ) { + $allowed_themes[ $blog_id ] = get_option( 'allowed_themes' ); + } else { + switch_to_blog( $blog_id ); + $allowed_themes[ $blog_id ] = get_option( 'allowed_themes' ); + restore_current_blog(); + } + + if ( ! is_array( $allowed_themes[ $blog_id ] ) || empty( $allowed_themes[ $blog_id ] ) ) { + $allowed_themes[ $blog_id ] = array(); + } else { + $converted = array(); + $themes = wp_get_themes(); + foreach ( $themes as $stylesheet => $theme_data ) { + if ( isset( $allowed_themes[ $blog_id ][ $theme_data->get('Name') ] ) ) + $converted[ $stylesheet ] = true; + } + $allowed_themes[ $blog_id ] = $converted; + } + // Set the option so we never have to go through this pain again. + if ( is_admin() && $allowed_themes[ $blog_id ] ) { + if ( $current ) { + update_option( 'allowedthemes', $allowed_themes[ $blog_id ] ); + delete_option( 'allowed_themes' ); + } else { + switch_to_blog( $blog_id ); + update_option( 'allowedthemes', $allowed_themes[ $blog_id ] ); + delete_option( 'allowed_themes' ); + restore_current_blog(); + } + } + } + + return (array) $allowed_themes[ $blog_id ]; + } + + /** + * Sort themes by name. + * + * @since 3.4.0 + * @access public + */ + public static function sort_by_name( &$themes ) { + if ( 0 === strpos( get_locale(), 'en_' ) ) { + uasort( $themes, array( 'WP_Theme', '_name_sort' ) ); + } else { + uasort( $themes, array( 'WP_Theme', '_name_sort_i18n' ) ); + } + } + + /** + * Callback function for usort() to naturally sort themes by name. + * + * Accesses the Name header directly from the class for maximum speed. + * Would choke on HTML but we don't care enough to slow it down with strip_tags(). + * + * @since 3.4.0 + * @access private + */ + private static function _name_sort( $a, $b ) { + return strnatcasecmp( $a->headers['Name'], $b->headers['Name'] ); + } + + /** + * Name sort (with translation). + * + * @since 3.4.0 + * @access private + */ + private static function _name_sort_i18n( $a, $b ) { + // Don't mark up; Do translate. + return strnatcasecmp( $a->display( 'Name', false, true ), $b->display( 'Name', false, true ) ); + } +} diff --git a/sources/wp-includes/class-wp-walker.php b/sources/wp-includes/class-wp-walker.php new file mode 100644 index 0000000..547defe --- /dev/null +++ b/sources/wp-includes/class-wp-walker.php @@ -0,0 +1,408 @@ +<?php +/** + * A class for displaying various tree-like structures. + * + * Extend the Walker class to use it, see examples below. Child classes + * do not need to implement all of the abstract methods in the class. The child + * only needs to implement the methods that are needed. + * + * @since 2.1.0 + * + * @package WordPress + * @abstract + */ +class Walker { + /** + * What the class handles. + * + * @since 2.1.0 + * @var string + * @access public + */ + var $tree_type; + + /** + * DB fields to use. + * + * @since 2.1.0 + * @var array + * @access protected + */ + var $db_fields; + + /** + * Max number of pages walked by the paged walker + * + * @since 2.7.0 + * @var int + * @access protected + */ + var $max_pages = 1; + + /** + * Starts the list before the elements are added. + * + * The $args parameter holds additional values that may be used with the child + * class methods. This method is called at the start of the output list. + * + * @since 2.1.0 + * @abstract + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + */ + function start_lvl( &$output, $depth = 0, $args = array() ) {} + + /** + * Ends the list of after the elements are added. + * + * The $args parameter holds additional values that may be used with the child + * class methods. This method finishes the list at the end of output of the elements. + * + * @since 2.1.0 + * @abstract + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + */ + function end_lvl( &$output, $depth = 0, $args = array() ) {} + + /** + * Start the element output. + * + * The $args parameter holds additional values that may be used with the child + * class methods. Includes the element output also. + * + * @since 2.1.0 + * @abstract + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $object The data object. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + * @param int $current_object_id ID of the current item. + */ + function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {} + + /** + * Ends the element output, if needed. + * + * The $args parameter holds additional values that may be used with the child class methods. + * + * @since 2.1.0 + * @abstract + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $object The data object. + * @param int $depth Depth of the item. + * @param array $args An array of additional arguments. + */ + function end_el( &$output, $object, $depth = 0, $args = array() ) {} + + /** + * Traverse elements to create list from elements. + * + * Display one element if the element doesn't have any children otherwise, + * display the element and its children. Will only traverse up to the max + * depth and no ignore elements under that depth. It is possible to set the + * max depth to include all depths, see walk() method. + * + * This method should not be called directly, use the walk() method instead. + * + * @since 2.5.0 + * + * @param object $element Data object. + * @param array $children_elements List of elements to continue traversing. + * @param int $max_depth Max depth to traverse. + * @param int $depth Depth of current element. + * @param array $args An array of arguments. + * @param string $output Passed by reference. Used to append additional content. + * @return null Null on failure with no changes to parameters. + */ + function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) { + + if ( !$element ) + return; + + $id_field = $this->db_fields['id']; + + //display this element + if ( isset( $args[0] ) && is_array( $args[0] ) ) + $args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] ); + $cb_args = array_merge( array(&$output, $element, $depth), $args); + call_user_func_array(array($this, 'start_el'), $cb_args); + + $id = $element->$id_field; + + // descend only when the depth is right and there are childrens for this element + if ( ($max_depth == 0 || $max_depth > $depth+1 ) && isset( $children_elements[$id]) ) { + + foreach( $children_elements[ $id ] as $child ){ + + if ( !isset($newlevel) ) { + $newlevel = true; + //start the child delimiter + $cb_args = array_merge( array(&$output, $depth), $args); + call_user_func_array(array($this, 'start_lvl'), $cb_args); + } + $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output ); + } + unset( $children_elements[ $id ] ); + } + + if ( isset($newlevel) && $newlevel ){ + //end the child delimiter + $cb_args = array_merge( array(&$output, $depth), $args); + call_user_func_array(array($this, 'end_lvl'), $cb_args); + } + + //end this element + $cb_args = array_merge( array(&$output, $element, $depth), $args); + call_user_func_array(array($this, 'end_el'), $cb_args); + } + + /** + * Display array of elements hierarchically. + * + * Does not assume any existing order of elements. + * + * $max_depth = -1 means flatly display every element. + * $max_depth = 0 means display all levels. + * $max_depth > 0 specifies the number of display levels. + * + * @since 2.1.0 + * + * @param array $elements An array of elements. + * @param int $max_depth The maximum hierarchical depth. + * @return string The hierarchical item output. + */ + function walk( $elements, $max_depth) { + + $args = array_slice(func_get_args(), 2); + $output = ''; + + if ($max_depth < -1) //invalid parameter + return $output; + + if (empty($elements)) //nothing to walk + return $output; + + $id_field = $this->db_fields['id']; + $parent_field = $this->db_fields['parent']; + + // flat display + if ( -1 == $max_depth ) { + $empty_array = array(); + foreach ( $elements as $e ) + $this->display_element( $e, $empty_array, 1, 0, $args, $output ); + return $output; + } + + /* + * Need to display in hierarchical order. + * Separate elements into two buckets: top level and children elements. + * Children_elements is two dimensional array, eg. + * Children_elements[10][] contains all sub-elements whose parent is 10. + */ + $top_level_elements = array(); + $children_elements = array(); + foreach ( $elements as $e) { + if ( 0 == $e->$parent_field ) + $top_level_elements[] = $e; + else + $children_elements[ $e->$parent_field ][] = $e; + } + + /* + * When none of the elements is top level. + * Assume the first one must be root of the sub elements. + */ + if ( empty($top_level_elements) ) { + + $first = array_slice( $elements, 0, 1 ); + $root = $first[0]; + + $top_level_elements = array(); + $children_elements = array(); + foreach ( $elements as $e) { + if ( $root->$parent_field == $e->$parent_field ) + $top_level_elements[] = $e; + else + $children_elements[ $e->$parent_field ][] = $e; + } + } + + foreach ( $top_level_elements as $e ) + $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); + + /* + * If we are displaying all levels, and remaining children_elements is not empty, + * then we got orphans, which should be displayed regardless. + */ + if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) { + $empty_array = array(); + foreach ( $children_elements as $orphans ) + foreach( $orphans as $op ) + $this->display_element( $op, $empty_array, 1, 0, $args, $output ); + } + + return $output; + } + + /** + * paged_walk() - produce a page of nested elements + * + * Given an array of hierarchical elements, the maximum depth, a specific page number, + * and number of elements per page, this function first determines all top level root elements + * belonging to that page, then lists them and all of their children in hierarchical order. + * + * $max_depth = 0 means display all levels. + * $max_depth > 0 specifies the number of display levels. + * + * @since 2.7.0 + * + * @param int $max_depth The maximum hierarchical depth. + * @param int $page_num The specific page number, beginning with 1. + * @return string XHTML of the specified page of elements + */ + function paged_walk( $elements, $max_depth, $page_num, $per_page ) { + + /* sanity check */ + if ( empty($elements) || $max_depth < -1 ) + return ''; + + $args = array_slice( func_get_args(), 4 ); + $output = ''; + + $id_field = $this->db_fields['id']; + $parent_field = $this->db_fields['parent']; + + $count = -1; + if ( -1 == $max_depth ) + $total_top = count( $elements ); + if ( $page_num < 1 || $per_page < 0 ) { + // No paging + $paging = false; + $start = 0; + if ( -1 == $max_depth ) + $end = $total_top; + $this->max_pages = 1; + } else { + $paging = true; + $start = ( (int)$page_num - 1 ) * (int)$per_page; + $end = $start + $per_page; + if ( -1 == $max_depth ) + $this->max_pages = ceil($total_top / $per_page); + } + + // flat display + if ( -1 == $max_depth ) { + if ( !empty($args[0]['reverse_top_level']) ) { + $elements = array_reverse( $elements ); + $oldstart = $start; + $start = $total_top - $end; + $end = $total_top - $oldstart; + } + + $empty_array = array(); + foreach ( $elements as $e ) { + $count++; + if ( $count < $start ) + continue; + if ( $count >= $end ) + break; + $this->display_element( $e, $empty_array, 1, 0, $args, $output ); + } + return $output; + } + + /* + * Separate elements into two buckets: top level and children elements. + * Children_elements is two dimensional array, e.g. + * $children_elements[10][] contains all sub-elements whose parent is 10. + */ + $top_level_elements = array(); + $children_elements = array(); + foreach ( $elements as $e) { + if ( 0 == $e->$parent_field ) + $top_level_elements[] = $e; + else + $children_elements[ $e->$parent_field ][] = $e; + } + + $total_top = count( $top_level_elements ); + if ( $paging ) + $this->max_pages = ceil($total_top / $per_page); + else + $end = $total_top; + + if ( !empty($args[0]['reverse_top_level']) ) { + $top_level_elements = array_reverse( $top_level_elements ); + $oldstart = $start; + $start = $total_top - $end; + $end = $total_top - $oldstart; + } + if ( !empty($args[0]['reverse_children']) ) { + foreach ( $children_elements as $parent => $children ) + $children_elements[$parent] = array_reverse( $children ); + } + + foreach ( $top_level_elements as $e ) { + $count++; + + // For the last page, need to unset earlier children in order to keep track of orphans. + if ( $end >= $total_top && $count < $start ) + $this->unset_children( $e, $children_elements ); + + if ( $count < $start ) + continue; + + if ( $count >= $end ) + break; + + $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); + } + + if ( $end >= $total_top && count( $children_elements ) > 0 ) { + $empty_array = array(); + foreach ( $children_elements as $orphans ) + foreach( $orphans as $op ) + $this->display_element( $op, $empty_array, 1, 0, $args, $output ); + } + + return $output; + } + + function get_number_of_root_elements( $elements ){ + + $num = 0; + $parent_field = $this->db_fields['parent']; + + foreach ( $elements as $e) { + if ( 0 == $e->$parent_field ) + $num++; + } + return $num; + } + + // Unset all the children for a given top level element. + function unset_children( $e, &$children_elements ){ + + if ( !$e || !$children_elements ) + return; + + $id_field = $this->db_fields['id']; + $id = $e->$id_field; + + if ( !empty($children_elements[$id]) && is_array($children_elements[$id]) ) + foreach ( (array) $children_elements[$id] as $child ) + $this->unset_children( $child, $children_elements ); + + if ( isset($children_elements[$id]) ) + unset( $children_elements[$id] ); + + } + +} // Walker diff --git a/sources/wp-includes/class-wp-xmlrpc-server.php b/sources/wp-includes/class-wp-xmlrpc-server.php new file mode 100644 index 0000000..d3ebdb8 --- /dev/null +++ b/sources/wp-includes/class-wp-xmlrpc-server.php @@ -0,0 +1,5525 @@ +<?php +/** + * XML-RPC protocol support for WordPress + * + * @package WordPress + */ + +/** + * WordPress XMLRPC server implementation. + * + * Implements compatibility for Blogger API, MetaWeblog API, MovableType, and + * pingback. Additional WordPress API for managing comments, pages, posts, + * options, etc. + * + * As of WordPress 3.5.0, XML-RPC is enabled by default. It can be disabled + * via the xmlrpc_enabled filter found in wp_xmlrpc_server::login(). + * + * @package WordPress + * @subpackage Publishing + * @since 1.5.0 + */ +class wp_xmlrpc_server extends IXR_Server { + + /** + * Register all of the XMLRPC methods that XMLRPC server understands. + * + * Sets up server and method property. Passes XMLRPC + * methods through the 'xmlrpc_methods' filter to allow plugins to extend + * or replace XMLRPC methods. + * + * @since 1.5.0 + * + * @return wp_xmlrpc_server + */ + function __construct() { + $this->methods = array( + // WordPress API + 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs', + 'wp.newPost' => 'this:wp_newPost', + 'wp.editPost' => 'this:wp_editPost', + 'wp.deletePost' => 'this:wp_deletePost', + 'wp.getPost' => 'this:wp_getPost', + 'wp.getPosts' => 'this:wp_getPosts', + 'wp.newTerm' => 'this:wp_newTerm', + 'wp.editTerm' => 'this:wp_editTerm', + 'wp.deleteTerm' => 'this:wp_deleteTerm', + 'wp.getTerm' => 'this:wp_getTerm', + 'wp.getTerms' => 'this:wp_getTerms', + 'wp.getTaxonomy' => 'this:wp_getTaxonomy', + 'wp.getTaxonomies' => 'this:wp_getTaxonomies', + 'wp.getUser' => 'this:wp_getUser', + 'wp.getUsers' => 'this:wp_getUsers', + 'wp.getProfile' => 'this:wp_getProfile', + 'wp.editProfile' => 'this:wp_editProfile', + 'wp.getPage' => 'this:wp_getPage', + 'wp.getPages' => 'this:wp_getPages', + 'wp.newPage' => 'this:wp_newPage', + 'wp.deletePage' => 'this:wp_deletePage', + 'wp.editPage' => 'this:wp_editPage', + 'wp.getPageList' => 'this:wp_getPageList', + 'wp.getAuthors' => 'this:wp_getAuthors', + 'wp.getCategories' => 'this:mw_getCategories', // Alias + 'wp.getTags' => 'this:wp_getTags', + 'wp.newCategory' => 'this:wp_newCategory', + 'wp.deleteCategory' => 'this:wp_deleteCategory', + 'wp.suggestCategories' => 'this:wp_suggestCategories', + 'wp.uploadFile' => 'this:mw_newMediaObject', // Alias + 'wp.getCommentCount' => 'this:wp_getCommentCount', + 'wp.getPostStatusList' => 'this:wp_getPostStatusList', + 'wp.getPageStatusList' => 'this:wp_getPageStatusList', + 'wp.getPageTemplates' => 'this:wp_getPageTemplates', + 'wp.getOptions' => 'this:wp_getOptions', + 'wp.setOptions' => 'this:wp_setOptions', + 'wp.getComment' => 'this:wp_getComment', + 'wp.getComments' => 'this:wp_getComments', + 'wp.deleteComment' => 'this:wp_deleteComment', + 'wp.editComment' => 'this:wp_editComment', + 'wp.newComment' => 'this:wp_newComment', + 'wp.getCommentStatusList' => 'this:wp_getCommentStatusList', + 'wp.getMediaItem' => 'this:wp_getMediaItem', + 'wp.getMediaLibrary' => 'this:wp_getMediaLibrary', + 'wp.getPostFormats' => 'this:wp_getPostFormats', + 'wp.getPostType' => 'this:wp_getPostType', + 'wp.getPostTypes' => 'this:wp_getPostTypes', + 'wp.getRevisions' => 'this:wp_getRevisions', + 'wp.restoreRevision' => 'this:wp_restoreRevision', + + // Blogger API + 'blogger.getUsersBlogs' => 'this:blogger_getUsersBlogs', + 'blogger.getUserInfo' => 'this:blogger_getUserInfo', + 'blogger.getPost' => 'this:blogger_getPost', + 'blogger.getRecentPosts' => 'this:blogger_getRecentPosts', + 'blogger.newPost' => 'this:blogger_newPost', + 'blogger.editPost' => 'this:blogger_editPost', + 'blogger.deletePost' => 'this:blogger_deletePost', + + // MetaWeblog API (with MT extensions to structs) + 'metaWeblog.newPost' => 'this:mw_newPost', + 'metaWeblog.editPost' => 'this:mw_editPost', + 'metaWeblog.getPost' => 'this:mw_getPost', + 'metaWeblog.getRecentPosts' => 'this:mw_getRecentPosts', + 'metaWeblog.getCategories' => 'this:mw_getCategories', + 'metaWeblog.newMediaObject' => 'this:mw_newMediaObject', + + // MetaWeblog API aliases for Blogger API + // see http://www.xmlrpc.com/stories/storyReader$2460 + 'metaWeblog.deletePost' => 'this:blogger_deletePost', + 'metaWeblog.getUsersBlogs' => 'this:blogger_getUsersBlogs', + + // MovableType API + 'mt.getCategoryList' => 'this:mt_getCategoryList', + 'mt.getRecentPostTitles' => 'this:mt_getRecentPostTitles', + 'mt.getPostCategories' => 'this:mt_getPostCategories', + 'mt.setPostCategories' => 'this:mt_setPostCategories', + 'mt.supportedMethods' => 'this:mt_supportedMethods', + 'mt.supportedTextFilters' => 'this:mt_supportedTextFilters', + 'mt.getTrackbackPings' => 'this:mt_getTrackbackPings', + 'mt.publishPost' => 'this:mt_publishPost', + + // PingBack + 'pingback.ping' => 'this:pingback_ping', + 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks', + + 'demo.sayHello' => 'this:sayHello', + 'demo.addTwoNumbers' => 'this:addTwoNumbers' + ); + + $this->initialise_blog_option_info(); + $this->methods = apply_filters('xmlrpc_methods', $this->methods); + } + + function serve_request() { + $this->IXR_Server($this->methods); + } + + /** + * Test XMLRPC API by saying, "Hello!" to client. + * + * @since 1.5.0 + * + * @param array $args Method Parameters. + * @return string + */ + function sayHello($args) { + return 'Hello!'; + } + + /** + * Test XMLRPC API by adding two numbers for client. + * + * @since 1.5.0 + * + * @param array $args Method Parameters. + * @return int + */ + function addTwoNumbers($args) { + $number1 = $args[0]; + $number2 = $args[1]; + return $number1 + $number2; + } + + /** + * Log user in. + * + * @since 2.8.0 + * + * @param string $username User's username. + * @param string $password User's password. + * @return mixed WP_User object if authentication passed, false otherwise + */ + function login( $username, $password ) { + // Respect any old filters against get_option() for 'enable_xmlrpc'. + $enabled = apply_filters( 'pre_option_enable_xmlrpc', false ); // Deprecated + if ( false === $enabled ) + $enabled = apply_filters( 'option_enable_xmlrpc', true ); // Deprecated + + // Proper filter for turning off XML-RPC. It is on by default. + $enabled = apply_filters( 'xmlrpc_enabled', $enabled ); + + if ( ! $enabled ) { + $this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.' ) ) ); + return false; + } + + $user = wp_authenticate($username, $password); + + if (is_wp_error($user)) { + $this->error = new IXR_Error( 403, __( 'Incorrect username or password.' ) ); + $this->error = apply_filters( 'xmlrpc_login_error', $this->error, $user ); + return false; + } + + wp_set_current_user( $user->ID ); + return $user; + } + + /** + * Check user's credentials. Deprecated. + * + * @since 1.5.0 + * @deprecated 2.8.0 + * @deprecated use wp_xmlrpc_server::login + * @see wp_xmlrpc_server::login + * + * @param string $username User's username. + * @param string $password User's password. + * @return bool Whether authentication passed. + */ + function login_pass_ok( $username, $password ) { + return (bool) $this->login( $username, $password ); + } + + /** + * Escape string or array of strings for database. + * + * @since 1.5.2 + * + * @param string|array $data Escape single string or array of strings. + * @return string|array Type matches $data and sanitized for the database. + */ + function escape( &$data ) { + if ( ! is_array( $data ) ) + return wp_slash( $data ); + + foreach ( $data as &$v ) { + if ( is_array( $v ) ) + $this->escape( $v ); + elseif ( ! is_object( $v ) ) + $v = wp_slash( $v ); + } + } + + /** + * Retrieve custom fields for post. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @return array Custom fields, if exist. + */ + function get_custom_fields($post_id) { + $post_id = (int) $post_id; + + $custom_fields = array(); + + foreach ( (array) has_meta($post_id) as $meta ) { + // Don't expose protected fields. + if ( ! current_user_can( 'edit_post_meta', $post_id , $meta['meta_key'] ) ) + continue; + + $custom_fields[] = array( + "id" => $meta['meta_id'], + "key" => $meta['meta_key'], + "value" => $meta['meta_value'] + ); + } + + return $custom_fields; + } + + /** + * Set custom fields for post. + * + * @since 2.5.0 + * + * @param int $post_id Post ID. + * @param array $fields Custom fields. + */ + function set_custom_fields($post_id, $fields) { + $post_id = (int) $post_id; + + foreach ( (array) $fields as $meta ) { + if ( isset($meta['id']) ) { + $meta['id'] = (int) $meta['id']; + $pmeta = get_metadata_by_mid( 'post', $meta['id'] ); + if ( isset($meta['key']) ) { + $meta['key'] = wp_unslash( $meta['key'] ); + if ( $meta['key'] !== $pmeta->meta_key ) + continue; + $meta['value'] = wp_unslash( $meta['value'] ); + if ( current_user_can( 'edit_post_meta', $post_id, $meta['key'] ) ) + update_metadata_by_mid( 'post', $meta['id'], $meta['value'] ); + } elseif ( current_user_can( 'delete_post_meta', $post_id, $pmeta->meta_key ) ) { + delete_metadata_by_mid( 'post', $meta['id'] ); + } + } elseif ( current_user_can( 'add_post_meta', $post_id, wp_unslash( $meta['key'] ) ) ) { + add_post_meta( $post_id, $meta['key'], $meta['value'] ); + } + } + } + + /** + * Set up blog options property. + * + * Passes property through 'xmlrpc_blog_options' filter. + * + * @since 2.6.0 + */ + function initialise_blog_option_info() { + global $wp_version; + + $this->blog_options = array( + // Read only options + 'software_name' => array( + 'desc' => __( 'Software Name' ), + 'readonly' => true, + 'value' => 'WordPress' + ), + 'software_version' => array( + 'desc' => __( 'Software Version' ), + 'readonly' => true, + 'value' => $wp_version + ), + 'blog_url' => array( + 'desc' => __( 'WordPress Address (URL)' ), + 'readonly' => true, + 'option' => 'siteurl' + ), + 'home_url' => array( + 'desc' => __( 'Site Address (URL)' ), + 'readonly' => true, + 'option' => 'home' + ), + 'login_url' => array( + 'desc' => __( 'Login Address (URL)' ), + 'readonly' => true, + 'value' => wp_login_url( ) + ), + 'admin_url' => array( + 'desc' => __( 'The URL to the admin area' ), + 'readonly' => true, + 'value' => get_admin_url( ) + ), + 'image_default_link_type' => array( + 'desc' => __( 'Image default link type' ), + 'readonly' => true, + 'option' => 'image_default_link_type' + ), + 'image_default_size' => array( + 'desc' => __( 'Image default size' ), + 'readonly' => true, + 'option' => 'image_default_size' + ), + 'image_default_align' => array( + 'desc' => __( 'Image default align' ), + 'readonly' => true, + 'option' => 'image_default_align' + ), + 'template' => array( + 'desc' => __( 'Template' ), + 'readonly' => true, + 'option' => 'template' + ), + 'stylesheet' => array( + 'desc' => __( 'Stylesheet' ), + 'readonly' => true, + 'option' => 'stylesheet' + ), + 'post_thumbnail' => array( + 'desc' => __('Post Thumbnail'), + 'readonly' => true, + 'value' => current_theme_supports( 'post-thumbnails' ) + ), + + // Updatable options + 'time_zone' => array( + 'desc' => __( 'Time Zone' ), + 'readonly' => false, + 'option' => 'gmt_offset' + ), + 'blog_title' => array( + 'desc' => __( 'Site Title' ), + 'readonly' => false, + 'option' => 'blogname' + ), + 'blog_tagline' => array( + 'desc' => __( 'Site Tagline' ), + 'readonly' => false, + 'option' => 'blogdescription' + ), + 'date_format' => array( + 'desc' => __( 'Date Format' ), + 'readonly' => false, + 'option' => 'date_format' + ), + 'time_format' => array( + 'desc' => __( 'Time Format' ), + 'readonly' => false, + 'option' => 'time_format' + ), + 'users_can_register' => array( + 'desc' => __( 'Allow new users to sign up' ), + 'readonly' => false, + 'option' => 'users_can_register' + ), + 'thumbnail_size_w' => array( + 'desc' => __( 'Thumbnail Width' ), + 'readonly' => false, + 'option' => 'thumbnail_size_w' + ), + 'thumbnail_size_h' => array( + 'desc' => __( 'Thumbnail Height' ), + 'readonly' => false, + 'option' => 'thumbnail_size_h' + ), + 'thumbnail_crop' => array( + 'desc' => __( 'Crop thumbnail to exact dimensions' ), + 'readonly' => false, + 'option' => 'thumbnail_crop' + ), + 'medium_size_w' => array( + 'desc' => __( 'Medium size image width' ), + 'readonly' => false, + 'option' => 'medium_size_w' + ), + 'medium_size_h' => array( + 'desc' => __( 'Medium size image height' ), + 'readonly' => false, + 'option' => 'medium_size_h' + ), + 'large_size_w' => array( + 'desc' => __( 'Large size image width' ), + 'readonly' => false, + 'option' => 'large_size_w' + ), + 'large_size_h' => array( + 'desc' => __( 'Large size image height' ), + 'readonly' => false, + 'option' => 'large_size_h' + ), + 'default_comment_status' => array( + 'desc' => __( 'Allow people to post comments on new articles' ), + 'readonly' => false, + 'option' => 'default_comment_status' + ), + 'default_ping_status' => array( + 'desc' => __( 'Allow link notifications from other blogs (pingbacks and trackbacks)' ), + 'readonly' => false, + 'option' => 'default_ping_status' + ) + ); + + $this->blog_options = apply_filters( 'xmlrpc_blog_options', $this->blog_options ); + } + + /** + * Retrieve the blogs of the user. + * + * @since 2.6.0 + * + * @param array $args Method parameters. Contains: + * - username + * - password + * @return array. Contains: + * - 'isAdmin' + * - 'url' + * - 'blogid' + * - 'blogName' + * - 'xmlrpc' - url of xmlrpc endpoint + */ + function wp_getUsersBlogs( $args ) { + global $current_site; + // If this isn't on WPMU then just use blogger_getUsersBlogs + if ( !is_multisite() ) { + array_unshift( $args, 1 ); + return $this->blogger_getUsersBlogs( $args ); + } + + $this->escape( $args ); + + $username = $args[0]; + $password = $args[1]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getUsersBlogs' ); + + $blogs = (array) get_blogs_of_user( $user->ID ); + $struct = array(); + + foreach ( $blogs as $blog ) { + // Don't include blogs that aren't hosted at this site + if ( $blog->site_id != $current_site->id ) + continue; + + $blog_id = $blog->userblog_id; + + switch_to_blog( $blog_id ); + + $is_admin = current_user_can( 'manage_options' ); + + $struct[] = array( + 'isAdmin' => $is_admin, + 'url' => home_url( '/' ), + 'blogid' => (string) $blog_id, + 'blogName' => get_option( 'blogname' ), + 'xmlrpc' => site_url( 'xmlrpc.php', 'rpc' ), + ); + + restore_current_blog(); + } + + return $struct; + } + + /** + * Checks if the method received at least the minimum number of arguments. + * + * @since 3.4.0 + * + * @param string|array $args Sanitize single string or array of strings. + * @param int $count Minimum number of arguments. + * @return boolean if $args contains at least $count arguments. + */ + protected function minimum_args( $args, $count ) { + if ( count( $args ) < $count ) { + $this->error = new IXR_Error( 400, __( 'Insufficient arguments passed to this XML-RPC method.' ) ); + return false; + } + + return true; + } + + /** + * Prepares taxonomy data for return in an XML-RPC object. + * + * @access protected + * + * @param object $taxonomy The unprepared taxonomy data + * @param array $fields The subset of taxonomy fields to return + * @return array The prepared taxonomy data + */ + protected function _prepare_taxonomy( $taxonomy, $fields ) { + $_taxonomy = array( + 'name' => $taxonomy->name, + 'label' => $taxonomy->label, + 'hierarchical' => (bool) $taxonomy->hierarchical, + 'public' => (bool) $taxonomy->public, + 'show_ui' => (bool) $taxonomy->show_ui, + '_builtin' => (bool) $taxonomy->_builtin, + ); + + if ( in_array( 'labels', $fields ) ) + $_taxonomy['labels'] = (array) $taxonomy->labels; + + if ( in_array( 'cap', $fields ) ) + $_taxonomy['cap'] = (array) $taxonomy->cap; + + if ( in_array( 'menu', $fields ) ) + $_taxonomy['show_in_menu'] = (bool) $_taxonomy->show_in_menu; + + if ( in_array( 'object_type', $fields ) ) + $_taxonomy['object_type'] = array_unique( (array) $taxonomy->object_type ); + + return apply_filters( 'xmlrpc_prepare_taxonomy', $_taxonomy, $taxonomy, $fields ); + } + + /** + * Prepares term data for return in an XML-RPC object. + * + * @access protected + * + * @param array|object $term The unprepared term data + * @return array The prepared term data + */ + protected function _prepare_term( $term ) { + $_term = $term; + if ( ! is_array( $_term) ) + $_term = get_object_vars( $_term ); + + // For integers which may be larger than XML-RPC supports ensure we return strings. + $_term['term_id'] = strval( $_term['term_id'] ); + $_term['term_group'] = strval( $_term['term_group'] ); + $_term['term_taxonomy_id'] = strval( $_term['term_taxonomy_id'] ); + $_term['parent'] = strval( $_term['parent'] ); + + // Count we are happy to return as an integer because people really shouldn't use terms that much. + $_term['count'] = intval( $_term['count'] ); + + return apply_filters( 'xmlrpc_prepare_term', $_term, $term ); + } + + /** + * Convert a WordPress date string to an IXR_Date object. + * + * @access protected + * + * @param string $date + * @return IXR_Date + */ + protected function _convert_date( $date ) { + if ( $date === '0000-00-00 00:00:00' ) { + return new IXR_Date( '00000000T00:00:00Z' ); + } + return new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date, false ) ); + } + + /** + * Convert a WordPress GMT date string to an IXR_Date object. + * + * @access protected + * + * @param string $date_gmt + * @param string $date + * @return IXR_Date + */ + protected function _convert_date_gmt( $date_gmt, $date ) { + if ( $date !== '0000-00-00 00:00:00' && $date_gmt === '0000-00-00 00:00:00' ) { + return new IXR_Date( get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $date, false ), 'Ymd\TH:i:s' ) ); + } + return $this->_convert_date( $date_gmt ); + } + + /** + * Prepares post data for return in an XML-RPC object. + * + * @access protected + * + * @param array $post The unprepared post data + * @param array $fields The subset of post type fields to return + * @return array The prepared post data + */ + protected function _prepare_post( $post, $fields ) { + // holds the data for this post. built up based on $fields + $_post = array( 'post_id' => strval( $post['ID'] ) ); + + // prepare common post fields + $post_fields = array( + 'post_title' => $post['post_title'], + 'post_date' => $this->_convert_date( $post['post_date'] ), + 'post_date_gmt' => $this->_convert_date_gmt( $post['post_date_gmt'], $post['post_date'] ), + 'post_modified' => $this->_convert_date( $post['post_modified'] ), + 'post_modified_gmt' => $this->_convert_date_gmt( $post['post_modified_gmt'], $post['post_modified'] ), + 'post_status' => $post['post_status'], + 'post_type' => $post['post_type'], + 'post_name' => $post['post_name'], + 'post_author' => $post['post_author'], + 'post_password' => $post['post_password'], + 'post_excerpt' => $post['post_excerpt'], + 'post_content' => $post['post_content'], + 'post_parent' => strval( $post['post_parent'] ), + 'post_mime_type' => $post['post_mime_type'], + 'link' => post_permalink( $post['ID'] ), + 'guid' => $post['guid'], + 'menu_order' => intval( $post['menu_order'] ), + 'comment_status' => $post['comment_status'], + 'ping_status' => $post['ping_status'], + 'sticky' => ( $post['post_type'] === 'post' && is_sticky( $post['ID'] ) ), + ); + + // Thumbnail + $post_fields['post_thumbnail'] = array(); + $thumbnail_id = get_post_thumbnail_id( $post['ID'] ); + if ( $thumbnail_id ) { + $thumbnail_size = current_theme_supports('post-thumbnail') ? 'post-thumbnail' : 'thumbnail'; + $post_fields['post_thumbnail'] = $this->_prepare_media_item( get_post( $thumbnail_id ), $thumbnail_size ); + } + + // Consider future posts as published + if ( $post_fields['post_status'] === 'future' ) + $post_fields['post_status'] = 'publish'; + + // Fill in blank post format + $post_fields['post_format'] = get_post_format( $post['ID'] ); + if ( empty( $post_fields['post_format'] ) ) + $post_fields['post_format'] = 'standard'; + + // Merge requested $post_fields fields into $_post + if ( in_array( 'post', $fields ) ) { + $_post = array_merge( $_post, $post_fields ); + } else { + $requested_fields = array_intersect_key( $post_fields, array_flip( $fields ) ); + $_post = array_merge( $_post, $requested_fields ); + } + + $all_taxonomy_fields = in_array( 'taxonomies', $fields ); + + if ( $all_taxonomy_fields || in_array( 'terms', $fields ) ) { + $post_type_taxonomies = get_object_taxonomies( $post['post_type'], 'names' ); + $terms = wp_get_object_terms( $post['ID'], $post_type_taxonomies ); + $_post['terms'] = array(); + foreach ( $terms as $term ) { + $_post['terms'][] = $this->_prepare_term( $term ); + } + } + + if ( in_array( 'custom_fields', $fields ) ) + $_post['custom_fields'] = $this->get_custom_fields( $post['ID'] ); + + if ( in_array( 'enclosure', $fields ) ) { + $_post['enclosure'] = array(); + $enclosures = (array) get_post_meta( $post['ID'], 'enclosure' ); + if ( ! empty( $enclosures ) ) { + $encdata = explode( "\n", $enclosures[0] ); + $_post['enclosure']['url'] = trim( htmlspecialchars( $encdata[0] ) ); + $_post['enclosure']['length'] = (int) trim( $encdata[1] ); + $_post['enclosure']['type'] = trim( $encdata[2] ); + } + } + + return apply_filters( 'xmlrpc_prepare_post', $_post, $post, $fields ); + } + + /** + * Prepares post data for return in an XML-RPC object. + * + * @access protected + * + * @param object $post_type Post type object + * @param array $fields The subset of post fields to return + * @return array The prepared post type data + */ + protected function _prepare_post_type( $post_type, $fields ) { + $_post_type = array( + 'name' => $post_type->name, + 'label' => $post_type->label, + 'hierarchical' => (bool) $post_type->hierarchical, + 'public' => (bool) $post_type->public, + 'show_ui' => (bool) $post_type->show_ui, + '_builtin' => (bool) $post_type->_builtin, + 'has_archive' => (bool) $post_type->has_archive, + 'supports' => get_all_post_type_supports( $post_type->name ), + ); + + if ( in_array( 'labels', $fields ) ) { + $_post_type['labels'] = (array) $post_type->labels; + } + + if ( in_array( 'cap', $fields ) ) { + $_post_type['cap'] = (array) $post_type->cap; + $_post_type['map_meta_cap'] = (bool) $post_type->map_meta_cap; + } + + if ( in_array( 'menu', $fields ) ) { + $_post_type['menu_position'] = (int) $post_type->menu_position; + $_post_type['menu_icon'] = $post_type->menu_icon; + $_post_type['show_in_menu'] = (bool) $post_type->show_in_menu; + } + + if ( in_array( 'taxonomies', $fields ) ) + $_post_type['taxonomies'] = get_object_taxonomies( $post_type->name, 'names' ); + + return apply_filters( 'xmlrpc_prepare_post_type', $_post_type, $post_type ); + } + + /** + * Prepares media item data for return in an XML-RPC object. + * + * @access protected + * + * @param object $media_item The unprepared media item data + * @param string $thumbnail_size The image size to use for the thumbnail URL + * @return array The prepared media item data + */ + protected function _prepare_media_item( $media_item, $thumbnail_size = 'thumbnail' ) { + $_media_item = array( + 'attachment_id' => strval( $media_item->ID ), + 'date_created_gmt' => $this->_convert_date_gmt( $media_item->post_date_gmt, $media_item->post_date ), + 'parent' => $media_item->post_parent, + 'link' => wp_get_attachment_url( $media_item->ID ), + 'title' => $media_item->post_title, + 'caption' => $media_item->post_excerpt, + 'description' => $media_item->post_content, + 'metadata' => wp_get_attachment_metadata( $media_item->ID ), + ); + + $thumbnail_src = image_downsize( $media_item->ID, $thumbnail_size ); + if ( $thumbnail_src ) + $_media_item['thumbnail'] = $thumbnail_src[0]; + else + $_media_item['thumbnail'] = $_media_item['link']; + + return apply_filters( 'xmlrpc_prepare_media_item', $_media_item, $media_item, $thumbnail_size ); + } + + /** + * Prepares page data for return in an XML-RPC object. + * + * @access protected + * + * @param object $page The unprepared page data + * @return array The prepared page data + */ + protected function _prepare_page( $page ) { + // Get all of the page content and link. + $full_page = get_extended( $page->post_content ); + $link = post_permalink( $page->ID ); + + // Get info the page parent if there is one. + $parent_title = ""; + if ( ! empty( $page->post_parent ) ) { + $parent = get_post( $page->post_parent ); + $parent_title = $parent->post_title; + } + + // Determine comment and ping settings. + $allow_comments = comments_open( $page->ID ) ? 1 : 0; + $allow_pings = pings_open( $page->ID ) ? 1 : 0; + + // Format page date. + $page_date = $this->_convert_date( $page->post_date ); + $page_date_gmt = $this->_convert_date_gmt( $page->post_date_gmt, $page->post_date ); + + // Pull the categories info together. + $categories = array(); + foreach ( wp_get_post_categories( $page->ID ) as $cat_id ) { + $categories[] = get_cat_name( $cat_id ); + } + + // Get the author info. + $author = get_userdata( $page->post_author ); + + $page_template = get_page_template_slug( $page->ID ); + if ( empty( $page_template ) ) + $page_template = 'default'; + + $_page = array( + 'dateCreated' => $page_date, + 'userid' => $page->post_author, + 'page_id' => $page->ID, + 'page_status' => $page->post_status, + 'description' => $full_page['main'], + 'title' => $page->post_title, + 'link' => $link, + 'permaLink' => $link, + 'categories' => $categories, + 'excerpt' => $page->post_excerpt, + 'text_more' => $full_page['extended'], + 'mt_allow_comments' => $allow_comments, + 'mt_allow_pings' => $allow_pings, + 'wp_slug' => $page->post_name, + 'wp_password' => $page->post_password, + 'wp_author' => $author->display_name, + 'wp_page_parent_id' => $page->post_parent, + 'wp_page_parent_title' => $parent_title, + 'wp_page_order' => $page->menu_order, + 'wp_author_id' => (string) $author->ID, + 'wp_author_display_name' => $author->display_name, + 'date_created_gmt' => $page_date_gmt, + 'custom_fields' => $this->get_custom_fields( $page->ID ), + 'wp_page_template' => $page_template + ); + + return apply_filters( 'xmlrpc_prepare_page', $_page, $page ); + } + + /** + * Prepares comment data for return in an XML-RPC object. + * + * @access protected + * + * @param object $comment The unprepared comment data + * @return array The prepared comment data + */ + protected function _prepare_comment( $comment ) { + // Format page date. + $comment_date = $this->_convert_date( $comment->comment_date ); + $comment_date_gmt = $this->_convert_date_gmt( $comment->comment_date_gmt, $comment->comment_date ); + + if ( '0' == $comment->comment_approved ) + $comment_status = 'hold'; + else if ( 'spam' == $comment->comment_approved ) + $comment_status = 'spam'; + else if ( '1' == $comment->comment_approved ) + $comment_status = 'approve'; + else + $comment_status = $comment->comment_approved; + + $_comment = array( + 'date_created_gmt' => $comment_date_gmt, + 'user_id' => $comment->user_id, + 'comment_id' => $comment->comment_ID, + 'parent' => $comment->comment_parent, + 'status' => $comment_status, + 'content' => $comment->comment_content, + 'link' => get_comment_link($comment), + 'post_id' => $comment->comment_post_ID, + 'post_title' => get_the_title($comment->comment_post_ID), + 'author' => $comment->comment_author, + 'author_url' => $comment->comment_author_url, + 'author_email' => $comment->comment_author_email, + 'author_ip' => $comment->comment_author_IP, + 'type' => $comment->comment_type, + ); + + return apply_filters( 'xmlrpc_prepare_comment', $_comment, $comment ); + } + + /** + * Prepares user data for return in an XML-RPC object. + * + * @access protected + * + * @param WP_User $user The unprepared user object + * @param array $fields The subset of user fields to return + * @return array The prepared user data + */ + protected function _prepare_user( $user, $fields ) { + $_user = array( 'user_id' => strval( $user->ID ) ); + + $user_fields = array( + 'username' => $user->user_login, + 'first_name' => $user->user_firstname, + 'last_name' => $user->user_lastname, + 'registered' => $this->_convert_date( $user->user_registered ), + 'bio' => $user->user_description, + 'email' => $user->user_email, + 'nickname' => $user->nickname, + 'nicename' => $user->user_nicename, + 'url' => $user->user_url, + 'display_name' => $user->display_name, + 'roles' => $user->roles, + ); + + if ( in_array( 'all', $fields ) ) { + $_user = array_merge( $_user, $user_fields ); + } else { + if ( in_array( 'basic', $fields ) ) { + $basic_fields = array( 'username', 'email', 'registered', 'display_name', 'nicename' ); + $fields = array_merge( $fields, $basic_fields ); + } + $requested_fields = array_intersect_key( $user_fields, array_flip( $fields ) ); + $_user = array_merge( $_user, $requested_fields ); + } + + return apply_filters( 'xmlrpc_prepare_user', $_user, $user, $fields ); + } + + /** + * Create a new post for any registered post type. + * + * @since 3.4.0 + * + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $content_struct + * $content_struct can contain: + * - post_type (default: 'post') + * - post_status (default: 'draft') + * - post_title + * - post_author + * - post_excerpt + * - post_content + * - post_date_gmt | post_date + * - post_format + * - post_password + * - comment_status - can be 'open' | 'closed' + * - ping_status - can be 'open' | 'closed' + * - sticky + * - post_thumbnail - ID of a media item to use as the post thumbnail/featured image + * - custom_fields - array, with each element containing 'key' and 'value' + * - terms - array, with taxonomy names as keys and arrays of term IDs as values + * - terms_names - array, with taxonomy names as keys and arrays of term names as values + * - enclosure + * - any other fields supported by wp_insert_post() + * @return string post_id + */ + function wp_newPost( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $content_struct = $args[3]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.newPost' ); + + unset( $content_struct['ID'] ); + + return $this->_insert_post( $user, $content_struct ); + } + + /** + * Helper method for filtering out elements from an array. + * + * @since 3.4.0 + * + * @param int $count Number to compare to one. + */ + private function _is_greater_than_one( $count ) { + return $count > 1; + } + + /** + * Helper method for wp_newPost and wp_editPost, containing shared logic. + * + * @since 3.4.0 + * @uses wp_insert_post() + * + * @param WP_User $user The post author if post_author isn't set in $content_struct. + * @param array $content_struct Post data to insert. + */ + protected function _insert_post( $user, $content_struct ) { + $defaults = array( 'post_status' => 'draft', 'post_type' => 'post', 'post_author' => 0, + 'post_password' => '', 'post_excerpt' => '', 'post_content' => '', 'post_title' => '' ); + + $post_data = wp_parse_args( $content_struct, $defaults ); + + $post_type = get_post_type_object( $post_data['post_type'] ); + if ( ! $post_type ) + return new IXR_Error( 403, __( 'Invalid post type' ) ); + + $update = ! empty( $post_data['ID'] ); + + if ( $update ) { + if ( ! get_post( $post_data['ID'] ) ) + return new IXR_Error( 401, __( 'Invalid post ID.' ) ); + if ( ! current_user_can( 'edit_post', $post_data['ID'] ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post.' ) ); + if ( $post_data['post_type'] != get_post_type( $post_data['ID'] ) ) + return new IXR_Error( 401, __( 'The post type may not be changed.' ) ); + } else { + if ( ! current_user_can( $post_type->cap->create_posts ) || ! current_user_can( $post_type->cap->edit_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to post on this site.' ) ); + } + + switch ( $post_data['post_status'] ) { + case 'draft': + case 'pending': + break; + case 'private': + if ( ! current_user_can( $post_type->cap->publish_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to create private posts in this post type' ) ); + break; + case 'publish': + case 'future': + if ( ! current_user_can( $post_type->cap->publish_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish posts in this post type' ) ); + break; + default: + if ( ! get_post_status_object( $post_data['post_status'] ) ) + $post_data['post_status'] = 'draft'; + break; + } + + if ( ! empty( $post_data['post_password'] ) && ! current_user_can( $post_type->cap->publish_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to create password protected posts in this post type' ) ); + + $post_data['post_author'] = absint( $post_data['post_author'] ); + if ( ! empty( $post_data['post_author'] ) && $post_data['post_author'] != $user->ID ) { + if ( ! current_user_can( $post_type->cap->edit_others_posts ) ) + return new IXR_Error( 401, __( 'You are not allowed to create posts as this user.' ) ); + + $author = get_userdata( $post_data['post_author'] ); + + if ( ! $author ) + return new IXR_Error( 404, __( 'Invalid author ID.' ) ); + } else { + $post_data['post_author'] = $user->ID; + } + + if ( isset( $post_data['comment_status'] ) && $post_data['comment_status'] != 'open' && $post_data['comment_status'] != 'closed' ) + unset( $post_data['comment_status'] ); + + if ( isset( $post_data['ping_status'] ) && $post_data['ping_status'] != 'open' && $post_data['ping_status'] != 'closed' ) + unset( $post_data['ping_status'] ); + + // Do some timestamp voodoo + if ( ! empty( $post_data['post_date_gmt'] ) ) { + // We know this is supposed to be GMT, so we're going to slap that Z on there by force + $dateCreated = rtrim( $post_data['post_date_gmt']->getIso(), 'Z' ) . 'Z'; + } elseif ( ! empty( $post_data['post_date'] ) ) { + $dateCreated = $post_data['post_date']->getIso(); + } + + if ( ! empty( $dateCreated ) ) { + $post_data['post_date'] = get_date_from_gmt( iso8601_to_datetime( $dateCreated ) ); + $post_data['post_date_gmt'] = iso8601_to_datetime( $dateCreated, 'GMT' ); + } + + if ( ! isset( $post_data['ID'] ) ) + $post_data['ID'] = get_default_post_to_edit( $post_data['post_type'], true )->ID; + $post_ID = $post_data['ID']; + + if ( $post_data['post_type'] == 'post' ) { + // Private and password-protected posts cannot be stickied. + if ( $post_data['post_status'] == 'private' || ! empty( $post_data['post_password'] ) ) { + // Error if the client tried to stick the post, otherwise, silently unstick. + if ( ! empty( $post_data['sticky'] ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot stick a private post.' ) ); + if ( $update ) + unstick_post( $post_ID ); + } elseif ( isset( $post_data['sticky'] ) ) { + if ( ! current_user_can( $post_type->cap->edit_others_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to stick this post.' ) ); + if ( $post_data['sticky'] ) + stick_post( $post_ID ); + else + unstick_post( $post_ID ); + } + } + + if ( isset( $post_data['post_thumbnail'] ) ) { + // empty value deletes, non-empty value adds/updates + if ( ! $post_data['post_thumbnail'] ) + delete_post_thumbnail( $post_ID ); + elseif ( ! get_post( absint( $post_data['post_thumbnail'] ) ) ) + return new IXR_Error( 404, __( 'Invalid attachment ID.' ) ); + set_post_thumbnail( $post_ID, $post_data['post_thumbnail'] ); + unset( $content_struct['post_thumbnail'] ); + } + + if ( isset( $post_data['custom_fields'] ) ) + $this->set_custom_fields( $post_ID, $post_data['custom_fields'] ); + + if ( isset( $post_data['terms'] ) || isset( $post_data['terms_names'] ) ) { + $post_type_taxonomies = get_object_taxonomies( $post_data['post_type'], 'objects' ); + + // accumulate term IDs from terms and terms_names + $terms = array(); + + // first validate the terms specified by ID + if ( isset( $post_data['terms'] ) && is_array( $post_data['terms'] ) ) { + $taxonomies = array_keys( $post_data['terms'] ); + + // validating term ids + foreach ( $taxonomies as $taxonomy ) { + if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) ) + return new IXR_Error( 401, __( 'Sorry, one of the given taxonomies is not supported by the post type.' ) ); + + if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign a term to one of the given taxonomies.' ) ); + + $term_ids = $post_data['terms'][$taxonomy]; + foreach ( $term_ids as $term_id ) { + $term = get_term_by( 'id', $term_id, $taxonomy ); + + if ( ! $term ) + return new IXR_Error( 403, __( 'Invalid term ID' ) ); + + $terms[$taxonomy][] = (int) $term_id; + } + } + } + + // now validate terms specified by name + if ( isset( $post_data['terms_names'] ) && is_array( $post_data['terms_names'] ) ) { + $taxonomies = array_keys( $post_data['terms_names'] ); + + foreach ( $taxonomies as $taxonomy ) { + if ( ! array_key_exists( $taxonomy , $post_type_taxonomies ) ) + return new IXR_Error( 401, __( 'Sorry, one of the given taxonomies is not supported by the post type.' ) ); + + if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->assign_terms ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to assign a term to one of the given taxonomies.' ) ); + + // for hierarchical taxonomies, we can't assign a term when multiple terms in the hierarchy share the same name + $ambiguous_terms = array(); + if ( is_taxonomy_hierarchical( $taxonomy ) ) { + $tax_term_names = get_terms( $taxonomy, array( 'fields' => 'names', 'hide_empty' => false ) ); + + // count the number of terms with the same name + $tax_term_names_count = array_count_values( $tax_term_names ); + + // filter out non-ambiguous term names + $ambiguous_tax_term_counts = array_filter( $tax_term_names_count, array( $this, '_is_greater_than_one') ); + + $ambiguous_terms = array_keys( $ambiguous_tax_term_counts ); + } + + $term_names = $post_data['terms_names'][$taxonomy]; + foreach ( $term_names as $term_name ) { + if ( in_array( $term_name, $ambiguous_terms ) ) + return new IXR_Error( 401, __( 'Ambiguous term name used in a hierarchical taxonomy. Please use term ID instead.' ) ); + + $term = get_term_by( 'name', $term_name, $taxonomy ); + + if ( ! $term ) { + // term doesn't exist, so check that the user is allowed to create new terms + if ( ! current_user_can( $post_type_taxonomies[$taxonomy]->cap->edit_terms ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to add a term to one of the given taxonomies.' ) ); + + // create the new term + $term_info = wp_insert_term( $term_name, $taxonomy ); + if ( is_wp_error( $term_info ) ) + return new IXR_Error( 500, $term_info->get_error_message() ); + + $terms[$taxonomy][] = (int) $term_info['term_id']; + } else { + $terms[$taxonomy][] = (int) $term->term_id; + } + } + } + } + + $post_data['tax_input'] = $terms; + unset( $post_data['terms'], $post_data['terms_names'] ); + } else { + // do not allow direct submission of 'tax_input', clients must use 'terms' and/or 'terms_names' + unset( $post_data['tax_input'], $post_data['post_category'], $post_data['tags_input'] ); + } + + if ( isset( $post_data['post_format'] ) ) { + $format = set_post_format( $post_ID, $post_data['post_format'] ); + + if ( is_wp_error( $format ) ) + return new IXR_Error( 500, $format->get_error_message() ); + + unset( $post_data['post_format'] ); + } + + // Handle enclosures + $enclosure = isset( $post_data['enclosure'] ) ? $post_data['enclosure'] : null; + $this->add_enclosure_if_new( $post_ID, $enclosure ); + + $this->attach_uploads( $post_ID, $post_data['post_content'] ); + + $post_data = apply_filters( 'xmlrpc_wp_insert_post_data', $post_data, $content_struct ); + + $post_ID = $update ? wp_update_post( $post_data, true ) : wp_insert_post( $post_data, true ); + if ( is_wp_error( $post_ID ) ) + return new IXR_Error( 500, $post_ID->get_error_message() ); + + if ( ! $post_ID ) + return new IXR_Error( 401, __( 'Sorry, your entry could not be posted. Something wrong happened.' ) ); + + return strval( $post_ID ); + } + + /** + * Edit a post for any registered post type. + * + * The $content_struct parameter only needs to contain fields that + * should be changed. All other fields will retain their existing values. + * + * @since 3.4.0 + * + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - int $post_id + * - array $content_struct + * @return true on success + */ + function wp_editPost( $args ) { + if ( ! $this->minimum_args( $args, 5 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post_id = (int) $args[3]; + $content_struct = $args[4]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.editPost' ); + + $post = get_post( $post_id, ARRAY_A ); + + if ( empty( $post['ID'] ) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( isset( $content_struct['if_not_modified_since'] ) ) { + // If the post has been modified since the date provided, return an error. + if ( mysql2date( 'U', $post['post_modified_gmt'] ) > $content_struct['if_not_modified_since']->getTimestamp() ) { + return new IXR_Error( 409, __( 'There is a revision of this post that is more recent.' ) ); + } + } + + // convert the date field back to IXR form + $post['post_date'] = $this->_convert_date( $post['post_date'] ); + + // ignore the existing GMT date if it is empty or a non-GMT date was supplied in $content_struct, + // since _insert_post will ignore the non-GMT date if the GMT date is set + if ( $post['post_date_gmt'] == '0000-00-00 00:00:00' || isset( $content_struct['post_date'] ) ) + unset( $post['post_date_gmt'] ); + else + $post['post_date_gmt'] = $this->_convert_date( $post['post_date_gmt'] ); + + $this->escape( $post ); + $merged_content_struct = array_merge( $post, $content_struct ); + + $retval = $this->_insert_post( $user, $merged_content_struct ); + if ( $retval instanceof IXR_Error ) + return $retval; + + return true; + } + + /** + * Delete a post for any registered post type. + * + * @since 3.4.0 + * + * @uses wp_delete_post() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - int $post_id + * @return true on success + */ + function wp_deletePost( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post_id = (int) $args[3]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.deletePost' ); + + $post = get_post( $post_id, ARRAY_A ); + if ( empty( $post['ID'] ) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( ! current_user_can( 'delete_post', $post_id ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to delete this post.' ) ); + + $result = wp_delete_post( $post_id ); + + if ( ! $result ) + return new IXR_Error( 500, __( 'The post cannot be deleted.' ) ); + + return true; + } + + /** + * Retrieve a post. + * + * @since 3.4.0 + * + * The optional $fields parameter specifies what fields will be included + * in the response array. This should be a list of field names. 'post_id' will + * always be included in the response regardless of the value of $fields. + * + * Instead of, or in addition to, individual field names, conceptual group + * names can be used to specify multiple fields. The available conceptual + * groups are 'post' (all basic fields), 'taxonomies', 'custom_fields', + * and 'enclosure'. + * + * @uses get_post() + * @param array $args Method parameters. Contains: + * - int $post_id + * - string $username + * - string $password + * - array $fields optional + * @return array contains (based on $fields parameter): + * - 'post_id' + * - 'post_title' + * - 'post_date' + * - 'post_date_gmt' + * - 'post_modified' + * - 'post_modified_gmt' + * - 'post_status' + * - 'post_type' + * - 'post_name' + * - 'post_author' + * - 'post_password' + * - 'post_excerpt' + * - 'post_content' + * - 'link' + * - 'comment_status' + * - 'ping_status' + * - 'sticky' + * - 'custom_fields' + * - 'terms' + * - 'categories' + * - 'tags' + * - 'enclosure' + */ + function wp_getPost( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post_id = (int) $args[3]; + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPost' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getPost' ); + + $post = get_post( $post_id, ARRAY_A ); + + if ( empty( $post['ID'] ) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( ! current_user_can( 'edit_post', $post_id ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); + + return $this->_prepare_post( $post, $fields ); + } + + /** + * Retrieve posts. + * + * @since 3.4.0 + * + * The optional $filter parameter modifies the query used to retrieve posts. + * Accepted keys are 'post_type', 'post_status', 'number', 'offset', + * 'orderby', and 'order'. + * + * The optional $fields parameter specifies what fields will be included + * in the response array. + * + * @uses wp_get_recent_posts() + * @see wp_getPost() for more on $fields + * @see get_posts() for more on $filter values + * + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $filter optional + * - array $fields optional + * @return array contains a collection of posts. + */ + function wp_getPosts( $args ) { + if ( ! $this->minimum_args( $args, 3 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $filter = isset( $args[3] ) ? $args[3] : array(); + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_post_fields', array( 'post', 'terms', 'custom_fields' ), 'wp.getPosts' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getPosts' ); + + $query = array(); + + if ( isset( $filter['post_type'] ) ) { + $post_type = get_post_type_object( $filter['post_type'] ); + if ( ! ( (bool) $post_type ) ) + return new IXR_Error( 403, __( 'The post type specified is not valid' ) ); + } else { + $post_type = get_post_type_object( 'post' ); + } + + if ( ! current_user_can( $post_type->cap->edit_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts in this post type' )); + + $query['post_type'] = $post_type->name; + + if ( isset( $filter['post_status'] ) ) + $query['post_status'] = $filter['post_status']; + + if ( isset( $filter['number'] ) ) + $query['numberposts'] = absint( $filter['number'] ); + + if ( isset( $filter['offset'] ) ) + $query['offset'] = absint( $filter['offset'] ); + + if ( isset( $filter['orderby'] ) ) { + $query['orderby'] = $filter['orderby']; + + if ( isset( $filter['order'] ) ) + $query['order'] = $filter['order']; + } + + if ( isset( $filter['s'] ) ) { + $query['s'] = $filter['s']; + } + + $posts_list = wp_get_recent_posts( $query ); + + if ( ! $posts_list ) + return array(); + + // holds all the posts data + $struct = array(); + + foreach ( $posts_list as $post ) { + if ( ! current_user_can( 'edit_post', $post['ID'] ) ) + continue; + + $struct[] = $this->_prepare_post( $post, $fields ); + } + + return $struct; + } + + /** + * Create a new term. + * + * @since 3.4.0 + * + * @uses wp_insert_term() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $content_struct + * The $content_struct must contain: + * - 'name' + * - 'taxonomy' + * Also, it can optionally contain: + * - 'parent' + * - 'description' + * - 'slug' + * @return string term_id + */ + function wp_newTerm( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $content_struct = $args[3]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.newTerm' ); + + if ( ! taxonomy_exists( $content_struct['taxonomy'] ) ) + return new IXR_Error( 403, __( 'Invalid taxonomy' ) ); + + $taxonomy = get_taxonomy( $content_struct['taxonomy'] ); + + if ( ! current_user_can( $taxonomy->cap->manage_terms ) ) + return new IXR_Error( 401, __( 'You are not allowed to create terms in this taxonomy.' ) ); + + $taxonomy = (array) $taxonomy; + + // hold the data of the term + $term_data = array(); + + $term_data['name'] = trim( $content_struct['name'] ); + if ( empty( $term_data['name'] ) ) + return new IXR_Error( 403, __( 'The term name cannot be empty.' ) ); + + if ( isset( $content_struct['parent'] ) ) { + if ( ! $taxonomy['hierarchical'] ) + return new IXR_Error( 403, __( 'This taxonomy is not hierarchical.' ) ); + + $parent_term_id = (int) $content_struct['parent']; + $parent_term = get_term( $parent_term_id , $taxonomy['name'] ); + + if ( is_wp_error( $parent_term ) ) + return new IXR_Error( 500, $parent_term->get_error_message() ); + + if ( ! $parent_term ) + return new IXR_Error( 403, __( 'Parent term does not exist.' ) ); + + $term_data['parent'] = $content_struct['parent']; + } + + if ( isset( $content_struct['description'] ) ) + $term_data['description'] = $content_struct['description']; + + if ( isset( $content_struct['slug'] ) ) + $term_data['slug'] = $content_struct['slug']; + + $term = wp_insert_term( $term_data['name'] , $taxonomy['name'] , $term_data ); + + if ( is_wp_error( $term ) ) + return new IXR_Error( 500, $term->get_error_message() ); + + if ( ! $term ) + return new IXR_Error( 500, __( 'Sorry, your term could not be created. Something wrong happened.' ) ); + + return strval( $term['term_id'] ); + } + + /** + * Edit a term. + * + * @since 3.4.0 + * + * @uses wp_update_term() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - string $term_id + * - array $content_struct + * The $content_struct must contain: + * - 'taxonomy' + * Also, it can optionally contain: + * - 'name' + * - 'parent' + * - 'description' + * - 'slug' + * @return bool True, on success. + */ + function wp_editTerm( $args ) { + if ( ! $this->minimum_args( $args, 5 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $term_id = (int) $args[3]; + $content_struct = $args[4]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.editTerm' ); + + if ( ! taxonomy_exists( $content_struct['taxonomy'] ) ) + return new IXR_Error( 403, __( 'Invalid taxonomy' ) ); + + $taxonomy = get_taxonomy( $content_struct['taxonomy'] ); + + if ( ! current_user_can( $taxonomy->cap->edit_terms ) ) + return new IXR_Error( 401, __( 'You are not allowed to edit terms in this taxonomy.' ) ); + + $taxonomy = (array) $taxonomy; + + // hold the data of the term + $term_data = array(); + + $term = get_term( $term_id , $content_struct['taxonomy'] ); + + if ( is_wp_error( $term ) ) + return new IXR_Error( 500, $term->get_error_message() ); + + if ( ! $term ) + return new IXR_Error( 404, __( 'Invalid term ID' ) ); + + if ( isset( $content_struct['name'] ) ) { + $term_data['name'] = trim( $content_struct['name'] ); + + if ( empty( $term_data['name'] ) ) + return new IXR_Error( 403, __( 'The term name cannot be empty.' ) ); + } + + if ( isset( $content_struct['parent'] ) ) { + if ( ! $taxonomy['hierarchical'] ) + return new IXR_Error( 403, __( "This taxonomy is not hierarchical so you can't set a parent." ) ); + + $parent_term_id = (int) $content_struct['parent']; + $parent_term = get_term( $parent_term_id , $taxonomy['name'] ); + + if ( is_wp_error( $parent_term ) ) + return new IXR_Error( 500, $parent_term->get_error_message() ); + + if ( ! $parent_term ) + return new IXR_Error( 403, __( 'Parent term does not exist.' ) ); + + $term_data['parent'] = $content_struct['parent']; + } + + if ( isset( $content_struct['description'] ) ) + $term_data['description'] = $content_struct['description']; + + if ( isset( $content_struct['slug'] ) ) + $term_data['slug'] = $content_struct['slug']; + + $term = wp_update_term( $term_id , $taxonomy['name'] , $term_data ); + + if ( is_wp_error( $term ) ) + return new IXR_Error( 500, $term->get_error_message() ); + + if ( ! $term ) + return new IXR_Error( 500, __( 'Sorry, editing the term failed.' ) ); + + return true; + } + + /** + * Delete a term. + * + * @since 3.4.0 + * + * @uses wp_delete_term() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - string $taxnomy_name + * - string $term_id + * @return boolean|IXR_Error If it suceeded true else a reason why not + */ + function wp_deleteTerm( $args ) { + if ( ! $this->minimum_args( $args, 5 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $taxonomy = $args[3]; + $term_id = (int) $args[4]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.deleteTerm' ); + + if ( ! taxonomy_exists( $taxonomy ) ) + return new IXR_Error( 403, __( 'Invalid taxonomy' ) ); + + $taxonomy = get_taxonomy( $taxonomy ); + + if ( ! current_user_can( $taxonomy->cap->delete_terms ) ) + return new IXR_Error( 401, __( 'You are not allowed to delete terms in this taxonomy.' ) ); + + $term = get_term( $term_id, $taxonomy->name ); + + if ( is_wp_error( $term ) ) + return new IXR_Error( 500, $term->get_error_message() ); + + if ( ! $term ) + return new IXR_Error( 404, __( 'Invalid term ID' ) ); + + $result = wp_delete_term( $term_id, $taxonomy->name ); + + if ( is_wp_error( $result ) ) + return new IXR_Error( 500, $term->get_error_message() ); + + if ( ! $result ) + return new IXR_Error( 500, __( 'Sorry, deleting the term failed.' ) ); + + return $result; + } + + /** + * Retrieve a term. + * + * @since 3.4.0 + * + * @uses get_term() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - string $taxonomy + * - string $term_id + * @return array contains: + * - 'term_id' + * - 'name' + * - 'slug' + * - 'term_group' + * - 'term_taxonomy_id' + * - 'taxonomy' + * - 'description' + * - 'parent' + * - 'count' + */ + function wp_getTerm( $args ) { + if ( ! $this->minimum_args( $args, 5 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $taxonomy = $args[3]; + $term_id = (int) $args[4]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getTerm' ); + + if ( ! taxonomy_exists( $taxonomy ) ) + return new IXR_Error( 403, __( 'Invalid taxonomy' ) ); + + $taxonomy = get_taxonomy( $taxonomy ); + + if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) + return new IXR_Error( 401, __( 'You are not allowed to assign terms in this taxonomy.' ) ); + + $term = get_term( $term_id , $taxonomy->name, ARRAY_A ); + + if ( is_wp_error( $term ) ) + return new IXR_Error( 500, $term->get_error_message() ); + + if ( ! $term ) + return new IXR_Error( 404, __( 'Invalid term ID' ) ); + + return $this->_prepare_term( $term ); + } + + /** + * Retrieve all terms for a taxonomy. + * + * @since 3.4.0 + * + * The optional $filter parameter modifies the query used to retrieve terms. + * Accepted keys are 'number', 'offset', 'orderby', 'order', 'hide_empty', and 'search'. + * + * @uses get_terms() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - string $taxonomy + * - array $filter optional + * @return array terms + */ + function wp_getTerms( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $taxonomy = $args[3]; + $filter = isset( $args[4] ) ? $args[4] : array(); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getTerms' ); + + if ( ! taxonomy_exists( $taxonomy ) ) + return new IXR_Error( 403, __( 'Invalid taxonomy' ) ); + + $taxonomy = get_taxonomy( $taxonomy ); + + if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) + return new IXR_Error( 401, __( 'You are not allowed to assign terms in this taxonomy.' ) ); + + $query = array(); + + if ( isset( $filter['number'] ) ) + $query['number'] = absint( $filter['number'] ); + + if ( isset( $filter['offset'] ) ) + $query['offset'] = absint( $filter['offset'] ); + + if ( isset( $filter['orderby'] ) ) { + $query['orderby'] = $filter['orderby']; + + if ( isset( $filter['order'] ) ) + $query['order'] = $filter['order']; + } + + if ( isset( $filter['hide_empty'] ) ) + $query['hide_empty'] = $filter['hide_empty']; + else + $query['get'] = 'all'; + + if ( isset( $filter['search'] ) ) + $query['search'] = $filter['search']; + + $terms = get_terms( $taxonomy->name, $query ); + + if ( is_wp_error( $terms ) ) + return new IXR_Error( 500, $terms->get_error_message() ); + + $struct = array(); + + foreach ( $terms as $term ) { + $struct[] = $this->_prepare_term( $term ); + } + + return $struct; + } + + /** + * Retrieve a taxonomy. + * + * @since 3.4.0 + * + * @uses get_taxonomy() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - string $taxonomy + * @return array (@see get_taxonomy()) + */ + function wp_getTaxonomy( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $taxonomy = $args[3]; + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_taxonomy_fields', array( 'labels', 'cap', 'object_type' ), 'wp.getTaxonomy' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getTaxonomy' ); + + if ( ! taxonomy_exists( $taxonomy ) ) + return new IXR_Error( 403, __( 'Invalid taxonomy' ) ); + + $taxonomy = get_taxonomy( $taxonomy ); + + if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) + return new IXR_Error( 401, __( 'You are not allowed to assign terms in this taxonomy.' ) ); + + return $this->_prepare_taxonomy( $taxonomy, $fields ); + } + + /** + * Retrieve all taxonomies. + * + * @since 3.4.0 + * + * @uses get_taxonomies() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * @return array taxonomies + */ + function wp_getTaxonomies( $args ) { + if ( ! $this->minimum_args( $args, 3 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $filter = isset( $args[3] ) ? $args[3] : array( 'public' => true ); + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_taxonomy_fields', array( 'labels', 'cap', 'object_type' ), 'wp.getTaxonomies' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getTaxonomies' ); + + $taxonomies = get_taxonomies( $filter, 'objects' ); + + // holds all the taxonomy data + $struct = array(); + + foreach ( $taxonomies as $taxonomy ) { + // capability check for post_types + if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) + continue; + + $struct[] = $this->_prepare_taxonomy( $taxonomy, $fields ); + } + + return $struct; + } + + /** + * Retrieve a user. + * + * The optional $fields parameter specifies what fields will be included + * in the response array. This should be a list of field names. 'user_id' will + * always be included in the response regardless of the value of $fields. + * + * Instead of, or in addition to, individual field names, conceptual group + * names can be used to specify multiple fields. The available conceptual + * groups are 'basic' and 'all'. + * + * @uses get_userdata() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - int $user_id + * - array $fields optional + * @return array contains (based on $fields parameter): + * - 'user_id' + * - 'username' + * - 'first_name' + * - 'last_name' + * - 'registered' + * - 'bio' + * - 'email' + * - 'nickname' + * - 'nicename' + * - 'url' + * - 'display_name' + * - 'roles' + */ + function wp_getUser( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $user_id = (int) $args[3]; + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_user_fields', array( 'all' ), 'wp.getUser' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getUser' ); + + if ( ! current_user_can( 'edit_user', $user_id ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit users.' ) ); + + $user_data = get_userdata( $user_id ); + + if ( ! $user_data ) + return new IXR_Error( 404, __( 'Invalid user ID' ) ); + + return $this->_prepare_user( $user_data, $fields ); + } + + /** + * Retrieve users. + * + * The optional $filter parameter modifies the query used to retrieve users. + * Accepted keys are 'number' (default: 50), 'offset' (default: 0), 'role', + * 'who', 'orderby', and 'order'. + * + * The optional $fields parameter specifies what fields will be included + * in the response array. + * + * @uses get_users() + * @see wp_getUser() for more on $fields and return values + * + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $filter optional + * - array $fields optional + * @return array users data + */ + function wp_getUsers( $args ) { + if ( ! $this->minimum_args( $args, 3 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $filter = isset( $args[3] ) ? $args[3] : array(); + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_user_fields', array( 'all' ), 'wp.getUsers' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getUsers' ); + + if ( ! current_user_can( 'list_users' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot list users.' ) ); + + $query = array( 'fields' => 'all_with_meta' ); + + $query['number'] = ( isset( $filter['number'] ) ) ? absint( $filter['number'] ) : 50; + $query['offset'] = ( isset( $filter['offset'] ) ) ? absint( $filter['offset'] ) : 0; + + if ( isset( $filter['orderby'] ) ) { + $query['orderby'] = $filter['orderby']; + + if ( isset( $filter['order'] ) ) + $query['order'] = $filter['order']; + } + + if ( isset( $filter['role'] ) ) { + if ( get_role( $filter['role'] ) === null ) + return new IXR_Error( 403, __( 'The role specified is not valid' ) ); + + $query['role'] = $filter['role']; + } + + if ( isset( $filter['who'] ) ) { + $query['who'] = $filter['who']; + } + + $users = get_users( $query ); + + $_users = array(); + foreach ( $users as $user_data ) { + if ( current_user_can( 'edit_user', $user_data->ID ) ) + $_users[] = $this->_prepare_user( $user_data, $fields ); + } + return $_users; + } + + /** + * Retrieve information about the requesting user. + * + * @uses get_userdata() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $fields optional + * @return array (@see wp_getUser) + */ + function wp_getProfile( $args ) { + if ( ! $this->minimum_args( $args, 3 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( isset( $args[3] ) ) + $fields = $args[3]; + else + $fields = apply_filters( 'xmlrpc_default_user_fields', array( 'all' ), 'wp.getProfile' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getProfile' ); + + if ( ! current_user_can( 'edit_user', $user->ID ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit your profile.' ) ); + + $user_data = get_userdata( $user->ID ); + + return $this->_prepare_user( $user_data, $fields ); + } + + /** + * Edit user's profile. + * + * @uses wp_update_user() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $content_struct + * It can optionally contain: + * - 'first_name' + * - 'last_name' + * - 'website' + * - 'display_name' + * - 'nickname' + * - 'nicename' + * - 'bio' + * @return bool True, on success. + */ + function wp_editProfile( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $content_struct = $args[3]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.editProfile' ); + + if ( ! current_user_can( 'edit_user', $user->ID ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit your profile.' ) ); + + // holds data of the user + $user_data = array(); + $user_data['ID'] = $user->ID; + + // only set the user details if it was given + if ( isset( $content_struct['first_name'] ) ) + $user_data['first_name'] = $content_struct['first_name']; + + if ( isset( $content_struct['last_name'] ) ) + $user_data['last_name'] = $content_struct['last_name']; + + if ( isset( $content_struct['url'] ) ) + $user_data['user_url'] = $content_struct['url']; + + if ( isset( $content_struct['display_name'] ) ) + $user_data['display_name'] = $content_struct['display_name']; + + if ( isset( $content_struct['nickname'] ) ) + $user_data['nickname'] = $content_struct['nickname']; + + if ( isset( $content_struct['nicename'] ) ) + $user_data['user_nicename'] = $content_struct['nicename']; + + if ( isset( $content_struct['bio'] ) ) + $user_data['description'] = $content_struct['bio']; + + $result = wp_update_user( $user_data ); + + if ( is_wp_error( $result ) ) + return new IXR_Error( 500, $result->get_error_message() ); + + if ( ! $result ) + return new IXR_Error( 500, __( 'Sorry, the user cannot be updated.' ) ); + + return true; + } + + /** + * Retrieve page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - page_id + * - username + * - password + * @return array + */ + function wp_getPage($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $page_id = (int) $args[1]; + $username = $args[2]; + $password = $args[3]; + + if ( !$user = $this->login($username, $password) ) { + return $this->error; + } + + $page = get_post($page_id); + if ( ! $page ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( !current_user_can( 'edit_page', $page_id ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit this page.' ) ); + + do_action('xmlrpc_call', 'wp.getPage'); + + // If we found the page then format the data. + if ( $page->ID && ($page->post_type == 'page') ) { + return $this->_prepare_page( $page ); + } + // If the page doesn't exist indicate that. + else { + return(new IXR_Error(404, __('Sorry, no such page.'))); + } + } + + /** + * Retrieve Pages. + * + * @since 2.2.0 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - username + * - password + * - num_pages + * @return array + */ + function wp_getPages($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $num_pages = isset($args[3]) ? (int) $args[3] : 10; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_pages' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) ); + + do_action('xmlrpc_call', 'wp.getPages'); + + $pages = get_posts( array('post_type' => 'page', 'post_status' => 'any', 'numberposts' => $num_pages) ); + $num_pages = count($pages); + + // If we have pages, put together their info. + if ( $num_pages >= 1 ) { + $pages_struct = array(); + + foreach ($pages as $page) { + if ( current_user_can( 'edit_page', $page->ID ) ) + $pages_struct[] = $this->_prepare_page( $page ); + } + + return($pages_struct); + } + // If no pages were found return an error. + else { + return(array()); + } + } + + /** + * Create new page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. See {@link wp_xmlrpc_server::mw_newPost()} + * @return unknown + */ + function wp_newPage($args) { + // Items not escaped here will be escaped in newPost. + $username = $this->escape($args[1]); + $password = $this->escape($args[2]); + $page = $args[3]; + $publish = $args[4]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'wp.newPage'); + + // Mark this as content for a page. + $args[3]["post_type"] = 'page'; + + // Let mw_newPost do all of the heavy lifting. + return($this->mw_newPost($args)); + } + + /** + * Delete page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return bool True, if success. + */ + function wp_deletePage($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $page_id = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'wp.deletePage'); + + // Get the current page based on the page_id and + // make sure it is a page and not a post. + $actual_page = get_post($page_id, ARRAY_A); + if ( !$actual_page || ($actual_page['post_type'] != 'page') ) + return(new IXR_Error(404, __('Sorry, no such page.'))); + + // Make sure the user can delete pages. + if ( !current_user_can('delete_page', $page_id) ) + return(new IXR_Error(401, __('Sorry, you do not have the right to delete this page.'))); + + // Attempt to delete the page. + $result = wp_delete_post($page_id); + if ( !$result ) + return(new IXR_Error(500, __('Failed to delete the page.'))); + + do_action( 'xmlrpc_call_success_wp_deletePage', $page_id, $args ); + + return(true); + } + + /** + * Edit page. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return unknown + */ + function wp_editPage($args) { + // Items not escaped here will be escaped in editPost. + $blog_id = (int) $args[0]; + $page_id = (int) $this->escape($args[1]); + $username = $this->escape($args[2]); + $password = $this->escape($args[3]); + $content = $args[4]; + $publish = $args[5]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'wp.editPage'); + + // Get the page data and make sure it is a page. + $actual_page = get_post($page_id, ARRAY_A); + if ( !$actual_page || ($actual_page['post_type'] != 'page') ) + return(new IXR_Error(404, __('Sorry, no such page.'))); + + // Make sure the user is allowed to edit pages. + if ( !current_user_can('edit_page', $page_id) ) + return(new IXR_Error(401, __('Sorry, you do not have the right to edit this page.'))); + + // Mark this as content for a page. + $content['post_type'] = 'page'; + + // Arrange args in the way mw_editPost understands. + $args = array( + $page_id, + $username, + $password, + $content, + $publish + ); + + // Let mw_editPost do all of the heavy lifting. + return($this->mw_editPost($args)); + } + + /** + * Retrieve page list. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return unknown + */ + function wp_getPageList($args) { + global $wpdb; + + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_pages' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit pages.' ) ); + + do_action('xmlrpc_call', 'wp.getPageList'); + + // Get list of pages ids and titles + $page_list = $wpdb->get_results(" + SELECT ID page_id, + post_title page_title, + post_parent page_parent_id, + post_date_gmt, + post_date, + post_status + FROM {$wpdb->posts} + WHERE post_type = 'page' + ORDER BY ID + "); + + // The date needs to be formatted properly. + $num_pages = count($page_list); + for ( $i = 0; $i < $num_pages; $i++ ) { + $page_list[$i]->dateCreated = $this->_convert_date( $page_list[$i]->post_date ); + $page_list[$i]->date_created_gmt = $this->_convert_date_gmt( $page_list[$i]->post_date_gmt, $page_list[$i]->post_date ); + + unset($page_list[$i]->post_date_gmt); + unset($page_list[$i]->post_date); + unset($page_list[$i]->post_status); + } + + return($page_list); + } + + /** + * Retrieve authors list. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getAuthors($args) { + + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can('edit_posts') ) + return(new IXR_Error(401, __('Sorry, you cannot edit posts on this site.'))); + + do_action('xmlrpc_call', 'wp.getAuthors'); + + $authors = array(); + foreach ( get_users( array( 'fields' => array('ID','user_login','display_name') ) ) as $user ) { + $authors[] = array( + 'user_id' => $user->ID, + 'user_login' => $user->user_login, + 'display_name' => $user->display_name + ); + } + + return $authors; + } + + /** + * Get list of all tags + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getTags( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view tags.' ) ); + + do_action( 'xmlrpc_call', 'wp.getKeywords' ); + + $tags = array(); + + if ( $all_tags = get_tags() ) { + foreach( (array) $all_tags as $tag ) { + $struct['tag_id'] = $tag->term_id; + $struct['name'] = $tag->name; + $struct['count'] = $tag->count; + $struct['slug'] = $tag->slug; + $struct['html_url'] = esc_html( get_tag_link( $tag->term_id ) ); + $struct['rss_url'] = esc_html( get_tag_feed_link( $tag->term_id ) ); + + $tags[] = $struct; + } + } + + return $tags; + } + + /** + * Create new category. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return int Category ID. + */ + function wp_newCategory($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $category = $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'wp.newCategory'); + + // Make sure the user is allowed to add a category. + if ( !current_user_can('manage_categories') ) + return(new IXR_Error(401, __('Sorry, you do not have the right to add a category.'))); + + // If no slug was provided make it empty so that + // WordPress will generate one. + if ( empty($category['slug']) ) + $category['slug'] = ''; + + // If no parent_id was provided make it empty + // so that it will be a top level page (no parent). + if ( !isset($category['parent_id']) ) + $category['parent_id'] = ''; + + // If no description was provided make it empty. + if ( empty($category["description"]) ) + $category["description"] = ""; + + $new_category = array( + 'cat_name' => $category['name'], + 'category_nicename' => $category['slug'], + 'category_parent' => $category['parent_id'], + 'category_description' => $category['description'] + ); + + $cat_id = wp_insert_category($new_category, true); + if ( is_wp_error( $cat_id ) ) { + if ( 'term_exists' == $cat_id->get_error_code() ) + return (int) $cat_id->get_error_data(); + else + return(new IXR_Error(500, __('Sorry, the new category failed.'))); + } elseif ( ! $cat_id ) { + return(new IXR_Error(500, __('Sorry, the new category failed.'))); + } + + do_action( 'xmlrpc_call_success_wp_newCategory', $cat_id, $args ); + + return $cat_id; + } + + /** + * Remove category. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return mixed See {@link wp_delete_term()} for return info. + */ + function wp_deleteCategory($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $category_id = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'wp.deleteCategory'); + + if ( !current_user_can('manage_categories') ) + return new IXR_Error( 401, __( 'Sorry, you do not have the right to delete a category.' ) ); + + $status = wp_delete_term( $category_id, 'category' ); + + if( true == $status ) + do_action( 'xmlrpc_call_success_wp_deleteCategory', $category_id, $args ); + + return $status; + } + + /** + * Retrieve category list. + * + * @since 2.2.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_suggestCategories($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $category = $args[3]; + $max_results = (int) $args[4]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts to this site in order to view categories.' ) ); + + do_action('xmlrpc_call', 'wp.suggestCategories'); + + $category_suggestions = array(); + $args = array('get' => 'all', 'number' => $max_results, 'name__like' => $category); + foreach ( (array) get_categories($args) as $cat ) { + $category_suggestions[] = array( + 'category_id' => $cat->term_id, + 'category_name' => $cat->name + ); + } + + return($category_suggestions); + } + + /** + * Retrieve comment. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getComment($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $comment_id = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + + do_action('xmlrpc_call', 'wp.getComment'); + + if ( ! $comment = get_comment($comment_id) ) + return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + + return $this->_prepare_comment( $comment ); + } + + /** + * Retrieve comments. + * + * Besides the common blog_id, username, and password arguments, it takes a filter + * array as last argument. + * + * Accepted 'filter' keys are 'status', 'post_id', 'offset', and 'number'. + * + * The defaults are as follows: + * - 'status' - Default is ''. Filter by status (e.g., 'approve', 'hold') + * - 'post_id' - Default is ''. The post where the comment is posted. Empty string shows all comments. + * - 'number' - Default is 10. Total number of media items to retrieve. + * - 'offset' - Default is 0. See {@link WP_Query::query()} for more. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array. Contains a collection of comments. See {@link wp_xmlrpc_server::wp_getComment()} for a description of each item contents + */ + function wp_getComments($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $struct = isset( $args[3] ) ? $args[3] : array(); + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit comments.' ) ); + + do_action('xmlrpc_call', 'wp.getComments'); + + if ( isset($struct['status']) ) + $status = $struct['status']; + else + $status = ''; + + $post_id = ''; + if ( isset($struct['post_id']) ) + $post_id = absint($struct['post_id']); + + $offset = 0; + if ( isset($struct['offset']) ) + $offset = absint($struct['offset']); + + $number = 10; + if ( isset($struct['number']) ) + $number = absint($struct['number']); + + $comments = get_comments( array('status' => $status, 'post_id' => $post_id, 'offset' => $offset, 'number' => $number ) ); + + $comments_struct = array(); + + foreach ( $comments as $comment ) { + $comments_struct[] = $this->_prepare_comment( $comment ); + } + + return $comments_struct; + } + + /** + * Delete a comment. + * + * By default, the comment will be moved to the trash instead of deleted. + * See {@link wp_delete_comment()} for more information on + * this behavior. + * + * @since 2.7.0 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - username + * - password + * - comment_id + * @return mixed {@link wp_delete_comment()} + */ + function wp_deleteComment($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $comment_ID = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + + if ( ! get_comment($comment_ID) ) + return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + + if ( !current_user_can( 'edit_comment', $comment_ID ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + + do_action('xmlrpc_call', 'wp.deleteComment'); + + $status = wp_delete_comment( $comment_ID ); + + if( true == $status ) + do_action( 'xmlrpc_call_success_wp_deleteComment', $comment_ID, $args ); + + return $status; + } + + /** + * Edit comment. + * + * Besides the common blog_id, username, and password arguments, it takes a + * comment_id integer and a content_struct array as last argument. + * + * The allowed keys in the content_struct array are: + * - 'author' + * - 'author_url' + * - 'author_email' + * - 'content' + * - 'date_created_gmt' + * - 'status'. Common statuses are 'approve', 'hold', 'spam'. See {@link get_comment_statuses()} for more details + * + * @since 2.7.0 + * + * @param array $args. Contains: + * - blog_id + * - username + * - password + * - comment_id + * - content_struct + * @return bool True, on success. + */ + function wp_editComment($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $comment_ID = (int) $args[3]; + $content_struct = $args[4]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + + if ( ! get_comment($comment_ID) ) + return new IXR_Error( 404, __( 'Invalid comment ID.' ) ); + + if ( !current_user_can( 'edit_comment', $comment_ID ) ) + return new IXR_Error( 403, __( 'You are not allowed to moderate comments on this site.' ) ); + + do_action('xmlrpc_call', 'wp.editComment'); + + if ( isset($content_struct['status']) ) { + $statuses = get_comment_statuses(); + $statuses = array_keys($statuses); + + if ( ! in_array($content_struct['status'], $statuses) ) + return new IXR_Error( 401, __( 'Invalid comment status.' ) ); + $comment_approved = $content_struct['status']; + } + + // Do some timestamp voodoo + if ( !empty( $content_struct['date_created_gmt'] ) ) { + // We know this is supposed to be GMT, so we're going to slap that Z on there by force + $dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z'; + $comment_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); + $comment_date_gmt = iso8601_to_datetime($dateCreated, 'GMT'); + } + + if ( isset($content_struct['content']) ) + $comment_content = $content_struct['content']; + + if ( isset($content_struct['author']) ) + $comment_author = $content_struct['author']; + + if ( isset($content_struct['author_url']) ) + $comment_author_url = $content_struct['author_url']; + + if ( isset($content_struct['author_email']) ) + $comment_author_email = $content_struct['author_email']; + + // We've got all the data -- post it: + $comment = compact('comment_ID', 'comment_content', 'comment_approved', 'comment_date', 'comment_date_gmt', 'comment_author', 'comment_author_email', 'comment_author_url'); + + $result = wp_update_comment($comment); + if ( is_wp_error( $result ) ) + return new IXR_Error(500, $result->get_error_message()); + + if ( !$result ) + return new IXR_Error(500, __('Sorry, the comment could not be edited. Something wrong happened.')); + + do_action( 'xmlrpc_call_success_wp_editComment', $comment_ID, $args ); + + return true; + } + + /** + * Create new comment. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return mixed {@link wp_new_comment()} + */ + function wp_newComment($args) { + global $wpdb; + + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post = $args[3]; + $content_struct = $args[4]; + + $allow_anon = apply_filters('xmlrpc_allow_anonymous_comments', false); + + $user = $this->login($username, $password); + + if ( !$user ) { + $logged_in = false; + if ( $allow_anon && get_option('comment_registration') ) + return new IXR_Error( 403, __( 'You must be registered to comment' ) ); + else if ( !$allow_anon ) + return $this->error; + } else { + $logged_in = true; + } + + if ( is_numeric($post) ) + $post_id = absint($post); + else + $post_id = url_to_postid($post); + + if ( ! $post_id ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( ! get_post($post_id) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + $comment['comment_post_ID'] = $post_id; + + if ( $logged_in ) { + $comment['comment_author'] = $this->escape( $user->display_name ); + $comment['comment_author_email'] = $this->escape( $user->user_email ); + $comment['comment_author_url'] = $this->escape( $user->user_url ); + $comment['user_ID'] = $user->ID; + } else { + $comment['comment_author'] = ''; + if ( isset($content_struct['author']) ) + $comment['comment_author'] = $content_struct['author']; + + $comment['comment_author_email'] = ''; + if ( isset($content_struct['author_email']) ) + $comment['comment_author_email'] = $content_struct['author_email']; + + $comment['comment_author_url'] = ''; + if ( isset($content_struct['author_url']) ) + $comment['comment_author_url'] = $content_struct['author_url']; + + $comment['user_ID'] = 0; + + if ( get_option('require_name_email') ) { + if ( 6 > strlen($comment['comment_author_email']) || '' == $comment['comment_author'] ) + return new IXR_Error( 403, __( 'Comment author name and email are required' ) ); + elseif ( !is_email($comment['comment_author_email']) ) + return new IXR_Error( 403, __( 'A valid email address is required' ) ); + } + } + + $comment['comment_parent'] = isset($content_struct['comment_parent']) ? absint($content_struct['comment_parent']) : 0; + + $comment['comment_content'] = isset($content_struct['content']) ? $content_struct['content'] : null; + + do_action('xmlrpc_call', 'wp.newComment'); + + $comment_ID = wp_new_comment( $comment ); + + do_action( 'xmlrpc_call_success_wp_newComment', $comment_ID, $args ); + + return $comment_ID; + } + + /** + * Retrieve all of the comment status. + * + * @since 2.7.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getCommentStatusList($args) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'moderate_comments' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) ); + + do_action('xmlrpc_call', 'wp.getCommentStatusList'); + + return get_comment_statuses(); + } + + /** + * Retrieve comment count. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getCommentCount( $args ) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post_id = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about comments.' ) ); + + do_action('xmlrpc_call', 'wp.getCommentCount'); + + $count = wp_count_comments( $post_id ); + return array( + 'approved' => $count->approved, + 'awaiting_moderation' => $count->moderated, + 'spam' => $count->spam, + 'total_comments' => $count->total_comments + ); + } + + /** + * Retrieve post statuses. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getPostStatusList( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) ); + + do_action('xmlrpc_call', 'wp.getPostStatusList'); + + return get_post_statuses(); + } + + /** + * Retrieve page statuses. + * + * @since 2.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getPageStatusList( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_pages' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) ); + + do_action('xmlrpc_call', 'wp.getPageStatusList'); + + return get_page_statuses(); + } + + /** + * Retrieve page templates. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getPageTemplates( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_pages' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) ); + + $templates = get_page_templates(); + $templates['Default'] = 'default'; + + return $templates; + } + + /** + * Retrieve blog options. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return array + */ + function wp_getOptions( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $options = isset( $args[3] ) ? (array) $args[3] : array(); + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + // If no specific options where asked for, return all of them + if ( count( $options ) == 0 ) + $options = array_keys($this->blog_options); + + return $this->_getOptions($options); + } + + /** + * Retrieve blog options value from list. + * + * @since 2.6.0 + * + * @param array $options Options to retrieve. + * @return array + */ + function _getOptions($options) { + $data = array(); + $can_manage = current_user_can( 'manage_options' ); + foreach ( $options as $option ) { + if ( array_key_exists( $option, $this->blog_options ) ) { + $data[$option] = $this->blog_options[$option]; + //Is the value static or dynamic? + if ( isset( $data[$option]['option'] ) ) { + $data[$option]['value'] = get_option( $data[$option]['option'] ); + unset($data[$option]['option']); + } + + if ( ! $can_manage ) + $data[$option]['readonly'] = true; + } + } + + return $data; + } + + /** + * Update blog options. + * + * @since 2.6.0 + * + * @param array $args Method parameters. + * @return unknown + */ + function wp_setOptions( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $options = (array) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'manage_options' ) ) + return new IXR_Error( 403, __( 'You are not allowed to update options.' ) ); + + foreach ( $options as $o_name => $o_value ) { + $option_names[] = $o_name; + if ( !array_key_exists( $o_name, $this->blog_options ) ) + continue; + + if ( $this->blog_options[$o_name]['readonly'] == true ) + continue; + + update_option( $this->blog_options[$o_name]['option'], $o_value ); + } + + //Now return the updated values + return $this->_getOptions($option_names); + } + + /** + * Retrieve a media item by ID + * + * @since 3.1.0 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - username + * - password + * - attachment_id + * @return array. Associative array containing: + * - 'date_created_gmt' + * - 'parent' + * - 'link' + * - 'thumbnail' + * - 'title' + * - 'caption' + * - 'description' + * - 'metadata' + */ + function wp_getMediaItem($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $attachment_id = (int) $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'upload_files' ) ) + return new IXR_Error( 403, __( 'You do not have permission to upload files.' ) ); + + do_action('xmlrpc_call', 'wp.getMediaItem'); + + if ( ! $attachment = get_post($attachment_id) ) + return new IXR_Error( 404, __( 'Invalid attachment ID.' ) ); + + return $this->_prepare_media_item( $attachment ); + } + + /** + * Retrieves a collection of media library items (or attachments) + * + * Besides the common blog_id, username, and password arguments, it takes a filter + * array as last argument. + * + * Accepted 'filter' keys are 'parent_id', 'mime_type', 'offset', and 'number'. + * + * The defaults are as follows: + * - 'number' - Default is 5. Total number of media items to retrieve. + * - 'offset' - Default is 0. See {@link WP_Query::query()} for more. + * - 'parent_id' - Default is ''. The post where the media item is attached. Empty string shows all media items. 0 shows unattached media items. + * - 'mime_type' - Default is ''. Filter by mime type (e.g., 'image/jpeg', 'application/pdf') + * + * @since 3.1.0 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - username + * - password + * - filter + * @return array. Contains a collection of media items. See {@link wp_xmlrpc_server::wp_getMediaItem()} for a description of each item contents + */ + function wp_getMediaLibrary($args) { + $this->escape($args); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $struct = isset( $args[3] ) ? $args[3] : array() ; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'upload_files' ) ) + return new IXR_Error( 401, __( 'You do not have permission to upload files.' ) ); + + do_action('xmlrpc_call', 'wp.getMediaLibrary'); + + $parent_id = ( isset($struct['parent_id']) ) ? absint($struct['parent_id']) : '' ; + $mime_type = ( isset($struct['mime_type']) ) ? $struct['mime_type'] : '' ; + $offset = ( isset($struct['offset']) ) ? absint($struct['offset']) : 0 ; + $number = ( isset($struct['number']) ) ? absint($struct['number']) : -1 ; + + $attachments = get_posts( array('post_type' => 'attachment', 'post_parent' => $parent_id, 'offset' => $offset, 'numberposts' => $number, 'post_mime_type' => $mime_type ) ); + + $attachments_struct = array(); + + foreach ($attachments as $attachment ) + $attachments_struct[] = $this->_prepare_media_item( $attachment ); + + return $attachments_struct; + } + + /** + * Retrieves a list of post formats used by the site + * + * @since 3.1 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - username + * - password + * @return array + */ + function wp_getPostFormats( $args ) { + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login( $username, $password ) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 403, __( 'You are not allowed access to details about this site.' ) ); + + do_action( 'xmlrpc_call', 'wp.getPostFormats' ); + + $formats = get_post_format_strings(); + + # find out if they want a list of currently supports formats + if ( isset( $args[3] ) && is_array( $args[3] ) ) { + if ( $args[3]['show-supported'] ) { + if ( current_theme_supports( 'post-formats' ) ) { + $supported = get_theme_support( 'post-formats' ); + + $data['all'] = $formats; + $data['supported'] = $supported[0]; + + $formats = $data; + } + } + } + + return $formats; + } + + /** + * Retrieves a post type + * + * @since 3.4.0 + * + * @uses get_post_type_object() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - string $post_type_name + * - array $fields + * @return array contains: + * - 'labels' + * - 'description' + * - 'capability_type' + * - 'cap' + * - 'map_meta_cap' + * - 'hierarchical' + * - 'menu_position' + * - 'taxonomies' + * - 'supports' + */ + function wp_getPostType( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post_type_name = $args[3]; + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_posttype_fields', array( 'labels', 'cap', 'taxonomies' ), 'wp.getPostType' ); + + if ( !$user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getPostType' ); + + if( ! post_type_exists( $post_type_name ) ) + return new IXR_Error( 403, __( 'Invalid post type' ) ); + + $post_type = get_post_type_object( $post_type_name ); + + if( ! current_user_can( $post_type->cap->edit_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit this post type.' ) ); + + return $this->_prepare_post_type( $post_type, $fields ); + } + + /** + * Retrieves a post types + * + * @since 3.4.0 + * + * @uses get_post_types() + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - array $filter + * - array $fields + * @return array + */ + function wp_getPostTypes( $args ) { + if ( ! $this->minimum_args( $args, 3 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $filter = isset( $args[3] ) ? $args[3] : array( 'public' => true ); + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_posttype_fields', array( 'labels', 'cap', 'taxonomies' ), 'wp.getPostTypes' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getPostTypes' ); + + $post_types = get_post_types( $filter, 'objects' ); + + $struct = array(); + + foreach( $post_types as $post_type ) { + if( ! current_user_can( $post_type->cap->edit_posts ) ) + continue; + + $struct[$post_type->name] = $this->_prepare_post_type( $post_type, $fields ); + } + + return $struct; + } + + /** + * Retrieve revisions for a specific post. + * + * @since 3.5.0 + * + * The optional $fields parameter specifies what fields will be included + * in the response array. + * + * @uses wp_get_post_revisions() + * @see wp_getPost() for more on $fields + * + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - int $post_id + * - array $fields + * @return array contains a collection of posts. + */ + function wp_getRevisions( $args ) { + if ( ! $this->minimum_args( $args, 4 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $post_id = (int) $args[3]; + + if ( isset( $args[4] ) ) + $fields = $args[4]; + else + $fields = apply_filters( 'xmlrpc_default_revision_fields', array( 'post_date', 'post_date_gmt' ), 'wp.getRevisions' ); + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.getRevisions' ); + + if ( ! $post = get_post( $post_id ) ) + return new IXR_Error( 404, __( 'Invalid post ID' ) ); + + if ( ! current_user_can( 'edit_post', $post_id ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to edit posts.' ) ); + + // Check if revisions are enabled. + if ( ! wp_revisions_enabled( $post ) ) + return new IXR_Error( 401, __( 'Sorry, revisions are disabled.' ) ); + + $revisions = wp_get_post_revisions( $post_id ); + + if ( ! $revisions ) + return array(); + + $struct = array(); + + foreach ( $revisions as $revision ) { + if ( ! current_user_can( 'read_post', $revision->ID ) ) + continue; + + // Skip autosaves + if ( wp_is_post_autosave( $revision ) ) + continue; + + $struct[] = $this->_prepare_post( get_object_vars( $revision ), $fields ); + } + + return $struct; + } + + /** + * Restore a post revision + * + * @since 3.5.0 + * + * @uses wp_restore_post_revision() + * + * @param array $args Method parameters. Contains: + * - int $blog_id + * - string $username + * - string $password + * - int $post_id + * @return bool false if there was an error restoring, true if success. + */ + function wp_restoreRevision( $args ) { + if ( ! $this->minimum_args( $args, 3 ) ) + return $this->error; + + $this->escape( $args ); + + $blog_id = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $revision_id = (int) $args[3]; + + if ( ! $user = $this->login( $username, $password ) ) + return $this->error; + + do_action( 'xmlrpc_call', 'wp.restoreRevision' ); + + if ( ! $revision = wp_get_post_revision( $revision_id ) ) + return new IXR_Error( 404, __( 'Invalid post ID' ) ); + + if ( wp_is_post_autosave( $revision ) ) + return new IXR_Error( 404, __( 'Invalid post ID' ) ); + + if ( ! $post = get_post( $revision->post_parent ) ) + return new IXR_Error( 404, __( 'Invalid post ID' ) ); + + if ( ! current_user_can( 'edit_post', $revision->post_parent ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); + + // Check if revisions are disabled. + if ( ! wp_revisions_enabled( $post ) ) + return new IXR_Error( 401, __( 'Sorry, revisions are disabled.' ) ); + + $post = wp_restore_post_revision( $revision_id ); + + return (bool) $post; + } + + /* Blogger API functions. + * specs on http://plant.blogger.com/api and http://groups.yahoo.com/group/bloggerDev/ + */ + + /** + * Retrieve blogs that user owns. + * + * Will make more sense once we support multiple blogs. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function blogger_getUsersBlogs($args) { + if ( is_multisite() ) + return $this->_multisite_getUsersBlogs($args); + + $this->escape($args); + + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'blogger.getUsersBlogs'); + + $is_admin = current_user_can('manage_options'); + + $struct = array( + 'isAdmin' => $is_admin, + 'url' => get_option('home') . '/', + 'blogid' => '1', + 'blogName' => get_option('blogname'), + 'xmlrpc' => site_url( 'xmlrpc.php', 'rpc' ), + ); + + return array($struct); + } + + /** + * Private function for retrieving a users blogs for multisite setups + * + * @access protected + */ + function _multisite_getUsersBlogs($args) { + $current_blog = get_blog_details(); + + $domain = $current_blog->domain; + $path = $current_blog->path . 'xmlrpc.php'; + + $rpc = new IXR_Client( set_url_scheme( "http://{$domain}{$path}" ) ); + $rpc->query('wp.getUsersBlogs', $args[1], $args[2]); + $blogs = $rpc->getResponse(); + + if ( isset($blogs['faultCode']) ) + return new IXR_Error($blogs['faultCode'], $blogs['faultString']); + + if ( $_SERVER['HTTP_HOST'] == $domain && $_SERVER['REQUEST_URI'] == $path ) { + return $blogs; + } else { + foreach ( (array) $blogs as $blog ) { + if ( strpos($blog['url'], $_SERVER['HTTP_HOST']) ) + return array($blog); + } + return array(); + } + } + + /** + * Retrieve user's data. + * + * Gives your client some info about you, so you don't have to. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function blogger_getUserInfo($args) { + + $this->escape($args); + + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you do not have access to user data on this site.' ) ); + + do_action('xmlrpc_call', 'blogger.getUserInfo'); + + $struct = array( + 'nickname' => $user->nickname, + 'userid' => $user->ID, + 'url' => $user->user_url, + 'lastname' => $user->last_name, + 'firstname' => $user->first_name + ); + + return $struct; + } + + /** + * Retrieve post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function blogger_getPost($args) { + + $this->escape($args); + + $post_ID = (int) $args[1]; + $username = $args[2]; + $password = $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + $post_data = get_post($post_ID, ARRAY_A); + if ( ! $post_data ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( !current_user_can( 'edit_post', $post_ID ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); + + do_action('xmlrpc_call', 'blogger.getPost'); + + $categories = implode(',', wp_get_post_categories($post_ID)); + + $content = '<title>'.wp_unslash($post_data['post_title']).''; + $content .= ''.$categories.''; + $content .= wp_unslash($post_data['post_content']); + + $struct = array( + 'userid' => $post_data['post_author'], + 'dateCreated' => $this->_convert_date( $post_data['post_date'] ), + 'content' => $content, + 'postid' => (string) $post_data['ID'] + ); + + return $struct; + } + + /** + * Retrieve list of recent posts. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function blogger_getRecentPosts($args) { + + $this->escape($args); + + // $args[0] = appkey - ignored + $blog_ID = (int) $args[1]; /* though we don't use it yet */ + $username = $args[2]; + $password = $args[3]; + if ( isset( $args[4] ) ) + $query = array( 'numberposts' => absint( $args[4] ) ); + else + $query = array(); + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( ! current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit posts on this site.' ) ); + + do_action('xmlrpc_call', 'blogger.getRecentPosts'); + + $posts_list = wp_get_recent_posts( $query ); + + if ( !$posts_list ) { + $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.')); + return $this->error; + } + + foreach ($posts_list as $entry) { + if ( !current_user_can( 'edit_post', $entry['ID'] ) ) + continue; + + $post_date = $this->_convert_date( $entry['post_date'] ); + $categories = implode(',', wp_get_post_categories($entry['ID'])); + + $content = ''.wp_unslash($entry['post_title']).''; + $content .= ''.$categories.''; + $content .= wp_unslash($entry['post_content']); + + $struct[] = array( + 'userid' => $entry['post_author'], + 'dateCreated' => $post_date, + 'content' => $content, + 'postid' => (string) $entry['ID'], + ); + + } + + $recent_posts = array(); + for ( $j=0; $jescape($args); + + $blog_ID = (int) $args[1]; /* though we don't use it yet */ + $username = $args[2]; + $password = $args[3]; + $content = $args[4]; + $publish = $args[5]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'blogger.newPost'); + + $cap = ($publish) ? 'publish_posts' : 'edit_posts'; + if ( ! current_user_can( get_post_type_object( 'post' )->cap->create_posts ) || !current_user_can($cap) ) + return new IXR_Error(401, __('Sorry, you are not allowed to post on this site.')); + + $post_status = ($publish) ? 'publish' : 'draft'; + + $post_author = $user->ID; + + $post_title = xmlrpc_getposttitle($content); + $post_category = xmlrpc_getpostcategory($content); + $post_content = xmlrpc_removepostdata($content); + + $post_date = current_time('mysql'); + $post_date_gmt = current_time('mysql', 1); + + $post_data = compact('blog_ID', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status'); + + $post_ID = wp_insert_post($post_data); + if ( is_wp_error( $post_ID ) ) + return new IXR_Error(500, $post_ID->get_error_message()); + + if ( !$post_ID ) + return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.')); + + $this->attach_uploads( $post_ID, $post_content ); + + do_action( 'xmlrpc_call_success_blogger_newPost', $post_ID, $args ); + + return $post_ID; + } + + /** + * Edit a post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return bool true when done. + */ + function blogger_editPost($args) { + + $this->escape($args); + + $post_ID = (int) $args[1]; + $username = $args[2]; + $password = $args[3]; + $content = $args[4]; + $publish = $args[5]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'blogger.editPost'); + + $actual_post = get_post($post_ID,ARRAY_A); + + if ( !$actual_post || $actual_post['post_type'] != 'post' ) + return new IXR_Error(404, __('Sorry, no such post.')); + + $this->escape($actual_post); + + if ( !current_user_can('edit_post', $post_ID) ) + return new IXR_Error(401, __('Sorry, you do not have the right to edit this post.')); + + extract($actual_post, EXTR_SKIP); + + if ( ('publish' == $post_status) && !current_user_can('publish_posts') ) + return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.')); + + $post_title = xmlrpc_getposttitle($content); + $post_category = xmlrpc_getpostcategory($content); + $post_content = xmlrpc_removepostdata($content); + + $postdata = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt'); + + $result = wp_update_post($postdata); + + if ( !$result ) + return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be edited.')); + + $this->attach_uploads( $ID, $post_content ); + + do_action( 'xmlrpc_call_success_blogger_editPost', $post_ID, $args ); + + return true; + } + + /** + * Remove a post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return bool True when post is deleted. + */ + function blogger_deletePost($args) { + $this->escape($args); + + $post_ID = (int) $args[1]; + $username = $args[2]; + $password = $args[3]; + $publish = $args[4]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'blogger.deletePost'); + + $actual_post = get_post($post_ID,ARRAY_A); + + if ( !$actual_post || $actual_post['post_type'] != 'post' ) + return new IXR_Error(404, __('Sorry, no such post.')); + + if ( !current_user_can('delete_post', $post_ID) ) + return new IXR_Error(401, __('Sorry, you do not have the right to delete this post.')); + + $result = wp_delete_post($post_ID); + + if ( !$result ) + return new IXR_Error(500, __('For some strange yet very annoying reason, this post could not be deleted.')); + + do_action( 'xmlrpc_call_success_blogger_deletePost', $post_ID, $args ); + + return true; + } + + /* MetaWeblog API functions + * specs on wherever Dave Winer wants them to be + */ + + /** + * Create a new post. + * + * The 'content_struct' argument must contain: + * - title + * - description + * - mt_excerpt + * - mt_text_more + * - mt_keywords + * - mt_tb_ping_urls + * - categories + * + * Also, it can optionally contain: + * - wp_slug + * - wp_password + * - wp_page_parent_id + * - wp_page_order + * - wp_author_id + * - post_status | page_status - can be 'draft', 'private', 'publish', or 'pending' + * - mt_allow_comments - can be 'open' or 'closed' + * - mt_allow_pings - can be 'open' or 'closed' + * - date_created_gmt + * - dateCreated + * - wp_post_thumbnail + * + * @since 1.5.0 + * + * @param array $args Method parameters. Contains: + * - blog_id + * - username + * - password + * - content_struct + * - publish + * @return int + */ + function mw_newPost($args) { + $this->escape($args); + + $blog_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $content_struct = $args[3]; + $publish = isset( $args[4] ) ? $args[4] : 0; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'metaWeblog.newPost'); + + $page_template = ''; + if ( !empty( $content_struct['post_type'] ) ) { + if ( $content_struct['post_type'] == 'page' ) { + if ( $publish ) + $cap = 'publish_pages'; + elseif ( isset( $content_struct['page_status'] ) && 'publish' == $content_struct['page_status'] ) + $cap = 'publish_pages'; + else + $cap = 'edit_pages'; + $error_message = __( 'Sorry, you are not allowed to publish pages on this site.' ); + $post_type = 'page'; + if ( !empty( $content_struct['wp_page_template'] ) ) + $page_template = $content_struct['wp_page_template']; + } elseif ( $content_struct['post_type'] == 'post' ) { + if ( $publish ) + $cap = 'publish_posts'; + elseif ( isset( $content_struct['post_status'] ) && 'publish' == $content_struct['post_status'] ) + $cap = 'publish_posts'; + else + $cap = 'edit_posts'; + $error_message = __( 'Sorry, you are not allowed to publish posts on this site.' ); + $post_type = 'post'; + } else { + // No other post_type values are allowed here + return new IXR_Error( 401, __( 'Invalid post type' ) ); + } + } else { + if ( $publish ) + $cap = 'publish_posts'; + elseif ( isset( $content_struct['post_status'] ) && 'publish' == $content_struct['post_status']) + $cap = 'publish_posts'; + else + $cap = 'edit_posts'; + $error_message = __( 'Sorry, you are not allowed to publish posts on this site.' ); + $post_type = 'post'; + } + + if ( ! current_user_can( get_post_type_object( $post_type )->cap->create_posts ) ) + return new IXR_Error( 401, __( 'Sorry, you are not allowed to publish posts on this site.' ) ); + if ( !current_user_can( $cap ) ) + return new IXR_Error( 401, $error_message ); + + // Check for a valid post format if one was given + if ( isset( $content_struct['wp_post_format'] ) ) { + $content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] ); + if ( !array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) { + return new IXR_Error( 404, __( 'Invalid post format' ) ); + } + } + + // Let WordPress generate the post_name (slug) unless + // one has been provided. + $post_name = ""; + if ( isset($content_struct['wp_slug']) ) + $post_name = $content_struct['wp_slug']; + + // Only use a password if one was given. + if ( isset($content_struct['wp_password']) ) + $post_password = $content_struct['wp_password']; + + // Only set a post parent if one was provided. + if ( isset($content_struct['wp_page_parent_id']) ) + $post_parent = $content_struct['wp_page_parent_id']; + + // Only set the menu_order if it was provided. + if ( isset($content_struct['wp_page_order']) ) + $menu_order = $content_struct['wp_page_order']; + + $post_author = $user->ID; + + // If an author id was provided then use it instead. + if ( isset( $content_struct['wp_author_id'] ) && ( $user->ID != $content_struct['wp_author_id'] ) ) { + switch ( $post_type ) { + case "post": + if ( !current_user_can( 'edit_others_posts' ) ) + return( new IXR_Error( 401, __( 'You are not allowed to create posts as this user.' ) ) ); + break; + case "page": + if ( !current_user_can( 'edit_others_pages' ) ) + return( new IXR_Error( 401, __( 'You are not allowed to create pages as this user.' ) ) ); + break; + default: + return( new IXR_Error( 401, __( 'Invalid post type' ) ) ); + break; + } + $author = get_userdata( $content_struct['wp_author_id'] ); + if ( ! $author ) + return new IXR_Error( 404, __( 'Invalid author ID.' ) ); + $post_author = $content_struct['wp_author_id']; + } + + $post_title = isset( $content_struct['title'] ) ? $content_struct['title'] : null; + $post_content = isset( $content_struct['description'] ) ? $content_struct['description'] : null; + + $post_status = $publish ? 'publish' : 'draft'; + + if ( isset( $content_struct["{$post_type}_status"] ) ) { + switch ( $content_struct["{$post_type}_status"] ) { + case 'draft': + case 'pending': + case 'private': + case 'publish': + $post_status = $content_struct["{$post_type}_status"]; + break; + default: + $post_status = $publish ? 'publish' : 'draft'; + break; + } + } + + $post_excerpt = isset($content_struct['mt_excerpt']) ? $content_struct['mt_excerpt'] : null; + $post_more = isset($content_struct['mt_text_more']) ? $content_struct['mt_text_more'] : null; + + $tags_input = isset($content_struct['mt_keywords']) ? $content_struct['mt_keywords'] : null; + + if ( isset($content_struct['mt_allow_comments']) ) { + if ( !is_numeric($content_struct['mt_allow_comments']) ) { + switch ( $content_struct['mt_allow_comments'] ) { + case 'closed': + $comment_status = 'closed'; + break; + case 'open': + $comment_status = 'open'; + break; + default: + $comment_status = get_option('default_comment_status'); + break; + } + } else { + switch ( (int) $content_struct['mt_allow_comments'] ) { + case 0: + case 2: + $comment_status = 'closed'; + break; + case 1: + $comment_status = 'open'; + break; + default: + $comment_status = get_option('default_comment_status'); + break; + } + } + } else { + $comment_status = get_option('default_comment_status'); + } + + if ( isset($content_struct['mt_allow_pings']) ) { + if ( !is_numeric($content_struct['mt_allow_pings']) ) { + switch ( $content_struct['mt_allow_pings'] ) { + case 'closed': + $ping_status = 'closed'; + break; + case 'open': + $ping_status = 'open'; + break; + default: + $ping_status = get_option('default_ping_status'); + break; + } + } else { + switch ( (int) $content_struct['mt_allow_pings'] ) { + case 0: + $ping_status = 'closed'; + break; + case 1: + $ping_status = 'open'; + break; + default: + $ping_status = get_option('default_ping_status'); + break; + } + } + } else { + $ping_status = get_option('default_ping_status'); + } + + if ( $post_more ) + $post_content = $post_content . '' . $post_more; + + $to_ping = null; + if ( isset( $content_struct['mt_tb_ping_urls'] ) ) { + $to_ping = $content_struct['mt_tb_ping_urls']; + if ( is_array($to_ping) ) + $to_ping = implode(' ', $to_ping); + } + + // Do some timestamp voodoo + if ( !empty( $content_struct['date_created_gmt'] ) ) + // We know this is supposed to be GMT, so we're going to slap that Z on there by force + $dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z'; + elseif ( !empty( $content_struct['dateCreated']) ) + $dateCreated = $content_struct['dateCreated']->getIso(); + + if ( !empty( $dateCreated ) ) { + $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); + $post_date_gmt = iso8601_to_datetime($dateCreated, 'GMT'); + } else { + $post_date = current_time('mysql'); + $post_date_gmt = current_time('mysql', 1); + } + + $post_category = array(); + if ( isset( $content_struct['categories'] ) ) { + $catnames = $content_struct['categories']; + + if ( is_array($catnames) ) { + foreach ($catnames as $cat) { + $post_category[] = get_cat_ID($cat); + } + } + } + + $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'to_ping', 'post_type', 'post_name', 'post_password', 'post_parent', 'menu_order', 'tags_input', 'page_template'); + + $post_ID = $postdata['ID'] = get_default_post_to_edit( $post_type, true )->ID; + + // Only posts can be sticky + if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) { + if ( $content_struct['sticky'] == true ) + stick_post( $post_ID ); + elseif ( $content_struct['sticky'] == false ) + unstick_post( $post_ID ); + } + + if ( isset($content_struct['custom_fields']) ) + $this->set_custom_fields($post_ID, $content_struct['custom_fields']); + + if ( isset ( $content_struct['wp_post_thumbnail'] ) ) { + if ( set_post_thumbnail( $post_ID, $content_struct['wp_post_thumbnail'] ) === false ) + return new IXR_Error( 404, __( 'Invalid attachment ID.' ) ); + + unset( $content_struct['wp_post_thumbnail'] ); + } + + // Handle enclosures + $thisEnclosure = isset($content_struct['enclosure']) ? $content_struct['enclosure'] : null; + $this->add_enclosure_if_new($post_ID, $thisEnclosure); + + $this->attach_uploads( $post_ID, $post_content ); + + // Handle post formats if assigned, value is validated earlier + // in this function + if ( isset( $content_struct['wp_post_format'] ) ) + set_post_format( $post_ID, $content_struct['wp_post_format'] ); + + $post_ID = wp_insert_post( $postdata, true ); + if ( is_wp_error( $post_ID ) ) + return new IXR_Error(500, $post_ID->get_error_message()); + + if ( !$post_ID ) + return new IXR_Error(500, __('Sorry, your entry could not be posted. Something wrong happened.')); + + do_action( 'xmlrpc_call_success_mw_newPost', $post_ID, $args ); + + return strval($post_ID); + } + + function add_enclosure_if_new( $post_ID, $enclosure ) { + if ( is_array( $enclosure ) && isset( $enclosure['url'] ) && isset( $enclosure['length'] ) && isset( $enclosure['type'] ) ) { + $encstring = $enclosure['url'] . "\n" . $enclosure['length'] . "\n" . $enclosure['type'] . "\n"; + $found = false; + if ( $enclosures = get_post_meta( $post_ID, 'enclosure' ) ) { + foreach ( $enclosures as $enc ) { + // This method used to omit the trailing new line. #23219 + if ( rtrim( $enc, "\n" ) == rtrim( $encstring, "\n" ) ) { + $found = true; + break; + } + } + } + if ( ! $found ) + add_post_meta( $post_ID, 'enclosure', $encstring ); + } + } + + /** + * Attach upload to a post. + * + * @since 2.1.0 + * + * @param int $post_ID Post ID. + * @param string $post_content Post Content for attachment. + */ + function attach_uploads( $post_ID, $post_content ) { + global $wpdb; + + // find any unattached files + $attachments = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts} WHERE post_parent = '0' AND post_type = 'attachment'" ); + if ( is_array( $attachments ) ) { + foreach ( $attachments as $file ) { + if ( ! empty( $file->guid ) && strpos( $post_content, $file->guid ) !== false ) + $wpdb->update($wpdb->posts, array('post_parent' => $post_ID), array('ID' => $file->ID) ); + } + } + } + + /** + * Edit a post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return bool True on success. + */ + function mw_editPost($args) { + + $this->escape($args); + + $post_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $content_struct = $args[3]; + $publish = isset( $args[4] ) ? $args[4] : 0; + + if ( ! $user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'metaWeblog.editPost'); + + $postdata = get_post( $post_ID, ARRAY_A ); + + // If there is no post data for the give post id, stop + // now and return an error. Other wise a new post will be + // created (which was the old behavior). + if ( ! $postdata || empty( $postdata[ 'ID' ] ) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( ! current_user_can( 'edit_post', $post_ID ) ) + return new IXR_Error( 401, __( 'Sorry, you do not have the right to edit this post.' ) ); + + // Use wp.editPost to edit post types other than post and page. + if ( ! in_array( $postdata[ 'post_type' ], array( 'post', 'page' ) ) ) + return new IXR_Error( 401, __( 'Invalid post type' ) ); + + // Thwart attempt to change the post type. + if ( ! empty( $content_struct[ 'post_type' ] ) && ( $content_struct['post_type'] != $postdata[ 'post_type' ] ) ) + return new IXR_Error( 401, __( 'The post type may not be changed.' ) ); + + // Check for a valid post format if one was given + if ( isset( $content_struct['wp_post_format'] ) ) { + $content_struct['wp_post_format'] = sanitize_key( $content_struct['wp_post_format'] ); + if ( !array_key_exists( $content_struct['wp_post_format'], get_post_format_strings() ) ) { + return new IXR_Error( 404, __( 'Invalid post format' ) ); + } + } + + $this->escape($postdata); + extract($postdata, EXTR_SKIP); + + // Let WordPress manage slug if none was provided. + $post_name = ""; + $post_name = $postdata['post_name']; + if ( isset($content_struct['wp_slug']) ) + $post_name = $content_struct['wp_slug']; + + // Only use a password if one was given. + if ( isset($content_struct['wp_password']) ) + $post_password = $content_struct['wp_password']; + + // Only set a post parent if one was given. + if ( isset($content_struct['wp_page_parent_id']) ) + $post_parent = $content_struct['wp_page_parent_id']; + + // Only set the menu_order if it was given. + if ( isset($content_struct['wp_page_order']) ) + $menu_order = $content_struct['wp_page_order']; + + if ( ! empty( $content_struct['wp_page_template'] ) && 'page' == $post_type ) + $page_template = $content_struct['wp_page_template']; + + $post_author = $postdata['post_author']; + + // Only set the post_author if one is set. + if ( isset($content_struct['wp_author_id']) && ($user->ID != $content_struct['wp_author_id']) ) { + switch ( $post_type ) { + case 'post': + if ( !current_user_can('edit_others_posts') ) + return(new IXR_Error(401, __('You are not allowed to change the post author as this user.'))); + break; + case 'page': + if ( !current_user_can('edit_others_pages') ) + return(new IXR_Error(401, __('You are not allowed to change the page author as this user.'))); + break; + default: + return(new IXR_Error(401, __('Invalid post type'))); + break; + } + $post_author = $content_struct['wp_author_id']; + } + + if ( isset($content_struct['mt_allow_comments']) ) { + if ( !is_numeric($content_struct['mt_allow_comments']) ) { + switch ( $content_struct['mt_allow_comments'] ) { + case 'closed': + $comment_status = 'closed'; + break; + case 'open': + $comment_status = 'open'; + break; + default: + $comment_status = get_option('default_comment_status'); + break; + } + } else { + switch ( (int) $content_struct['mt_allow_comments'] ) { + case 0: + case 2: + $comment_status = 'closed'; + break; + case 1: + $comment_status = 'open'; + break; + default: + $comment_status = get_option('default_comment_status'); + break; + } + } + } + + if ( isset($content_struct['mt_allow_pings']) ) { + if ( !is_numeric($content_struct['mt_allow_pings']) ) { + switch ( $content_struct['mt_allow_pings'] ) { + case 'closed': + $ping_status = 'closed'; + break; + case 'open': + $ping_status = 'open'; + break; + default: + $ping_status = get_option('default_ping_status'); + break; + } + } else { + switch ( (int) $content_struct["mt_allow_pings"] ) { + case 0: + $ping_status = 'closed'; + break; + case 1: + $ping_status = 'open'; + break; + default: + $ping_status = get_option('default_ping_status'); + break; + } + } + } + + if ( isset( $content_struct['title'] ) ) + $post_title = $content_struct['title']; + + if ( isset( $content_struct['description'] ) ) + $post_content = $content_struct['description']; + + $post_category = array(); + if ( isset( $content_struct['categories'] ) ) { + $catnames = $content_struct['categories']; + if ( is_array($catnames) ) { + foreach ($catnames as $cat) { + $post_category[] = get_cat_ID($cat); + } + } + } + + if ( isset( $content_struct['mt_excerpt'] ) ) + $post_excerpt = $content_struct['mt_excerpt']; + + $post_more = isset( $content_struct['mt_text_more'] ) ? $content_struct['mt_text_more'] : null; + + $post_status = $publish ? 'publish' : 'draft'; + if ( isset( $content_struct["{$post_type}_status"] ) ) { + switch( $content_struct["{$post_type}_status"] ) { + case 'draft': + case 'pending': + case 'private': + case 'publish': + $post_status = $content_struct["{$post_type}_status"]; + break; + default: + $post_status = $publish ? 'publish' : 'draft'; + break; + } + } + + $tags_input = isset( $content_struct['mt_keywords'] ) ? $content_struct['mt_keywords'] : null; + + if ( ('publish' == $post_status) ) { + if ( ( 'page' == $post_type ) && !current_user_can('publish_pages') ) + return new IXR_Error(401, __('Sorry, you do not have the right to publish this page.')); + else if ( !current_user_can('publish_posts') ) + return new IXR_Error(401, __('Sorry, you do not have the right to publish this post.')); + } + + if ( $post_more ) + $post_content = $post_content . "" . $post_more; + + $to_ping = null; + if ( isset( $content_struct['mt_tb_ping_urls'] ) ) { + $to_ping = $content_struct['mt_tb_ping_urls']; + if ( is_array($to_ping) ) + $to_ping = implode(' ', $to_ping); + } + + // Do some timestamp voodoo + if ( !empty( $content_struct['date_created_gmt'] ) ) + // We know this is supposed to be GMT, so we're going to slap that Z on there by force + $dateCreated = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z'; + elseif ( !empty( $content_struct['dateCreated']) ) + $dateCreated = $content_struct['dateCreated']->getIso(); + + if ( !empty( $dateCreated ) ) { + $post_date = get_date_from_gmt(iso8601_to_datetime($dateCreated)); + $post_date_gmt = iso8601_to_datetime($dateCreated, 'GMT'); + } else { + $post_date = $postdata['post_date']; + $post_date_gmt = $postdata['post_date_gmt']; + } + + // We've got all the data -- post it: + $newpost = compact('ID', 'post_content', 'post_title', 'post_category', 'post_status', 'post_excerpt', 'comment_status', 'ping_status', 'post_date', 'post_date_gmt', 'to_ping', 'post_name', 'post_password', 'post_parent', 'menu_order', 'post_author', 'tags_input', 'page_template'); + + $result = wp_update_post($newpost, true); + if ( is_wp_error( $result ) ) + return new IXR_Error(500, $result->get_error_message()); + + if ( !$result ) + return new IXR_Error(500, __('Sorry, your entry could not be edited. Something wrong happened.')); + + // Only posts can be sticky + if ( $post_type == 'post' && isset( $content_struct['sticky'] ) ) { + if ( $content_struct['sticky'] == true ) + stick_post( $post_ID ); + elseif ( $content_struct['sticky'] == false ) + unstick_post( $post_ID ); + } + + if ( isset($content_struct['custom_fields']) ) + $this->set_custom_fields($post_ID, $content_struct['custom_fields']); + + if ( isset ( $content_struct['wp_post_thumbnail'] ) ) { + // empty value deletes, non-empty value adds/updates + if ( empty( $content_struct['wp_post_thumbnail'] ) ) { + delete_post_thumbnail( $post_ID ); + } else { + if ( set_post_thumbnail( $post_ID, $content_struct['wp_post_thumbnail'] ) === false ) + return new IXR_Error( 404, __( 'Invalid attachment ID.' ) ); + } + unset( $content_struct['wp_post_thumbnail'] ); + } + + // Handle enclosures + $thisEnclosure = isset($content_struct['enclosure']) ? $content_struct['enclosure'] : null; + $this->add_enclosure_if_new($post_ID, $thisEnclosure); + + $this->attach_uploads( $ID, $post_content ); + + // Handle post formats if assigned, validation is handled + // earlier in this function + if ( isset( $content_struct['wp_post_format'] ) ) + set_post_format( $post_ID, $content_struct['wp_post_format'] ); + + do_action( 'xmlrpc_call_success_mw_editPost', $post_ID, $args ); + + return true; + } + + /** + * Retrieve post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function mw_getPost($args) { + + $this->escape($args); + + $post_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + $postdata = get_post($post_ID, ARRAY_A); + if ( ! $postdata ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( !current_user_can( 'edit_post', $post_ID ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); + + do_action('xmlrpc_call', 'metaWeblog.getPost'); + + if ($postdata['post_date'] != '') { + $post_date = $this->_convert_date( $postdata['post_date'] ); + $post_date_gmt = $this->_convert_date_gmt( $postdata['post_date_gmt'], $postdata['post_date'] ); + $post_modified = $this->_convert_date( $postdata['post_modified'] ); + $post_modified_gmt = $this->_convert_date_gmt( $postdata['post_modified_gmt'], $postdata['post_modified'] ); + + $categories = array(); + $catids = wp_get_post_categories($post_ID); + foreach($catids as $catid) + $categories[] = get_cat_name($catid); + + $tagnames = array(); + $tags = wp_get_post_tags( $post_ID ); + if ( !empty( $tags ) ) { + foreach ( $tags as $tag ) + $tagnames[] = $tag->name; + $tagnames = implode( ', ', $tagnames ); + } else { + $tagnames = ''; + } + + $post = get_extended($postdata['post_content']); + $link = post_permalink($postdata['ID']); + + // Get the author info. + $author = get_userdata($postdata['post_author']); + + $allow_comments = ('open' == $postdata['comment_status']) ? 1 : 0; + $allow_pings = ('open' == $postdata['ping_status']) ? 1 : 0; + + // Consider future posts as published + if ( $postdata['post_status'] === 'future' ) + $postdata['post_status'] = 'publish'; + + // Get post format + $post_format = get_post_format( $post_ID ); + if ( empty( $post_format ) ) + $post_format = 'standard'; + + $sticky = false; + if ( is_sticky( $post_ID ) ) + $sticky = true; + + $enclosure = array(); + foreach ( (array) get_post_custom($post_ID) as $key => $val) { + if ($key == 'enclosure') { + foreach ( (array) $val as $enc ) { + $encdata = explode("\n", $enc); + $enclosure['url'] = trim(htmlspecialchars($encdata[0])); + $enclosure['length'] = (int) trim($encdata[1]); + $enclosure['type'] = trim($encdata[2]); + break 2; + } + } + } + + $resp = array( + 'dateCreated' => $post_date, + 'userid' => $postdata['post_author'], + 'postid' => $postdata['ID'], + 'description' => $post['main'], + 'title' => $postdata['post_title'], + 'link' => $link, + 'permaLink' => $link, + // commented out because no other tool seems to use this + // 'content' => $entry['post_content'], + 'categories' => $categories, + 'mt_excerpt' => $postdata['post_excerpt'], + 'mt_text_more' => $post['extended'], + 'wp_more_text' => $post['more_text'], + 'mt_allow_comments' => $allow_comments, + 'mt_allow_pings' => $allow_pings, + 'mt_keywords' => $tagnames, + 'wp_slug' => $postdata['post_name'], + 'wp_password' => $postdata['post_password'], + 'wp_author_id' => (string) $author->ID, + 'wp_author_display_name' => $author->display_name, + 'date_created_gmt' => $post_date_gmt, + 'post_status' => $postdata['post_status'], + 'custom_fields' => $this->get_custom_fields($post_ID), + 'wp_post_format' => $post_format, + 'sticky' => $sticky, + 'date_modified' => $post_modified, + 'date_modified_gmt' => $post_modified_gmt + ); + + if ( !empty($enclosure) ) $resp['enclosure'] = $enclosure; + + $resp['wp_post_thumbnail'] = get_post_thumbnail_id( $postdata['ID'] ); + + return $resp; + } else { + return new IXR_Error(404, __('Sorry, no such post.')); + } + } + + /** + * Retrieve list of recent posts. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function mw_getRecentPosts($args) { + + $this->escape($args); + + $blog_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + if ( isset( $args[3] ) ) + $query = array( 'numberposts' => absint( $args[3] ) ); + else + $query = array(); + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( ! current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit posts on this site.' ) ); + + do_action('xmlrpc_call', 'metaWeblog.getRecentPosts'); + + $posts_list = wp_get_recent_posts( $query ); + + if ( !$posts_list ) + return array(); + + $struct = array(); + foreach ($posts_list as $entry) { + if ( !current_user_can( 'edit_post', $entry['ID'] ) ) + continue; + + $post_date = $this->_convert_date( $entry['post_date'] ); + $post_date_gmt = $this->_convert_date_gmt( $entry['post_date_gmt'], $entry['post_date'] ); + $post_modified = $this->_convert_date( $entry['post_modified'] ); + $post_modified_gmt = $this->_convert_date_gmt( $entry['post_modified_gmt'], $entry['post_modified'] ); + + $categories = array(); + $catids = wp_get_post_categories($entry['ID']); + foreach( $catids as $catid ) + $categories[] = get_cat_name($catid); + + $tagnames = array(); + $tags = wp_get_post_tags( $entry['ID'] ); + if ( !empty( $tags ) ) { + foreach ( $tags as $tag ) { + $tagnames[] = $tag->name; + } + $tagnames = implode( ', ', $tagnames ); + } else { + $tagnames = ''; + } + + $post = get_extended($entry['post_content']); + $link = post_permalink($entry['ID']); + + // Get the post author info. + $author = get_userdata($entry['post_author']); + + $allow_comments = ('open' == $entry['comment_status']) ? 1 : 0; + $allow_pings = ('open' == $entry['ping_status']) ? 1 : 0; + + // Consider future posts as published + if ( $entry['post_status'] === 'future' ) + $entry['post_status'] = 'publish'; + + // Get post format + $post_format = get_post_format( $entry['ID'] ); + if ( empty( $post_format ) ) + $post_format = 'standard'; + + $struct[] = array( + 'dateCreated' => $post_date, + 'userid' => $entry['post_author'], + 'postid' => (string) $entry['ID'], + 'description' => $post['main'], + 'title' => $entry['post_title'], + 'link' => $link, + 'permaLink' => $link, + // commented out because no other tool seems to use this + // 'content' => $entry['post_content'], + 'categories' => $categories, + 'mt_excerpt' => $entry['post_excerpt'], + 'mt_text_more' => $post['extended'], + 'wp_more_text' => $post['more_text'], + 'mt_allow_comments' => $allow_comments, + 'mt_allow_pings' => $allow_pings, + 'mt_keywords' => $tagnames, + 'wp_slug' => $entry['post_name'], + 'wp_password' => $entry['post_password'], + 'wp_author_id' => (string) $author->ID, + 'wp_author_display_name' => $author->display_name, + 'date_created_gmt' => $post_date_gmt, + 'post_status' => $entry['post_status'], + 'custom_fields' => $this->get_custom_fields($entry['ID']), + 'wp_post_format' => $post_format, + 'date_modified' => $post_modified, + 'date_modified_gmt' => $post_modified_gmt + ); + + $entry_index = count( $struct ) - 1; + $struct[ $entry_index ][ 'wp_post_thumbnail' ] = get_post_thumbnail_id( $entry['ID'] ); + } + + $recent_posts = array(); + for ( $j=0; $jescape($args); + + $blog_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view categories.' ) ); + + do_action('xmlrpc_call', 'metaWeblog.getCategories'); + + $categories_struct = array(); + + if ( $cats = get_categories(array('get' => 'all')) ) { + foreach ( $cats as $cat ) { + $struct['categoryId'] = $cat->term_id; + $struct['parentId'] = $cat->parent; + $struct['description'] = $cat->name; + $struct['categoryDescription'] = $cat->description; + $struct['categoryName'] = $cat->name; + $struct['htmlUrl'] = esc_html(get_category_link($cat->term_id)); + $struct['rssUrl'] = esc_html(get_category_feed_link($cat->term_id, 'rss2')); + + $categories_struct[] = $struct; + } + } + + return $categories_struct; + } + + /** + * Uploads a file, following your settings. + * + * Adapted from a patch by Johann Richard. + * + * @link http://mycvs.org/archives/2004/06/30/file-upload-to-wordpress-in-ecto/ + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function mw_newMediaObject($args) { + global $wpdb; + + $blog_ID = (int) $args[0]; + $username = $this->escape($args[1]); + $password = $this->escape($args[2]); + $data = $args[3]; + + $name = sanitize_file_name( $data['name'] ); + $type = $data['type']; + $bits = $data['bits']; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'metaWeblog.newMediaObject'); + + if ( !current_user_can('upload_files') ) { + $this->error = new IXR_Error( 401, __( 'You do not have permission to upload files.' ) ); + return $this->error; + } + + if ( $upload_err = apply_filters( 'pre_upload_error', false ) ) + return new IXR_Error(500, $upload_err); + + if ( !empty($data['overwrite']) && ($data['overwrite'] == true) ) { + // Get postmeta info on the object. + $old_file = $wpdb->get_row(" + SELECT ID + FROM {$wpdb->posts} + WHERE post_title = '{$name}' + AND post_type = 'attachment' + "); + + // Delete previous file. + wp_delete_attachment($old_file->ID); + + // Make sure the new name is different by pre-pending the + // previous post id. + $filename = preg_replace('/^wpid\d+-/', '', $name); + $name = "wpid{$old_file->ID}-{$filename}"; + } + + $upload = wp_upload_bits($name, null, $bits); + if ( ! empty($upload['error']) ) { + $errorString = sprintf(__('Could not write file %1$s (%2$s)'), $name, $upload['error']); + return new IXR_Error(500, $errorString); + } + // Construct the attachment array + $post_id = 0; + if ( ! empty( $data['post_id'] ) ) { + $post_id = (int) $data['post_id']; + + if ( ! current_user_can( 'edit_post', $post_id ) ) + return new IXR_Error( 401, __( 'Sorry, you cannot edit this post.' ) ); + } + $attachment = array( + 'post_title' => $name, + 'post_content' => '', + 'post_type' => 'attachment', + 'post_parent' => $post_id, + 'post_mime_type' => $type, + 'guid' => $upload[ 'url' ] + ); + + // Save the data + $id = wp_insert_attachment( $attachment, $upload[ 'file' ], $post_id ); + wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) ); + + do_action( 'xmlrpc_call_success_mw_newMediaObject', $id, $args ); + + $struct = array( + 'id' => strval( $id ), + 'file' => $name, + 'url' => $upload[ 'url' ], + 'type' => $type + ); + return apply_filters( 'wp_handle_upload', $struct, 'upload' ); + } + + /* MovableType API functions + * specs on http://www.movabletype.org/docs/mtmanual_programmatic.html + */ + + /** + * Retrieve the post titles of recent posts. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function mt_getRecentPostTitles($args) { + + $this->escape($args); + + $blog_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + if ( isset( $args[3] ) ) + $query = array( 'numberposts' => absint( $args[3] ) ); + else + $query = array(); + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'mt.getRecentPostTitles'); + + $posts_list = wp_get_recent_posts( $query ); + + if ( !$posts_list ) { + $this->error = new IXR_Error(500, __('Either there are no posts, or something went wrong.')); + return $this->error; + } + + $struct = array(); + + foreach ($posts_list as $entry) { + if ( !current_user_can( 'edit_post', $entry['ID'] ) ) + continue; + + $post_date = $this->_convert_date( $entry['post_date'] ); + $post_date_gmt = $this->_convert_date_gmt( $entry['post_date_gmt'], $entry['post_date'] ); + + $struct[] = array( + 'dateCreated' => $post_date, + 'userid' => $entry['post_author'], + 'postid' => (string) $entry['ID'], + 'title' => $entry['post_title'], + 'post_status' => $entry['post_status'], + 'date_created_gmt' => $post_date_gmt + ); + + } + + $recent_posts = array(); + for ( $j=0; $jescape($args); + + $blog_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( !current_user_can( 'edit_posts' ) ) + return new IXR_Error( 401, __( 'Sorry, you must be able to edit posts on this site in order to view categories.' ) ); + + do_action('xmlrpc_call', 'mt.getCategoryList'); + + $categories_struct = array(); + + if ( $cats = get_categories(array('hide_empty' => 0, 'hierarchical' => 0)) ) { + foreach ( $cats as $cat ) { + $struct['categoryId'] = $cat->term_id; + $struct['categoryName'] = $cat->name; + + $categories_struct[] = $struct; + } + } + + return $categories_struct; + } + + /** + * Retrieve post categories. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function mt_getPostCategories($args) { + + $this->escape($args); + + $post_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + if ( ! get_post( $post_ID ) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( !current_user_can( 'edit_post', $post_ID ) ) + return new IXR_Error( 401, __( 'Sorry, you can not edit this post.' ) ); + + do_action('xmlrpc_call', 'mt.getPostCategories'); + + $categories = array(); + $catids = wp_get_post_categories(intval($post_ID)); + // first listed category will be the primary category + $isPrimary = true; + foreach ( $catids as $catid ) { + $categories[] = array( + 'categoryName' => get_cat_name($catid), + 'categoryId' => (string) $catid, + 'isPrimary' => $isPrimary + ); + $isPrimary = false; + } + + return $categories; + } + + /** + * Sets categories for a post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return bool True on success. + */ + function mt_setPostCategories($args) { + + $this->escape($args); + + $post_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + $categories = $args[3]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'mt.setPostCategories'); + + if ( ! get_post( $post_ID ) ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( !current_user_can('edit_post', $post_ID) ) + return new IXR_Error(401, __('Sorry, you cannot edit this post.')); + + $catids = array(); + foreach ( $categories as $cat ) { + $catids[] = $cat['categoryId']; + } + + wp_set_post_categories($post_ID, $catids); + + return true; + } + + /** + * Retrieve an array of methods supported by this server. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function mt_supportedMethods($args) { + + do_action('xmlrpc_call', 'mt.supportedMethods'); + + $supported_methods = array(); + foreach ( $this->methods as $key => $value ) { + $supported_methods[] = $key; + } + + return $supported_methods; + } + + /** + * Retrieve an empty array because we don't support per-post text filters. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + */ + function mt_supportedTextFilters($args) { + do_action('xmlrpc_call', 'mt.supportedTextFilters'); + return apply_filters('xmlrpc_text_filters', array()); + } + + /** + * Retrieve trackbacks sent to a given post. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return mixed + */ + function mt_getTrackbackPings($args) { + + global $wpdb; + + $post_ID = intval($args); + + do_action('xmlrpc_call', 'mt.getTrackbackPings'); + + $actual_post = get_post($post_ID, ARRAY_A); + + if ( !$actual_post ) + return new IXR_Error(404, __('Sorry, no such post.')); + + $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) ); + + if ( !$comments ) + return array(); + + $trackback_pings = array(); + foreach ( $comments as $comment ) { + if ( 'trackback' == $comment->comment_type ) { + $content = $comment->comment_content; + $title = substr($content, 8, (strpos($content, '') - 8)); + $trackback_pings[] = array( + 'pingTitle' => $title, + 'pingURL' => $comment->comment_author_url, + 'pingIP' => $comment->comment_author_IP + ); + } + } + + return $trackback_pings; + } + + /** + * Sets a post's publish status to 'publish'. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return int + */ + function mt_publishPost($args) { + + $this->escape($args); + + $post_ID = (int) $args[0]; + $username = $args[1]; + $password = $args[2]; + + if ( !$user = $this->login($username, $password) ) + return $this->error; + + do_action('xmlrpc_call', 'mt.publishPost'); + + $postdata = get_post($post_ID, ARRAY_A); + if ( ! $postdata ) + return new IXR_Error( 404, __( 'Invalid post ID.' ) ); + + if ( !current_user_can('publish_posts') || !current_user_can('edit_post', $post_ID) ) + return new IXR_Error(401, __('Sorry, you cannot publish this post.')); + + $postdata['post_status'] = 'publish'; + + // retain old cats + $cats = wp_get_post_categories($post_ID); + $postdata['post_category'] = $cats; + $this->escape($postdata); + + $result = wp_update_post($postdata); + + return $result; + } + + /* PingBack functions + * specs on www.hixie.ch/specs/pingback/pingback + */ + + /** + * Retrieves a pingback and registers it. + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function pingback_ping($args) { + global $wpdb; + + do_action('xmlrpc_call', 'pingback.ping'); + + $this->escape($args); + + $pagelinkedfrom = $args[0]; + $pagelinkedto = $args[1]; + + $title = ''; + + $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); + $pagelinkedto = str_replace('&', '&', $pagelinkedto); + $pagelinkedto = str_replace('&', '&', $pagelinkedto); + + $pagelinkedfrom = apply_filters( 'pingback_ping_source_uri', $pagelinkedfrom, $pagelinkedto ); + if ( ! $pagelinkedfrom ) + return $this->pingback_error( 0, __( 'A valid URL was not provided.' ) ); + + // Check if the page linked to is in our site + $pos1 = strpos($pagelinkedto, str_replace(array('http://www.','http://','https://www.','https://'), '', get_option('home'))); + if ( !$pos1 ) + return $this->pingback_error( 0, __( 'Is there no link to us?' ) ); + + // let's find which post is linked to + // FIXME: does url_to_postid() cover all these cases already? + // if so, then let's use it and drop the old code. + $urltest = parse_url($pagelinkedto); + if ( $post_ID = url_to_postid($pagelinkedto) ) { + $way = 'url_to_postid()'; + } elseif ( preg_match('#p/[0-9]{1,}#', $urltest['path'], $match) ) { + // the path defines the post_ID (archives/p/XXXX) + $blah = explode('/', $match[0]); + $post_ID = (int) $blah[1]; + $way = 'from the path'; + } elseif ( isset( $urltest['query'] ) && preg_match('#p=[0-9]{1,}#', $urltest['query'], $match) ) { + // the querystring defines the post_ID (?p=XXXX) + $blah = explode('=', $match[0]); + $post_ID = (int) $blah[1]; + $way = 'from the querystring'; + } elseif ( isset($urltest['fragment']) ) { + // an #anchor is there, it's either... + if ( intval($urltest['fragment']) ) { + // ...an integer #XXXX (simplest case) + $post_ID = (int) $urltest['fragment']; + $way = 'from the fragment (numeric)'; + } elseif ( preg_match('/post-[0-9]+/',$urltest['fragment']) ) { + // ...a post id in the form 'post-###' + $post_ID = preg_replace('/[^0-9]+/', '', $urltest['fragment']); + $way = 'from the fragment (post-###)'; + } elseif ( is_string($urltest['fragment']) ) { + // ...or a string #title, a little more complicated + $title = preg_replace('/[^a-z0-9]/i', '.', $urltest['fragment']); + $sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title RLIKE %s", like_escape( $title ) ); + if (! ($post_ID = $wpdb->get_var($sql)) ) { + // returning unknown error '0' is better than die()ing + return $this->pingback_error( 0, '' ); + } + $way = 'from the fragment (title)'; + } + } else { + // TODO: Attempt to extract a post ID from the given URL + return $this->pingback_error( 33, __('The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.' ) ); + } + $post_ID = (int) $post_ID; + + $post = get_post($post_ID); + + if ( !$post ) // Post_ID not found + return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.' ) ); + + if ( $post_ID == url_to_postid($pagelinkedfrom) ) + return $this->pingback_error( 0, __( 'The source URL and the target URL cannot both point to the same resource.' ) ); + + // Check if pings are on + if ( !pings_open($post) ) + return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.' ) ); + + // Let's check that the remote site didn't already pingback this entry + if ( $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_author_url = %s", $post_ID, $pagelinkedfrom) ) ) + return $this->pingback_error( 48, __( 'The pingback has already been registered.' ) ); + + // very stupid, but gives time to the 'from' server to publish ! + sleep(1); + + // Let's check the remote site + $http_api_args = array( + 'timeout' => 10, + 'redirection' => 0, + 'limit_response_size' => 153600, // 150 KB + ); + $linea = wp_remote_retrieve_body( wp_safe_remote_get( $pagelinkedfrom, $http_api_args ) ); + + if ( !$linea ) + return $this->pingback_error( 16, __( 'The source URL does not exist.' ) ); + + $linea = apply_filters('pre_remote_source', $linea, $pagelinkedto); + + // Work around bug in strip_tags(): + $linea = str_replace(']*>/", "\n\n", $linea ); + + preg_match('|([^<]*?)|is', $linea, $matchtitle); + $title = $matchtitle[1]; + if ( empty( $title ) ) + return $this->pingback_error( 32, __('We cannot find a title on that page.' ) ); + + $linea = strip_tags( $linea, '' ); // just keep the tag we need + + $p = explode( "\n\n", $linea ); + + $preg_target = preg_quote($pagelinkedto, '|'); + + foreach ( $p as $para ) { + if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link? + preg_match("|]+?".$preg_target."[^>]*>([^>]+?)|", $para, $context); + + // If the URL isn't in a link context, keep looking + if ( empty($context) ) + continue; + + // We're going to use this fake tag to mark the context in a bit + // the marker is needed in case the link text appears more than once in the paragraph + $excerpt = preg_replace('|\|', '', $para); + + // prevent really long link text + if ( strlen($context[1]) > 100 ) + $context[1] = substr($context[1], 0, 100) . '…'; + + $marker = ''.$context[1].''; // set up our marker + $excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker + $excerpt = strip_tags($excerpt, ''); // strip all tags but our context marker + $excerpt = trim($excerpt); + $preg_marker = preg_quote($marker, '|'); + $excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt); + $excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper + break; + } + } + + if ( empty($context) ) // Link to target not found + return $this->pingback_error( 17, __( 'The source URL does not contain a link to the target URL, and so cannot be used as a source.' ) ); + + $pagelinkedfrom = str_replace('&', '&', $pagelinkedfrom); + + $context = '[…] ' . esc_html( $excerpt ) . ' […]'; + $pagelinkedfrom = $this->escape( $pagelinkedfrom ); + + $comment_post_ID = (int) $post_ID; + $comment_author = $title; + $comment_author_email = ''; + $this->escape($comment_author); + $comment_author_url = $pagelinkedfrom; + $comment_content = $context; + $this->escape($comment_content); + $comment_type = 'pingback'; + + $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_author_email', 'comment_content', 'comment_type'); + + $comment_ID = wp_new_comment($commentdata); + do_action('pingback_post', $comment_ID); + + return sprintf(__('Pingback from %1$s to %2$s registered. Keep the web talking! :-)'), $pagelinkedfrom, $pagelinkedto); + } + + /** + * Retrieve array of URLs that pingbacked the given URL. + * + * Specs on http://www.aquarionics.com/misc/archives/blogite/0198.html + * + * @since 1.5.0 + * + * @param array $args Method parameters. + * @return array + */ + function pingback_extensions_getPingbacks($args) { + + global $wpdb; + + do_action('xmlrpc_call', 'pingback.extensions.getPingbacks'); + + $this->escape($args); + + $url = $args; + + $post_ID = url_to_postid($url); + if ( !$post_ID ) { + // We aren't sure that the resource is available and/or pingback enabled + return $this->pingback_error( 33, __( 'The specified target URL cannot be used as a target. It either doesn’t exist, or it is not a pingback-enabled resource.' ) ); + } + + $actual_post = get_post($post_ID, ARRAY_A); + + if ( !$actual_post ) { + // No such post = resource not found + return $this->pingback_error( 32, __('The specified target URL does not exist.' ) ); + } + + $comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_author_url, comment_content, comment_author_IP, comment_type FROM $wpdb->comments WHERE comment_post_ID = %d", $post_ID) ); + + if ( !$comments ) + return array(); + + $pingbacks = array(); + foreach ( $comments as $comment ) { + if ( 'pingback' == $comment->comment_type ) + $pingbacks[] = $comment->comment_author_url; + } + + return $pingbacks; + } + + protected function pingback_error( $code, $message ) { + return apply_filters( 'xmlrpc_pingback_error', new IXR_Error( $code, $message ) ); + } +} diff --git a/sources/wp-includes/class-wp.php b/sources/wp-includes/class-wp.php new file mode 100644 index 0000000..05fd43e --- /dev/null +++ b/sources/wp-includes/class-wp.php @@ -0,0 +1,645 @@ +public_query_vars) ) + $this->public_query_vars[] = $qv; + } + + /** + * Set the value of a query variable. + * + * @since 2.3.0 + * + * @param string $key Query variable name. + * @param mixed $value Query variable value. + */ + function set_query_var($key, $value) { + $this->query_vars[$key] = $value; + } + + /** + * Parse request to find correct WordPress query. + * + * Sets up the query variables based on the request. There are also many + * filters and actions that can be used to further manipulate the result. + * + * @since 2.0.0 + * + * @param array|string $extra_query_vars Set the extra query variables. + */ + function parse_request($extra_query_vars = '') { + global $wp_rewrite; + + if ( ! apply_filters( 'do_parse_request', true, $this, $extra_query_vars ) ) + return; + + $this->query_vars = array(); + $post_type_query_vars = array(); + + if ( is_array($extra_query_vars) ) + $this->extra_query_vars = & $extra_query_vars; + else if (! empty($extra_query_vars)) + parse_str($extra_query_vars, $this->extra_query_vars); + + // Process PATH_INFO, REQUEST_URI, and 404 for permalinks. + + // Fetch the rewrite rules. + $rewrite = $wp_rewrite->wp_rewrite_rules(); + + if ( ! empty($rewrite) ) { + // If we match a rewrite rule, this will be cleared. + $error = '404'; + $this->did_permalink = true; + + $pathinfo = isset( $_SERVER['PATH_INFO'] ) ? $_SERVER['PATH_INFO'] : ''; + list( $pathinfo ) = explode( '?', $pathinfo ); + $pathinfo = str_replace( "%", "%25", $pathinfo ); + + list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] ); + $self = $_SERVER['PHP_SELF']; + $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' ); + + // Trim path info from the end and the leading home path from the + // front. For path info requests, this leaves us with the requesting + // filename, if any. For 404 requests, this leaves us with the + // requested permalink. + $req_uri = str_replace($pathinfo, '', $req_uri); + $req_uri = trim($req_uri, '/'); + $req_uri = preg_replace("|^$home_path|i", '', $req_uri); + $req_uri = trim($req_uri, '/'); + $pathinfo = trim($pathinfo, '/'); + $pathinfo = preg_replace("|^$home_path|i", '', $pathinfo); + $pathinfo = trim($pathinfo, '/'); + $self = trim($self, '/'); + $self = preg_replace("|^$home_path|i", '', $self); + $self = trim($self, '/'); + + // The requested permalink is in $pathinfo for path info requests and + // $req_uri for other requests. + if ( ! empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo) ) { + $request = $pathinfo; + } else { + // If the request uri is the index, blank it out so that we don't try to match it against a rule. + if ( $req_uri == $wp_rewrite->index ) + $req_uri = ''; + $request = $req_uri; + } + + $this->request = $request; + + // Look for matches. + $request_match = $request; + if ( empty( $request_match ) ) { + // An empty request could only match against ^$ regex + if ( isset( $rewrite['$'] ) ) { + $this->matched_rule = '$'; + $query = $rewrite['$']; + $matches = array(''); + } + } else { + foreach ( (array) $rewrite as $match => $query ) { + // If the requesting file is the anchor of the match, prepend it to the path info. + if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request ) + $request_match = $req_uri . '/' . $request; + + if ( preg_match("#^$match#", $request_match, $matches) || + preg_match("#^$match#", urldecode($request_match), $matches) ) { + + if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) { + // this is a verbose page match, lets check to be sure about it + if ( ! get_page_by_path( $matches[ $varmatch[1] ] ) ) + continue; + } + + // Got a match. + $this->matched_rule = $match; + break; + } + } + } + + if ( isset( $this->matched_rule ) ) { + // Trim the query of everything up to the '?'. + $query = preg_replace("!^.+\?!", '', $query); + + // Substitute the substring matches into the query. + $query = addslashes(WP_MatchesMapRegex::apply($query, $matches)); + + $this->matched_query = $query; + + // Parse the query. + parse_str($query, $perma_query_vars); + + // If we're processing a 404 request, clear the error var since we found something. + if ( '404' == $error ) + unset( $error, $_GET['error'] ); + } + + // If req_uri is empty or if it is a request for ourself, unset error. + if ( empty($request) || $req_uri == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) { + unset( $error, $_GET['error'] ); + + if ( isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) + unset( $perma_query_vars ); + + $this->did_permalink = false; + } + } + + $this->public_query_vars = apply_filters('query_vars', $this->public_query_vars); + + foreach ( get_post_types( array(), 'objects' ) as $post_type => $t ) + if ( $t->query_var ) + $post_type_query_vars[$t->query_var] = $post_type; + + foreach ( $this->public_query_vars as $wpvar ) { + if ( isset( $this->extra_query_vars[$wpvar] ) ) + $this->query_vars[$wpvar] = $this->extra_query_vars[$wpvar]; + elseif ( isset( $_POST[$wpvar] ) ) + $this->query_vars[$wpvar] = $_POST[$wpvar]; + elseif ( isset( $_GET[$wpvar] ) ) + $this->query_vars[$wpvar] = $_GET[$wpvar]; + elseif ( isset( $perma_query_vars[$wpvar] ) ) + $this->query_vars[$wpvar] = $perma_query_vars[$wpvar]; + + if ( !empty( $this->query_vars[$wpvar] ) ) { + if ( ! is_array( $this->query_vars[$wpvar] ) ) { + $this->query_vars[$wpvar] = (string) $this->query_vars[$wpvar]; + } else { + foreach ( $this->query_vars[$wpvar] as $vkey => $v ) { + if ( !is_object( $v ) ) { + $this->query_vars[$wpvar][$vkey] = (string) $v; + } + } + } + + if ( isset($post_type_query_vars[$wpvar] ) ) { + $this->query_vars['post_type'] = $post_type_query_vars[$wpvar]; + $this->query_vars['name'] = $this->query_vars[$wpvar]; + } + } + } + + // Convert urldecoded spaces back into + + foreach ( get_taxonomies( array() , 'objects' ) as $taxonomy => $t ) + if ( $t->query_var && isset( $this->query_vars[$t->query_var] ) ) + $this->query_vars[$t->query_var] = str_replace( ' ', '+', $this->query_vars[$t->query_var] ); + + // Limit publicly queried post_types to those that are publicly_queryable + if ( isset( $this->query_vars['post_type']) ) { + $queryable_post_types = get_post_types( array('publicly_queryable' => true) ); + if ( ! is_array( $this->query_vars['post_type'] ) ) { + if ( ! in_array( $this->query_vars['post_type'], $queryable_post_types ) ) + unset( $this->query_vars['post_type'] ); + } else { + $this->query_vars['post_type'] = array_intersect( $this->query_vars['post_type'], $queryable_post_types ); + } + } + + foreach ( (array) $this->private_query_vars as $var) { + if ( isset($this->extra_query_vars[$var]) ) + $this->query_vars[$var] = $this->extra_query_vars[$var]; + } + + if ( isset($error) ) + $this->query_vars['error'] = $error; + + $this->query_vars = apply_filters('request', $this->query_vars); + + do_action_ref_array('parse_request', array(&$this)); + } + + /** + * Send additional HTTP headers for caching, content type, etc. + * + * Sets the X-Pingback header, 404 status (if 404), Content-type. If showing + * a feed, it will also send last-modified, etag, and 304 status if needed. + * + * @since 2.0.0 + */ + function send_headers() { + $headers = array('X-Pingback' => get_bloginfo('pingback_url')); + $status = null; + $exit_required = false; + + if ( is_user_logged_in() ) + $headers = array_merge($headers, wp_get_nocache_headers()); + if ( ! empty( $this->query_vars['error'] ) ) { + $status = (int) $this->query_vars['error']; + if ( 404 === $status ) { + if ( ! is_user_logged_in() ) + $headers = array_merge($headers, wp_get_nocache_headers()); + $headers['Content-Type'] = get_option('html_type') . '; charset=' . get_option('blog_charset'); + } elseif ( in_array( $status, array( 403, 500, 502, 503 ) ) ) { + $exit_required = true; + } + } else if ( empty($this->query_vars['feed']) ) { + $headers['Content-Type'] = get_option('html_type') . '; charset=' . get_option('blog_charset'); + } else { + // We're showing a feed, so WP is indeed the only thing that last changed + if ( !empty($this->query_vars['withcomments']) + || false !== strpos( $this->query_vars['feed'], 'comments-' ) + || ( empty($this->query_vars['withoutcomments']) + && ( !empty($this->query_vars['p']) + || !empty($this->query_vars['name']) + || !empty($this->query_vars['page_id']) + || !empty($this->query_vars['pagename']) + || !empty($this->query_vars['attachment']) + || !empty($this->query_vars['attachment_id']) + ) + ) + ) + $wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastcommentmodified('GMT'), 0).' GMT'; + else + $wp_last_modified = mysql2date('D, d M Y H:i:s', get_lastpostmodified('GMT'), 0).' GMT'; + $wp_etag = '"' . md5($wp_last_modified) . '"'; + $headers['Last-Modified'] = $wp_last_modified; + $headers['ETag'] = $wp_etag; + + // Support for Conditional GET + if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) + $client_etag = wp_unslash( $_SERVER['HTTP_IF_NONE_MATCH'] ); + else $client_etag = false; + + $client_last_modified = empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? '' : trim($_SERVER['HTTP_IF_MODIFIED_SINCE']); + // If string is empty, return 0. If not, attempt to parse into a timestamp + $client_modified_timestamp = $client_last_modified ? strtotime($client_last_modified) : 0; + + // Make a timestamp for our most recent modification... + $wp_modified_timestamp = strtotime($wp_last_modified); + + if ( ($client_last_modified && $client_etag) ? + (($client_modified_timestamp >= $wp_modified_timestamp) && ($client_etag == $wp_etag)) : + (($client_modified_timestamp >= $wp_modified_timestamp) || ($client_etag == $wp_etag)) ) { + $status = 304; + $exit_required = true; + } + } + + $headers = apply_filters('wp_headers', $headers, $this); + + if ( ! empty( $status ) ) + status_header( $status ); + + // If Last-Modified is set to false, it should not be sent (no-cache situation). + if ( isset( $headers['Last-Modified'] ) && false === $headers['Last-Modified'] ) { + unset( $headers['Last-Modified'] ); + + // In PHP 5.3+, make sure we are not sending a Last-Modified header. + if ( function_exists( 'header_remove' ) ) { + @header_remove( 'Last-Modified' ); + } else { + // In PHP 5.2, send an empty Last-Modified header, but only as a + // last resort to override a header already sent. #WP23021 + foreach ( headers_list() as $header ) { + if ( 0 === stripos( $header, 'Last-Modified' ) ) { + $headers['Last-Modified'] = ''; + break; + } + } + } + } + + foreach( (array) $headers as $name => $field_value ) + @header("{$name}: {$field_value}"); + + if ( $exit_required ) + exit(); + + do_action_ref_array('send_headers', array(&$this)); + } + + /** + * Sets the query string property based off of the query variable property. + * + * The 'query_string' filter is deprecated, but still works. Plugins should + * use the 'request' filter instead. + * + * @since 2.0.0 + */ + function build_query_string() { + $this->query_string = ''; + foreach ( (array) array_keys($this->query_vars) as $wpvar) { + if ( '' != $this->query_vars[$wpvar] ) { + $this->query_string .= (strlen($this->query_string) < 1) ? '' : '&'; + if ( !is_scalar($this->query_vars[$wpvar]) ) // Discard non-scalars. + continue; + $this->query_string .= $wpvar . '=' . rawurlencode($this->query_vars[$wpvar]); + } + } + + // query_string filter deprecated. Use request filter instead. + if ( has_filter('query_string') ) { // Don't bother filtering and parsing if no plugins are hooked in. + $this->query_string = apply_filters('query_string', $this->query_string); + parse_str($this->query_string, $this->query_vars); + } + } + + /** + * Set up the WordPress Globals. + * + * The query_vars property will be extracted to the GLOBALS. So care should + * be taken when naming global variables that might interfere with the + * WordPress environment. + * + * @global string $query_string Query string for the loop. + * @global array $posts The found posts. + * @global WP_Post|null $post The current post, if available. + * @global string $request The SQL statement for the request. + * @global int $more Only set, if single page or post. + * @global int $single If single page or post. Only set, if single page or post. + * @global WP_User $authordata Only set, if author archive. + * + * @since 2.0.0 + */ + function register_globals() { + global $wp_query; + + // Extract updated query vars back into global namespace. + foreach ( (array) $wp_query->query_vars as $key => $value ) { + $GLOBALS[ $key ] = $value; + } + + $GLOBALS['query_string'] = $this->query_string; + $GLOBALS['posts'] = & $wp_query->posts; + $GLOBALS['post'] = isset( $wp_query->post ) ? $wp_query->post : null; + $GLOBALS['request'] = $wp_query->request; + + if ( $wp_query->is_single() || $wp_query->is_page() ) { + $GLOBALS['more'] = 1; + $GLOBALS['single'] = 1; + } + + if ( $wp_query->is_author() && isset( $wp_query->post ) ) + $GLOBALS['authordata'] = get_userdata( $wp_query->post->post_author ); + } + + /** + * Set up the current user. + * + * @since 2.0.0 + */ + function init() { + wp_get_current_user(); + } + + /** + * Set up the Loop based on the query variables. + * + * @uses WP::$query_vars + * @since 2.0.0 + */ + function query_posts() { + global $wp_the_query; + $this->build_query_string(); + $wp_the_query->query($this->query_vars); + } + + /** + * Set the Headers for 404, if nothing is found for requested URL. + * + * Issue a 404 if a request doesn't match any posts and doesn't match + * any object (e.g. an existing-but-empty category, tag, author) and a 404 was not already + * issued, and if the request was not a search or the homepage. + * + * Otherwise, issue a 200. + * + * @since 2.0.0 + */ + function handle_404() { + global $wp_query; + + // If we've already issued a 404, bail. + if ( is_404() ) + return; + + // Never 404 for the admin, robots, or if we found posts. + if ( is_admin() || is_robots() || $wp_query->posts ) { + status_header( 200 ); + return; + } + + // We will 404 for paged queries, as no posts were found. + if ( ! is_paged() ) { + + // Don't 404 for these queries if they matched an object. + if ( ( is_tag() || is_category() || is_tax() || is_author() || is_post_type_archive() ) && $wp_query->get_queried_object() ) { + status_header( 200 ); + return; + } + + // Don't 404 for these queries either. + if ( is_home() || is_search() ) { + status_header( 200 ); + return; + } + } + + // Guess it's time to 404. + $wp_query->set_404(); + status_header( 404 ); + nocache_headers(); + } + + /** + * Sets up all of the variables required by the WordPress environment. + * + * The action 'wp' has one parameter that references the WP object. It + * allows for accessing the properties and methods to further manipulate the + * object. + * + * @since 2.0.0 + * + * @param string|array $query_args Passed to {@link parse_request()} + */ + function main($query_args = '') { + $this->init(); + $this->parse_request($query_args); + $this->send_headers(); + $this->query_posts(); + $this->handle_404(); + $this->register_globals(); + do_action_ref_array('wp', array(&$this)); + } + +} + +/** + * Helper class to remove the need to use eval to replace $matches[] in query strings. + * + * @since 2.9.0 + */ +class WP_MatchesMapRegex { + /** + * store for matches + * + * @access private + * @var array + */ + var $_matches; + + /** + * store for mapping result + * + * @access public + * @var string + */ + var $output; + + /** + * subject to perform mapping on (query string containing $matches[] references + * + * @access private + * @var string + */ + var $_subject; + + /** + * regexp pattern to match $matches[] references + * + * @var string + */ + var $_pattern = '(\$matches\[[1-9]+[0-9]*\])'; // magic number + + /** + * constructor + * + * @param string $subject subject if regex + * @param array $matches data to use in map + * @return self + */ + function WP_MatchesMapRegex($subject, $matches) { + $this->_subject = $subject; + $this->_matches = $matches; + $this->output = $this->_map(); + } + + /** + * Substitute substring matches in subject. + * + * static helper function to ease use + * + * @access public + * @param string $subject subject + * @param array $matches data used for substitution + * @return string + */ + public static function apply($subject, $matches) { + $oSelf = new WP_MatchesMapRegex($subject, $matches); + return $oSelf->output; + } + + /** + * do the actual mapping + * + * @access private + * @return string + */ + function _map() { + $callback = array($this, 'callback'); + return preg_replace_callback($this->_pattern, $callback, $this->_subject); + } + + /** + * preg_replace_callback hook + * + * @access public + * @param array $matches preg_replace regexp matches + * @return string + */ + function callback($matches) { + $index = intval(substr($matches[0], 9, -1)); + return ( isset( $this->_matches[$index] ) ? urlencode($this->_matches[$index]) : '' ); + } + +} diff --git a/sources/wp-includes/class.wp-dependencies.php b/sources/wp-includes/class.wp-dependencies.php new file mode 100644 index 0000000..158d3e0 --- /dev/null +++ b/sources/wp-includes/class.wp-dependencies.php @@ -0,0 +1,481 @@ +queue : (array) $handles; + $this->all_deps( $handles ); + + foreach( $this->to_do as $key => $handle ) { + if ( !in_array($handle, $this->done, true) && isset($this->registered[$handle]) ) { + + /** + * A single item may alias a set of items, by having dependencies, + * but no source. Queuing the item queues the dependencies. + * + * Example: The extending class WP_Scripts is used to register 'scriptaculous' as a set of registered handles: + * add( 'scriptaculous', false, array( 'scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls' ) ); + * + * The src property is false. + **/ + if ( ! $this->registered[$handle]->src ) { + $this->done[] = $handle; + continue; + } + + /** + * Attempt to process the item. If successful, + * add the handle to the done array. + * + * Unset the item from the to_do array. + */ + if ( $this->do_item( $handle, $group ) ) + $this->done[] = $handle; + + unset( $this->to_do[$key] ); + } + } + + return $this->done; + } + + /** + * Process a dependency. + * + * @access public + * @since 2.6.0 + * + * @param string $handle Name of the item. Should be unique. + * @return bool True on success, false if not set. + */ + public function do_item( $handle ) { + return isset($this->registered[$handle]); + } + + /** + * Determine dependencies. + * + * Recursively builds an array of items to process taking + * dependencies into account. Does NOT catch infinite loops. + * + * @access public + * @since 2.1.0 + * + * @param mixed $handles Item handle and argument (string) or item handles and arguments (array of strings). + * @param bool $recursion Internal flag that function is calling itself. + * @param mixed $group Group level: (int) level, (false) no groups. + * @return bool True on success, false on failure. + */ + public function all_deps( $handles, $recursion = false, $group = false ) { + if ( !$handles = (array) $handles ) + return false; + + foreach ( $handles as $handle ) { + $handle_parts = explode('?', $handle); + $handle = $handle_parts[0]; + $queued = in_array($handle, $this->to_do, true); + + if ( in_array($handle, $this->done, true) ) // Already done + continue; + + $moved = $this->set_group( $handle, $recursion, $group ); + + if ( $queued && !$moved ) // already queued and in the right group + continue; + + $keep_going = true; + if ( !isset($this->registered[$handle]) ) + $keep_going = false; // Item doesn't exist. + elseif ( $this->registered[$handle]->deps && array_diff($this->registered[$handle]->deps, array_keys($this->registered)) ) + $keep_going = false; // Item requires dependencies that don't exist. + elseif ( $this->registered[$handle]->deps && !$this->all_deps( $this->registered[$handle]->deps, true, $group ) ) + $keep_going = false; // Item requires dependencies that don't exist. + + if ( ! $keep_going ) { // Either item or its dependencies don't exist. + if ( $recursion ) + return false; // Abort this branch. + else + continue; // We're at the top level. Move on to the next one. + } + + if ( $queued ) // Already grabbed it and its dependencies. + continue; + + if ( isset($handle_parts[1]) ) + $this->args[$handle] = $handle_parts[1]; + + $this->to_do[] = $handle; + } + + return true; + } + + /** + * Register an item. + * + * Registers the item if no item of that name already exists. + * + * @access public + * @since 2.1.0 + * + * @param string $handle Unique item name. + * @param string $src The item url. + * @param array $deps Optional. An array of item handle strings on which this item depends. + * @param string $ver Optional. Version (used for cache busting). + * @param mixed $args Optional. Custom property of the item. NOT the class property $args. Examples: $media, $in_footer. + * @return bool True on success, false on failure. + */ + public function add( $handle, $src, $deps = array(), $ver = false, $args = null ) { + if ( isset($this->registered[$handle]) ) + return false; + $this->registered[$handle] = new _WP_Dependency( $handle, $src, $deps, $ver, $args ); + return true; + } + + /** + * Add extra item data. + * + * Adds data to a registered item. + * + * @access public + * @since 2.6.0 + * + * @param string $handle Name of the item. Should be unique. + * @param string $key The data key. + * @param mixed $value The data value. + * @return bool True on success, false on failure. + */ + public function add_data( $handle, $key, $value ) { + if ( !isset( $this->registered[$handle] ) ) + return false; + + return $this->registered[$handle]->add_data( $key, $value ); + } + + /** + * Get extra item data. + * + * Gets data associated with a registered item. + * + * @access public + * @since 3.3.0 + * + * @param string $handle Name of the item. Should be unique. + * @param string $key The data key. + * @return mixed Extra item data (string), false otherwise. + */ + public function get_data( $handle, $key ) { + if ( !isset( $this->registered[$handle] ) ) + return false; + + if ( !isset( $this->registered[$handle]->extra[$key] ) ) + return false; + + return $this->registered[$handle]->extra[$key]; + } + + /** + * Un-register an item or items. + * + * @access public + * @since 2.1.0 + * + * @param mixed $handles Item handle and argument (string) or item handles and arguments (array of strings). + * @return void + */ + public function remove( $handles ) { + foreach ( (array) $handles as $handle ) + unset($this->registered[$handle]); + } + + /** + * Queue an item or items. + * + * Decodes handles and arguments, then queues handles and stores + * arguments in the class property $args. For example in extending + * classes, $args is appended to the item url as a query string. + * Note $args is NOT the $args property of items in the $registered array. + * + * @access public + * @since 2.1.0 + * + * @param mixed $handles Item handle and argument (string) or item handles and arguments (array of strings). + */ + public function enqueue( $handles ) { + foreach ( (array) $handles as $handle ) { + $handle = explode('?', $handle); + if ( !in_array($handle[0], $this->queue) && isset($this->registered[$handle[0]]) ) { + $this->queue[] = $handle[0]; + if ( isset($handle[1]) ) + $this->args[$handle[0]] = $handle[1]; + } + } + } + + /** + * Dequeue an item or items. + * + * Decodes handles and arguments, then dequeues handles + * and removes arguments from the class property $args. + * + * @access public + * @since 2.1.0 + * + * @param mixed $handles Item handle and argument (string) or item handles and arguments (array of strings). + */ + public function dequeue( $handles ) { + foreach ( (array) $handles as $handle ) { + $handle = explode('?', $handle); + $key = array_search($handle[0], $this->queue); + if ( false !== $key ) { + unset($this->queue[$key]); + unset($this->args[$handle[0]]); + } + } + } + + /** + * Query list for an item. + * + * @access public + * @since 2.1.0 + * + * @param string $handle Name of the item. Should be unique. + * @param string $list Property name of list array. + * @return bool Found, or object Item data. + */ + public function query( $handle, $list = 'registered' ) { + switch ( $list ) { + case 'registered' : + case 'scripts': // back compat + if ( isset( $this->registered[ $handle ] ) ) + return $this->registered[ $handle ]; + return false; + + case 'enqueued' : + case 'queue' : + return in_array( $handle, $this->queue ); + + case 'to_do' : + case 'to_print': // back compat + return in_array( $handle, $this->to_do ); + + case 'done' : + case 'printed': // back compat + return in_array( $handle, $this->done ); + } + return false; + } + + /** + * Set item group, unless already in a lower group. + * + * @access public + * @since 2.8.0 + * + * @param string $handle Name of the item. Should be unique. + * @param bool $recursion Internal flag that calling function was called recursively. + * @param mixed $group Group level. + * @return bool Not already in the group or a lower group + */ + public function set_group( $handle, $recursion, $group ) { + $group = (int) $group; + + if ( $recursion ) + $group = min($this->group, $group); + else + $this->group = $group; + + if ( isset($this->groups[$handle]) && $this->groups[$handle] <= $group ) + return false; + + $this->groups[$handle] = $group; + return true; + } + +} // WP_Dependencies + +/** + * Class _WP_Dependency + * + * Helper class to register a handle and associated data. + * + * @access private + * @since 2.6.0 + */ +class _WP_Dependency { + /** + * The handle name. + * + * @access public + * @since 2.6.0 + * @var null + */ + var $handle; + + /** + * The handle source. + * + * @access public + * @since 2.6.0 + * @var null + */ + var $src; + + /** + * An array of handle dependencies. + * + * @access public + * @since 2.6.0 + * @var array + */ + var $deps = array(); + + /** + * The handle version. + * + * Used for cache-busting. + * + * @access public + * @since 2.6.0 + * @var bool|string + */ + var $ver = false; + + /** + * Additional arguments for the handle. + * + * @access public + * @since 2.6.0 + * @var null + */ + var $args = null; // Custom property, such as $in_footer or $media. + + /** + * Extra data to supply to the handle. + * + * @access public + * @since 2.6.0 + * @var array + */ + var $extra = array(); + + /** + * Setup dependencies. + * + * @since 2.6.0 + */ + function __construct() { + @list( $this->handle, $this->src, $this->deps, $this->ver, $this->args ) = func_get_args(); + if ( ! is_array($this->deps) ) + $this->deps = array(); + } + + /** + * Add handle data. + * + * @access public + * @since 2.6.0 + * + * @param string $name The data key to add. + * @param mixed $data The data value to add. + * @return bool False if not scalar, true otherwise. + */ + function add_data( $name, $data ) { + if ( !is_scalar($name) ) + return false; + $this->extra[$name] = $data; + return true; + } + +} // _WP_Dependencies diff --git a/sources/wp-includes/class.wp-scripts.php b/sources/wp-includes/class.wp-scripts.php new file mode 100644 index 0000000..5e16632 --- /dev/null +++ b/sources/wp-includes/class.wp-scripts.php @@ -0,0 +1,220 @@ +init(); + add_action( 'init', array( $this, 'init' ), 0 ); + } + + function init() { + do_action_ref_array( 'wp_default_scripts', array(&$this) ); + } + + /** + * Prints scripts + * + * Prints the scripts passed to it or the print queue. Also prints all necessary dependencies. + * + * @param mixed $handles (optional) Scripts to be printed. (void) prints queue, (string) prints that script, (array of strings) prints those scripts. + * @param int $group (optional) If scripts were queued in groups prints this group number. + * @return array Scripts that have been printed + */ + function print_scripts( $handles = false, $group = false ) { + return $this->do_items( $handles, $group ); + } + + // Deprecated since 3.3, see print_extra_script() + function print_scripts_l10n( $handle, $echo = true ) { + _deprecated_function( __FUNCTION__, '3.3', 'print_extra_script()' ); + return $this->print_extra_script( $handle, $echo ); + } + + function print_extra_script( $handle, $echo = true ) { + if ( !$output = $this->get_data( $handle, 'data' ) ) + return; + + if ( !$echo ) + return $output; + + echo "\n"; + + return true; + } + + function do_item( $handle, $group = false ) { + if ( !parent::do_item($handle) ) + return false; + + if ( 0 === $group && $this->groups[$handle] > 0 ) { + $this->in_footer[] = $handle; + return false; + } + + if ( false === $group && in_array($handle, $this->in_footer, true) ) + $this->in_footer = array_diff( $this->in_footer, (array) $handle ); + + if ( null === $this->registered[$handle]->ver ) + $ver = ''; + else + $ver = $this->registered[$handle]->ver ? $this->registered[$handle]->ver : $this->default_version; + + if ( isset($this->args[$handle]) ) + $ver = $ver ? $ver . '&' . $this->args[$handle] : $this->args[$handle]; + + $src = $this->registered[$handle]->src; + + if ( $this->do_concat ) { + $srce = apply_filters( 'script_loader_src', $src, $handle ); + if ( $this->in_default_dir($srce) ) { + $this->print_code .= $this->print_extra_script( $handle, false ); + $this->concat .= "$handle,"; + $this->concat_version .= "$handle$ver"; + return true; + } else { + $this->ext_handles .= "$handle,"; + $this->ext_version .= "$handle$ver"; + } + } + + $this->print_extra_script( $handle ); + if ( !preg_match('|^(https?:)?//|', $src) && ! ( $this->content_url && 0 === strpos($src, $this->content_url) ) ) { + $src = $this->base_url . $src; + } + + if ( !empty($ver) ) + $src = add_query_arg('ver', $ver, $src); + + $src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) ); + + if ( ! $src ) + return true; + + if ( $this->do_concat ) + $this->print_html .= "\n"; + else + echo "\n"; + + return true; + } + + /** + * Localizes a script + * + * Localizes only if the script has already been added + */ + function localize( $handle, $object_name, $l10n ) { + if ( $handle === 'jquery' ) + $handle = 'jquery-core'; + + if ( is_array($l10n) && isset($l10n['l10n_print_after']) ) { // back compat, preserve the code in 'l10n_print_after' if present + $after = $l10n['l10n_print_after']; + unset($l10n['l10n_print_after']); + } + + foreach ( (array) $l10n as $key => $value ) { + if ( !is_scalar($value) ) + continue; + + $l10n[$key] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8'); + } + + $script = "var $object_name = " . json_encode($l10n) . ';'; + + if ( !empty($after) ) + $script .= "\n$after;"; + + $data = $this->get_data( $handle, 'data' ); + + if ( !empty( $data ) ) + $script = "$data\n$script"; + + return $this->add_data( $handle, 'data', $script ); + } + + function set_group( $handle, $recursion, $group = false ) { + + if ( $this->registered[$handle]->args === 1 ) + $grp = 1; + else + $grp = (int) $this->get_data( $handle, 'group' ); + + if ( false !== $group && $grp > $group ) + $grp = $group; + + return parent::set_group( $handle, $recursion, $grp ); + } + + function all_deps( $handles, $recursion = false, $group = false ) { + $r = parent::all_deps( $handles, $recursion ); + if ( !$recursion ) + $this->to_do = apply_filters( 'print_scripts_array', $this->to_do ); + return $r; + } + + function do_head_items() { + $this->do_items(false, 0); + return $this->done; + } + + function do_footer_items() { + $this->do_items(false, 1); + return $this->done; + } + + function in_default_dir($src) { + if ( ! $this->default_dirs ) + return true; + + if ( 0 === strpos( $src, '/wp-includes/js/l10n' ) ) + return false; + + foreach ( (array) $this->default_dirs as $test ) { + if ( 0 === strpos($src, $test) ) + return true; + } + return false; + } + + function reset() { + $this->do_concat = false; + $this->print_code = ''; + $this->concat = ''; + $this->concat_version = ''; + $this->print_html = ''; + $this->ext_version = ''; + $this->ext_handles = ''; + } +} diff --git a/sources/wp-includes/class.wp-styles.php b/sources/wp-includes/class.wp-styles.php new file mode 100644 index 0000000..927a7e7 --- /dev/null +++ b/sources/wp-includes/class.wp-styles.php @@ -0,0 +1,171 @@ +registered[$handle]; + if ( null === $obj->ver ) + $ver = ''; + else + $ver = $obj->ver ? $obj->ver : $this->default_version; + + if ( isset($this->args[$handle]) ) + $ver = $ver ? $ver . '&' . $this->args[$handle] : $this->args[$handle]; + + if ( $this->do_concat ) { + if ( $this->in_default_dir($obj->src) && !isset($obj->extra['conditional']) && !isset($obj->extra['alt']) ) { + $this->concat .= "$handle,"; + $this->concat_version .= "$handle$ver"; + + $this->print_code .= $this->print_inline_style( $handle, false ); + + return true; + } + } + + if ( isset($obj->args) ) + $media = esc_attr( $obj->args ); + else + $media = 'all'; + + $href = $this->_css_href( $obj->src, $ver, $handle ); + $rel = isset($obj->extra['alt']) && $obj->extra['alt'] ? 'alternate stylesheet' : 'stylesheet'; + $title = isset($obj->extra['title']) ? "title='" . esc_attr( $obj->extra['title'] ) . "'" : ''; + + $end_cond = $tag = ''; + if ( isset($obj->extra['conditional']) && $obj->extra['conditional'] ) { + $tag .= "\n"; + } + + $tag .= apply_filters( 'style_loader_tag', "\n", $handle ); + if ( 'rtl' === $this->text_direction && isset($obj->extra['rtl']) && $obj->extra['rtl'] ) { + if ( is_bool( $obj->extra['rtl'] ) ) { + $suffix = isset( $obj->extra['suffix'] ) ? $obj->extra['suffix'] : ''; + $rtl_href = str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $this->_css_href( $obj->src , $ver, "$handle-rtl" )); + } else { + $rtl_href = $this->_css_href( $obj->extra['rtl'], $ver, "$handle-rtl" ); + } + + $tag .= apply_filters( 'style_loader_tag', "\n", $handle ); + } + + $tag .= $end_cond; + + if ( $this->do_concat ) { + $this->print_html .= $tag; + if ( $inline_style = $this->print_inline_style( $handle, false ) ) + $this->print_html .= sprintf( "\n", $inline_style ); + } else { + echo $tag; + $this->print_inline_style( $handle ); + } + + return true; + } + + function add_inline_style( $handle, $code ) { + if ( !$code ) + return false; + + $after = $this->get_data( $handle, 'after' ); + if ( !$after ) + $after = array(); + + $after[] = $code; + + return $this->add_data( $handle, 'after', $after ); + } + + function print_inline_style( $handle, $echo = true ) { + $output = $this->get_data( $handle, 'after' ); + + if ( empty( $output ) ) + return false; + + $output = implode( "\n", $output ); + + if ( !$echo ) + return $output; + + echo "\n"; + + return true; + } + + function all_deps( $handles, $recursion = false, $group = false ) { + $r = parent::all_deps( $handles, $recursion ); + if ( !$recursion ) + $this->to_do = apply_filters( 'print_styles_array', $this->to_do ); + return $r; + } + + function _css_href( $src, $ver, $handle ) { + if ( !is_bool($src) && !preg_match('|^(https?:)?//|', $src) && ! ( $this->content_url && 0 === strpos($src, $this->content_url) ) ) { + $src = $this->base_url . $src; + } + + if ( !empty($ver) ) + $src = add_query_arg('ver', $ver, $src); + $src = apply_filters( 'style_loader_src', $src, $handle ); + return esc_url( $src ); + } + + function in_default_dir($src) { + if ( ! $this->default_dirs ) + return true; + + foreach ( (array) $this->default_dirs as $test ) { + if ( 0 === strpos($src, $test) ) + return true; + } + return false; + } + + function do_footer_items() { // HTML 5 allows styles in the body, grab late enqueued items and output them in the footer. + $this->do_items(false, 1); + return $this->done; + } + + function reset() { + $this->do_concat = false; + $this->concat = ''; + $this->concat_version = ''; + $this->print_html = ''; + } +} diff --git a/sources/wp-includes/comment-template.php b/sources/wp-includes/comment-template.php new file mode 100644 index 0000000..f08e2ef --- /dev/null +++ b/sources/wp-includes/comment-template.php @@ -0,0 +1,2128 @@ +comment_author ) ) { + if ( $comment->user_id && $user = get_userdata( $comment->user_id ) ) + $author = $user->display_name; + else + $author = __('Anonymous'); + } else { + $author = $comment->comment_author; + } + + /** + * Filter the returned comment author name. + * + * @since 1.5.2 + * + * @param string $author The comment author's username. + */ + return apply_filters( 'get_comment_author', $author ); +} + +/** + * Displays the author of the current comment. + * + * @since 0.71 + * + * @param int $comment_ID Optional. The ID of the comment for which to print the author. Default current comment. + */ +function comment_author( $comment_ID = 0 ) { + $author = get_comment_author( $comment_ID ); + /** + * Filter the comment author's name for display. + * + * @since 1.2.1 + * + * @param string $author The comment author's username. + */ + $author = apply_filters( 'comment_author', $author ); + echo $author; +} + +/** + * Retrieve the email of the author of the current comment. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the author's email. Default current comment. + * @return string The current comment author's email + */ +function get_comment_author_email( $comment_ID = 0 ) { + $comment = get_comment( $comment_ID ); + /** + * Filter the comment author's returned email address. + * + * @since 1.5.2 + * + * @param string $comment->comment_author_email The comment author's email address. + */ + return apply_filters( 'get_comment_author_email', $comment->comment_author_email ); +} + +/** + * Display the email of the author of the current global $comment. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commentors' email address. Most assume that + * their email address will not appear in raw form on the blog. Doing so will + * enable anyone, including those that people don't want to get the email + * address and use it for their own means good and bad. + * + * @since 0.71 + * + * @param int $comment_ID Optional. The ID of the comment for which to print the author's email. Default current comment. + */ +function comment_author_email( $comment_ID = 0 ) { + $author_email = get_comment_author_email( $comment_ID ); + /** + * Filter the comment author's email for display. + * + * @since 1.2.1 + * + * @param string $author_email The comment author's email address. + */ + echo apply_filters( 'author_email', $author_email ); +} + +/** + * Display the html email link to the author of the current comment. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commentors' email address. Most assume that + * their email address will not appear in raw form on the blog. Doing so will + * enable anyone, including those that people don't want to get the email + * address and use it for their own means good and bad. + * + * @global object $comment The current Comment row object + + * @since 0.71 + * + * @param string $linktext Optional. The text to display instead of the comment author's email address. Default empty. + * @param string $before Optional. The text or HTML to display before the email link.Default empty. + * @param string $after Optional. The text or HTML to display after the email link. Default empty. + */ +function comment_author_email_link( $linktext = '', $before = '', $after = '' ) { + if ( $link = get_comment_author_email_link( $linktext, $before, $after ) ) + echo $link; +} + +/** + * Return the html email link to the author of the current comment. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commentors' email address. Most assume that + * their email address will not appear in raw form on the blog. Doing so will + * enable anyone, including those that people don't want to get the email + * address and use it for their own means good and bad. + * + * @global object $comment The current Comment row object. + * + * @since 2.7 + * + * @param string $linktext Optional. The text to display instead of the comment author's email address. Default empty. + * @param string $before Optional. The text or HTML to display before the email link. Default empty. + * @param string $after Optional. The text or HTML to display after the email link. Default empty. + */ +function get_comment_author_email_link( $linktext = '', $before = '', $after = '' ) { + global $comment; + /** + * Filter the comment author's email for display. + * + * Care should be taken to protect the email address and assure that email + * harvesters do not capture your commentors' email address. + * + * @since 1.2.1 + * + * @param string $comment->comment_author_email The comment author's email address. + */ + $email = apply_filters( 'comment_email', $comment->comment_author_email ); + if ((!empty($email)) && ($email != '@')) { + $display = ($linktext != '') ? $linktext : $email; + $return = $before; + $return .= "$display"; + $return .= $after; + return $return; + } else { + return ''; + } +} + +/** + * Retrieve the HTML link to the URL of the author of the current comment. + * + * Both get_comment_author_url() and get_comment_author() rely on get_comment(), + * which falls back to the global comment variable if the $comment_ID argument is empty. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the author's link. Default current comment. + * @return string The comment author name or HTML link for author's URL. + */ +function get_comment_author_link( $comment_ID = 0 ) { + $url = get_comment_author_url( $comment_ID ); + $author = get_comment_author( $comment_ID ); + + if ( empty( $url ) || 'http://' == $url ) + $return = $author; + else + $return = "$author"; + + /** + * Filter the comment author's link for display. + * + * @since 1.5.2 + * + * @param string $return The HTML-formatted comment author link. Empty for an invalid URL. + */ + return apply_filters( 'get_comment_author_link', $return ); +} + +/** + * Display the html link to the url of the author of the current comment. + * + * @since 0.71 + * @see get_comment_author_link() Echoes result + * + * @param int $comment_ID Optional. The ID of the comment for which to print the author's link. Default current comment. + */ +function comment_author_link( $comment_ID = 0 ) { + echo get_comment_author_link( $comment_ID ); +} + +/** + * Retrieve the IP address of the author of the current comment. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the author's IP address. Default current comment. + * @return string The comment author's IP address. + */ +function get_comment_author_IP( $comment_ID = 0 ) { + $comment = get_comment( $comment_ID ); + + /** + * Filter the comment author's returned IP address. + * + * @since 1.5.2 + * + * @param string $comment->comment_author_IP The comment author's IP address. + */ + return apply_filters( 'get_comment_author_IP', $comment->comment_author_IP ); +} + +/** + * Display the IP address of the author of the current comment. + * + * @since 0.71 + * + * @param int $comment_ID Optional. The ID of the comment for which to print the author's IP address. Default current comment. + */ +function comment_author_IP( $comment_ID = 0 ) { + echo get_comment_author_IP( $comment_ID ); +} + +/** + * Retrieve the url of the author of the current comment. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the author's URL. Default current comment. + * @return string + */ +function get_comment_author_url( $comment_ID = 0 ) { + $comment = get_comment( $comment_ID ); + $url = ('http://' == $comment->comment_author_url) ? '' : $comment->comment_author_url; + $url = esc_url( $url, array('http', 'https') ); + return apply_filters('get_comment_author_url', $url); +} + +/** + * Display the url of the author of the current comment. + * + * @since 0.71 + * + * @param int $comment_ID Optional. The ID of the comment for which to print the author's URL. Default current comment. + */ +function comment_author_url( $comment_ID = 0 ) { + $author_url = get_comment_author_url( $comment_ID ); + /** + * Filter the comment author's URL for display. + * + * @since 1.2.1 + * + * @param string $author_url The comment author's URL. + */ + echo apply_filters( 'comment_url', $author_url ); +} + +/** + * Retrieves the HTML link of the url of the author of the current comment. + * + * $linktext parameter is only used if the URL does not exist for the comment + * author. If the URL does exist then the URL will be used and the $linktext + * will be ignored. + * + * Encapsulate the HTML link between the $before and $after. So it will appear + * in the order of $before, link, and finally $after. + * + * @since 1.5.0 + * + * @param string $linktext Optional. The text to display instead of the comment author's email address. Default empty. + * @param string $before Optional. The text or HTML to display before the email link. Default empty. + * @param string $after Optional. The text or HTML to display after the email link. Default empty. + * @return string The HTML link between the $before and $after parameters. + */ +function get_comment_author_url_link( $linktext = '', $before = '', $after = '' ) { + $url = get_comment_author_url(); + $display = ($linktext != '') ? $linktext : $url; + $display = str_replace( 'http://www.', '', $display ); + $display = str_replace( 'http://', '', $display ); + if ( '/' == substr($display, -1) ) + $display = substr($display, 0, -1); + $return = "$before$display$after"; + + /** + * Filter the comment author's returned URL link. + * + * @since 1.5.2 + * + * @param string $return The HTML-formatted comment author URL link. + */ + return apply_filters( 'get_comment_author_url_link', $return ); +} + +/** + * Displays the HTML link of the url of the author of the current comment. + * + * @since 0.71 + * + * @param string $linktext Optional. The text to display instead of the comment author's email address. Default empty. + * @param string $before Optional. The text or HTML to display before the email link. Default empty. + * @param string $after Optional. The text or HTML to display after the email link. Default empty. + */ +function comment_author_url_link( $linktext = '', $before = '', $after = '' ) { + echo get_comment_author_url_link( $linktext, $before, $after ); +} + +/** + * Generates semantic classes for each comment element + * + * @since 2.7.0 + * + * @param string|array $class Optional. One or more classes to add to the class list. Default empty. + * @param int $comment_id Optional. Comment ID. Default current comment. + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default current post. + * @param bool $echo Optional. Whether comment_class should echo or return. Default true. + */ +function comment_class( $class = '', $comment_id = null, $post_id = null, $echo = true ) { + // Separates classes with a single space, collates classes for comment DIV + $class = 'class="' . join( ' ', get_comment_class( $class, $comment_id, $post_id ) ) . '"'; + if ( $echo) + echo $class; + else + return $class; +} + +/** + * Returns the classes for the comment div as an array + * + * @since 2.7.0 + * + * @param string|array $class Optional. One or more classes to add to the class list. Default empty. + * @param int $comment_id Optional. Comment ID. Default current comment. + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default current post. + * @return array An array of classes. + */ +function get_comment_class( $class = '', $comment_id = null, $post_id = null ) { + global $comment_alt, $comment_depth, $comment_thread_alt; + + $comment = get_comment($comment_id); + + $classes = array(); + + // Get the comment type (comment, trackback), + $classes[] = ( empty( $comment->comment_type ) ) ? 'comment' : $comment->comment_type; + + // If the comment author has an id (registered), then print the log in name + if ( $comment->user_id > 0 && $user = get_userdata($comment->user_id) ) { + // For all registered users, 'byuser' + $classes[] = 'byuser'; + $classes[] = 'comment-author-' . sanitize_html_class($user->user_nicename, $comment->user_id); + // For comment authors who are the author of the post + if ( $post = get_post($post_id) ) { + if ( $comment->user_id === $post->post_author ) + $classes[] = 'bypostauthor'; + } + } + + if ( empty($comment_alt) ) + $comment_alt = 0; + if ( empty($comment_depth) ) + $comment_depth = 1; + if ( empty($comment_thread_alt) ) + $comment_thread_alt = 0; + + if ( $comment_alt % 2 ) { + $classes[] = 'odd'; + $classes[] = 'alt'; + } else { + $classes[] = 'even'; + } + + $comment_alt++; + + // Alt for top-level comments + if ( 1 == $comment_depth ) { + if ( $comment_thread_alt % 2 ) { + $classes[] = 'thread-odd'; + $classes[] = 'thread-alt'; + } else { + $classes[] = 'thread-even'; + } + $comment_thread_alt++; + } + + $classes[] = "depth-$comment_depth"; + + if ( !empty($class) ) { + if ( !is_array( $class ) ) + $class = preg_split('#\s+#', $class); + $classes = array_merge($classes, $class); + } + + $classes = array_map('esc_attr', $classes); + + /** + * Filter the returned CSS classes for the current comment. + * + * @since 2.7.0 + * + * @param array $classes An array of comment classes. + * @param string $class A comma-separated list of additional classes added to the list. + * @param int $comment_id The comment id. + * @param int|WP_Post $post_id The post ID or WP_Post object. + */ + return apply_filters( 'comment_class', $classes, $class, $comment_id, $post_id ); +} + +/** + * Retrieve the comment date of the current comment. + * + * @since 1.5.0 + * + * @param string $d Optional. The format of the date. Default user's setting. + * @param int $comment_ID Optional. The ID of the comment for which to get the date. Default current comment. + * @return string The comment's date. + */ +function get_comment_date( $d = '', $comment_ID = 0 ) { + $comment = get_comment( $comment_ID ); + if ( '' == $d ) + $date = mysql2date(get_option('date_format'), $comment->comment_date); + else + $date = mysql2date($d, $comment->comment_date); + /** + * Filter the returned comment date. + * + * @since 1.5.2 + * + * @param string|int $date Formatted date string or Unix timestamp. + * @param string $d The format of the date. + */ + return apply_filters( 'get_comment_date', $date, $d ); +} + +/** + * Display the comment date of the current comment. + * + * @since 0.71 + * + * @param string $d Optional. The format of the date. Default user's settings. + * @param int $comment_ID Optional. The ID of the comment for which to print the date. Default current comment. + */ +function comment_date( $d = '', $comment_ID = 0 ) { + echo get_comment_date( $d, $comment_ID ); +} + +/** + * Retrieve the excerpt of the current comment. + * + * Will cut each word and only output the first 20 words with '…' at the end. + * If the word count is less than 20, then no truncating is done and no '…' + * will appear. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the excerpt. Default current comment. + * @return string The maybe truncated comment with 20 words or less. + */ +function get_comment_excerpt( $comment_ID = 0 ) { + $comment = get_comment( $comment_ID ); + $comment_text = strip_tags($comment->comment_content); + $blah = explode(' ', $comment_text); + if (count($blah) > 20) { + $k = 20; + $use_dotdotdot = 1; + } else { + $k = count($blah); + $use_dotdotdot = 0; + } + $excerpt = ''; + for ($i=0; $i<$k; $i++) { + $excerpt .= $blah[$i] . ' '; + } + $excerpt .= ($use_dotdotdot) ? '…' : ''; + return apply_filters('get_comment_excerpt', $excerpt); +} + +/** + * Display the excerpt of the current comment. + * + * @since 1.2.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to print the excerpt. Default current comment. + */ +function comment_excerpt( $comment_ID = 0 ) { + $comment_excerpt = get_comment_excerpt($comment_ID); + /** + * Filter the comment excerpt for display. + * + * @since 1.2.1 + * + * @param string $comment_excerpt The comment excerpt text. + */ + echo apply_filters( 'comment_excerpt', $comment_excerpt ); +} + +/** + * Retrieve the comment id of the current comment. + * + * @since 1.5.0 + * + * @return int The comment ID. + */ +function get_comment_ID() { + global $comment; + /** + * Filter the returned comment ID. + * + * @since 1.5.2 + * + * @param int $comment->comment_ID The current comment ID. + */ + return apply_filters( 'get_comment_ID', $comment->comment_ID ); +} + +/** + * Display the comment id of the current comment. + * + * @since 0.71 + */ +function comment_ID() { + echo get_comment_ID(); +} + +/** + * Retrieve the link to a given comment. + * + * @since 1.5.0 + * + * @param mixed $comment Optional. Comment to retrieve. Default current comment. + * @param array $args Optional. An array of arguments to override the defaults. @see get_page_of_comment() + * @return string The permalink to the given comment. + */ +function get_comment_link( $comment = null, $args = array() ) { + global $wp_rewrite, $in_comment_loop; + + $comment = get_comment($comment); + + // Backwards compat + if ( !is_array($args) ) { + $page = $args; + $args = array(); + $args['page'] = $page; + } + + $defaults = array( 'type' => 'all', 'page' => '', 'per_page' => '', 'max_depth' => '' ); + $args = wp_parse_args( $args, $defaults ); + + if ( '' === $args['per_page'] && get_option('page_comments') ) + $args['per_page'] = get_option('comments_per_page'); + + if ( empty($args['per_page']) ) { + $args['per_page'] = 0; + $args['page'] = 0; + } + + if ( $args['per_page'] ) { + if ( '' == $args['page'] ) + $args['page'] = ( !empty($in_comment_loop) ) ? get_query_var('cpage') : get_page_of_comment( $comment->comment_ID, $args ); + + if ( $wp_rewrite->using_permalinks() ) + $link = user_trailingslashit( trailingslashit( get_permalink( $comment->comment_post_ID ) ) . 'comment-page-' . $args['page'], 'comment' ); + else + $link = add_query_arg( 'cpage', $args['page'], get_permalink( $comment->comment_post_ID ) ); + } else { + $link = get_permalink( $comment->comment_post_ID ); + } + + $link = $link . '#comment-' . $comment->comment_ID; + /** + * Filter the returned single comment permalink. + * + * @since 2.8.0 + * + * @param string $link The comment permalink with '#comment-$id' appended. + * @param object $comment The current comment object. + * @param array $args An array of arguments to override the defaults. @see get_page_of_comment() + */ + return apply_filters( 'get_comment_link', $link, $comment, $args ); +} + +/** + * Retrieve the link to the current post comments. + * + * @since 1.5.0 + * + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default current post. + * @return string The link to the comments. + */ +function get_comments_link( $post_id = 0 ) { + $comments_link = get_permalink( $post_id ) . '#comments'; + /** + * Filter the returned post comments permalink. + * + * @since + * + * @param string $comments_link The post comments permalink with '#comments' appended. + * @param int|WP_Post $post_id The post ID or WP_Post object. + */ + return apply_filters( 'get_comments_link', $comments_link, $post_id ); +} + +/** + * Display the link to the current post comments. + * + * @since 0.71 + * + * @param string $deprecated Not Used. + * @param bool $deprecated_2 Not Used. + */ +function comments_link( $deprecated = '', $deprecated_2 = '' ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '0.72' ); + if ( !empty( $deprecated_2 ) ) + _deprecated_argument( __FUNCTION__, '1.3' ); + echo esc_url( get_comments_link() ); +} + +/** + * Retrieve the amount of comments a post has. + * + * @since 1.5.0 + * + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default current post. + * @return int The number of comments a post has. + */ +function get_comments_number( $post_id = 0 ) { + $post_id = absint( $post_id ); + + if ( !$post_id ) + $post_id = get_the_ID(); + + $post = get_post($post_id); + if ( ! isset($post->comment_count) ) + $count = 0; + else + $count = $post->comment_count; + + /** + * Filter the returned comment count for a post. + * + * @since 1.5.2 + * + * @param int $count The number of comments a post has. + * @param int|WP_Post $post_id The post ID or WP_Post object. + */ + return apply_filters( 'get_comments_number', $count, $post_id ); +} + +/** + * Display the language string for the number of comments the current post has. + * + * @since 0.71 + * + * @param string $zero Optional. Text for no comments. Default false. + * @param string $one Optional. Text for one comment. Default false. + * @param string $more Optional. Text for more than one comment. Default false. + * @param string $deprecated Not used. + */ +function comments_number( $zero = false, $one = false, $more = false, $deprecated = '' ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '1.3' ); + + $number = get_comments_number(); + + if ( $number > 1 ) + $output = str_replace('%', number_format_i18n($number), ( false === $more ) ? __('% Comments') : $more); + elseif ( $number == 0 ) + $output = ( false === $zero ) ? __('No Comments') : $zero; + else // must be one + $output = ( false === $one ) ? __('1 Comment') : $one; + + /** + * Filter the comments count for display. + * + * @since 1.5.2 + * + * @param string $output A translatable string formatted based on whether the count is equal to 0, 1, or 1+. @see _n() + * @param int $number The number of post comments. + */ + echo apply_filters( 'comments_number', $output, $number ); +} + +/** + * Retrieve the text of the current comment. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the text. Default current comment. + * @param array $args Optional. An array of arguments. @see Walker_Comment::comment() + * @return string The comment content. + */ +function get_comment_text( $comment_ID = 0, $args = array() ) { + $comment = get_comment( $comment_ID ); + + /** + * Filter the text of a comment. + * + * @since 1.5.2 + * + * @param string $comment->comment_content The text of the comment. + * @param object $comment The comment object. + * @param array $args An array of arguments. @see Walker_Comment::comment() + */ + return apply_filters( 'get_comment_text', $comment->comment_content, $comment, $args ); +} + +/** + * Display the text of the current comment. + * + * @since 0.71 + * + * @param int $comment_ID Optional. The ID of the comment for which to print the text. + * Default 0. + * @param array $args Optional. An array of arguments. @see Walker_Comment::comment() + * Default empty array. + */ +function comment_text( $comment_ID = 0, $args = array() ) { + $comment = get_comment( $comment_ID ); + + $comment_text = get_comment_text( $comment_ID , $args ); + /** + * Filter the text of a comment to be displayed. + * + * @since 1.2.1 + * + * @param string $comment_text The text of the current comment. + * @param object $comment The comment object. + * @param array $args An array of arguments. @see Walker_Comment::comment() + */ + echo apply_filters( 'comment_text', $comment_text, $comment, $args ); +} + +/** + * Retrieve the comment time of the current comment. + * + * @since 1.5.0 + * + * @param string $d Optional. The format of the time. Default user's settings. + * @param bool $gmt Optional. Whether to use the GMT date. Default false. + * @param bool $translate Optional. Whether to translate the time (for use in feeds). Default true. + * @return string The formatted time + */ +function get_comment_time( $d = '', $gmt = false, $translate = true ) { + global $comment; + $comment_date = $gmt ? $comment->comment_date_gmt : $comment->comment_date; + if ( '' == $d ) + $date = mysql2date(get_option('time_format'), $comment_date, $translate); + else + $date = mysql2date($d, $comment_date, $translate); + + /** + * Filter the returned comment time. + * + * @since 1.5.2 + * + * @param string|int $date The comment time, formatted as a date string or Unix timestamp. + * @param string $d The date format. + * @param bool $gmt Whether the GMT date is in use. + * @param bool $translate Whether the time is translated. + */ + return apply_filters( 'get_comment_time', $date, $d, $gmt, $translate ); +} + +/** + * Display the comment time of the current comment. + * + * @since 0.71 + * + * @param string $d Optional. The format of the time. Default user's settings. + */ +function comment_time( $d = '' ) { + echo get_comment_time($d); +} + +/** + * Retrieve the comment type of the current comment. + * + * @since 1.5.0 + * + * @param int $comment_ID Optional. The ID of the comment for which to get the type. Default current comment. + * @return string The comment type + */ +function get_comment_type( $comment_ID = 0 ) { + $comment = get_comment( $comment_ID ); + if ( '' == $comment->comment_type ) + $comment->comment_type = 'comment'; + + /** + * Filter the returned comment type. + * + * @since 1.5.2 + * + * @param string $comment->comment_type The type of comment, such as 'comment', 'pingback', or 'trackback'. + */ + return apply_filters( 'get_comment_type', $comment->comment_type ); +} + +/** + * Display the comment type of the current comment. + * + * @since 0.71 + * + * @param string $commenttxt Optional. The string to display for comment type. Default false. + * @param string $trackbacktxt Optional. The string to display for trackback type. Default false. + * @param string $pingbacktxt Optional. The string to display for pingback type. Default false. + */ +function comment_type( $commenttxt = false, $trackbacktxt = false, $pingbacktxt = false ) { + if ( false === $commenttxt ) $commenttxt = _x( 'Comment', 'noun' ); + if ( false === $trackbacktxt ) $trackbacktxt = __( 'Trackback' ); + if ( false === $pingbacktxt ) $pingbacktxt = __( 'Pingback' ); + $type = get_comment_type(); + switch( $type ) { + case 'trackback' : + echo $trackbacktxt; + break; + case 'pingback' : + echo $pingbacktxt; + break; + default : + echo $commenttxt; + } +} + +/** + * Retrieve The current post's trackback URL. + * + * There is a check to see if permalink's have been enabled and if so, will + * retrieve the pretty path. If permalinks weren't enabled, the ID of the + * current post is used and appended to the correct page to go to. + * + * @since 1.5.0 + * + * @return string The trackback URL after being filtered. + */ +function get_trackback_url() { + if ( '' != get_option('permalink_structure') ) + $tb_url = trailingslashit(get_permalink()) . user_trailingslashit('trackback', 'single_trackback'); + else + $tb_url = get_option('siteurl') . '/wp-trackback.php?p=' . get_the_ID(); + + /** + * Filter the returned trackback URL. + * + * @since 2.2.0 + * + * @param string $tb_url The trackback URL. + */ + return apply_filters( 'trackback_url', $tb_url ); +} + +/** + * Display the current post's trackback URL. + * + * @since 0.71 + * + * @param bool $deprecated_echo Not used. + * @return void|string Should only be used to echo the trackback URL, use get_trackback_url() for the result instead. + */ +function trackback_url( $deprecated_echo = true ) { + if ( $deprecated_echo !== true ) + _deprecated_argument( __FUNCTION__, '2.5', __('Use get_trackback_url() instead if you do not want the value echoed.') ); + if ( $deprecated_echo ) + echo get_trackback_url(); + else + return get_trackback_url(); +} + +/** + * Generate and display the RDF for the trackback information of current post. + * + * Deprecated in 3.0.0, and restored in 3.0.1. + * + * @since 0.71 + * + * @param int $deprecated Not used (Was $timezone = 0). + */ +function trackback_rdf( $deprecated = '' ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.5' ); + + if ( false !== stripos($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator') ) + return; + + echo ' + \n"; + echo ''; +} + +/** + * Whether the current post is open for comments. + * + * @since 1.5.0 + * + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default current post. + * @return bool True if the comments are open. + */ +function comments_open( $post_id = null ) { + + $_post = get_post($post_id); + + $open = ( 'open' == $_post->comment_status ); + + /** + * Filter whether the current post is open for comments. + * + * @since + * + * @param bool $open Whether the current post is open for comments. + * @param int|WP_Post $post_id The post ID or WP_Post object. + */ + return apply_filters( 'comments_open', $open, $post_id ); +} + +/** + * Whether the current post is open for pings. + * + * @since 1.5.0 + * + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default current post. + * @return bool True if pings are accepted + */ +function pings_open( $post_id = null ) { + + $_post = get_post($post_id); + + $open = ( 'open' == $_post->ping_status ); + return apply_filters( 'pings_open', $open, $post_id ); +} + +/** + * Display form token for unfiltered comments. + * + * Will only display nonce token if the current user has permissions for + * unfiltered html. Won't display the token for other users. + * + * The function was backported to 2.0.10 and was added to versions 2.1.3 and + * above. Does not exist in versions prior to 2.0.10 in the 2.0 branch and in + * the 2.1 branch, prior to 2.1.3. Technically added in 2.2.0. + * + * Backported to 2.0.10. + * + * @since 2.1.3 + */ +function wp_comment_form_unfiltered_html_nonce() { + $post = get_post(); + $post_id = $post ? $post->ID : 0; + + if ( current_user_can( 'unfiltered_html' ) ) { + wp_nonce_field( 'unfiltered-html-comment_' . $post_id, '_wp_unfiltered_html_comment_disabled', false ); + echo "\n"; + } +} + +/** + * Load the comment template specified in $file. + * + * Will not display the comments template if not on single post or page, or if + * the post does not have comments. + * + * Uses the WordPress database object to query for the comments. The comments + * are passed through the 'comments_array' filter hook with the list of comments + * and the post ID respectively. + * + * The $file path is passed through a filter hook called, 'comments_template' + * which includes the TEMPLATEPATH and $file combined. Tries the $filtered path + * first and if it fails it will require the default comment template from the + * default theme. If either does not exist, then the WordPress process will be + * halted. It is advised for that reason, that the default theme is not deleted. + * + * @todo Document globals + * @uses $withcomments Will not try to get the comments if the post has none. + * + * @since 1.5.0 + * + * @param string $file Optional. The file to load. Default '/comments.php'. + * @param bool $separate_comments Optional. Whether to separate the comments by comment type. Default false. + * @return null Returns null if no comments appear. + */ +function comments_template( $file = '/comments.php', $separate_comments = false ) { + global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $user_login, $user_ID, $user_identity, $overridden_cpage; + + if ( !(is_single() || is_page() || $withcomments) || empty($post) ) + return; + + if ( empty($file) ) + $file = '/comments.php'; + + $req = get_option('require_name_email'); + + /** + * Comment author information fetched from the comment cookies. + * + * @uses wp_get_current_commenter() + */ + $commenter = wp_get_current_commenter(); + + /** + * The name of the current comment author escaped for use in attributes. + */ + $comment_author = $commenter['comment_author']; // Escaped by sanitize_comment_cookies() + + /** + * The email address of the current comment author escaped for use in attributes. + */ + $comment_author_email = $commenter['comment_author_email']; // Escaped by sanitize_comment_cookies() + + /** + * The url of the current comment author escaped for use in attributes. + */ + $comment_author_url = esc_url($commenter['comment_author_url']); + + /** @todo Use API instead of SELECTs. */ + if ( $user_ID) { + $comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND (comment_approved = '1' OR ( user_id = %d AND comment_approved = '0' ) ) ORDER BY comment_date_gmt", $post->ID, $user_ID)); + } else if ( empty($comment_author) ) { + $comments = get_comments( array('post_id' => $post->ID, 'status' => 'approve', 'order' => 'ASC') ); + } else { + $comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND ( comment_approved = '1' OR ( comment_author = %s AND comment_author_email = %s AND comment_approved = '0' ) ) ORDER BY comment_date_gmt", $post->ID, wp_specialchars_decode($comment_author,ENT_QUOTES), $comment_author_email)); + } + + // keep $comments for legacy's sake + /** + * Filter the comments array. + * + * @since 2.1.0 + * + * @param array $comments The array of comments supplied to the comments template. + * @param int $post->ID The post ID. + */ + $wp_query->comments = apply_filters( 'comments_array', $comments, $post->ID ); + $comments = &$wp_query->comments; + $wp_query->comment_count = count($wp_query->comments); + update_comment_cache($wp_query->comments); + + if ( $separate_comments ) { + $wp_query->comments_by_type = separate_comments($comments); + $comments_by_type = &$wp_query->comments_by_type; + } + + $overridden_cpage = false; + if ( '' == get_query_var('cpage') && get_option('page_comments') ) { + set_query_var( 'cpage', 'newest' == get_option('default_comments_page') ? get_comment_pages_count() : 1 ); + $overridden_cpage = true; + } + + if ( !defined('COMMENTS_TEMPLATE') ) + define('COMMENTS_TEMPLATE', true); + + $theme_template = STYLESHEETPATH . $file; + /** + * Filter the path to the theme template file used for the comments template. + * + * @since 1.5.2 + * + * @param string $theme_template The path to the theme template file. + */ + $include = apply_filters( 'comments_template', $theme_template ); + if ( file_exists( $include ) ) + require( $include ); + elseif ( file_exists( TEMPLATEPATH . $file ) ) + require( TEMPLATEPATH . $file ); + else // Backward compat code will be removed in a future release + require( ABSPATH . WPINC . '/theme-compat/comments.php'); +} + +/** + * Display the JS popup script to show a comment. + * + * If the $file parameter is empty, then the home page is assumed. The defaults + * for the window are 400px by 400px. + * + * For the comment link popup to work, this function has to be called or the + * normal comment link will be assumed. + * + * @global string $wpcommentspopupfile The URL to use for the popup window. + * @global int $wpcommentsjavascript Whether to use JavaScript. Set when function is called. + * + * @since 0.71 + * + * @param int $width Optional. The width of the popup window. Default 400. + * @param int $height Optional. The height of the popup window. Default 400. + * @param string $file Optional. Sets the location of the popup window. + */ +function comments_popup_script( $width = 400, $height = 400, $file = '' ) { + global $wpcommentspopupfile, $wpcommentsjavascript; + + if (empty ($file)) { + $wpcommentspopupfile = ''; // Use the index. + } else { + $wpcommentspopupfile = $file; + } + + $wpcommentsjavascript = 1; + $javascript = "\n"; + echo $javascript; +} + +/** + * Displays the link to the comments popup window for the current post ID. + * + * Is not meant to be displayed on single posts and pages. Should be used on the + * lists of posts + * + * @global string $wpcommentspopupfile The URL to use for the popup window. + * @global int $wpcommentsjavascript Whether to use JavaScript. Set when function is called. + * + * @since 0.71 + * + * @param string $zero Optional. The string to display when no comments. Default false. + * @param string $one Optional. The string to display when only one comment is available. Default false. + * @param string $more Optional. The string to display when there are more than one comment. Default false. + * @param string $css_class Optional. The CSS class to use for comments. Default empty. + * @param string $none Optional. The string to display when comments have been turned off. Default false. + * @return null Returns null on single posts and pages. + */ +function comments_popup_link( $zero = false, $one = false, $more = false, $css_class = '', $none = false ) { + global $wpcommentspopupfile, $wpcommentsjavascript; + + $id = get_the_ID(); + + if ( false === $zero ) $zero = __( 'No Comments' ); + if ( false === $one ) $one = __( '1 Comment' ); + if ( false === $more ) $more = __( '% Comments' ); + if ( false === $none ) $none = __( 'Comments Off' ); + + $number = get_comments_number( $id ); + + if ( 0 == $number && !comments_open() && !pings_open() ) { + echo '' . $none . ''; + return; + } + + if ( post_password_required() ) { + echo __('Enter your password to view comments.'); + return; + } + + echo ' 0 ) ); + + $attributes = ''; + /** + * Filter the comments popup link attributes for display. + * + * @since 2.5.0 + * + * @param string $attributes The comments popup link attributes. Default empty. + */ + echo apply_filters( 'comments_popup_link_attributes', $attributes ); + + echo ' title="' . esc_attr( sprintf( __('Comment on %s'), $title ) ) . '">'; + comments_number( $zero, $one, $more ); + echo ''; +} + +/** + * Retrieve HTML content for reply to comment link. + * + * @since 2.7.0 + * + * @param array $args { + * Optional. Override default arguments. + * + * @type string 'add_below' The first part of the selector used to identify the comment to respond below. The resulting + * value is passed as the first parameter to addComment.moveForm(), concatenated + * as $add_below-$comment->comment_ID. Default 'comment'. + * @type string 'respond_id' The selector identifying the responding comment. Passed as the third parameter to addComment.moveForm(), + * and appended to the link URL as a hash value. Default 'respond'. + * @type string 'reply_text' The text of the Reply link. Default 'Reply'. + * @type string 'login_text' The text of the link to reply if logged out. Default 'Log in to Reply'. + * @type int 'depth' The depth of the new comment. Must be greater than 0 and less than the value of the 'thread_comments_depth' + * option set in Settings > Discussion. + * Default 0. + * @type string 'before' The text or HTML to add before the reply link. Default empty. + * @type string 'after' The text or HTML to add after the reply link. Default empty. + * } + * @param int $comment Optional. Comment being replied to. Default current comment. + * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on. Default current post. + * @return mixed Link to show comment form, if successful. False, if comments are closed. + */ +function get_comment_reply_link($args = array(), $comment = null, $post = null) { + + $defaults = array( + 'add_below' => 'comment', + 'respond_id' => 'respond', + 'reply_text' => __('Reply'), + 'login_text' => __('Log in to Reply'), + 'depth' => 0, + 'before' => '', + 'after' => '' + ); + + $args = wp_parse_args($args, $defaults); + + if ( 0 == $args['depth'] || $args['max_depth'] <= $args['depth'] ) + return; + + extract($args, EXTR_SKIP); + + $comment = get_comment($comment); + if ( empty($post) ) + $post = $comment->comment_post_ID; + $post = get_post($post); + + if ( !comments_open($post->ID) ) + return false; + + $link = ''; + + if ( get_option('comment_registration') && ! is_user_logged_in() ) + $link = ''; + else + $link = "comment_ID ) ) . "#" . $respond_id . "' onclick='return addComment.moveForm(\"$add_below-$comment->comment_ID\", \"$comment->comment_ID\", \"$respond_id\", \"$post->ID\")'>$reply_text"; + + /** + * Filter the comment reply link. + * + * @since 2.7.0 + * + * @param string $before Text or HTML displayed before the reply link. + * @param string $link The HTML markup for the comment reply link. + * @param string $after Text or HTML displayed after the reply link. + * @param array $args An array of arguments overriding the defaults. + * @param object $comment The object of the comment being replied. + * @param WP_Post $post The WP_Post object. + */ + return apply_filters( 'comment_reply_link', $before . $link . $after, $args, $comment, $post ); +} + +/** + * Displays the HTML content for reply to comment link. + * + * @since 2.7.0 + * + * @param array $args Optional. Override default options, @see get_comment_reply_link() + * @param int $comment Optional. Comment being replied to. Default current comment. + * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on. Default current post. + * @return mixed Link to show comment form, if successful. False, if comments are closed. + */ +function comment_reply_link($args = array(), $comment = null, $post = null) { + echo get_comment_reply_link($args, $comment, $post); +} + +/** + * Retrieve HTML content for reply to post link. + * + * @since 2.7.0 + * + * @param array $args { + * Optional. Override default arguments. + * + * @type string 'add_below' The first part of the selector used to identify the comment to respond below. + * The resulting value is passed as the first parameter to addComment.moveForm(), + * concatenated as $add_below-$comment->comment_ID. Default is 'post'. + * @type string 'respond_id' The selector identifying the responding comment. Passed as the third parameter + * to addComment.moveForm(), and appended to the link URL as a hash value. Default is 'respond'. + * @type string 'reply_text' The text of the Reply link. Default is 'Leave a Comment'. + * @type string 'login_text' The text of the link to reply if logged out. Default is 'Log in to leave a Comment'. + * @type string 'before' The text or HTML to add before the reply link. Default empty. + * @type string 'after' The text or HTML to add after the reply link. Default empty. + * } + * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on. Default current post. + * @return string|bool|null Link to show comment form, if successful. False, if comments are closed. + */ +function get_post_reply_link($args = array(), $post = null) { + $defaults = array( + 'add_below' => 'post', + 'respond_id' => 'respond', + 'reply_text' => __('Leave a Comment'), + 'login_text' => __('Log in to leave a Comment'), + 'before' => '', + 'after' => '', + ); + + $args = wp_parse_args($args, $defaults); + extract($args, EXTR_SKIP); + $post = get_post($post); + + if ( !comments_open($post->ID) ) + return false; + + if ( get_option('comment_registration') && ! is_user_logged_in() ) + $link = '' . $login_text . ''; + else + $link = "$reply_text"; + + $formatted_link = $before . $link . $after; + /** + * Filter the formatted post comments link HTML. + * + * @since 2.7.0 + * + * @param string $formatted The HTML-formatted post comments link. + * @param int|WP_Post $post The post ID or WP_Post object. + */ + return apply_filters( 'post_comments_link', $formatted_link, $post ); +} + +/** + * Displays the HTML content for reply to post link. + * + * @since 2.7.0 + * + * @param array $args Optional. Override default options, @see get_post_reply_link() + * @param int|WP_Post $post Optional. Post ID or WP_Post object the comment is going to be displayed on. Default current post. + * @return string|bool|null Link to show comment form, if successful. False, if comments are closed. + */ +function post_reply_link($args = array(), $post = null) { + echo get_post_reply_link($args, $post); +} + +/** + * Retrieve HTML content for cancel comment reply link. + * + * @since 2.7.0 + * + * @param string $text Optional. Text to display for cancel reply link. Default empty. + */ +function get_cancel_comment_reply_link( $text = '' ) { + if ( empty($text) ) + $text = __('Click here to cancel reply.'); + + $style = isset($_GET['replytocom']) ? '' : ' style="display:none;"'; + $link = esc_html( remove_query_arg('replytocom') ) . '#respond'; + + $formatted_link = '' . $text . ''; + /** + * Filter the cancel comment reply link HTML. + * + * @since 2.7.0 + * + * @param string $formatted_link The HTML-formatted cancel comment reply link. + * @param string $link The cancel comment reply link URL. + * @param string $text The cancel comment reply link text. + */ + return apply_filters( 'cancel_comment_reply_link', $formatted_link, $link, $text ); +} + +/** + * Display HTML content for cancel comment reply link. + * + * @since 2.7.0 + * + * @param string $text Optional. Text to display for cancel reply link. Default empty. + */ +function cancel_comment_reply_link( $text = '' ) { + echo get_cancel_comment_reply_link($text); +} + +/** + * Retrieve hidden input HTML for replying to comments. + * + * @since 3.0.0 + * + * @param int $id Optional. Post ID. Default current post ID. + * @return string Hidden input HTML for replying to comments + */ +function get_comment_id_fields( $id = 0 ) { + if ( empty( $id ) ) + $id = get_the_ID(); + + $replytoid = isset($_GET['replytocom']) ? (int) $_GET['replytocom'] : 0; + $result = "\n"; + $result .= "\n"; + + /** + * Filter the returned comment id fields. + * + * @since 3.0.0 + * + * @param string $result The HTML-formatted hidden id field comment elements. + * @param int $id The post ID. + * @param int $replytoid The id of the comment being replied to. + */ + return apply_filters( 'comment_id_fields', $result, $id, $replytoid ); +} + +/** + * Output hidden input HTML for replying to comments. + * + * @since 2.7.0 + * + * @param int $id Optional. Post ID. Default current post ID. + */ +function comment_id_fields( $id = 0 ) { + echo get_comment_id_fields( $id ); +} + +/** + * Display text based on comment reply status. + * + * Only affects users with Javascript disabled. + * + * @since 2.7.0 + * + * @param string $noreplytext Optional. Text to display when not replying to a comment. Default false. + * @param string $replytext Optional. Text to display when replying to a comment. + * Default false. Accepts "%s" for the author of the comment being replied to. + * @param string $linktoparent Optional. Boolean to control making the author's name a link to their comment. Default true. + */ +function comment_form_title( $noreplytext = false, $replytext = false, $linktoparent = true ) { + global $comment; + + if ( false === $noreplytext ) $noreplytext = __( 'Leave a Reply' ); + if ( false === $replytext ) $replytext = __( 'Leave a Reply to %s' ); + + $replytoid = isset($_GET['replytocom']) ? (int) $_GET['replytocom'] : 0; + + if ( 0 == $replytoid ) + echo $noreplytext; + else { + $comment = get_comment($replytoid); + $author = ( $linktoparent ) ? '' . get_comment_author() . '' : get_comment_author(); + printf( $replytext, $author ); + } +} + +/** + * HTML comment list class. + * + * @package WordPress + * @uses Walker + * @since 2.7.0 + */ +class Walker_Comment extends Walker { + /** + * What the class handles. + * + * @see Walker::$tree_type + * + * @since 2.7.0 + * @var string + */ + var $tree_type = 'comment'; + + /** + * DB fields to use. + * + * @see Walker::$db_fields + * + * @since 2.7.0 + * @var array + */ + var $db_fields = array ('parent' => 'comment_parent', 'id' => 'comment_ID'); + + /** + * Start the list before the elements are added. + * + * @see Walker::start_lvl() + * + * @since 2.7.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of comment. + * @param array $args Uses 'style' argument for type of HTML list. + */ + function start_lvl( &$output, $depth = 0, $args = array() ) { + $GLOBALS['comment_depth'] = $depth + 1; + + switch ( $args['style'] ) { + case 'div': + break; + case 'ol': + echo '
      ' . "\n"; + break; + default: + case 'ul': + echo '
        ' . "\n"; + break; + } + } + + /** + * End the list of items after the elements are added. + * + * @see Walker::end_lvl() + * + * @since 2.7.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param int $depth Depth of comment. + * @param array $args Will only append content if style argument value is 'ol' or 'ul'. + */ + function end_lvl( &$output, $depth = 0, $args = array() ) { + $GLOBALS['comment_depth'] = $depth + 1; + + switch ( $args['style'] ) { + case 'div': + break; + case 'ol': + echo "
    \n"; + break; + default: + case 'ul': + echo "\n"; + break; + } + } + + /** + * Traverse elements to create list from elements. + * + * This function is designed to enhance Walker::display_element() to + * display children of higher nesting levels than selected inline on + * the highest depth level displayed. This prevents them being orphaned + * at the end of the comment list. + * + * Example: max_depth = 2, with 5 levels of nested content. + * 1 + * 1.1 + * 1.1.1 + * 1.1.1.1 + * 1.1.1.1.1 + * 1.1.2 + * 1.1.2.1 + * 2 + * 2.2 + * + * @see Walker::display_element() + * + * @since 2.7.0 + * + * @param object $element Data object. + * @param array $children_elements List of elements to continue traversing. + * @param int $max_depth Max depth to traverse. + * @param int $depth Depth of current element. + * @param array $args An array of arguments. @see wp_list_comments() + * @param string $output Passed by reference. Used to append additional content. + * @return null Null on failure with no changes to parameters. + */ + function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) { + + if ( !$element ) + return; + + $id_field = $this->db_fields['id']; + $id = $element->$id_field; + + parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output ); + + // If we're at the max depth, and the current element still has children, loop over those and display them at this level + // This is to prevent them being orphaned to the end of the list. + if ( $max_depth <= $depth + 1 && isset( $children_elements[$id]) ) { + foreach ( $children_elements[ $id ] as $child ) + $this->display_element( $child, $children_elements, $max_depth, $depth, $args, $output ); + + unset( $children_elements[ $id ] ); + } + + } + + /** + * Start the element output. + * + * @see Walker::start_el() + * + * @since 2.7.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $comment Comment data object. + * @param int $depth Depth of comment in reference to parents. + * @param array $args An array of arguments. @see wp_list_comments() + */ + function start_el( &$output, $comment, $depth = 0, $args = array(), $id = 0 ) { + $depth++; + $GLOBALS['comment_depth'] = $depth; + $GLOBALS['comment'] = $comment; + + if ( !empty( $args['callback'] ) ) { + call_user_func( $args['callback'], $comment, $args, $depth ); + return; + } + + if ( ( 'pingback' == $comment->comment_type || 'trackback' == $comment->comment_type ) && $args['short_ping'] ) { + $this->ping( $comment, $depth, $args ); + } elseif ( 'html5' === $args['format'] ) { + $this->html5_comment( $comment, $depth, $args ); + } else { + $this->comment( $comment, $depth, $args ); + } + } + + /** + * Ends the element output, if needed. + * + * @see Walker::end_el() + * + * @since 2.7.0 + * + * @param string $output Passed by reference. Used to append additional content. + * @param object $comment The comment object. Default current comment. + * @param int $depth Depth of comment. + * @param array $args An array of arguments. @see wp_list_comments() + */ + function end_el( &$output, $comment, $depth = 0, $args = array() ) { + if ( !empty( $args['end-callback'] ) ) { + call_user_func( $args['end-callback'], $comment, $args, $depth ); + return; + } + if ( 'div' == $args['style'] ) + echo "
    \n"; + else + echo "
  • \n"; + } + + /** + * Output a pingback comment. + * + * @access protected + * @since 3.6.0 + * + * @param object $comment The comment object. + * @param int $depth Depth of comment. + * @param array $args An array of arguments. @see wp_list_comments() + */ + protected function ping( $comment, $depth, $args ) { + $tag = ( 'div' == $args['style'] ) ? 'div' : 'li'; +?> + < id="comment-" > +
    + ', '' ); ?> +
    + + < id="comment-"> + +
    + +
    + + %s says:' ), get_comment_author_link() ); ?> +
    + comment_approved ) : ?> + +
    + + + + + $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?> + +
    + $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?> +
    + +
    + + + < id="comment-" > +
    +
    +
    + + says:' ), sprintf( '%s', get_comment_author_link() ) ); ?> +
    + + + + comment_approved ) : ?> +

    + +
    + +
    + +
    + +
    + 'div-comment', 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?> +
    +
    +comments + */ +function wp_list_comments( $args = array(), $comments = null ) { + global $wp_query, $comment_alt, $comment_depth, $comment_thread_alt, $overridden_cpage, $in_comment_loop; + + $in_comment_loop = true; + + $comment_alt = $comment_thread_alt = 0; + $comment_depth = 1; + + $defaults = array( + 'walker' => null, + 'max_depth' => '', + 'style' => 'ul', + 'callback' => null, + 'end-callback' => null, + 'type' => 'all', + 'page' => '', + 'per_page' => '', + 'avatar_size' => 32, + 'reverse_top_level' => null, + 'reverse_children' => '', + 'format' => current_theme_supports( 'html5', 'comment-list' ) ? 'html5' : 'xhtml', + 'short_ping' => false, + ); + + $r = wp_parse_args( $args, $defaults ); + + // Figure out what comments we'll be looping through ($_comments) + if ( null !== $comments ) { + $comments = (array) $comments; + if ( empty($comments) ) + return; + if ( 'all' != $r['type'] ) { + $comments_by_type = separate_comments($comments); + if ( empty($comments_by_type[$r['type']]) ) + return; + $_comments = $comments_by_type[$r['type']]; + } else { + $_comments = $comments; + } + } else { + if ( empty($wp_query->comments) ) + return; + if ( 'all' != $r['type'] ) { + if ( empty($wp_query->comments_by_type) ) + $wp_query->comments_by_type = separate_comments($wp_query->comments); + if ( empty($wp_query->comments_by_type[$r['type']]) ) + return; + $_comments = $wp_query->comments_by_type[$r['type']]; + } else { + $_comments = $wp_query->comments; + } + } + + if ( '' === $r['per_page'] && get_option('page_comments') ) + $r['per_page'] = get_query_var('comments_per_page'); + + if ( empty($r['per_page']) ) { + $r['per_page'] = 0; + $r['page'] = 0; + } + + if ( '' === $r['max_depth'] ) { + if ( get_option('thread_comments') ) + $r['max_depth'] = get_option('thread_comments_depth'); + else + $r['max_depth'] = -1; + } + + if ( '' === $r['page'] ) { + if ( empty($overridden_cpage) ) { + $r['page'] = get_query_var('cpage'); + } else { + $threaded = ( -1 != $r['max_depth'] ); + $r['page'] = ( 'newest' == get_option('default_comments_page') ) ? get_comment_pages_count($_comments, $r['per_page'], $threaded) : 1; + set_query_var( 'cpage', $r['page'] ); + } + } + // Validation check + $r['page'] = intval($r['page']); + if ( 0 == $r['page'] && 0 != $r['per_page'] ) + $r['page'] = 1; + + if ( null === $r['reverse_top_level'] ) + $r['reverse_top_level'] = ( 'desc' == get_option('comment_order') ); + + extract( $r, EXTR_SKIP ); + + if ( empty($walker) ) + $walker = new Walker_Comment; + + $walker->paged_walk($_comments, $max_depth, $page, $per_page, $r); + $wp_query->max_num_comment_pages = $walker->max_pages; + + $in_comment_loop = false; +} + +/** + * Output a complete commenting form for use within a template. + * + * Most strings and form fields may be controlled through the $args array passed + * into the function, while you may also choose to use the comment_form_default_fields + * filter to modify the array of default fields if you'd just like to add a new + * one or remove a single field. All fields are also individually passed through + * a filter of the form comment_form_field_$name where $name is the key used + * in the array of fields. + * + * @since 3.0.0 + * + * @param array $args { + * Optional. Default arguments and form fields to override. + * + * @type array 'fields' { + * Default comment fields, filterable by default via the 'comment_form_default_fields' hook. + * + * @type string 'author' The comment author field HTML. + * @type string 'email' The comment author email field HTML. + * @type string 'url' The comment author URL field HTML. + * } + * @type string 'comment_field' The comment textarea field HTML. + * @type string 'must_log_in' HTML element for a 'must be logged in to comment' message. + * @type string 'logged_in_as' HTML element for a 'logged in as ' message. + * @type string 'comment_notes_before' HTML element for a message displayed before the comment form. + * Default 'Your email address will not be published.'. + * @type string 'comment_notes_after' HTML element for a message displayed after the comment form. + * Default 'You may use these HTML tags and attributes ...'. + * @type string 'id_form' The comment form element id attribute. Default 'commentform'. + * @type string 'id_submit' The comment submit element id attribute. Default 'submit'. + * @type string 'title_reply' The translatable 'reply' button label. Default 'Leave a Reply'. + * @type string 'title_reply_to' The translatable 'reply-to' button label. Default 'Leave a Reply to %s', + * where %s is the author of the comment being replied to. + * @type string 'cancel_reply_link' The translatable 'cancel reply' button label. Default 'Cancel reply'. + * @type string 'label_submit' The translatable 'submit' button label. Default 'Post a comment'. + * @type string 'format' The comment form format. Default 'xhtml'. Accepts 'xhtml', 'html5'. + * } + * @param int|WP_Post $post_id Optional. Post ID or WP_Post object to generate the form for. Default current post. + */ +function comment_form( $args = array(), $post_id = null ) { + if ( null === $post_id ) + $post_id = get_the_ID(); + else + $id = $post_id; + + $commenter = wp_get_current_commenter(); + $user = wp_get_current_user(); + $user_identity = $user->exists() ? $user->display_name : ''; + + $args = wp_parse_args( $args ); + if ( ! isset( $args['format'] ) ) + $args['format'] = current_theme_supports( 'html5', 'comment-form' ) ? 'html5' : 'xhtml'; + + $req = get_option( 'require_name_email' ); + $aria_req = ( $req ? " aria-required='true'" : '' ); + $html5 = 'html5' === $args['format']; + $fields = array( + 'author' => '

    ' . ' ' . + '

    ', + 'email' => '', + 'url' => '

    ' . + '

    ', + ); + + $required_text = sprintf( ' ' . __('Required fields are marked %s'), '*' ); + + /** + * Filter the default comment form fields. + * + * @since 3.0.0 + * + * @param array $fields The default comment fields. + */ + $fields = apply_filters( 'comment_form_default_fields', $fields ); + $defaults = array( + 'fields' => $fields, + 'comment_field' => '

    ', + 'must_log_in' => '', + 'logged_in_as' => '

    ' . sprintf( __( 'Logged in as %2$s. Log out?' ), get_edit_user_link(), $user_identity, wp_logout_url( apply_filters( 'the_permalink', get_permalink( $post_id ) ) ) ) . '

    ', + 'comment_notes_before' => '

    ' . __( 'Your email address will not be published.' ) . ( $req ? $required_text : '' ) . '

    ', + 'comment_notes_after' => '

    ' . sprintf( __( 'You may use these HTML tags and attributes: %s' ), ' ' . allowed_tags() . '' ) . '

    ', + 'id_form' => 'commentform', + 'id_submit' => 'submit', + 'title_reply' => __( 'Leave a Reply' ), + 'title_reply_to' => __( 'Leave a Reply to %s' ), + 'cancel_reply_link' => __( 'Cancel reply' ), + 'label_submit' => __( 'Post Comment' ), + 'format' => 'xhtml', + ); + + /** + * Filter the comment form default arguments. + * + * Use 'comment_form_default_fields' to filter the comment fields. + * + * @since 3.0.0 + * + * @param array $defaults The default comment form arguments. + */ + $args = wp_parse_args( $args, apply_filters( 'comment_form_defaults', $defaults ) ); + + ?> + + +
    +

    + + + + +
    > + tag. + * + * @since 3.0.0 + */ + do_action( 'comment_form_top' ); + ?> + + + + + + $field ) { + /** + * Filter a comment form field for display. + * + * The dynamic portion of the filter hook, $name, refers to the name + * of the comment form field. Such as 'author', 'email', or 'url'. + * + * @since 3.0.0 + * + * @param string $field The HTML-formatted output of the comment form field. + */ + echo apply_filters( "comment_form_field_{$name}", $field ) . "\n"; + } + /** + * Fires after the comment fields in the comment form. + * + * @since 3.0.0 + */ + do_action( 'comment_form_after_fields' ); + ?> + + + +

    + + +

    + tag. + * + * @since 1.5.2 + * + * @param int $post_id The post ID. + */ + do_action( 'comment_form', $post_id ); + ?> +
    + +
    + ]*href/i', $comment, $out ); + $num_links = apply_filters( 'comment_max_links_url', $num_links, $url ); // provide for counting of $url as a link + if ( $num_links >= $max_links ) + return false; + } + + $mod_keys = trim(get_option('moderation_keys')); + if ( !empty($mod_keys) ) { + $words = explode("\n", $mod_keys ); + + foreach ( (array) $words as $word) { + $word = trim($word); + + // Skip empty lines + if ( empty($word) ) + continue; + + // Do some escaping magic so that '#' chars in the + // spam words don't break things: + $word = preg_quote($word, '#'); + + $pattern = "#$word#i"; + if ( preg_match($pattern, $author) ) return false; + if ( preg_match($pattern, $email) ) return false; + if ( preg_match($pattern, $url) ) return false; + if ( preg_match($pattern, $comment) ) return false; + if ( preg_match($pattern, $user_ip) ) return false; + if ( preg_match($pattern, $user_agent) ) return false; + } + } + + // Comment whitelisting: + if ( 1 == get_option('comment_whitelist')) { + if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) { + // expected_slashed ($author, $email) + $ok_to_comment = $wpdb->get_var("SELECT comment_approved FROM $wpdb->comments WHERE comment_author = '$author' AND comment_author_email = '$email' and comment_approved = '1' LIMIT 1"); + if ( ( 1 == $ok_to_comment ) && + ( empty($mod_keys) || false === strpos( $email, $mod_keys) ) ) + return true; + else + return false; + } else { + return false; + } + } + return true; +} + +/** + * Retrieve the approved comments for post $post_id. + * + * @since 2.0.0 + * @uses $wpdb + * + * @param int $post_id The ID of the post + * @return array $comments The approved comments + */ +function get_approved_comments($post_id) { + global $wpdb; + return $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1' ORDER BY comment_date", $post_id)); +} + +/** + * Retrieves comment data given a comment ID or comment object. + * + * If an object is passed then the comment data will be cached and then returned + * after being passed through a filter. If the comment is empty, then the global + * comment variable will be used, if it is set. + * + * @since 2.0.0 + * @uses $wpdb + * + * @param object|string|int $comment Comment to retrieve. + * @param string $output Optional. OBJECT or ARRAY_A or ARRAY_N constants. + * @return object|array|null Depends on $output value. + */ +function get_comment(&$comment, $output = OBJECT) { + global $wpdb; + $null = null; + + if ( empty($comment) ) { + if ( isset($GLOBALS['comment']) ) + $_comment = & $GLOBALS['comment']; + else + $_comment = null; + } elseif ( is_object($comment) ) { + wp_cache_add($comment->comment_ID, $comment, 'comment'); + $_comment = $comment; + } else { + if ( isset($GLOBALS['comment']) && ($GLOBALS['comment']->comment_ID == $comment) ) { + $_comment = & $GLOBALS['comment']; + } elseif ( ! $_comment = wp_cache_get($comment, 'comment') ) { + $_comment = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment)); + if ( ! $_comment ) + return $null; + wp_cache_add($_comment->comment_ID, $_comment, 'comment'); + } + } + + $_comment = apply_filters('get_comment', $_comment); + + if ( $output == OBJECT ) { + return $_comment; + } elseif ( $output == ARRAY_A ) { + $__comment = get_object_vars($_comment); + return $__comment; + } elseif ( $output == ARRAY_N ) { + $__comment = array_values(get_object_vars($_comment)); + return $__comment; + } else { + return $_comment; + } +} + +/** + * Retrieve a list of comments. + * + * The comment list can be for the blog as a whole or for an individual post. + * + * The list of comment arguments are 'status', 'orderby', 'comment_date_gmt', + * 'order', 'number', 'offset', and 'post_id'. + * + * @since 2.7.0 + * @uses $wpdb + * + * @param mixed $args Optional. Array or string of options to override defaults. + * @return array List of comments. + */ +function get_comments( $args = '' ) { + $query = new WP_Comment_Query; + return $query->query( $args ); +} + +/** + * WordPress Comment Query class. + * + * @since 3.1.0 + */ +class WP_Comment_Query { + /** + * Metadata query container + * + * @since 3.5.0 + * @access public + * @var object WP_Meta_Query + */ + var $meta_query = false; + + /** + * Date query container + * + * @since 3.7.0 + * @access public + * @var object WP_Date_Query + */ + var $date_query = false; + + /** + * Execute the query + * + * @since 3.1.0 + * + * @param string|array $query_vars + * @return int|array + */ + function query( $query_vars ) { + global $wpdb; + + $defaults = array( + 'author_email' => '', + 'ID' => '', + 'karma' => '', + 'number' => '', + 'offset' => '', + 'orderby' => '', + 'order' => 'DESC', + 'parent' => '', + 'post_ID' => '', + 'post_id' => 0, + 'post_author' => '', + 'post_name' => '', + 'post_parent' => '', + 'post_status' => '', + 'post_type' => '', + 'status' => '', + 'type' => '', + 'user_id' => '', + 'search' => '', + 'count' => false, + 'meta_key' => '', + 'meta_value' => '', + 'meta_query' => '', + 'date_query' => null, // See WP_Date_Query + ); + + $groupby = ''; + + $this->query_vars = wp_parse_args( $query_vars, $defaults ); + + // Parse meta query + $this->meta_query = new WP_Meta_Query(); + $this->meta_query->parse_query_vars( $this->query_vars ); + + do_action_ref_array( 'pre_get_comments', array( &$this ) ); + extract( $this->query_vars, EXTR_SKIP ); + + // $args can be whatever, only use the args defined in defaults to compute the key + $key = md5( serialize( compact(array_keys($defaults)) ) ); + $last_changed = wp_cache_get( 'last_changed', 'comment' ); + if ( ! $last_changed ) { + $last_changed = microtime(); + wp_cache_set( 'last_changed', $last_changed, 'comment' ); + } + $cache_key = "get_comments:$key:$last_changed"; + + if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) + return $cache; + + $post_id = absint($post_id); + + if ( 'hold' == $status ) + $approved = "comment_approved = '0'"; + elseif ( 'approve' == $status ) + $approved = "comment_approved = '1'"; + elseif ( ! empty( $status ) && 'all' != $status ) + $approved = $wpdb->prepare( "comment_approved = %s", $status ); + else + $approved = "( comment_approved = '0' OR comment_approved = '1' )"; + + $order = ( 'ASC' == strtoupper($order) ) ? 'ASC' : 'DESC'; + + if ( ! empty( $orderby ) ) { + $ordersby = is_array($orderby) ? $orderby : preg_split('/[,\s]/', $orderby); + $allowed_keys = array( + 'comment_agent', + 'comment_approved', + 'comment_author', + 'comment_author_email', + 'comment_author_IP', + 'comment_author_url', + 'comment_content', + 'comment_date', + 'comment_date_gmt', + 'comment_ID', + 'comment_karma', + 'comment_parent', + 'comment_post_ID', + 'comment_type', + 'user_id', + ); + if ( ! empty( $this->query_vars['meta_key'] ) ) { + $allowed_keys[] = $this->query_vars['meta_key']; + $allowed_keys[] = 'meta_value'; + $allowed_keys[] = 'meta_value_num'; + } + $ordersby = array_intersect( $ordersby, $allowed_keys ); + foreach ( $ordersby as $key => $value ) { + if ( $value == $this->query_vars['meta_key'] || $value == 'meta_value' ) { + $ordersby[ $key ] = "$wpdb->commentmeta.meta_value"; + } elseif ( $value == 'meta_value_num' ) { + $ordersby[ $key ] = "$wpdb->commentmeta.meta_value+0"; + } + } + $orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby); + } else { + $orderby = 'comment_date_gmt'; + } + + $number = absint($number); + $offset = absint($offset); + + if ( !empty($number) ) { + if ( $offset ) + $limits = 'LIMIT ' . $offset . ',' . $number; + else + $limits = 'LIMIT ' . $number; + } else { + $limits = ''; + } + + if ( $count ) + $fields = 'COUNT(*)'; + else + $fields = '*'; + + $join = ''; + $where = $approved; + + if ( ! empty($post_id) ) + $where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id ); + if ( '' !== $author_email ) + $where .= $wpdb->prepare( ' AND comment_author_email = %s', $author_email ); + if ( '' !== $karma ) + $where .= $wpdb->prepare( ' AND comment_karma = %d', $karma ); + if ( 'comment' == $type ) { + $where .= " AND comment_type = ''"; + } elseif( 'pings' == $type ) { + $where .= ' AND comment_type IN ("pingback", "trackback")'; + } elseif ( ! empty( $type ) ) { + $where .= $wpdb->prepare( ' AND comment_type = %s', $type ); + } + if ( '' !== $parent ) + $where .= $wpdb->prepare( ' AND comment_parent = %d', $parent ); + if ( '' !== $user_id ) + $where .= $wpdb->prepare( ' AND user_id = %d', $user_id ); + if ( '' !== $search ) + $where .= $this->get_search_sql( $search, array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' ) ); + + $post_fields = array_filter( compact( array( 'post_author', 'post_name', 'post_parent', 'post_status', 'post_type', ) ) ); + if ( ! empty( $post_fields ) ) { + $join = "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID"; + foreach( $post_fields as $field_name => $field_value ) + $where .= $wpdb->prepare( " AND {$wpdb->posts}.{$field_name} = %s", $field_value ); + } + + if ( ! empty( $this->meta_query->queries ) ) { + $clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this ); + $join .= $clauses['join']; + $where .= $clauses['where']; + $groupby = "{$wpdb->comments}.comment_ID"; + } + + if ( ! empty( $date_query ) && is_array( $date_query ) ) { + $date_query_object = new WP_Date_Query( $date_query, 'comment_date' ); + $where .= $date_query_object->get_sql(); + } + + $pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits', 'groupby' ); + $clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) ); + foreach ( $pieces as $piece ) + $$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : ''; + + if ( $groupby ) + $groupby = 'GROUP BY ' . $groupby; + + $query = "SELECT $fields FROM $wpdb->comments $join WHERE $where $groupby ORDER BY $orderby $order $limits"; + + if ( $count ) + return $wpdb->get_var( $query ); + + $comments = $wpdb->get_results( $query ); + $comments = apply_filters_ref_array( 'the_comments', array( $comments, &$this ) ); + + wp_cache_add( $cache_key, $comments, 'comment' ); + + return $comments; + } + + /* + * Used internally to generate an SQL string for searching across multiple columns + * + * @access protected + * @since 3.1.0 + * + * @param string $string + * @param array $cols + * @return string + */ + function get_search_sql( $string, $cols ) { + $string = esc_sql( like_escape( $string ) ); + + $searches = array(); + foreach ( $cols as $col ) + $searches[] = "$col LIKE '%$string%'"; + + return ' AND (' . implode(' OR ', $searches) . ')'; + } +} + +/** + * Retrieve all of the WordPress supported comment statuses. + * + * Comments have a limited set of valid status values, this provides the comment + * status values and descriptions. + * + * @package WordPress + * @subpackage Post + * @since 2.7.0 + * + * @return array List of comment statuses. + */ +function get_comment_statuses() { + $status = array( + 'hold' => __('Unapproved'), + /* translators: comment status */ + 'approve' => _x('Approved', 'adjective'), + /* translators: comment status */ + 'spam' => _x('Spam', 'adjective'), + ); + + return $status; +} + +/** + * The date the last comment was modified. + * + * @since 1.5.0 + * @uses $wpdb + * + * @param string $timezone Which timezone to use in reference to 'gmt', 'blog', + * or 'server' locations. + * @return string Last comment modified date. + */ +function get_lastcommentmodified($timezone = 'server') { + global $wpdb; + static $cache_lastcommentmodified = array(); + + if ( isset($cache_lastcommentmodified[$timezone]) ) + return $cache_lastcommentmodified[$timezone]; + + $add_seconds_server = date('Z'); + + switch ( strtolower($timezone)) { + case 'gmt': + $lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); + break; + case 'blog': + $lastcommentmodified = $wpdb->get_var("SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); + break; + case 'server': + $lastcommentmodified = $wpdb->get_var($wpdb->prepare("SELECT DATE_ADD(comment_date_gmt, INTERVAL %s SECOND) FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1", $add_seconds_server)); + break; + } + + $cache_lastcommentmodified[$timezone] = $lastcommentmodified; + + return $lastcommentmodified; +} + +/** + * The amount of comments in a post or total comments. + * + * A lot like {@link wp_count_comments()}, in that they both return comment + * stats (albeit with different types). The {@link wp_count_comments()} actual + * caches, but this function does not. + * + * @since 2.0.0 + * @uses $wpdb + * + * @param int $post_id Optional. Comment amount in post if > 0, else total comments blog wide. + * @return array The amount of spam, approved, awaiting moderation, and total comments. + */ +function get_comment_count( $post_id = 0 ) { + global $wpdb; + + $post_id = (int) $post_id; + + $where = ''; + if ( $post_id > 0 ) { + $where = $wpdb->prepare("WHERE comment_post_ID = %d", $post_id); + } + + $totals = (array) $wpdb->get_results(" + SELECT comment_approved, COUNT( * ) AS total + FROM {$wpdb->comments} + {$where} + GROUP BY comment_approved + ", ARRAY_A); + + $comment_count = array( + "approved" => 0, + "awaiting_moderation" => 0, + "spam" => 0, + "total_comments" => 0 + ); + + foreach ( $totals as $row ) { + switch ( $row['comment_approved'] ) { + case 'spam': + $comment_count['spam'] = $row['total']; + $comment_count["total_comments"] += $row['total']; + break; + case 1: + $comment_count['approved'] = $row['total']; + $comment_count['total_comments'] += $row['total']; + break; + case 0: + $comment_count['awaiting_moderation'] = $row['total']; + $comment_count['total_comments'] += $row['total']; + break; + default: + break; + } + } + + return $comment_count; +} + +// +// Comment meta functions +// + +/** + * Add meta data field to a comment. + * + * @since 2.9.0 + * @uses add_metadata + * @link http://codex.wordpress.org/Function_Reference/add_comment_meta + * + * @param int $comment_id Comment ID. + * @param string $meta_key Metadata name. + * @param mixed $meta_value Metadata value. + * @param bool $unique Optional, default is false. Whether the same key should not be added. + * @return int|bool Meta ID on success, false on failure. + */ +function add_comment_meta($comment_id, $meta_key, $meta_value, $unique = false) { + return add_metadata('comment', $comment_id, $meta_key, $meta_value, $unique); +} + +/** + * Remove metadata matching criteria from a comment. + * + * You can match based on the key, or key and value. Removing based on key and + * value, will keep from removing duplicate metadata with the same key. It also + * allows removing all metadata matching key, if needed. + * + * @since 2.9.0 + * @uses delete_metadata + * @link http://codex.wordpress.org/Function_Reference/delete_comment_meta + * + * @param int $comment_id comment ID + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. + * @return bool True on success, false on failure. + */ +function delete_comment_meta($comment_id, $meta_key, $meta_value = '') { + return delete_metadata('comment', $comment_id, $meta_key, $meta_value); +} + +/** + * Retrieve comment meta field for a comment. + * + * @since 2.9.0 + * @uses get_metadata + * @link http://codex.wordpress.org/Function_Reference/get_comment_meta + * + * @param int $comment_id Comment ID. + * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys. + * @param bool $single Whether to return a single value. + * @return mixed Will be an array if $single is false. Will be value of meta data field if $single + * is true. + */ +function get_comment_meta($comment_id, $key = '', $single = false) { + return get_metadata('comment', $comment_id, $key, $single); +} + +/** + * Update comment meta field based on comment ID. + * + * Use the $prev_value parameter to differentiate between meta fields with the + * same key and comment ID. + * + * If the meta field for the comment does not exist, it will be added. + * + * @since 2.9.0 + * @uses update_metadata + * @link http://codex.wordpress.org/Function_Reference/update_comment_meta + * + * @param int $comment_id Comment ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. + * @param mixed $prev_value Optional. Previous value to check before removing. + * @return bool True on success, false on failure. + */ +function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') { + return update_metadata('comment', $comment_id, $meta_key, $meta_value, $prev_value); +} + +/** + * Sets the cookies used to store an unauthenticated commentator's identity. Typically used + * to recall previous comments by this commentator that are still held in moderation. + * + * @param object $comment Comment object. + * @param object $user Comment author's object. + * + * @since 3.4.0 + */ +function wp_set_comment_cookies($comment, $user) { + if ( $user->exists() ) + return; + + $comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000); + setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); + setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); + setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); +} + +/** + * Sanitizes the cookies sent to the user already. + * + * Will only do anything if the cookies have already been created for the user. + * Mostly used after cookies had been sent to use elsewhere. + * + * @since 2.0.4 + */ +function sanitize_comment_cookies() { + if ( isset($_COOKIE['comment_author_'.COOKIEHASH]) ) { + $comment_author = apply_filters('pre_comment_author_name', $_COOKIE['comment_author_'.COOKIEHASH]); + $comment_author = wp_unslash($comment_author); + $comment_author = esc_attr($comment_author); + $_COOKIE['comment_author_'.COOKIEHASH] = $comment_author; + } + + if ( isset($_COOKIE['comment_author_email_'.COOKIEHASH]) ) { + $comment_author_email = apply_filters('pre_comment_author_email', $_COOKIE['comment_author_email_'.COOKIEHASH]); + $comment_author_email = wp_unslash($comment_author_email); + $comment_author_email = esc_attr($comment_author_email); + $_COOKIE['comment_author_email_'.COOKIEHASH] = $comment_author_email; + } + + if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) ) { + $comment_author_url = apply_filters('pre_comment_author_url', $_COOKIE['comment_author_url_'.COOKIEHASH]); + $comment_author_url = wp_unslash($comment_author_url); + $_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url; + } +} + +/** + * Validates whether this comment is allowed to be made. + * + * @since 2.0.0 + * @uses $wpdb + * @uses apply_filters() Calls 'pre_comment_approved' hook on the type of comment + * @uses apply_filters() Calls 'comment_duplicate_trigger' hook on commentdata. + * @uses do_action() Calls 'check_comment_flood' hook on $comment_author_IP, $comment_author_email, and $comment_date_gmt + * + * @param array $commentdata Contains information on the comment + * @return mixed Signifies the approval status (0|1|'spam') + */ +function wp_allow_comment($commentdata) { + global $wpdb; + extract($commentdata, EXTR_SKIP); + + // Simple duplicate check + // expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content) + $dupe = $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = %s AND comment_approved != 'trash' AND ( comment_author = %s ", wp_unslash( $comment_post_ID ), wp_unslash( $comment_parent ), wp_unslash( $comment_author ) ); + if ( $comment_author_email ) + $dupe .= $wpdb->prepare( "OR comment_author_email = %s ", wp_unslash( $comment_author_email ) ); + $dupe .= $wpdb->prepare( ") AND comment_content = %s LIMIT 1", wp_unslash( $comment_content ) ); + if ( $wpdb->get_var($dupe) ) { + do_action( 'comment_duplicate_trigger', $commentdata ); + if ( defined('DOING_AJAX') ) + die( __('Duplicate comment detected; it looks as though you’ve already said that!') ); + + wp_die( __('Duplicate comment detected; it looks as though you’ve already said that!') ); + } + + do_action( 'check_comment_flood', $comment_author_IP, $comment_author_email, $comment_date_gmt ); + + if ( ! empty( $user_id ) ) { + $user = get_userdata( $user_id ); + $post_author = $wpdb->get_var($wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1", $comment_post_ID)); + } + + if ( isset( $user ) && ( $user_id == $post_author || $user->has_cap( 'moderate_comments' ) ) ) { + // The author and the admins get respect. + $approved = 1; + } else { + // Everyone else's comments will be checked. + if ( check_comment($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent, $comment_type) ) + $approved = 1; + else + $approved = 0; + if ( wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent) ) + $approved = 'spam'; + } + + $approved = apply_filters( 'pre_comment_approved', $approved, $commentdata ); + return $approved; +} + +/** + * Check whether comment flooding is occurring. + * + * Won't run, if current user can manage options, so to not block + * administrators. + * + * @since 2.3.0 + * @uses $wpdb + * @uses apply_filters() Calls 'comment_flood_filter' filter with first + * parameter false, last comment timestamp, new comment timestamp. + * @uses do_action() Calls 'comment_flood_trigger' action with parameters with + * last comment timestamp and new comment timestamp. + * + * @param string $ip Comment IP. + * @param string $email Comment author email address. + * @param string $date MySQL time string. + */ +function check_comment_flood_db( $ip, $email, $date ) { + global $wpdb; + if ( current_user_can( 'manage_options' ) ) + return; // don't throttle admins + $hour_ago = gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS ); + if ( $lasttime = $wpdb->get_var( $wpdb->prepare( "SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( `comment_author_IP` = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1", $hour_ago, $ip, $email ) ) ) { + $time_lastcomment = mysql2date('U', $lasttime, false); + $time_newcomment = mysql2date('U', $date, false); + $flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment); + if ( $flood_die ) { + do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment); + + if ( defined('DOING_AJAX') ) + die( __('You are posting comments too quickly. Slow down.') ); + + wp_die( __('You are posting comments too quickly. Slow down.'), '', array('response' => 403) ); + } + } +} + +/** + * Separates an array of comments into an array keyed by comment_type. + * + * @since 2.7.0 + * + * @param array $comments Array of comments + * @return array Array of comments keyed by comment_type. + */ +function separate_comments(&$comments) { + $comments_by_type = array('comment' => array(), 'trackback' => array(), 'pingback' => array(), 'pings' => array()); + $count = count($comments); + for ( $i = 0; $i < $count; $i++ ) { + $type = $comments[$i]->comment_type; + if ( empty($type) ) + $type = 'comment'; + $comments_by_type[$type][] = &$comments[$i]; + if ( 'trackback' == $type || 'pingback' == $type ) + $comments_by_type['pings'][] = &$comments[$i]; + } + + return $comments_by_type; +} + +/** + * Calculate the total number of comment pages. + * + * @since 2.7.0 + * @uses get_query_var() Used to fill in the default for $per_page parameter. + * @uses get_option() Used to fill in defaults for parameters. + * @uses Walker_Comment + * + * @param array $comments Optional array of comment objects. Defaults to $wp_query->comments + * @param int $per_page Optional comments per page. + * @param boolean $threaded Optional control over flat or threaded comments. + * @return int Number of comment pages. + */ +function get_comment_pages_count( $comments = null, $per_page = null, $threaded = null ) { + global $wp_query; + + if ( null === $comments && null === $per_page && null === $threaded && !empty($wp_query->max_num_comment_pages) ) + return $wp_query->max_num_comment_pages; + + if ( !$comments || !is_array($comments) ) + $comments = $wp_query->comments; + + if ( empty($comments) ) + return 0; + + if ( ! get_option( 'page_comments' ) ) + return 1; + + if ( !isset($per_page) ) + $per_page = (int) get_query_var('comments_per_page'); + if ( 0 === $per_page ) + $per_page = (int) get_option('comments_per_page'); + if ( 0 === $per_page ) + return 1; + + if ( !isset($threaded) ) + $threaded = get_option('thread_comments'); + + if ( $threaded ) { + $walker = new Walker_Comment; + $count = ceil( $walker->get_number_of_root_elements( $comments ) / $per_page ); + } else { + $count = ceil( count( $comments ) / $per_page ); + } + + return $count; +} + +/** + * Calculate what page number a comment will appear on for comment paging. + * + * @since 2.7.0 + * @uses get_comment() Gets the full comment of the $comment_ID parameter. + * @uses get_option() Get various settings to control function and defaults. + * @uses get_page_of_comment() Used to loop up to top level comment. + * + * @param int $comment_ID Comment ID. + * @param array $args Optional args. + * @return int|null Comment page number or null on error. + */ +function get_page_of_comment( $comment_ID, $args = array() ) { + global $wpdb; + + if ( !$comment = get_comment( $comment_ID ) ) + return; + + $defaults = array( 'type' => 'all', 'page' => '', 'per_page' => '', 'max_depth' => '' ); + $args = wp_parse_args( $args, $defaults ); + + if ( '' === $args['per_page'] && get_option('page_comments') ) + $args['per_page'] = get_query_var('comments_per_page'); + if ( empty($args['per_page']) ) { + $args['per_page'] = 0; + $args['page'] = 0; + } + if ( $args['per_page'] < 1 ) + return 1; + + if ( '' === $args['max_depth'] ) { + if ( get_option('thread_comments') ) + $args['max_depth'] = get_option('thread_comments_depth'); + else + $args['max_depth'] = -1; + } + + // Find this comment's top level parent if threading is enabled + if ( $args['max_depth'] > 1 && 0 != $comment->comment_parent ) + return get_page_of_comment( $comment->comment_parent, $args ); + + $allowedtypes = array( + 'comment' => '', + 'pingback' => 'pingback', + 'trackback' => 'trackback', + ); + + $comtypewhere = ( 'all' != $args['type'] && isset($allowedtypes[$args['type']]) ) ? " AND comment_type = '" . $allowedtypes[$args['type']] . "'" : ''; + + // Count comments older than this one + $oldercoms = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = 0 AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comtypewhere, $comment->comment_post_ID, $comment->comment_date_gmt ) ); + + // No older comments? Then it's page #1. + if ( 0 == $oldercoms ) + return 1; + + // Divide comments older than this one by comments per page to get this comment's page number + return ceil( ( $oldercoms + 1 ) / $args['per_page'] ); +} + +/** + * Does comment contain blacklisted characters or words. + * + * @since 1.5.0 + * @uses do_action() Calls 'wp_blacklist_check' hook for all parameters. + * + * @param string $author The author of the comment + * @param string $email The email of the comment + * @param string $url The url used in the comment + * @param string $comment The comment content + * @param string $user_ip The comment author IP address + * @param string $user_agent The author's browser user agent + * @return bool True if comment contains blacklisted content, false if comment does not + */ +function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_agent) { + do_action('wp_blacklist_check', $author, $email, $url, $comment, $user_ip, $user_agent); + + $mod_keys = trim( get_option('blacklist_keys') ); + if ( '' == $mod_keys ) + return false; // If moderation keys are empty + $words = explode("\n", $mod_keys ); + + foreach ( (array) $words as $word ) { + $word = trim($word); + + // Skip empty lines + if ( empty($word) ) { continue; } + + // Do some escaping magic so that '#' chars in the + // spam words don't break things: + $word = preg_quote($word, '#'); + + $pattern = "#$word#i"; + if ( + preg_match($pattern, $author) + || preg_match($pattern, $email) + || preg_match($pattern, $url) + || preg_match($pattern, $comment) + || preg_match($pattern, $user_ip) + || preg_match($pattern, $user_agent) + ) + return true; + } + return false; +} + +/** + * Retrieve total comments for blog or single post. + * + * The properties of the returned object contain the 'moderated', 'approved', + * and spam comments for either the entire blog or single post. Those properties + * contain the amount of comments that match the status. The 'total_comments' + * property contains the integer of total comments. + * + * The comment stats are cached and then retrieved, if they already exist in the + * cache. + * + * @since 2.5.0 + * + * @param int $post_id Optional. Post ID. + * @return object Comment stats. + */ +function wp_count_comments( $post_id = 0 ) { + global $wpdb; + + $post_id = (int) $post_id; + + $stats = apply_filters('wp_count_comments', array(), $post_id); + if ( !empty($stats) ) + return $stats; + + $count = wp_cache_get("comments-{$post_id}", 'counts'); + + if ( false !== $count ) + return $count; + + $where = ''; + if ( $post_id > 0 ) + $where = $wpdb->prepare( "WHERE comment_post_ID = %d", $post_id ); + + $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A ); + + $total = 0; + $approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed'); + foreach ( (array) $count as $row ) { + // Don't count post-trashed toward totals + if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) + $total += $row['num_comments']; + if ( isset( $approved[$row['comment_approved']] ) ) + $stats[$approved[$row['comment_approved']]] = $row['num_comments']; + } + + $stats['total_comments'] = $total; + foreach ( $approved as $key ) { + if ( empty($stats[$key]) ) + $stats[$key] = 0; + } + + $stats = (object) $stats; + wp_cache_set("comments-{$post_id}", $stats, 'counts'); + + return $stats; +} + +/** + * Trashes or deletes a comment. + * + * The comment is moved to trash instead of permanently deleted unless trash is + * disabled, item is already in the trash, or $force_delete is true. + * + * The post comment count will be updated if the comment was approved and has a + * post ID available. + * + * @since 2.0.0 + * @uses $wpdb + * @uses do_action() Calls 'delete_comment' hook on comment ID + * @uses do_action() Calls 'deleted_comment' hook on comment ID after deletion, on success + * @uses do_action() Calls 'wp_set_comment_status' hook on comment ID with 'delete' set for the second parameter + * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object + * + * @param int $comment_id Comment ID + * @param bool $force_delete Whether to bypass trash and force deletion. Default is false. + * @return bool True on success, false on failure. + */ +function wp_delete_comment($comment_id, $force_delete = false) { + global $wpdb; + if (!$comment = get_comment($comment_id)) + return false; + + if ( !$force_delete && EMPTY_TRASH_DAYS && !in_array( wp_get_comment_status($comment_id), array( 'trash', 'spam' ) ) ) + return wp_trash_comment($comment_id); + + do_action('delete_comment', $comment_id); + + // Move children up a level. + $children = $wpdb->get_col( $wpdb->prepare("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent = %d", $comment_id) ); + if ( !empty($children) ) { + $wpdb->update($wpdb->comments, array('comment_parent' => $comment->comment_parent), array('comment_parent' => $comment_id)); + clean_comment_cache($children); + } + + // Delete metadata + $meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d", $comment_id ) ); + foreach ( $meta_ids as $mid ) + delete_metadata_by_mid( 'comment', $mid ); + + if ( ! $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $comment_id ) ) ) + return false; + do_action('deleted_comment', $comment_id); + + $post_id = $comment->comment_post_ID; + if ( $post_id && $comment->comment_approved == 1 ) + wp_update_comment_count($post_id); + + clean_comment_cache($comment_id); + + do_action('wp_set_comment_status', $comment_id, 'delete'); + wp_transition_comment_status('delete', $comment->comment_approved, $comment); + return true; +} + +/** + * Moves a comment to the Trash + * + * If trash is disabled, comment is permanently deleted. + * + * @since 2.9.0 + * @uses do_action() on 'trash_comment' before trashing + * @uses do_action() on 'trashed_comment' after trashing + * @uses wp_delete_comment() if trash is disabled + * + * @param int $comment_id Comment ID. + * @return bool True on success, false on failure. + */ +function wp_trash_comment($comment_id) { + if ( !EMPTY_TRASH_DAYS ) + return wp_delete_comment($comment_id, true); + + if ( !$comment = get_comment($comment_id) ) + return false; + + do_action('trash_comment', $comment_id); + + if ( wp_set_comment_status($comment_id, 'trash') ) { + add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved); + add_comment_meta($comment_id, '_wp_trash_meta_time', time() ); + do_action('trashed_comment', $comment_id); + return true; + } + + return false; +} + +/** + * Removes a comment from the Trash + * + * @since 2.9.0 + * @uses do_action() on 'untrash_comment' before untrashing + * @uses do_action() on 'untrashed_comment' after untrashing + * + * @param int $comment_id Comment ID. + * @return bool True on success, false on failure. + */ +function wp_untrash_comment($comment_id) { + if ( ! (int)$comment_id ) + return false; + + do_action('untrash_comment', $comment_id); + + $status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true); + if ( empty($status) ) + $status = '0'; + + if ( wp_set_comment_status($comment_id, $status) ) { + delete_comment_meta($comment_id, '_wp_trash_meta_time'); + delete_comment_meta($comment_id, '_wp_trash_meta_status'); + do_action('untrashed_comment', $comment_id); + return true; + } + + return false; +} + +/** + * Marks a comment as Spam + * + * @since 2.9.0 + * @uses do_action() on 'spam_comment' before spamming + * @uses do_action() on 'spammed_comment' after spamming + * + * @param int $comment_id Comment ID. + * @return bool True on success, false on failure. + */ +function wp_spam_comment($comment_id) { + if ( !$comment = get_comment($comment_id) ) + return false; + + do_action('spam_comment', $comment_id); + + if ( wp_set_comment_status($comment_id, 'spam') ) { + add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved); + do_action('spammed_comment', $comment_id); + return true; + } + + return false; +} + +/** + * Removes a comment from the Spam + * + * @since 2.9.0 + * @uses do_action() on 'unspam_comment' before unspamming + * @uses do_action() on 'unspammed_comment' after unspamming + * + * @param int $comment_id Comment ID. + * @return bool True on success, false on failure. + */ +function wp_unspam_comment($comment_id) { + if ( ! (int)$comment_id ) + return false; + + do_action('unspam_comment', $comment_id); + + $status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true); + if ( empty($status) ) + $status = '0'; + + if ( wp_set_comment_status($comment_id, $status) ) { + delete_comment_meta($comment_id, '_wp_trash_meta_status'); + do_action('unspammed_comment', $comment_id); + return true; + } + + return false; +} + +/** + * The status of a comment by ID. + * + * @since 1.0.0 + * + * @param int $comment_id Comment ID + * @return string|bool Status might be 'trash', 'approved', 'unapproved', 'spam'. False on failure. + */ +function wp_get_comment_status($comment_id) { + $comment = get_comment($comment_id); + if ( !$comment ) + return false; + + $approved = $comment->comment_approved; + + if ( $approved == null ) + return false; + elseif ( $approved == '1' ) + return 'approved'; + elseif ( $approved == '0' ) + return 'unapproved'; + elseif ( $approved == 'spam' ) + return 'spam'; + elseif ( $approved == 'trash' ) + return 'trash'; + else + return false; +} + +/** + * Call hooks for when a comment status transition occurs. + * + * Calls hooks for comment status transitions. If the new comment status is not the same + * as the previous comment status, then two hooks will be ran, the first is + * 'transition_comment_status' with new status, old status, and comment data. The + * next action called is 'comment_OLDSTATUS_to_NEWSTATUS' the NEWSTATUS is the + * $new_status parameter and the OLDSTATUS is $old_status parameter; it has the + * comment data. + * + * The final action will run whether or not the comment statuses are the same. The + * action is named 'comment_NEWSTATUS_COMMENTTYPE', NEWSTATUS is from the $new_status + * parameter and COMMENTTYPE is comment_type comment data. + * + * @since 2.7.0 + * + * @param string $new_status New comment status. + * @param string $old_status Previous comment status. + * @param object $comment Comment data. + */ +function wp_transition_comment_status($new_status, $old_status, $comment) { + // Translate raw statuses to human readable formats for the hooks + // This is not a complete list of comment status, it's only the ones that need to be renamed + $comment_statuses = array( + 0 => 'unapproved', + 'hold' => 'unapproved', // wp_set_comment_status() uses "hold" + 1 => 'approved', + 'approve' => 'approved', // wp_set_comment_status() uses "approve" + ); + if ( isset($comment_statuses[$new_status]) ) $new_status = $comment_statuses[$new_status]; + if ( isset($comment_statuses[$old_status]) ) $old_status = $comment_statuses[$old_status]; + + // Call the hooks + if ( $new_status != $old_status ) { + do_action('transition_comment_status', $new_status, $old_status, $comment); + do_action("comment_{$old_status}_to_{$new_status}", $comment); + } + do_action("comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment); +} + +/** + * Get current commenter's name, email, and URL. + * + * Expects cookies content to already be sanitized. User of this function might + * wish to recheck the returned array for validity. + * + * @see sanitize_comment_cookies() Use to sanitize cookies + * + * @since 2.0.4 + * + * @return array Comment author, email, url respectively. + */ +function wp_get_current_commenter() { + // Cookies should already be sanitized. + + $comment_author = ''; + if ( isset($_COOKIE['comment_author_'.COOKIEHASH]) ) + $comment_author = $_COOKIE['comment_author_'.COOKIEHASH]; + + $comment_author_email = ''; + if ( isset($_COOKIE['comment_author_email_'.COOKIEHASH]) ) + $comment_author_email = $_COOKIE['comment_author_email_'.COOKIEHASH]; + + $comment_author_url = ''; + if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) ) + $comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH]; + + return apply_filters('wp_get_current_commenter', compact('comment_author', 'comment_author_email', 'comment_author_url')); +} + +/** + * Inserts a comment to the database. + * + * The available comment data key names are 'comment_author_IP', 'comment_date', + * 'comment_date_gmt', 'comment_parent', 'comment_approved', and 'user_id'. + * + * @since 2.0.0 + * @uses $wpdb + * + * @param array $commentdata Contains information on the comment. + * @return int The new comment's ID. + */ +function wp_insert_comment($commentdata) { + global $wpdb; + extract(wp_unslash($commentdata), EXTR_SKIP); + + if ( ! isset($comment_author_IP) ) + $comment_author_IP = ''; + if ( ! isset($comment_date) ) + $comment_date = current_time('mysql'); + if ( ! isset($comment_date_gmt) ) + $comment_date_gmt = get_gmt_from_date($comment_date); + if ( ! isset($comment_parent) ) + $comment_parent = 0; + if ( ! isset($comment_approved) ) + $comment_approved = 1; + if ( ! isset($comment_karma) ) + $comment_karma = 0; + if ( ! isset($user_id) ) + $user_id = 0; + if ( ! isset($comment_type) ) + $comment_type = ''; + + $data = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_karma', 'comment_approved', 'comment_agent', 'comment_type', 'comment_parent', 'user_id'); + $wpdb->insert($wpdb->comments, $data); + + $id = (int) $wpdb->insert_id; + + if ( $comment_approved == 1 ) + wp_update_comment_count($comment_post_ID); + + $comment = get_comment($id); + do_action('wp_insert_comment', $id, $comment); + + wp_cache_set( 'last_changed', microtime(), 'comment' ); + + return $id; +} + +/** + * Filters and sanitizes comment data. + * + * Sets the comment data 'filtered' field to true when finished. This can be + * checked as to whether the comment should be filtered and to keep from + * filtering the same comment more than once. + * + * @since 2.0.0 + * @uses apply_filters() Calls 'pre_user_id' hook on comment author's user ID + * @uses apply_filters() Calls 'pre_comment_user_agent' hook on comment author's user agent + * @uses apply_filters() Calls 'pre_comment_author_name' hook on comment author's name + * @uses apply_filters() Calls 'pre_comment_content' hook on the comment's content + * @uses apply_filters() Calls 'pre_comment_user_ip' hook on comment author's IP + * @uses apply_filters() Calls 'pre_comment_author_url' hook on comment author's URL + * @uses apply_filters() Calls 'pre_comment_author_email' hook on comment author's email address + * + * @param array $commentdata Contains information on the comment. + * @return array Parsed comment information. + */ +function wp_filter_comment($commentdata) { + if ( isset($commentdata['user_ID']) ) + $commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_ID']); + elseif ( isset($commentdata['user_id']) ) + $commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_id']); + $commentdata['comment_agent'] = apply_filters('pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) ); + $commentdata['comment_author'] = apply_filters('pre_comment_author_name', $commentdata['comment_author']); + $commentdata['comment_content'] = apply_filters('pre_comment_content', $commentdata['comment_content']); + $commentdata['comment_author_IP'] = apply_filters('pre_comment_user_ip', $commentdata['comment_author_IP']); + $commentdata['comment_author_url'] = apply_filters('pre_comment_author_url', $commentdata['comment_author_url']); + $commentdata['comment_author_email'] = apply_filters('pre_comment_author_email', $commentdata['comment_author_email']); + $commentdata['filtered'] = true; + return $commentdata; +} + +/** + * Whether comment should be blocked because of comment flood. + * + * @since 2.1.0 + * + * @param bool $block Whether plugin has already blocked comment. + * @param int $time_lastcomment Timestamp for last comment. + * @param int $time_newcomment Timestamp for new comment. + * @return bool Whether comment should be blocked. + */ +function wp_throttle_comment_flood($block, $time_lastcomment, $time_newcomment) { + if ( $block ) // a plugin has already blocked... we'll let that decision stand + return $block; + if ( ($time_newcomment - $time_lastcomment) < 15 ) + return true; + return false; +} + +/** + * Adds a new comment to the database. + * + * Filters new comment to ensure that the fields are sanitized and valid before + * inserting comment into database. Calls 'comment_post' action with comment ID + * and whether comment is approved by WordPress. Also has 'preprocess_comment' + * filter for processing the comment data before the function handles it. + * + * We use REMOTE_ADDR here directly. If you are behind a proxy, you should ensure + * that it is properly set, such as in wp-config.php, for your environment. + * See {@link http://core.trac.wordpress.org/ticket/9235} + * + * @since 1.5.0 + * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing + * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved. + * @uses wp_filter_comment() Used to filter comment before adding comment. + * @uses wp_allow_comment() checks to see if comment is approved. + * @uses wp_insert_comment() Does the actual comment insertion to the database. + * + * @param array $commentdata Contains information on the comment. + * @return int The ID of the comment after adding. + */ +function wp_new_comment( $commentdata ) { + $commentdata = apply_filters('preprocess_comment', $commentdata); + + $commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID']; + if ( isset($commentdata['user_ID']) ) + $commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID']; + elseif ( isset($commentdata['user_id']) ) + $commentdata['user_id'] = (int) $commentdata['user_id']; + + $commentdata['comment_parent'] = isset($commentdata['comment_parent']) ? absint($commentdata['comment_parent']) : 0; + $parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status($commentdata['comment_parent']) : ''; + $commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0; + + $commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '',$_SERVER['REMOTE_ADDR'] ); + $commentdata['comment_agent'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : ''; + + $commentdata['comment_date'] = current_time('mysql'); + $commentdata['comment_date_gmt'] = current_time('mysql', 1); + + $commentdata = wp_filter_comment($commentdata); + + $commentdata['comment_approved'] = wp_allow_comment($commentdata); + + $comment_ID = wp_insert_comment($commentdata); + + do_action('comment_post', $comment_ID, $commentdata['comment_approved']); + + if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching + if ( '0' == $commentdata['comment_approved'] ) + wp_notify_moderator($comment_ID); + + $post = get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment + + if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) ) + wp_notify_postauthor($comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' ); + } + + return $comment_ID; +} + +/** + * Sets the status of a comment. + * + * The 'wp_set_comment_status' action is called after the comment is handled. + * If the comment status is not in the list, then false is returned. + * + * @since 1.0.0 + * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object + * + * @param int $comment_id Comment ID. + * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'. + * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false. + * @return bool|WP_Error True on success, false or WP_Error on failure. + */ +function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) { + global $wpdb; + + $status = '0'; + switch ( $comment_status ) { + case 'hold': + case '0': + $status = '0'; + break; + case 'approve': + case '1': + $status = '1'; + if ( get_option('comments_notify') ) { + $comment = get_comment($comment_id); + wp_notify_postauthor($comment_id, $comment->comment_type); + } + break; + case 'spam': + $status = 'spam'; + break; + case 'trash': + $status = 'trash'; + break; + default: + return false; + } + + $comment_old = clone get_comment($comment_id); + + if ( !$wpdb->update( $wpdb->comments, array('comment_approved' => $status), array('comment_ID' => $comment_id) ) ) { + if ( $wp_error ) + return new WP_Error('db_update_error', __('Could not update comment status'), $wpdb->last_error); + else + return false; + } + + clean_comment_cache($comment_id); + + $comment = get_comment($comment_id); + + do_action('wp_set_comment_status', $comment_id, $comment_status); + wp_transition_comment_status($comment_status, $comment_old->comment_approved, $comment); + + wp_update_comment_count($comment->comment_post_ID); + + return true; +} + +/** + * Updates an existing comment in the database. + * + * Filters the comment and makes sure certain fields are valid before updating. + * + * @since 2.0.0 + * @uses $wpdb + * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object + * + * @param array $commentarr Contains information on the comment. + * @return int Comment was updated if value is 1, or was not updated if value is 0. + */ +function wp_update_comment($commentarr) { + global $wpdb; + + // First, get all of the original fields + $comment = get_comment($commentarr['comment_ID'], ARRAY_A); + if ( empty( $comment ) ) + return 0; + + // Escape data pulled from DB. + $comment = wp_slash($comment); + + $old_status = $comment['comment_approved']; + + // Merge old and new fields with new fields overwriting old ones. + $commentarr = array_merge($comment, $commentarr); + + $commentarr = wp_filter_comment( $commentarr ); + + // Now extract the merged array. + extract(wp_unslash($commentarr), EXTR_SKIP); + + $comment_content = apply_filters('comment_save_pre', $comment_content); + + $comment_date_gmt = get_gmt_from_date($comment_date); + + if ( !isset($comment_approved) ) + $comment_approved = 1; + else if ( 'hold' == $comment_approved ) + $comment_approved = 0; + else if ( 'approve' == $comment_approved ) + $comment_approved = 1; + + $data = compact( 'comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt', 'comment_parent' ); + $rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) ); + + clean_comment_cache($comment_ID); + wp_update_comment_count($comment_post_ID); + do_action('edit_comment', $comment_ID); + $comment = get_comment($comment_ID); + wp_transition_comment_status($comment->comment_approved, $old_status, $comment); + return $rval; +} + +/** + * Whether to defer comment counting. + * + * When setting $defer to true, all post comment counts will not be updated + * until $defer is set to false. When $defer is set to false, then all + * previously deferred updated post comment counts will then be automatically + * updated without having to call wp_update_comment_count() after. + * + * @since 2.5.0 + * @staticvar bool $_defer + * + * @param bool $defer + * @return unknown + */ +function wp_defer_comment_counting($defer=null) { + static $_defer = false; + + if ( is_bool($defer) ) { + $_defer = $defer; + // flush any deferred counts + if ( !$defer ) + wp_update_comment_count( null, true ); + } + + return $_defer; +} + +/** + * Updates the comment count for post(s). + * + * When $do_deferred is false (is by default) and the comments have been set to + * be deferred, the post_id will be added to a queue, which will be updated at a + * later date and only updated once per post ID. + * + * If the comments have not be set up to be deferred, then the post will be + * updated. When $do_deferred is set to true, then all previous deferred post + * IDs will be updated along with the current $post_id. + * + * @since 2.1.0 + * @see wp_update_comment_count_now() For what could cause a false return value + * + * @param int $post_id Post ID + * @param bool $do_deferred Whether to process previously deferred post comment counts + * @return bool True on success, false on failure + */ +function wp_update_comment_count($post_id, $do_deferred=false) { + static $_deferred = array(); + + if ( $do_deferred ) { + $_deferred = array_unique($_deferred); + foreach ( $_deferred as $i => $_post_id ) { + wp_update_comment_count_now($_post_id); + unset( $_deferred[$i] ); /** @todo Move this outside of the foreach and reset $_deferred to an array instead */ + } + } + + if ( wp_defer_comment_counting() ) { + $_deferred[] = $post_id; + return true; + } + elseif ( $post_id ) { + return wp_update_comment_count_now($post_id); + } + +} + +/** + * Updates the comment count for the post. + * + * @since 2.5.0 + * @uses $wpdb + * @uses do_action() Calls 'wp_update_comment_count' hook on $post_id, $new, and $old + * @uses do_action() Calls 'edit_posts' hook on $post_id and $post + * + * @param int $post_id Post ID + * @return bool True on success, false on '0' $post_id or if post with ID does not exist. + */ +function wp_update_comment_count_now($post_id) { + global $wpdb; + $post_id = (int) $post_id; + if ( !$post_id ) + return false; + if ( !$post = get_post($post_id) ) + return false; + + $old = (int) $post->comment_count; + $new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) ); + $wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) ); + + clean_post_cache( $post ); + + do_action('wp_update_comment_count', $post_id, $new, $old); + do_action('edit_post', $post_id, $post); + + return true; +} + +// +// Ping and trackback functions. +// + +/** + * Finds a pingback server URI based on the given URL. + * + * Checks the HTML for the rel="pingback" link and x-pingback headers. It does + * a check for the x-pingback headers first and returns that, if available. The + * check for the rel="pingback" has more overhead than just the header. + * + * @since 1.5.0 + * + * @param string $url URL to ping. + * @param int $deprecated Not Used. + * @return bool|string False on failure, string containing URI on success. + */ +function discover_pingback_server_uri( $url, $deprecated = '' ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.7' ); + + $pingback_str_dquote = 'rel="pingback"'; + $pingback_str_squote = 'rel=\'pingback\''; + + /** @todo Should use Filter Extension or custom preg_match instead. */ + $parsed_url = parse_url($url); + + if ( ! isset( $parsed_url['host'] ) ) // Not an URL. This should never happen. + return false; + + //Do not search for a pingback server on our own uploads + $uploads_dir = wp_upload_dir(); + if ( 0 === strpos($url, $uploads_dir['baseurl']) ) + return false; + + $response = wp_safe_remote_head( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) ); + + if ( is_wp_error( $response ) ) + return false; + + if ( wp_remote_retrieve_header( $response, 'x-pingback' ) ) + return wp_remote_retrieve_header( $response, 'x-pingback' ); + + // Not an (x)html, sgml, or xml page, no use going further. + if ( preg_match('#(image|audio|video|model)/#is', wp_remote_retrieve_header( $response, 'content-type' )) ) + return false; + + // Now do a GET since we're going to look in the html headers (and we're sure it's not a binary file) + $response = wp_safe_remote_get( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) ); + + if ( is_wp_error( $response ) ) + return false; + + $contents = wp_remote_retrieve_body( $response ); + + $pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote); + $pingback_link_offset_squote = strpos($contents, $pingback_str_squote); + if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) { + $quote = ($pingback_link_offset_dquote) ? '"' : '\''; + $pingback_link_offset = ($quote=='"') ? $pingback_link_offset_dquote : $pingback_link_offset_squote; + $pingback_href_pos = @strpos($contents, 'href=', $pingback_link_offset); + $pingback_href_start = $pingback_href_pos+6; + $pingback_href_end = @strpos($contents, $quote, $pingback_href_start); + $pingback_server_url_len = $pingback_href_end - $pingback_href_start; + $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len); + + // We may find rel="pingback" but an incomplete pingback URL + if ( $pingback_server_url_len > 0 ) { // We got it! + return $pingback_server_url; + } + } + + return false; +} + +/** + * Perform all pingbacks, enclosures, trackbacks, and send to pingback services. + * + * @since 2.1.0 + * @uses $wpdb + */ +function do_all_pings() { + global $wpdb; + + // Do pingbacks + while ($ping = $wpdb->get_row("SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1")) { + delete_metadata_by_mid( 'post', $ping->meta_id ); + pingback( $ping->post_content, $ping->ID ); + } + + // Do Enclosures + while ($enclosure = $wpdb->get_row("SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1")) { + delete_metadata_by_mid( 'post', $enclosure->meta_id ); + do_enclose( $enclosure->post_content, $enclosure->ID ); + } + + // Do Trackbacks + $trackbacks = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE to_ping <> '' AND post_status = 'publish'"); + if ( is_array($trackbacks) ) + foreach ( $trackbacks as $trackback ) + do_trackbacks($trackback); + + //Do Update Services/Generic Pings + generic_ping(); +} + +/** + * Perform trackbacks. + * + * @since 1.5.0 + * @uses $wpdb + * + * @param int $post_id Post ID to do trackbacks on. + */ +function do_trackbacks($post_id) { + global $wpdb; + + $post = get_post( $post_id ); + $to_ping = get_to_ping($post_id); + $pinged = get_pung($post_id); + if ( empty($to_ping) ) { + $wpdb->update($wpdb->posts, array('to_ping' => ''), array('ID' => $post_id) ); + return; + } + + if ( empty($post->post_excerpt) ) + $excerpt = apply_filters('the_content', $post->post_content, $post->ID); + else + $excerpt = apply_filters('the_excerpt', $post->post_excerpt); + $excerpt = str_replace(']]>', ']]>', $excerpt); + $excerpt = wp_html_excerpt($excerpt, 252, '…'); + + /** This filter is documented in wp-includes/post-template.php */ + $post_title = apply_filters('the_title', $post->post_title, $post->ID); + $post_title = strip_tags($post_title); + + if ( $to_ping ) { + foreach ( (array) $to_ping as $tb_ping ) { + $tb_ping = trim($tb_ping); + if ( !in_array($tb_ping, $pinged) ) { + trackback($tb_ping, $post_title, $excerpt, $post_id); + $pinged[] = $tb_ping; + } else { + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $tb_ping, $post_id) ); + } + } + } +} + +/** + * Sends pings to all of the ping site services. + * + * @since 1.2.0 + * + * @param int $post_id Post ID. Not actually used. + * @return int Same as Post ID from parameter + */ +function generic_ping($post_id = 0) { + $services = get_option('ping_sites'); + + $services = explode("\n", $services); + foreach ( (array) $services as $service ) { + $service = trim($service); + if ( '' != $service ) + weblog_ping($service); + } + + return $post_id; +} + +/** + * Pings back the links found in a post. + * + * @since 0.71 + * @uses $wp_version + * @uses IXR_Client + * + * @param string $content Post content to check for links. + * @param int $post_ID Post ID. + */ +function pingback($content, $post_ID) { + global $wp_version; + include_once(ABSPATH . WPINC . '/class-IXR.php'); + include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php'); + + // original code by Mort (http://mort.mine.nu:8080) + $post_links = array(); + + $pung = get_pung($post_ID); + + // Step 1 + // Parsing the post, external links (if any) are stored in the $post_links array + $post_links_temp = wp_extract_urls( $content ); + + // Step 2. + // Walking thru the links array + // first we get rid of links pointing to sites, not to specific files + // Example: + // http://dummy-weblog.org + // http://dummy-weblog.org/ + // http://dummy-weblog.org/post.php + // We don't wanna ping first and second types, even if they have a valid + + foreach ( (array) $post_links_temp as $link_test ) : + if ( !in_array($link_test, $pung) && (url_to_postid($link_test) != $post_ID) // If we haven't pung it already and it isn't a link to itself + && !is_local_attachment($link_test) ) : // Also, let's never ping local attachments. + if ( $test = @parse_url($link_test) ) { + if ( isset($test['query']) ) + $post_links[] = $link_test; + elseif ( isset( $test['path'] ) && ( $test['path'] != '/' ) && ( $test['path'] != '' ) ) + $post_links[] = $link_test; + } + endif; + endforeach; + + $post_links = array_unique( $post_links ); + do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post_ID ) ); + + foreach ( (array) $post_links as $pagelinkedto ) { + $pingback_server_url = discover_pingback_server_uri( $pagelinkedto ); + + if ( $pingback_server_url ) { + @ set_time_limit( 60 ); + // Now, the RPC call + $pagelinkedfrom = get_permalink($post_ID); + + // using a timeout of 3 seconds should be enough to cover slow servers + $client = new WP_HTTP_IXR_Client($pingback_server_url); + $client->timeout = 3; + $client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom); + // when set to true, this outputs debug messages by itself + $client->debug = false; + + if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto) || ( isset($client->error->code) && 48 == $client->error->code ) ) // Already registered + add_ping( $post_ID, $pagelinkedto ); + } + } +} + +/** + * Check whether blog is public before returning sites. + * + * @since 2.1.0 + * + * @param mixed $sites Will return if blog is public, will not return if not public. + * @return mixed Empty string if blog is not public, returns $sites, if site is public. + */ +function privacy_ping_filter($sites) { + if ( '0' != get_option('blog_public') ) + return $sites; + else + return ''; +} + +/** + * Send a Trackback. + * + * Updates database when sending trackback to prevent duplicates. + * + * @since 0.71 + * @uses $wpdb + * + * @param string $trackback_url URL to send trackbacks. + * @param string $title Title of post. + * @param string $excerpt Excerpt of post. + * @param int $ID Post ID. + * @return mixed Database query from update. + */ +function trackback($trackback_url, $title, $excerpt, $ID) { + global $wpdb; + + if ( empty($trackback_url) ) + return; + + $options = array(); + $options['timeout'] = 4; + $options['body'] = array( + 'title' => $title, + 'url' => get_permalink($ID), + 'blog_name' => get_option('blogname'), + 'excerpt' => $excerpt + ); + + $response = wp_safe_remote_post( $trackback_url, $options ); + + if ( is_wp_error( $response ) ) + return; + + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', %s) WHERE ID = %d", $trackback_url, $ID) ); + return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $trackback_url, $ID) ); +} + +/** + * Send a pingback. + * + * @since 1.2.0 + * @uses $wp_version + * @uses IXR_Client + * + * @param string $server Host of blog to connect to. + * @param string $path Path to send the ping. + */ +function weblog_ping($server = '', $path = '') { + global $wp_version; + include_once(ABSPATH . WPINC . '/class-IXR.php'); + include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php'); + + // using a timeout of 3 seconds should be enough to cover slow servers + $client = new WP_HTTP_IXR_Client($server, ((!strlen(trim($path)) || ('/' == $path)) ? false : $path)); + $client->timeout = 3; + $client->useragent .= ' -- WordPress/'.$wp_version; + + // when set to true, this outputs debug messages by itself + $client->debug = false; + $home = trailingslashit( home_url() ); + if ( !$client->query('weblogUpdates.extendedPing', get_option('blogname'), $home, get_bloginfo('rss2_url') ) ) // then try a normal ping + $client->query('weblogUpdates.ping', get_option('blogname'), $home); +} + +/** + * Default filter attached to pingback_ping_source_uri to validate the pingback's Source URI + * + * @since 3.5.1 + * @see wp_http_validate_url() + * + * @param string $source_uri + * @return string + */ +function pingback_ping_source_uri( $source_uri ) { + return (string) wp_http_validate_url( $source_uri ); +} + +/** + * Default filter attached to xmlrpc_pingback_error. + * + * Returns a generic pingback error code unless the error code is 48, + * which reports that the pingback is already registered. + * + * @since 3.5.1 + * @link http://www.hixie.ch/specs/pingback/pingback#TOC3 + * + * @param IXR_Error $ixr_error + * @return IXR_Error + */ +function xmlrpc_pingback_error( $ixr_error ) { + if ( $ixr_error->code === 48 ) + return $ixr_error; + return new IXR_Error( 0, '' ); +} + +// +// Cache +// + +/** + * Removes comment ID from the comment cache. + * + * @since 2.3.0 + * @package WordPress + * @subpackage Cache + * + * @param int|array $ids Comment ID or array of comment IDs to remove from cache + */ +function clean_comment_cache($ids) { + foreach ( (array) $ids as $id ) + wp_cache_delete($id, 'comment'); + + wp_cache_set( 'last_changed', microtime(), 'comment' ); +} + +/** + * Updates the comment cache of given comments. + * + * Will add the comments in $comments to the cache. If comment ID already exists + * in the comment cache then it will not be updated. The comment is added to the + * cache using the comment group with the key using the ID of the comments. + * + * @since 2.3.0 + * @package WordPress + * @subpackage Cache + * + * @param array $comments Array of comment row objects + */ +function update_comment_cache($comments) { + foreach ( (array) $comments as $comment ) + wp_cache_add($comment->comment_ID, $comment, 'comment'); +} + +// +// Internal +// + +/** + * Close comments on old posts on the fly, without any extra DB queries. Hooked to the_posts. + * + * @access private + * @since 2.7.0 + * + * @param object $posts Post data object. + * @param object $query Query object. + * @return object + */ +function _close_comments_for_old_posts( $posts, $query ) { + if ( empty( $posts ) || ! $query->is_singular() || ! get_option( 'close_comments_for_old_posts' ) ) + return $posts; + + $post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) ); + if ( ! in_array( $posts[0]->post_type, $post_types ) ) + return $posts; + + $days_old = (int) get_option( 'close_comments_days_old' ); + if ( ! $days_old ) + return $posts; + + if ( time() - strtotime( $posts[0]->post_date_gmt ) > ( $days_old * DAY_IN_SECONDS ) ) { + $posts[0]->comment_status = 'closed'; + $posts[0]->ping_status = 'closed'; + } + + return $posts; +} + +/** + * Close comments on an old post. Hooked to comments_open and pings_open. + * + * @access private + * @since 2.7.0 + * + * @param bool $open Comments open or closed + * @param int $post_id Post ID + * @return bool $open + */ +function _close_comments_for_old_post( $open, $post_id ) { + if ( ! $open ) + return $open; + + if ( !get_option('close_comments_for_old_posts') ) + return $open; + + $days_old = (int) get_option('close_comments_days_old'); + if ( !$days_old ) + return $open; + + $post = get_post($post_id); + + $post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) ); + if ( ! in_array( $post->post_type, $post_types ) ) + return $open; + + if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * DAY_IN_SECONDS ) ) + return false; + + return $open; +} diff --git a/sources/wp-includes/compat.php b/sources/wp-includes/compat.php new file mode 100644 index 0000000..cb2a559 --- /dev/null +++ b/sources/wp-includes/compat.php @@ -0,0 +1,96 @@ + 'H32', 'sha1' => 'H40'); + + if ( !isset($packs[$algo]) ) + return false; + + $pack = $packs[$algo]; + + if (strlen($key) > 64) + $key = pack($pack, $algo($key)); + + $key = str_pad($key, 64, chr(0)); + + $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64)); + $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64)); + + $hmac = $algo($opad . pack($pack, $algo($ipad . $data))); + + if ( $raw_output ) + return pack( $pack, $hmac ); + return $hmac; +} + +if ( !function_exists('json_encode') ) { + function json_encode( $string ) { + global $wp_json; + + if ( !is_a($wp_json, 'Services_JSON') ) { + require_once( ABSPATH . WPINC . '/class-json.php' ); + $wp_json = new Services_JSON(); + } + + return $wp_json->encodeUnsafe( $string ); + } +} + +if ( !function_exists('json_decode') ) { + function json_decode( $string, $assoc_array = false ) { + global $wp_json; + + if ( !is_a($wp_json, 'Services_JSON') ) { + require_once( ABSPATH . WPINC . '/class-json.php' ); + $wp_json = new Services_JSON(); + } + + $res = $wp_json->decode( $string ); + if ( $assoc_array ) + $res = _json_decode_object_helper( $res ); + return $res; + } + function _json_decode_object_helper($data) { + if ( is_object($data) ) + $data = get_object_vars($data); + return is_array($data) ? array_map(__FUNCTION__, $data) : $data; + } +} diff --git a/sources/wp-includes/cron.php b/sources/wp-includes/cron.php new file mode 100644 index 0000000..6668dc5 --- /dev/null +++ b/sources/wp-includes/cron.php @@ -0,0 +1,414 @@ + $hook, 'timestamp' => $timestamp, 'schedule' => false, 'args' => $args ); + $event = apply_filters('schedule_event', $event); + + // A plugin disallowed this event + if ( ! $event ) + return false; + + $key = md5(serialize($event->args)); + + $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args ); + uksort( $crons, "strnatcasecmp" ); + _set_cron_array( $crons ); +} + +/** + * Schedule a periodic event. + * + * Schedules a hook which will be executed by the WordPress actions core on a + * specific interval, specified by you. The action will trigger when someone + * visits your WordPress site, if the scheduled time has passed. + * + * Valid values for the recurrence are hourly, daily and twicedaily. These can + * be extended using the cron_schedules filter in wp_get_schedules(). + * + * Use wp_next_scheduled() to prevent duplicates + * + * @since 2.1.0 + * + * @param int $timestamp Timestamp for when to run the event. + * @param string $recurrence How often the event should recur. + * @param string $hook Action hook to execute when cron is run. + * @param array $args Optional. Arguments to pass to the hook's callback function. + * @return bool|null False on failure, null when complete with scheduling event. + */ +function wp_schedule_event( $timestamp, $recurrence, $hook, $args = array()) { + $crons = _get_cron_array(); + $schedules = wp_get_schedules(); + + if ( !isset( $schedules[$recurrence] ) ) + return false; + + $event = (object) array( 'hook' => $hook, 'timestamp' => $timestamp, 'schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval'] ); + $event = apply_filters('schedule_event', $event); + + // A plugin disallowed this event + if ( ! $event ) + return false; + + $key = md5(serialize($event->args)); + + $crons[$event->timestamp][$event->hook][$key] = array( 'schedule' => $event->schedule, 'args' => $event->args, 'interval' => $event->interval ); + uksort( $crons, "strnatcasecmp" ); + _set_cron_array( $crons ); +} + +/** + * Reschedule a recurring event. + * + * @since 2.1.0 + * + * @param int $timestamp Timestamp for when to run the event. + * @param string $recurrence How often the event should recur. + * @param string $hook Action hook to execute when cron is run. + * @param array $args Optional. Arguments to pass to the hook's callback function. + * @return bool|null False on failure. Null when event is rescheduled. + */ +function wp_reschedule_event( $timestamp, $recurrence, $hook, $args = array()) { + $crons = _get_cron_array(); + $schedules = wp_get_schedules(); + $key = md5(serialize($args)); + $interval = 0; + + // First we try to get it from the schedule + if ( 0 == $interval ) + $interval = $schedules[$recurrence]['interval']; + // Now we try to get it from the saved interval in case the schedule disappears + if ( 0 == $interval ) + $interval = $crons[$timestamp][$hook][$key]['interval']; + // Now we assume something is wrong and fail to schedule + if ( 0 == $interval ) + return false; + + $now = time(); + + if ( $timestamp >= $now ) + $timestamp = $now + $interval; + else + $timestamp = $now + ($interval - (($now - $timestamp) % $interval)); + + wp_schedule_event( $timestamp, $recurrence, $hook, $args ); +} + +/** + * Unschedule a previously scheduled cron job. + * + * The $timestamp and $hook parameters are required, so that the event can be + * identified. + * + * @since 2.1.0 + * + * @param int $timestamp Timestamp for when to run the event. + * @param string $hook Action hook, the execution of which will be unscheduled. + * @param array $args Arguments to pass to the hook's callback function. + * Although not passed to a callback function, these arguments are used + * to uniquely identify the scheduled event, so they should be the same + * as those used when originally scheduling the event. + */ +function wp_unschedule_event( $timestamp, $hook, $args = array() ) { + $crons = _get_cron_array(); + $key = md5(serialize($args)); + unset( $crons[$timestamp][$hook][$key] ); + if ( empty($crons[$timestamp][$hook]) ) + unset( $crons[$timestamp][$hook] ); + if ( empty($crons[$timestamp]) ) + unset( $crons[$timestamp] ); + _set_cron_array( $crons ); +} + +/** + * Unschedule all cron jobs attached to a specific hook. + * + * @since 2.1.0 + * + * @param string $hook Action hook, the execution of which will be unscheduled. + * @param array $args Optional. Arguments that were to be pass to the hook's callback function. + */ +function wp_clear_scheduled_hook( $hook, $args = array() ) { + // Backward compatibility + // Previously this function took the arguments as discrete vars rather than an array like the rest of the API + if ( !is_array($args) ) { + _deprecated_argument( __FUNCTION__, '3.0', __('This argument has changed to an array to match the behavior of the other cron functions.') ); + $args = array_slice( func_get_args(), 1 ); + } + + while ( $timestamp = wp_next_scheduled( $hook, $args ) ) + wp_unschedule_event( $timestamp, $hook, $args ); +} + +/** + * Retrieve the next timestamp for a cron event. + * + * @since 2.1.0 + * + * @param string $hook Action hook to execute when cron is run. + * @param array $args Optional. Arguments to pass to the hook's callback function. + * @return bool|int The UNIX timestamp of the next time the scheduled event will occur. + */ +function wp_next_scheduled( $hook, $args = array() ) { + $crons = _get_cron_array(); + $key = md5(serialize($args)); + if ( empty($crons) ) + return false; + foreach ( $crons as $timestamp => $cron ) { + if ( isset( $cron[$hook][$key] ) ) + return $timestamp; + } + return false; +} + +/** + * Send request to run cron through HTTP request that doesn't halt page loading. + * + * @since 2.1.0 + * + * @return null Cron could not be spawned, because it is not needed to run. + */ +function spawn_cron( $gmt_time = 0 ) { + + if ( ! $gmt_time ) + $gmt_time = microtime( true ); + + if ( defined('DOING_CRON') || isset($_GET['doing_wp_cron']) ) + return; + + /* + * multiple processes on multiple web servers can run this code concurrently + * try to make this as atomic as possible by setting doing_cron switch + */ + $lock = get_transient('doing_cron'); + + if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) + $lock = 0; + + // don't run if another process is currently running it or more than once every 60 sec. + if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) + return; + + //sanity check + $crons = _get_cron_array(); + if ( !is_array($crons) ) + return; + + $keys = array_keys( $crons ); + if ( isset($keys[0]) && $keys[0] > $gmt_time ) + return; + + if ( defined('ALTERNATE_WP_CRON') && ALTERNATE_WP_CRON ) { + if ( !empty($_POST) || defined('DOING_AJAX') ) + return; + + $doing_wp_cron = sprintf( '%.22F', $gmt_time ); + set_transient( 'doing_cron', $doing_wp_cron ); + + ob_start(); + wp_redirect( add_query_arg( 'doing_wp_cron', $doing_wp_cron, wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); + echo ' '; + + // flush any buffers and send the headers + while ( @ob_end_flush() ); + flush(); + + WP_DEBUG ? include_once( ABSPATH . 'wp-cron.php' ) : @include_once( ABSPATH . 'wp-cron.php' ); + return; + } + + $doing_wp_cron = sprintf( '%.22F', $gmt_time ); + set_transient( 'doing_cron', $doing_wp_cron ); + + $cron_request = apply_filters( 'cron_request', array( + 'url' => site_url( 'wp-cron.php?doing_wp_cron=' . $doing_wp_cron ), + 'key' => $doing_wp_cron, + 'args' => array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ) + ) ); + + wp_remote_post( $cron_request['url'], $cron_request['args'] ); +} + +/** + * Run scheduled callbacks or spawn cron for all scheduled events. + * + * @since 2.1.0 + * + * @return null When doesn't need to run Cron. + */ +function wp_cron() { + + // Prevent infinite loops caused by lack of wp-cron.php + if ( strpos($_SERVER['REQUEST_URI'], '/wp-cron.php') !== false || ( defined('DISABLE_WP_CRON') && DISABLE_WP_CRON ) ) + return; + + if ( false === $crons = _get_cron_array() ) + return; + + $gmt_time = microtime( true ); + $keys = array_keys( $crons ); + if ( isset($keys[0]) && $keys[0] > $gmt_time ) + return; + + $schedules = wp_get_schedules(); + foreach ( $crons as $timestamp => $cronhooks ) { + if ( $timestamp > $gmt_time ) break; + foreach ( (array) $cronhooks as $hook => $args ) { + if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) ) + continue; + spawn_cron( $gmt_time ); + break 2; + } + } +} + +/** + * Retrieve supported and filtered Cron recurrences. + * + * The supported recurrences are 'hourly' and 'daily'. A plugin may add more by + * hooking into the 'cron_schedules' filter. The filter accepts an array of + * arrays. The outer array has a key that is the name of the schedule or for + * example 'weekly'. The value is an array with two keys, one is 'interval' and + * the other is 'display'. + * + * The 'interval' is a number in seconds of when the cron job should run. So for + * 'hourly', the time is 3600 or 60*60. For weekly, the value would be + * 60*60*24*7 or 604800. The value of 'interval' would then be 604800. + * + * The 'display' is the description. For the 'weekly' key, the 'display' would + * be __('Once Weekly'). + * + * For your plugin, you will be passed an array. you can easily add your + * schedule by doing the following. + * + * // filter parameter variable name is 'array' + * $array['weekly'] = array( + * 'interval' => 604800, + * 'display' => __('Once Weekly') + * ); + * + * + * @since 2.1.0 + * + * @return array + */ +function wp_get_schedules() { + $schedules = array( + 'hourly' => array( 'interval' => HOUR_IN_SECONDS, 'display' => __( 'Once Hourly' ) ), + 'twicedaily' => array( 'interval' => 12 * HOUR_IN_SECONDS, 'display' => __( 'Twice Daily' ) ), + 'daily' => array( 'interval' => DAY_IN_SECONDS, 'display' => __( 'Once Daily' ) ), + ); + return array_merge( apply_filters( 'cron_schedules', array() ), $schedules ); +} + +/** + * Retrieve Cron schedule for hook with arguments. + * + * @since 2.1.0 + * + * @param string $hook Action hook to execute when cron is run. + * @param array $args Optional. Arguments to pass to the hook's callback function. + * @return string|bool False, if no schedule. Schedule on success. + */ +function wp_get_schedule($hook, $args = array()) { + $crons = _get_cron_array(); + $key = md5(serialize($args)); + if ( empty($crons) ) + return false; + foreach ( $crons as $timestamp => $cron ) { + if ( isset( $cron[$hook][$key] ) ) + return $cron[$hook][$key]['schedule']; + } + return false; +} + +// +// Private functions +// + +/** + * Retrieve cron info array option. + * + * @since 2.1.0 + * @access private + * + * @return array CRON info array. + */ +function _get_cron_array() { + $cron = get_option('cron'); + if ( ! is_array($cron) ) + return false; + + if ( !isset($cron['version']) ) + $cron = _upgrade_cron_array($cron); + + unset($cron['version']); + + return $cron; +} + +/** + * Updates the CRON option with the new CRON array. + * + * @since 2.1.0 + * @access private + * + * @param array $cron Cron info array from {@link _get_cron_array()}. + */ +function _set_cron_array($cron) { + $cron['version'] = 2; + update_option( 'cron', $cron ); +} + +/** + * Upgrade a Cron info array. + * + * This function upgrades the Cron info array to version 2. + * + * @since 2.1.0 + * @access private + * + * @param array $cron Cron info array from {@link _get_cron_array()}. + * @return array An upgraded Cron info array. + */ +function _upgrade_cron_array($cron) { + if ( isset($cron['version']) && 2 == $cron['version']) + return $cron; + + $new_cron = array(); + + foreach ( (array) $cron as $timestamp => $hooks) { + foreach ( (array) $hooks as $hook => $args ) { + $key = md5(serialize($args['args'])); + $new_cron[$timestamp][$hook][$key] = $args; + } + } + + $new_cron['version'] = 2; + update_option( 'cron', $new_cron ); + return $new_cron; +} diff --git a/sources/wp-includes/css/admin-bar-rtl.css b/sources/wp-includes/css/admin-bar-rtl.css new file mode 100644 index 0000000..a190f21 --- /dev/null +++ b/sources/wp-includes/css/admin-bar-rtl.css @@ -0,0 +1,201 @@ +#wpadminbar * { + font-family: Tahoma, Arial, Helvetica, sans-serif; +} + +#wpadminbar { + direction: rtl; + font-family: Tahoma, Arial, Helvetica, sans-serif; + left: auto; + right: 0; +} + +#wpadminbar .quicklinks ul { + text-align: right; +} + +#wpadminbar li { + float: right; +} + +#wpadminbar .quicklinks > ul > li { + border-right: 0; + border-left: 1px solid #555; +} + +#wpadminbar .quicklinks > ul > li > a, +#wpadminbar .quicklinks > ul > li > .ab-empty-item { + border-right: 0; + border-left: 1px solid #333; +} + +#wpadminbar .quicklinks .ab-top-secondary > li { + border-left: 0; + border-right: 1px solid #333; + float: left; +} + +#wpadminbar .quicklinks .ab-top-secondary > li > a, +#wpadminbar .quicklinks .ab-top-secondary > li > .ab-empty-item { + border-right: 1px solid #555; + border-left: 0; +} + +#wpadminbar .menupop .ab-sub-wrapper, +#wpadminbar .shortlink-input { + margin: 0 -1px 0 0; +} + +#wpadminbar.ie7 .menupop .ab-sub-wrapper, +#wpadminbar.ie7 .shortlink-input { + left: auto; + right: 0; +} + +#wpadminbar .ab-top-secondary .menupop .ab-sub-wrapper { + right: auto; + left: 0; + margin: 0 0 0 -1px; +} + +#wpadminbar .menupop li:hover > .ab-sub-wrapper, +#wpadminbar .menupop li.hover > .ab-sub-wrapper { + margin-left: 0px; + margin-right: 100%; +} + +#wpadminbar .ab-top-secondary .menupop li:hover > .ab-sub-wrapper, +#wpadminbar .ab-top-secondary .menupop li.hover > .ab-sub-wrapper { + margin-left: inherit; + margin-right: 0; + left: 100%; + right: inherit; +} + +#wpadminbar .menupop .menupop > .ab-item { + background-position: 5% -46px; + padding-left: 2em; + padding-right: 1em; +} + +#wpadminbar .ab-top-secondary .menupop .menupop > .ab-item { + background-position: 95% -20px; + padding-left: 1em; + padding-right: 2em; +} + +#wpadminbar .quicklinks .menupop ul.ab-sub-secondary { + right: 0; + left: auto; +} + +#wpadminbar .ab-top-secondary { + float: left; + right: auto; + left: 0; +} + +#wpadminbar ul li:last-child, +#wpadminbar ul li:last-child .ab-item { + border-left: 0; +} + +#wpadminbar .screen-reader-shortcut:focus { + left: auto; + right: 6px; +} + +/** + * My Account + */ +#wpadminbar #wp-admin-bar-my-account.with-avatar #wp-admin-bar-user-actions > li { + margin-right: 88px; + margin-left: 16px; +} + +#wp-admin-bar-user-actions > li > .ab-item { + padding-left: 0; + padding-right: 8px; +} + +#wp-admin-bar-user-info .avatar { + left: auto; + right: -72px; +} + +#wpadminbar .quicklinks li#wp-admin-bar-my-account.with-avatar > a img { + margin-left: -1px; + margin-right: 4px +} + +/* + * My Sites + */ +#wpadminbar .quicklinks li .blavatar { + margin-right: 0px; + margin-left: 4px; +} + +/* + * Search + */ +#wpadminbar #adminbarsearch .adminbar-input { + font-family: Tahoma, Arial, Helvetica, sans-serif; + padding: 0 24px 0 3px; + margin: 0; + background-position: 50% 2px; +} + +#wpadminbar #adminbarsearch .adminbar-input:focus, +#wpadminbar.ie7 #adminbarsearch .adminbar-input { + background-position: 99% 2px; +} + +/** + * Comments icon + */ +#wpadminbar .ab-icon { + float: right; +} + +.ie7 #wp-admin-bar-wp-logo > .ab-item .ab-icon { + position: static; +} + +#wpadminbar.ie7 .ab-icon { + float: left; + left: 12px; +} + +#wpadminbar .ab-label { + margin-left: 0px; + margin-right: 4px; + float: left; +} + +#wpadminbar.ie7 .ab-label { + margin-right: 0; +} + +#wpadminbar.ie7 #wp-admin-bar-comments > a { + min-width: 25px; +} + +#wpadminbar a:hover .ab-comments-icon-arrow { + border-right-color: #bbb; +} + +#wpadminbar .menupop .ab-sub-wrapper, +#wpadminbar .shortlink-input { + right: 0; +} + +#wpadminbar .quicklinks .menupop ul li a { + position: relative; +} + +/** + * IE 6-targeted rules + */ +* html #wpadminbar .quicklinks ul li a { + float: right; +} diff --git a/sources/wp-includes/css/admin-bar-rtl.min.css b/sources/wp-includes/css/admin-bar-rtl.min.css new file mode 100644 index 0000000..d53db89 --- /dev/null +++ b/sources/wp-includes/css/admin-bar-rtl.min.css @@ -0,0 +1 @@ +#wpadminbar *{font-family:Tahoma,Arial,Helvetica,sans-serif}#wpadminbar{direction:rtl;font-family:Tahoma,Arial,Helvetica,sans-serif;left:auto;right:0}#wpadminbar .quicklinks ul{text-align:right}#wpadminbar li{float:right}#wpadminbar .quicklinks>ul>li{border-right:0;border-left:1px solid #555}#wpadminbar .quicklinks>ul>li>a,#wpadminbar .quicklinks>ul>li>.ab-empty-item{border-right:0;border-left:1px solid #333}#wpadminbar .quicklinks .ab-top-secondary>li{border-left:0;border-right:1px solid #333;float:left}#wpadminbar .quicklinks .ab-top-secondary>li>a,#wpadminbar .quicklinks .ab-top-secondary>li>.ab-empty-item{border-right:1px solid #555;border-left:0}#wpadminbar .menupop .ab-sub-wrapper,#wpadminbar .shortlink-input{margin:0 -1px 0 0}#wpadminbar.ie7 .menupop .ab-sub-wrapper,#wpadminbar.ie7 .shortlink-input{left:auto;right:0}#wpadminbar .ab-top-secondary .menupop .ab-sub-wrapper{right:auto;left:0;margin:0 0 0 -1px}#wpadminbar .menupop li:hover>.ab-sub-wrapper,#wpadminbar .menupop li.hover>.ab-sub-wrapper{margin-left:0;margin-right:100%}#wpadminbar .ab-top-secondary .menupop li:hover>.ab-sub-wrapper,#wpadminbar .ab-top-secondary .menupop li.hover>.ab-sub-wrapper{margin-left:inherit;margin-right:0;left:100%;right:inherit}#wpadminbar .menupop .menupop>.ab-item{background-position:5% -46px;padding-left:2em;padding-right:1em}#wpadminbar .ab-top-secondary .menupop .menupop>.ab-item{background-position:95% -20px;padding-left:1em;padding-right:2em}#wpadminbar .quicklinks .menupop ul.ab-sub-secondary{right:0;left:auto}#wpadminbar .ab-top-secondary{float:left;right:auto;left:0}#wpadminbar ul li:last-child,#wpadminbar ul li:last-child .ab-item{border-left:0}#wpadminbar .screen-reader-shortcut:focus{left:auto;right:6px}#wpadminbar #wp-admin-bar-my-account.with-avatar #wp-admin-bar-user-actions>li{margin-right:88px;margin-left:16px}#wp-admin-bar-user-actions>li>.ab-item{padding-left:0;padding-right:8px}#wp-admin-bar-user-info .avatar{left:auto;right:-72px}#wpadminbar .quicklinks li#wp-admin-bar-my-account.with-avatar>a img{margin-left:-1px;margin-right:4px}#wpadminbar .quicklinks li .blavatar{margin-right:0;margin-left:4px}#wpadminbar #adminbarsearch .adminbar-input{font-family:Tahoma,Arial,Helvetica,sans-serif;padding:0 24px 0 3px;margin:0;background-position:50% 2px}#wpadminbar #adminbarsearch .adminbar-input:focus,#wpadminbar.ie7 #adminbarsearch .adminbar-input{background-position:99% 2px}#wpadminbar .ab-icon{float:right}.ie7 #wp-admin-bar-wp-logo>.ab-item .ab-icon{position:static}#wpadminbar.ie7 .ab-icon{float:left;left:12px}#wpadminbar .ab-label{margin-left:0;margin-right:4px;float:left}#wpadminbar.ie7 .ab-label{margin-right:0}#wpadminbar.ie7 #wp-admin-bar-comments>a{min-width:25px}#wpadminbar a:hover .ab-comments-icon-arrow{border-right-color:#bbb}#wpadminbar .menupop .ab-sub-wrapper,#wpadminbar .shortlink-input{right:0}#wpadminbar .quicklinks .menupop ul li a{position:relative}* html #wpadminbar .quicklinks ul li a{float:right} \ No newline at end of file diff --git a/sources/wp-includes/css/admin-bar.css b/sources/wp-includes/css/admin-bar.css new file mode 100644 index 0000000..270fa9a --- /dev/null +++ b/sources/wp-includes/css/admin-bar.css @@ -0,0 +1,689 @@ +#wpadminbar * { + height: auto; + width: auto; + margin: 0; + padding: 0; + position: static; + text-transform: none; + letter-spacing: normal; + line-height: 1; + font: normal 13px/28px sans-serif; + color: #ccc; + text-shadow: #444 0px -1px 0px; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +#wpadminbar ul li:before, +#wpadminbar ul li:after { + content: normal; +} + +#wpadminbar a, +#wpadminbar a:hover, +#wpadminbar a img, +#wpadminbar a img:hover { + outline: none; + border: none; + text-decoration: none; + background: none; +} + +#wpadminbar a:focus, +#wpadminbar a:active, +#wpadminbar input[type="text"], +#wpadminbar input[type="password"], +#wpadminbar input[type="number"], +#wpadminbar input[type="search"], +#wpadminbar input[type="email"], +#wpadminbar input[type="url"], +#wpadminbar select, +#wpadminbar textarea, +#wpadminbar div { + outline: none; +} + +#wpadminbar { + direction: ltr; + color: #ccc; + font: normal 13px/28px sans-serif; + height: 28px; + position: fixed; + top: 0; + left: 0; + width: 100%; + min-width: 600px; /* match the min-width of the body in wp-admin.css */ + z-index: 99999; + background: #464646; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #373737), color-stop(18%, #464646)); + background-image: -webkit-linear-gradient(bottom, #373737 0, #464646 5px); + background-image: -moz-linear-gradient(bottom, #373737 0, #464646 5px); + background-image: -o-linear-gradient(bottom, #373737 0, #464646 5px); + background-image: linear-gradient(to top, #373737 0, #464646 5px); +} + +#wpadminbar .ab-sub-wrapper, +#wpadminbar ul, +#wpadminbar ul li { + background: none; + clear: none; + list-style: none; + margin: 0; + padding: 0; + position: relative; + text-indent: 0; + z-index: 99999; +} + +#wpadminbar .quicklinks { + border-left: 1px solid transparent; +} + +#wpadminbar .quicklinks ul { + text-align: left; +} + +#wpadminbar li { + float: left; +} + +#wpadminbar .ab-empty-item { + outline: none; +} + +#wpadminbar .quicklinks > ul > li { + border-right: 1px solid #555; +} + +#wpadminbar .quicklinks > ul > li > a, +#wpadminbar .quicklinks > ul > li > .ab-empty-item { + border-right: 1px solid #333; +} + +#wpadminbar .quicklinks .ab-top-secondary > li { + border-left: 1px solid #333; + border-right: 0; + float: right; +} + +#wpadminbar .quicklinks .ab-top-secondary > li > a, +#wpadminbar .quicklinks .ab-top-secondary > li > .ab-empty-item { + border-left: 1px solid #555; + border-right: 0; +} + +#wpadminbar .quicklinks a, +#wpadminbar .quicklinks .ab-empty-item, +#wpadminbar .shortlink-input { + height: 28px; + display: block; + padding: 0 12px; + margin: 0; +} + +#wpadminbar .menupop .ab-sub-wrapper, +#wpadminbar .shortlink-input { + margin: 0 0 0 -1px; + padding: 0; + -webkit-box-shadow: 0 4px 4px rgba(0,0,0,0.2); + box-shadow: 0 4px 4px rgba(0,0,0,0.2); + background: #fff; + display: none; + position: absolute; + float: none; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #dfdfdf; +} + +#wpadminbar.ie7 .menupop .ab-sub-wrapper, +#wpadminbar.ie7 .shortlink-input { + top: 28px; + left: 0; +} + +#wpadminbar .ab-top-menu > .menupop > .ab-sub-wrapper { + min-width: 100%; +} + +#wpadminbar .ab-top-secondary .menupop .ab-sub-wrapper { + right: 0; + left: auto; + margin: 0 -1px 0 0; +} + +#wpadminbar .ab-sub-wrapper > .ab-submenu:first-child { + border-top: none; +} + +#wpadminbar .ab-submenu { + padding: 6px 0; + border-top: 1px solid #dfdfdf; +} + +#wpadminbar .selected .shortlink-input { + display: block; +} + +#wpadminbar .quicklinks .menupop ul li { + float: none; +} + +#wpadminbar .quicklinks .menupop ul li a strong { + font-weight: bold; +} + +#wpadminbar .quicklinks .menupop ul li .ab-item, +#wpadminbar .quicklinks .menupop ul li a strong, +#wpadminbar .quicklinks .menupop.hover ul li .ab-item, +#wpadminbar.nojs .quicklinks .menupop:hover ul li .ab-item, +#wpadminbar .shortlink-input { + line-height: 26px; + height: 26px; + text-shadow: none; + white-space: nowrap; + min-width: 140px; +} + +#wpadminbar .shortlink-input { + width: 200px; +} + +#wpadminbar.nojs li:hover > .ab-sub-wrapper, +#wpadminbar li.hover > .ab-sub-wrapper { + display: block; +} + +#wpadminbar .menupop li:hover > .ab-sub-wrapper, +#wpadminbar .menupop li.hover > .ab-sub-wrapper { + margin-left: 100%; + margin-top: -33px; + border-width: 1px; +} + +#wpadminbar .ab-top-secondary .menupop li:hover > .ab-sub-wrapper, +#wpadminbar .ab-top-secondary .menupop li.hover > .ab-sub-wrapper { + margin-left: 0; + left: inherit; + right: 100%; +} + +#wpadminbar .ab-top-menu > li:hover > .ab-item, +#wpadminbar .ab-top-menu > li.hover > .ab-item, +#wpadminbar .ab-top-menu > li > .ab-item:focus, +#wpadminbar.nojq .quicklinks .ab-top-menu > li > .ab-item:focus { + color: #fafafa; + background: #222; + background-image: -webkit-gradient(linear, left bottom, left top, from(#3a3a3a), to(#222)); + background-image: -webkit-linear-gradient(bottom, #3a3a3a, #222); + background-image: -moz-linear-gradient(bottom, #3a3a3a, #222); + background-image: -o-linear-gradient(bottom, #3a3a3a, #222); + background-image: linear-gradient(to top, #3a3a3a, #222); +} + +#wpadminbar.nojs .ab-top-menu > li.menupop:hover > .ab-item, +#wpadminbar .ab-top-menu > li.menupop.hover > .ab-item { + background: #fff; + color: #333; + text-shadow: none; + border-right-color: transparent; + border-left-color: transparent; +} + +#wpadminbar .hover .ab-label, +#wpadminbar.nojq .ab-item:focus .ab-label { + color: #fafafa; +} + +#wpadminbar .menupop.hover .ab-label { + color: #333; + text-shadow: none; +} + +#wpadminbar .menupop li:hover, +#wpadminbar .menupop li.hover, +#wpadminbar .quicklinks .menupop .ab-item:focus, +#wpadminbar .quicklinks .ab-top-menu .menupop .ab-item:focus { + background-color: #eaf2fa; +} + +#wpadminbar .ab-submenu .ab-item { + color: #333; + text-shadow: none; +} + +#wpadminbar .quicklinks .menupop ul li a, +#wpadminbar .quicklinks .menupop ul li a strong, +#wpadminbar .quicklinks .menupop.hover ul li a, +#wpadminbar.nojs .quicklinks .menupop:hover ul li a { + color: #21759B; +} + +#wpadminbar .menupop .menupop > .ab-item { + display: block; + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: 95% -20px; + background-repeat: no-repeat; + padding-right: 2em; +} + +#wpadminbar .ab-top-secondary .menupop .menupop > .ab-item { + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: 5% -46px; + background-repeat: no-repeat; + padding-left: 2em; + padding-right: 1em; +} + +#wpadminbar .quicklinks .menupop ul.ab-sub-secondary { + display: block; + position: relative; + right: auto; + margin: 0; + background: #eee; + -webkit-box-shadow: none; + box-shadow: none; +} + +#wpadminbar .quicklinks .menupop .ab-sub-secondary > li:hover, +#wpadminbar .quicklinks .menupop .ab-sub-secondary > li.hover, +#wpadminbar .quicklinks .menupop .ab-sub-secondary > li .ab-item:focus { + background-color: #dfdfdf; +} + +#wpadminbar .quicklinks a span#ab-updates { + background: #eee; + color: #333; + text-shadow: none; + display: inline; + padding: 2px 5px; + font-size: 10px; + font-weight: bold; + -webkit-border-radius: 10px; + border-radius: 10px; +} + +#wpadminbar .quicklinks a:hover span#ab-updates { + background: #fff; + color: #000; +} + +#wpadminbar .ab-top-secondary { + float: right; + background: #464646; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #373737), color-stop(18%, #464646)); + background-image: -webkit-linear-gradient(bottom, #373737 0, #464646 5px); + background-image: -moz-linear-gradient(bottom, #373737 0, #464646 5px); + background-image: -o-linear-gradient(bottom, #373737 0, #464646 5px); + background-image: linear-gradient(to top, #373737 0, #464646 5px); +} + +#wpadminbar ul li:last-child, +#wpadminbar ul li:last-child .ab-item { + border-right: 0; + -webkit-box-shadow: none; + box-shadow: none; +} + +/** + * My Account + */ +#wp-admin-bar-my-account > ul { + min-width: 198px; +} + +#wp-admin-bar-my-account.with-avatar > ul { + min-width: 270px; +} + +#wpadminbar #wp-admin-bar-user-actions > li { + margin-left: 16px; + margin-right: 16px; +} + +#wpadminbar #wp-admin-bar-my-account.with-avatar #wp-admin-bar-user-actions > li { + margin-left: 88px; +} + +#wp-admin-bar-user-actions > li > .ab-item { + padding-left: 8px; +} + +#wpadminbar #wp-admin-bar-user-info { + margin-top: 6px; + margin-bottom: 15px; + height: auto; + background: none; +} + +#wp-admin-bar-user-info .avatar { + position: absolute; + left: -72px; + top: 4px; + width: 64px; + height: 64px; +} + +#wpadminbar #wp-admin-bar-user-info a { + background: none; + height: auto; +} + +#wpadminbar #wp-admin-bar-user-info span { + background: none; + padding: 0; + height: 18px; +} + +#wpadminbar #wp-admin-bar-user-info .display-name, +#wpadminbar #wp-admin-bar-user-info .username { + text-shadow: none; + display: block; +} + +#wpadminbar #wp-admin-bar-user-info .display-name { + color: #333; +} + +#wpadminbar #wp-admin-bar-user-info .username { + color: #999; + font-size: 11px; +} + +#wpadminbar .quicklinks li#wp-admin-bar-my-account.with-avatar > a img { + width: 16px; + height: 16px; + border: 1px solid #999; + padding: 0; + background: #eee; + line-height: 24px; + vertical-align: middle; + margin: -3px 0 0 6px; + float: none; + display: inline; +} + +/* + * My Sites + */ +#wpadminbar .quicklinks li .blavatar { + vertical-align: middle; + margin: -3px 4px 0 0; + padding: 0; +} + +#wpadminbar .quicklinks li div.blavatar { + background: url('../images/wpmini-blue.png') no-repeat; + height: 16px; + width: 16px; + display: inline-block; +} + +/** + * Search + */ +#wpadminbar #wp-admin-bar-search .ab-item { + padding: 0; +} + +#wpadminbar #wp-admin-bar-search .ab-item { + /* default background */ + background: transparent; +} + +#wpadminbar #adminbarsearch { + height: 28px; + padding: 0 2px; +} + +#wpadminbar #adminbarsearch .adminbar-input { + font: 13px/24px sans-serif; + height: 24px; + width: 24px; + border: none; + padding: 0 3px 0 23px; + margin: 0; + color: #ccc; + text-shadow: #444 0px -1px 0px; + background-color: rgba( 255, 255, 255, 0 ); + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: 3px 2px; + background-repeat: no-repeat; + outline: none; + cursor: pointer; + + -webkit-border-radius: 3px; + border-radius: 3px; + + -webkit-box-shadow: none; + box-shadow: none; + + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + + -webkit-transition-duration: 400ms; + -webkit-transition-property: width, background; + -webkit-transition-timing-function: ease; + -moz-transition-duration: 400ms; + -moz-transition-property: width, background; + -moz-transition-timing-function: ease; + -o-transition-duration: 400ms; + -o-transition-property: width, background; + -o-transition-timing-function: ease; +} + +#wpadminbar.ie7 #adminbarsearch .adminbar-input { + margin-top: 1px; + width: 120px; +} + +#wpadminbar #adminbarsearch .adminbar-input:focus { + color: #555; + text-shadow: 0 1px 0 #fff; + width: 200px; + background-color: rgba( 255, 255, 255, 0.9 ); + cursor: text; +} + +#wpadminbar.ie8 #adminbarsearch .adminbar-input { + background-color: #464646; +} + +#wpadminbar.ie8 #adminbarsearch .adminbar-input:focus { + background-color: #fff; +} + +/* Two rules to ensure browser recognition */ +#wpadminbar #adminbarsearch .adminbar-input::-webkit-input-placeholder { + color: #ddd; +} + +#wpadminbar #adminbarsearch .adminbar-input:-moz-placeholder { + color: #ddd; +} + +#wpadminbar #adminbarsearch .adminbar-button { + display: none; +} + +/** + * Site Menu + */ +#wpadminbar #wp-admin-bar-appearance { + border-top: none; + margin-top: -12px; +} + +/** + * Site Menu + */ +#wpadminbar #wp-admin-bar-appearance { + border-top: none; + margin-top: -12px; +} + +/** + * ICONS + */ +#wpadminbar .ab-icon { + position: relative; + float: left; + width: 16px; + height: 16px; + margin-top: 6px; +} + +#wpadminbar .ab-label { + margin-left: 4px; +} + +/** + * WP Logo icon + */ +#wp-admin-bar-wp-logo > .ab-item .ab-icon { + width: 20px; + height: 20px; + margin-top: 4px; + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: 0 -76px; + background-repeat: no-repeat; +} + +#wpadminbar.nojs #wp-admin-bar-wp-logo:hover > .ab-item .ab-icon, +#wpadminbar #wp-admin-bar-wp-logo.hover > .ab-item .ab-icon { + background-position: 0 -104px; +} + +/** + * Updates icon + */ +#wp-admin-bar-updates > .ab-item .ab-icon { + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: -2px -159px; + background-repeat: no-repeat; +} + +/** + * Comments icon + */ +#wp-admin-bar-comments > .ab-item .ab-icon { + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: -1px -134px; + background-repeat: no-repeat; +} + +#wpadminbar span.count-0 { + display: none; +} + +/** + * Add New icon + */ +#wpadminbar #wp-admin-bar-new-content > .ab-item .ab-icon { + background-image: url(../images/admin-bar-sprite.png?d=20120830); + background-position: -2px -182px; + background-repeat: no-repeat; +} + +/** + * Add New icon + */ +#wpadminbar.nojs #wp-admin-bar-new-content:hover > .ab-item .ab-icon, +#wpadminbar #wp-admin-bar-new-content.hover > .ab-item .ab-icon { + background-position: -2px -203px; +} + +/** + * Customize support classes + */ +.no-customize-support .hide-if-no-customize, +.customize-support .hide-if-customize, +.no-customize-support.wp-core-ui .hide-if-no-customize, +.no-customize-support .wp-core-ui .hide-if-no-customize, +.customize-support.wp-core-ui .hide-if-customize, +.customize-support .wp-core-ui .hide-if-customize { + display: none; +} + +/** + * Retina display 2x icons + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + #wpadminbar .menupop .menupop > .ab-item, + #wpadminbar .ab-top-secondary .menupop .menupop > .ab-item, + #wpadminbar #adminbarsearch .adminbar-input, + #wp-admin-bar-wp-logo > .ab-item .ab-icon, + #wp-admin-bar-updates > .ab-item .ab-icon, + #wp-admin-bar-comments > .ab-item .ab-icon, + #wpadminbar #wp-admin-bar-new-content > .ab-item .ab-icon { + background-image: url(../images/admin-bar-sprite-2x.png?d=20120830); + background-size: 20px 220px; + } + + #wpadminbar .quicklinks li div.blavatar { + background: url('../images/wpmini-blue-2x.png') no-repeat; + background-size: 16px 16px; + } +} + +/* Skip link */ +#wpadminbar .screen-reader-text, +#wpadminbar .screen-reader-text span { + position: absolute; + left: -1000em; + top: -1000em; + height: 1px; + width: 1px; + overflow: hidden; +} + +#wpadminbar .screen-reader-shortcut { + position: absolute; + top: -1000em; +} + +#wpadminbar .screen-reader-shortcut:focus { + left: 6px; + top: 7px; + height: auto; + width: auto; + display: block; + font-size: 14px; + font-weight: bold; + padding: 15px 23px 14px; + background: #f1f1f1; + color: #21759b; + text-shadow: none; + border-radius: 3px; + z-index: 100000; + line-height: normal; + -webkit-box-shadow: 0 0 2px 2px rgba(0,0,0,.6); + box-shadow: 0 0 2px 2px rgba(0,0,0,.6); + text-decoration: none; +} + +/** + * IE 6-targeted rules + */ +* html #wpadminbar { + overflow: hidden; + position: absolute; +} + +* html #wpadminbar .quicklinks ul li a { + float: left; +} + +* html #wpadminbar .menupop a span { + background-image: none; +} diff --git a/sources/wp-includes/css/admin-bar.min.css b/sources/wp-includes/css/admin-bar.min.css new file mode 100644 index 0000000..0f6f039 --- /dev/null +++ b/sources/wp-includes/css/admin-bar.min.css @@ -0,0 +1 @@ +#wpadminbar *{height:auto;width:auto;margin:0;padding:0;position:static;text-transform:none;letter-spacing:normal;line-height:1;font:400 13px/28px sans-serif;color:#ccc;text-shadow:#444 0 -1px 0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}#wpadminbar ul li:before,#wpadminbar ul li:after{content:normal}#wpadminbar a,#wpadminbar a:hover,#wpadminbar a img,#wpadminbar a img:hover{outline:0;border:0;text-decoration:none;background:0 0}#wpadminbar a:focus,#wpadminbar a:active,#wpadminbar input[type=text],#wpadminbar input[type=password],#wpadminbar input[type=number],#wpadminbar input[type=search],#wpadminbar input[type=email],#wpadminbar input[type=url],#wpadminbar select,#wpadminbar textarea,#wpadminbar div{outline:0}#wpadminbar{direction:ltr;color:#ccc;font:400 13px/28px sans-serif;height:28px;position:fixed;top:0;left:0;width:100%;min-width:600px;z-index:99999;background:#464646;background-image:-webkit-gradient(linear,left bottom,left top,color-stop(0,#373737),color-stop(18%,#464646));background-image:-webkit-linear-gradient(bottom,#373737 0,#464646 5px);background-image:-moz-linear-gradient(bottom,#373737 0,#464646 5px);background-image:-o-linear-gradient(bottom,#373737 0,#464646 5px);background-image:linear-gradient(to top,#373737 0,#464646 5px)}#wpadminbar .ab-sub-wrapper,#wpadminbar ul,#wpadminbar ul li{background:0 0;clear:none;list-style:none;margin:0;padding:0;position:relative;text-indent:0;z-index:99999}#wpadminbar .quicklinks{border-left:1px solid transparent}#wpadminbar .quicklinks ul{text-align:left}#wpadminbar li{float:left}#wpadminbar .ab-empty-item{outline:0}#wpadminbar .quicklinks>ul>li{border-right:1px solid #555}#wpadminbar .quicklinks>ul>li>a,#wpadminbar .quicklinks>ul>li>.ab-empty-item{border-right:1px solid #333}#wpadminbar .quicklinks .ab-top-secondary>li{border-left:1px solid #333;border-right:0;float:right}#wpadminbar .quicklinks .ab-top-secondary>li>a,#wpadminbar .quicklinks .ab-top-secondary>li>.ab-empty-item{border-left:1px solid #555;border-right:0}#wpadminbar .quicklinks a,#wpadminbar .quicklinks .ab-empty-item,#wpadminbar .shortlink-input{height:28px;display:block;padding:0 12px;margin:0}#wpadminbar .menupop .ab-sub-wrapper,#wpadminbar .shortlink-input{margin:0 0 0 -1px;padding:0;-webkit-box-shadow:0 4px 4px rgba(0,0,0,.2);box-shadow:0 4px 4px rgba(0,0,0,.2);background:#fff;display:none;position:absolute;float:none;border-width:0 1px 1px;border-style:solid;border-color:#dfdfdf}#wpadminbar.ie7 .menupop .ab-sub-wrapper,#wpadminbar.ie7 .shortlink-input{top:28px;left:0}#wpadminbar .ab-top-menu>.menupop>.ab-sub-wrapper{min-width:100%}#wpadminbar .ab-top-secondary .menupop .ab-sub-wrapper{right:0;left:auto;margin:0 -1px 0 0}#wpadminbar .ab-sub-wrapper>.ab-submenu:first-child{border-top:0}#wpadminbar .ab-submenu{padding:6px 0;border-top:1px solid #dfdfdf}#wpadminbar .selected .shortlink-input{display:block}#wpadminbar .quicklinks .menupop ul li{float:none}#wpadminbar .quicklinks .menupop ul li a strong{font-weight:700}#wpadminbar .quicklinks .menupop ul li .ab-item,#wpadminbar .quicklinks .menupop ul li a strong,#wpadminbar .quicklinks .menupop.hover ul li .ab-item,#wpadminbar.nojs .quicklinks .menupop:hover ul li .ab-item,#wpadminbar .shortlink-input{line-height:26px;height:26px;text-shadow:none;white-space:nowrap;min-width:140px}#wpadminbar .shortlink-input{width:200px}#wpadminbar.nojs li:hover>.ab-sub-wrapper,#wpadminbar li.hover>.ab-sub-wrapper{display:block}#wpadminbar .menupop li:hover>.ab-sub-wrapper,#wpadminbar .menupop li.hover>.ab-sub-wrapper{margin-left:100%;margin-top:-33px;border-width:1px}#wpadminbar .ab-top-secondary .menupop li:hover>.ab-sub-wrapper,#wpadminbar .ab-top-secondary .menupop li.hover>.ab-sub-wrapper{margin-left:0;left:inherit;right:100%}#wpadminbar .ab-top-menu>li:hover>.ab-item,#wpadminbar .ab-top-menu>li.hover>.ab-item,#wpadminbar .ab-top-menu>li>.ab-item:focus,#wpadminbar.nojq .quicklinks .ab-top-menu>li>.ab-item:focus{color:#fafafa;background:#222;background-image:-webkit-gradient(linear,left bottom,left top,from(#3a3a3a),to(#222));background-image:-webkit-linear-gradient(bottom,#3a3a3a,#222);background-image:-moz-linear-gradient(bottom,#3a3a3a,#222);background-image:-o-linear-gradient(bottom,#3a3a3a,#222);background-image:linear-gradient(to top,#3a3a3a,#222)}#wpadminbar.nojs .ab-top-menu>li.menupop:hover>.ab-item,#wpadminbar .ab-top-menu>li.menupop.hover>.ab-item{background:#fff;color:#333;text-shadow:none;border-right-color:transparent;border-left-color:transparent}#wpadminbar .hover .ab-label,#wpadminbar.nojq .ab-item:focus .ab-label{color:#fafafa}#wpadminbar .menupop.hover .ab-label{color:#333;text-shadow:none}#wpadminbar .menupop li:hover,#wpadminbar .menupop li.hover,#wpadminbar .quicklinks .menupop .ab-item:focus,#wpadminbar .quicklinks .ab-top-menu .menupop .ab-item:focus{background-color:#eaf2fa}#wpadminbar .ab-submenu .ab-item{color:#333;text-shadow:none}#wpadminbar .quicklinks .menupop ul li a,#wpadminbar .quicklinks .menupop ul li a strong,#wpadminbar .quicklinks .menupop.hover ul li a,#wpadminbar.nojs .quicklinks .menupop:hover ul li a{color:#21759B}#wpadminbar .menupop .menupop>.ab-item{display:block;background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:95% -20px;background-repeat:no-repeat;padding-right:2em}#wpadminbar .ab-top-secondary .menupop .menupop>.ab-item{background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:5% -46px;background-repeat:no-repeat;padding-left:2em;padding-right:1em}#wpadminbar .quicklinks .menupop ul.ab-sub-secondary{display:block;position:relative;right:auto;margin:0;background:#eee;-webkit-box-shadow:none;box-shadow:none}#wpadminbar .quicklinks .menupop .ab-sub-secondary>li:hover,#wpadminbar .quicklinks .menupop .ab-sub-secondary>li.hover,#wpadminbar .quicklinks .menupop .ab-sub-secondary>li .ab-item:focus{background-color:#dfdfdf}#wpadminbar .quicklinks a span#ab-updates{background:#eee;color:#333;text-shadow:none;display:inline;padding:2px 5px;font-size:10px;font-weight:700;-webkit-border-radius:10px;border-radius:10px}#wpadminbar .quicklinks a:hover span#ab-updates{background:#fff;color:#000}#wpadminbar .ab-top-secondary{float:right;background:#464646;background-image:-webkit-gradient(linear,left bottom,left top,color-stop(0,#373737),color-stop(18%,#464646));background-image:-webkit-linear-gradient(bottom,#373737 0,#464646 5px);background-image:-moz-linear-gradient(bottom,#373737 0,#464646 5px);background-image:-o-linear-gradient(bottom,#373737 0,#464646 5px);background-image:linear-gradient(to top,#373737 0,#464646 5px)}#wpadminbar ul li:last-child,#wpadminbar ul li:last-child .ab-item{border-right:0;-webkit-box-shadow:none;box-shadow:none}#wp-admin-bar-my-account>ul{min-width:198px}#wp-admin-bar-my-account.with-avatar>ul{min-width:270px}#wpadminbar #wp-admin-bar-user-actions>li{margin-left:16px;margin-right:16px}#wpadminbar #wp-admin-bar-my-account.with-avatar #wp-admin-bar-user-actions>li{margin-left:88px}#wp-admin-bar-user-actions>li>.ab-item{padding-left:8px}#wpadminbar #wp-admin-bar-user-info{margin-top:6px;margin-bottom:15px;height:auto;background:0 0}#wp-admin-bar-user-info .avatar{position:absolute;left:-72px;top:4px;width:64px;height:64px}#wpadminbar #wp-admin-bar-user-info a{background:0 0;height:auto}#wpadminbar #wp-admin-bar-user-info span{background:0 0;padding:0;height:18px}#wpadminbar #wp-admin-bar-user-info .display-name,#wpadminbar #wp-admin-bar-user-info .username{text-shadow:none;display:block}#wpadminbar #wp-admin-bar-user-info .display-name{color:#333}#wpadminbar #wp-admin-bar-user-info .username{color:#999;font-size:11px}#wpadminbar .quicklinks li#wp-admin-bar-my-account.with-avatar>a img{width:16px;height:16px;border:1px solid #999;padding:0;background:#eee;line-height:24px;vertical-align:middle;margin:-3px 0 0 6px;float:none;display:inline}#wpadminbar .quicklinks li .blavatar{vertical-align:middle;margin:-3px 4px 0 0;padding:0}#wpadminbar .quicklinks li div.blavatar{background:url(../images/wpmini-blue.png) no-repeat;height:16px;width:16px;display:inline-block}#wpadminbar #wp-admin-bar-search .ab-item{padding:0}#wpadminbar #wp-admin-bar-search .ab-item{background:transparent}#wpadminbar #adminbarsearch{height:28px;padding:0 2px}#wpadminbar #adminbarsearch .adminbar-input{font:13px/24px sans-serif;height:24px;width:24px;border:0;padding:0 3px 0 23px;margin:0;color:#ccc;text-shadow:#444 0 -1px 0;background-color:rgba(255,255,255,0);background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:3px 2px;background-repeat:no-repeat;outline:0;cursor:pointer;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-transition-duration:400ms;-webkit-transition-property:width,background;-webkit-transition-timing-function:ease;-moz-transition-duration:400ms;-moz-transition-property:width,background;-moz-transition-timing-function:ease;-o-transition-duration:400ms;-o-transition-property:width,background;-o-transition-timing-function:ease}#wpadminbar.ie7 #adminbarsearch .adminbar-input{margin-top:1px;width:120px}#wpadminbar #adminbarsearch .adminbar-input:focus{color:#555;text-shadow:0 1px 0 #fff;width:200px;background-color:rgba(255,255,255,.9);cursor:text}#wpadminbar.ie8 #adminbarsearch .adminbar-input{background-color:#464646}#wpadminbar.ie8 #adminbarsearch .adminbar-input:focus{background-color:#fff}#wpadminbar #adminbarsearch .adminbar-input::-webkit-input-placeholder{color:#ddd}#wpadminbar #adminbarsearch .adminbar-input:-moz-placeholder{color:#ddd}#wpadminbar #adminbarsearch .adminbar-button{display:none}#wpadminbar #wp-admin-bar-appearance{border-top:0;margin-top:-12px}#wpadminbar #wp-admin-bar-appearance{border-top:0;margin-top:-12px}#wpadminbar .ab-icon{position:relative;float:left;width:16px;height:16px;margin-top:6px}#wpadminbar .ab-label{margin-left:4px}#wp-admin-bar-wp-logo>.ab-item .ab-icon{width:20px;height:20px;margin-top:4px;background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:0 -76px;background-repeat:no-repeat}#wpadminbar.nojs #wp-admin-bar-wp-logo:hover>.ab-item .ab-icon,#wpadminbar #wp-admin-bar-wp-logo.hover>.ab-item .ab-icon{background-position:0 -104px}#wp-admin-bar-updates>.ab-item .ab-icon{background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:-2px -159px;background-repeat:no-repeat}#wp-admin-bar-comments>.ab-item .ab-icon{background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:-1px -134px;background-repeat:no-repeat}#wpadminbar span.count-0{display:none}#wpadminbar #wp-admin-bar-new-content>.ab-item .ab-icon{background-image:url(../images/admin-bar-sprite.png?d=20120830);background-position:-2px -182px;background-repeat:no-repeat}#wpadminbar.nojs #wp-admin-bar-new-content:hover>.ab-item .ab-icon,#wpadminbar #wp-admin-bar-new-content.hover>.ab-item .ab-icon{background-position:-2px -203px}.no-customize-support .hide-if-no-customize,.customize-support .hide-if-customize,.no-customize-support.wp-core-ui .hide-if-no-customize,.no-customize-support .wp-core-ui .hide-if-no-customize,.customize-support.wp-core-ui .hide-if-customize,.customize-support .wp-core-ui .hide-if-customize{display:none}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){#wpadminbar .menupop .menupop>.ab-item,#wpadminbar .ab-top-secondary .menupop .menupop>.ab-item,#wpadminbar #adminbarsearch .adminbar-input,#wp-admin-bar-wp-logo>.ab-item .ab-icon,#wp-admin-bar-updates>.ab-item .ab-icon,#wp-admin-bar-comments>.ab-item .ab-icon,#wpadminbar #wp-admin-bar-new-content>.ab-item .ab-icon{background-image:url(../images/admin-bar-sprite-2x.png?d=20120830);background-size:20px 220px}#wpadminbar .quicklinks li div.blavatar{background:url(../images/wpmini-blue-2x.png) no-repeat;background-size:16px 16px}}#wpadminbar .screen-reader-text,#wpadminbar .screen-reader-text span{position:absolute;left:-1000em;top:-1000em;height:1px;width:1px;overflow:hidden}#wpadminbar .screen-reader-shortcut{position:absolute;top:-1000em}#wpadminbar .screen-reader-shortcut:focus{left:6px;top:7px;height:auto;width:auto;display:block;font-size:14px;font-weight:700;padding:15px 23px 14px;background:#f1f1f1;color:#21759b;text-shadow:none;border-radius:3px;z-index:100000;line-height:normal;-webkit-box-shadow:0 0 2px 2px rgba(0,0,0,.6);box-shadow:0 0 2px 2px rgba(0,0,0,.6);text-decoration:none}* html #wpadminbar{overflow:hidden;position:absolute}* html #wpadminbar .quicklinks ul li a{float:left}* html #wpadminbar .menupop a span{background-image:none} \ No newline at end of file diff --git a/sources/wp-includes/css/buttons.css b/sources/wp-includes/css/buttons.css new file mode 100644 index 0000000..5ae473c --- /dev/null +++ b/sources/wp-includes/css/buttons.css @@ -0,0 +1,288 @@ +/* ---------------------------------------------------------------------------- + + +WordPress-style Buttons +======================= +Create a button by adding the `.button` class to an element. For backwards +compatibility, we support several other classes (such as `.button-secondary`), +but these will *not* work with the stackable classes described below. + +Button Styles +------------- +To display a primary button style, add the `.button-primary` class to a button. + +Button Sizes +------------ +Adjust a button's size by adding the `.button-large` or `.button-small` class. + +Button States +------------- +Lock the state of a button by adding the name of the pseudoclass as +an actual class (e.g. `.hover` for `:hover`). + + +TABLE OF CONTENTS: +------------------ + 1.0 - Button Layouts + 2.0 - Default Button Style + 3.0 - Primary Button Style + 4.0 - Button Groups + +---------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------------- + 1.0 - Button Layouts +---------------------------------------------------------------------------- */ + +.wp-core-ui .button, +.wp-core-ui .button-primary, +.wp-core-ui .button-secondary { + display: inline-block; + text-decoration: none; + font-size: 12px; + line-height: 23px; + height: 24px; + margin: 0; + padding: 0 10px 1px; + cursor: pointer; + border-width: 1px; + border-style: solid; + -webkit-border-radius: 3px; + -webkit-appearance: none; + border-radius: 3px; + white-space: nowrap; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* Remove the dotted border on :focus and the extra padding in Firefox */ +.wp-core-ui button::-moz-focus-inner, +.wp-core-ui input[type="reset"]::-moz-focus-inner, +.wp-core-ui input[type="button"]::-moz-focus-inner, +.wp-core-ui input[type="submit"]::-moz-focus-inner { + border-width: 1px 0; + border-style: solid none; + border-color: transparent; + padding: 0; +} + +.wp-core-ui .button.button-large, +.wp-core-ui .button-group.button-large .button { + height: 30px; + line-height: 28px; + padding: 0 12px 2px; +} + +.wp-core-ui .button.button-small, +.wp-core-ui .button-group.button-small .button { + height: 21px; + line-height: 20px; + padding: 0 8px 1px; +} + +.wp-core-ui .button.button-hero, +.wp-core-ui .button-group.button-hero .button { + font-size: 14px; + height: 46px; + line-height: 44px; + padding: 0 36px; +} + +.wp-core-ui .button:active { + outline: none; +} + +.wp-core-ui .button.hidden { + display: none; +} + +/* ---------------------------------------------------------------------------- + 2.0 - Default Button Style +---------------------------------------------------------------------------- */ + +.wp-core-ui .button, +.wp-core-ui .button-secondary { + background: #f3f3f3; + background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#f4f4f4)); + background-image: -webkit-linear-gradient(top, #fefefe, #f4f4f4); + background-image: -moz-linear-gradient(top, #fefefe, #f4f4f4); + background-image: -o-linear-gradient(top, #fefefe, #f4f4f4); + background-image: linear-gradient(to bottom, #fefefe, #f4f4f4); + border-color: #bbb; + color: #333; + text-shadow: 0 1px 0 #fff; +} + +.wp-core-ui .button.hover, +.wp-core-ui .button:hover, +.wp-core-ui .button-secondary:hover, +.wp-core-ui .button.focus, +.wp-core-ui .button:focus, +.wp-core-ui .button-secondary:focus { + background: #f3f3f3; + background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f3f3f3)); + background-image: -webkit-linear-gradient(top, #fff, #f3f3f3); + background-image: -moz-linear-gradient(top, #fff, #f3f3f3); + background-image: -ms-linear-gradient(top, #fff, #f3f3f3); + background-image: -o-linear-gradient(top, #fff, #f3f3f3); + background-image: linear-gradient(to bottom, #fff, #f3f3f3); + border-color: #999; + color: #222; +} + +.wp-core-ui .button.focus, +.wp-core-ui .button:focus, +.wp-core-ui .button-secondary:focus { + -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,.2); + box-shadow: 1px 1px 1px rgba(0,0,0,.2); +} + +.wp-core-ui .button.active, +.wp-core-ui .button.active:hover, +.wp-core-ui .button.active:focus, +.wp-core-ui .button:active, +.wp-core-ui .button-secondary:active { + background: #eee; + background-image: -webkit-gradient(linear, left top, left bottom, from(#f4f4f4), to(#fefefe)); + background-image: -webkit-linear-gradient(top, #f4f4f4, #fefefe); + background-image: -moz-linear-gradient(top, #f4f4f4, #fefefe); + background-image: -ms-linear-gradient(top, #f4f4f4, #fefefe); + background-image: -o-linear-gradient(top, #f4f4f4, #fefefe); + background-image: linear-gradient(to bottom, #f4f4f4, #fefefe); + border-color: #999; + color: #333; + text-shadow: 0 -1px 0 #fff; + -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ); + box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ); +} + +.wp-core-ui .button[disabled], +.wp-core-ui .button:disabled, +.wp-core-ui .button-secondary[disabled], +.wp-core-ui .button-secondary:disabled, +.wp-core-ui .button-disabled { + color: #aaa !important; + border-color: #ddd !important; + background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#f4f4f4)) !important; + background-image: -webkit-linear-gradient(top, #f9f9f9, #f4f4f4) !important; + background-image: -moz-linear-gradient(top, #f9f9f9, #f4f4f4) !important; + background-image: -ms-linear-gradient(top, #f9f9f9, #f4f4f4) !important; + background-image: -o-linear-gradient(top, #f9f9f9, #f4f4f4) !important; + background-image: linear-gradient(to bottom, #f9f9f9, #f4f4f4) !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: 0 1px 0 #fff !important; + cursor: default; +} + +/* ---------------------------------------------------------------------------- + 3.0 - Primary Button Style +---------------------------------------------------------------------------- */ + +.wp-core-ui .button-primary { + background-color: #21759b; + background-image: -webkit-gradient(linear, left top, left bottom, from(#2a95c5), to(#21759b)); + background-image: -webkit-linear-gradient(top, #2a95c5, #21759b); + background-image: -moz-linear-gradient(top, #2a95c5, #21759b); + background-image: -ms-linear-gradient(top, #2a95c5, #21759b); + background-image: -o-linear-gradient(top, #2a95c5, #21759b); + background-image: linear-gradient(to bottom, #2a95c5, #21759b); + border-color: #21759b; + border-bottom-color: #1e6a8d; + -webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5); + box-shadow: inset 0 1px 0 rgba(120,200,230,0.5); + color: #fff; + text-decoration: none; + text-shadow: 0 1px 0 rgba(0,0,0,0.1); +} + +.wp-core-ui .button-primary.hover, +.wp-core-ui .button-primary:hover, +.wp-core-ui .button-primary.focus, +.wp-core-ui .button-primary:focus { + background-color: #278ab7; + background-image: -webkit-gradient(linear, left top, left bottom, from(#2e9fd2), to(#21759b)); + background-image: -webkit-linear-gradient(top, #2e9fd2, #21759b); + background-image: -moz-linear-gradient(top, #2e9fd2, #21759b); + background-image: -ms-linear-gradient(top, #2e9fd2, #21759b); + background-image: -o-linear-gradient(top, #2e9fd2, #21759b); + background-image: linear-gradient(to bottom, #2e9fd2, #21759b); + border-color: #1b607f; + -webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.6); + box-shadow: inset 0 1px 0 rgba(120,200,230,0.6); + color: #fff; + text-shadow: 0 -1px 0 rgba(0,0,0,0.3); +} + +.wp-core-ui .button-primary.focus, +.wp-core-ui .button-primary:focus { + border-color: #0e3950; + -webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.6), 1px 1px 2px rgba(0,0,0,0.4); + box-shadow: inset 0 1px 0 rgba(120,200,230,0.6), 1px 1px 2px rgba(0,0,0,0.4); +} + +.wp-core-ui .button-primary.active, +.wp-core-ui .button-primary.active:hover, +.wp-core-ui .button-primary.active:focus, +.wp-core-ui .button-primary:active { + background: #1b607f; + background-image: -webkit-gradient(linear, left top, left bottom, from(#21759b), to(#278ab7)); + background-image: -webkit-linear-gradient(top, #21759b, #278ab7); + background-image: -moz-linear-gradient(top, #21759b, #278ab7); + background-image: -ms-linear-gradient(top, #21759b, #278ab7); + background-image: -o-linear-gradient(top, #21759b, #278ab7); + background-image: linear-gradient(to bottom, #21759b, #278ab7); + border-color: #124560 #2382ae #2382ae #2382ae; + color: rgba(255,255,255,0.95); + -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,0.1); + box-shadow: inset 0 1px 0 rgba(0,0,0,0.1); + text-shadow: 0 1px 0 rgba(0,0,0,0.1); +} + +.wp-core-ui .button-primary[disabled], +.wp-core-ui .button-primary:disabled, +.wp-core-ui .button-primary-disabled { + color: #94cde7 !important; + background: #298cba !important; + border-color: #1b607f !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: 0 -1px 0 rgba(0,0,0,0.1) !important; + cursor: default; +} + +/* ---------------------------------------------------------------------------- + 4.0 - Button Groups +---------------------------------------------------------------------------- */ + +.wp-core-ui .button-group { + position: relative; + display: inline-block; + white-space: nowrap; + font-size: 0; + vertical-align: middle; +} + +.wp-core-ui .button-group > .button { + display: inline-block; + border-radius: 0; + margin-right: -1px; + z-index: 10; +} + +.wp-core-ui .button-group > .button-primary { + z-index: 100; +} + +.wp-core-ui .button-group > .button:hover { + z-index: 20; +} + +.wp-core-ui .button-group > .button:first-child { + border-radius: 3px 0 0 3px; +} + +.wp-core-ui .button-group > .button:last-child { + border-radius: 0 3px 3px 0; +} diff --git a/sources/wp-includes/css/buttons.min.css b/sources/wp-includes/css/buttons.min.css new file mode 100644 index 0000000..5007946 --- /dev/null +++ b/sources/wp-includes/css/buttons.min.css @@ -0,0 +1 @@ +.wp-core-ui .button,.wp-core-ui .button-primary,.wp-core-ui .button-secondary{display:inline-block;text-decoration:none;font-size:12px;line-height:23px;height:24px;margin:0;padding:0 10px 1px;cursor:pointer;border-width:1px;border-style:solid;-webkit-border-radius:3px;-webkit-appearance:none;border-radius:3px;white-space:nowrap;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.wp-core-ui button::-moz-focus-inner,.wp-core-ui input[type=reset]::-moz-focus-inner,.wp-core-ui input[type=button]::-moz-focus-inner,.wp-core-ui input[type=submit]::-moz-focus-inner{border-width:1px 0;border-style:solid none;border-color:transparent;padding:0}.wp-core-ui .button.button-large,.wp-core-ui .button-group.button-large .button{height:30px;line-height:28px;padding:0 12px 2px}.wp-core-ui .button.button-small,.wp-core-ui .button-group.button-small .button{height:21px;line-height:20px;padding:0 8px 1px}.wp-core-ui .button.button-hero,.wp-core-ui .button-group.button-hero .button{font-size:14px;height:46px;line-height:44px;padding:0 36px}.wp-core-ui .button:active{outline:0}.wp-core-ui .button.hidden{display:none}.wp-core-ui .button,.wp-core-ui .button-secondary{background:#f3f3f3;background-image:-webkit-gradient(linear,left top,left bottom,from(#fefefe),to(#f4f4f4));background-image:-webkit-linear-gradient(top,#fefefe,#f4f4f4);background-image:-moz-linear-gradient(top,#fefefe,#f4f4f4);background-image:-o-linear-gradient(top,#fefefe,#f4f4f4);background-image:linear-gradient(to bottom,#fefefe,#f4f4f4);border-color:#bbb;color:#333;text-shadow:0 1px 0 #fff}.wp-core-ui .button.hover,.wp-core-ui .button:hover,.wp-core-ui .button-secondary:hover,.wp-core-ui .button.focus,.wp-core-ui .button:focus,.wp-core-ui .button-secondary:focus{background:#f3f3f3;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f3f3f3));background-image:-webkit-linear-gradient(top,#fff,#f3f3f3);background-image:-moz-linear-gradient(top,#fff,#f3f3f3);background-image:-ms-linear-gradient(top,#fff,#f3f3f3);background-image:-o-linear-gradient(top,#fff,#f3f3f3);background-image:linear-gradient(to bottom,#fff,#f3f3f3);border-color:#999;color:#222}.wp-core-ui .button.focus,.wp-core-ui .button:focus,.wp-core-ui .button-secondary:focus{-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2)}.wp-core-ui .button.active,.wp-core-ui .button.active:hover,.wp-core-ui .button.active:focus,.wp-core-ui .button:active,.wp-core-ui .button-secondary:active{background:#eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#f4f4f4),to(#fefefe));background-image:-webkit-linear-gradient(top,#f4f4f4,#fefefe);background-image:-moz-linear-gradient(top,#f4f4f4,#fefefe);background-image:-ms-linear-gradient(top,#f4f4f4,#fefefe);background-image:-o-linear-gradient(top,#f4f4f4,#fefefe);background-image:linear-gradient(to bottom,#f4f4f4,#fefefe);border-color:#999;color:#333;text-shadow:0 -1px 0 #fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.wp-core-ui .button[disabled],.wp-core-ui .button:disabled,.wp-core-ui .button-secondary[disabled],.wp-core-ui .button-secondary:disabled,.wp-core-ui .button-disabled{color:#aaa!important;border-color:#ddd!important;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#f4f4f4))!important;background-image:-webkit-linear-gradient(top,#f9f9f9,#f4f4f4)!important;background-image:-moz-linear-gradient(top,#f9f9f9,#f4f4f4)!important;background-image:-ms-linear-gradient(top,#f9f9f9,#f4f4f4)!important;background-image:-o-linear-gradient(top,#f9f9f9,#f4f4f4)!important;background-image:linear-gradient(to bottom,#f9f9f9,#f4f4f4)!important;-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:0 1px 0 #fff!important;cursor:default}.wp-core-ui .button-primary{background-color:#21759b;background-image:-webkit-gradient(linear,left top,left bottom,from(#2a95c5),to(#21759b));background-image:-webkit-linear-gradient(top,#2a95c5,#21759b);background-image:-moz-linear-gradient(top,#2a95c5,#21759b);background-image:-ms-linear-gradient(top,#2a95c5,#21759b);background-image:-o-linear-gradient(top,#2a95c5,#21759b);background-image:linear-gradient(to bottom,#2a95c5,#21759b);border-color:#21759b;border-bottom-color:#1e6a8d;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.5);box-shadow:inset 0 1px 0 rgba(120,200,230,.5);color:#fff;text-decoration:none;text-shadow:0 1px 0 rgba(0,0,0,.1)}.wp-core-ui .button-primary.hover,.wp-core-ui .button-primary:hover,.wp-core-ui .button-primary.focus,.wp-core-ui .button-primary:focus{background-color:#278ab7;background-image:-webkit-gradient(linear,left top,left bottom,from(#2e9fd2),to(#21759b));background-image:-webkit-linear-gradient(top,#2e9fd2,#21759b);background-image:-moz-linear-gradient(top,#2e9fd2,#21759b);background-image:-ms-linear-gradient(top,#2e9fd2,#21759b);background-image:-o-linear-gradient(top,#2e9fd2,#21759b);background-image:linear-gradient(to bottom,#2e9fd2,#21759b);border-color:#1b607f;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.6);box-shadow:inset 0 1px 0 rgba(120,200,230,.6);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.3)}.wp-core-ui .button-primary.focus,.wp-core-ui .button-primary:focus{border-color:#0e3950;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.6),1px 1px 2px rgba(0,0,0,.4);box-shadow:inset 0 1px 0 rgba(120,200,230,.6),1px 1px 2px rgba(0,0,0,.4)}.wp-core-ui .button-primary.active,.wp-core-ui .button-primary.active:hover,.wp-core-ui .button-primary.active:focus,.wp-core-ui .button-primary:active{background:#1b607f;background-image:-webkit-gradient(linear,left top,left bottom,from(#21759b),to(#278ab7));background-image:-webkit-linear-gradient(top,#21759b,#278ab7);background-image:-moz-linear-gradient(top,#21759b,#278ab7);background-image:-ms-linear-gradient(top,#21759b,#278ab7);background-image:-o-linear-gradient(top,#21759b,#278ab7);background-image:linear-gradient(to bottom,#21759b,#278ab7);border-color:#124560 #2382ae #2382ae;color:rgba(255,255,255,.95);-webkit-box-shadow:inset 0 1px 0 rgba(0,0,0,.1);box-shadow:inset 0 1px 0 rgba(0,0,0,.1);text-shadow:0 1px 0 rgba(0,0,0,.1)}.wp-core-ui .button-primary[disabled],.wp-core-ui .button-primary:disabled,.wp-core-ui .button-primary-disabled{color:#94cde7!important;background:#298cba!important;border-color:#1b607f!important;-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:0 -1px 0 rgba(0,0,0,.1)!important;cursor:default}.wp-core-ui .button-group{position:relative;display:inline-block;white-space:nowrap;font-size:0;vertical-align:middle}.wp-core-ui .button-group>.button{display:inline-block;border-radius:0;margin-right:-1px;z-index:10}.wp-core-ui .button-group>.button-primary{z-index:100}.wp-core-ui .button-group>.button:hover{z-index:20}.wp-core-ui .button-group>.button:first-child{border-radius:3px 0 0 3px}.wp-core-ui .button-group>.button:last-child{border-radius:0 3px 3px 0} \ No newline at end of file diff --git a/sources/wp-includes/css/editor.css b/sources/wp-includes/css/editor.css new file mode 100644 index 0000000..9cab91b --- /dev/null +++ b/sources/wp-includes/css/editor.css @@ -0,0 +1,2295 @@ + +/*------------------------------------------------------------------------------ + TinyMCE and Quicklinks toolbars +------------------------------------------------------------------------------*/ + +/* wp_theme/ui.css */ +.wp_themeSkin table, +.wp_themeSkin tbody, +.wp_themeSkin a, +.wp_themeSkin img, +.wp_themeSkin tr, +.wp_themeSkin div, +.wp_themeSkin td, +.wp_themeSkin iframe, +.wp_themeSkin span, +.wp_themeSkin *, +.wp_themeSkin .mceText { + border: 0; + margin: 0; + padding: 0; + white-space: nowrap; + text-decoration: none; + font-weight: normal; + cursor: default; + vertical-align: baseline; + width: auto; + border-collapse: separate; +} + +.wp_themeSkin a:hover, +.wp_themeSkin a:link, +.wp_themeSkin a:visited, +.wp_themeSkin a:active { + text-decoration: none; + font-weight: normal; + cursor: default; +} + +.wp_themeSkin table td { + vertical-align: middle; +} + +.wp_themeSkin *, +.wp_themeSkin a:hover, +.wp_themeSkin a:link, +.wp_themeSkin a:visited, +.wp_themeSkin a:active { + color: #555; +} + +/* Containers */ +.wp_themeSkin table {} + +.wp_themeSkin iframe { + display: block; +} + +.wp_themeSkin #mce_fullscreen_ifr { + background-color: #fff; +} + +.wp_themeSkin .mceToolbar { + padding: 1px; +} + +/* External */ +.wp_themeSkin .mceExternalToolbar { + position: absolute; + border-bottom: 0; + display: none; +} + +.wp_themeSkin .mceExternalToolbar td.mceToolbar { + padding-right: 13px; +} + +.wp_themeSkin .mceExternalClose { + position: absolute; + top: 3px; + right: 3px; + width: 7px; + height: 7px; + background: url("../js/tinymce/themes/advanced/img/icons.gif") -820px 0; +} + +/* Layout */ +.wp_themeSkin table.mceToolbar, +.wp_themeSkin tr.mceFirst .mceToolbar tr td, +.wp_themeSkin tr.mceLast .mceToolbar tr td { + border: 0; + margin: 0; + padding: 0; +} + +.wp_themeSkin table.mceLayout { + border: 0; +} + +.wp_themeSkin .mceStatusbar { + display: block; + font-family: sans-serif; + font-size: 12px; + line-height: 16px; + padding: 0 0 0 8px; + overflow: visible; + height: 20px; + border-top: 1px solid #dfdfdf; + color: #000; + background-color: #f5f5f5; +} + +.rtl .wp_themeSkin .mceStatusbar { + padding: 0 8px 0 0; +} + +.wp_themeSkin .mceStatusbar * { + color: #555; +} + +.wp_themeSkin .mceStatusbar div { + float: left; + padding: 2px; +} + +.rtl .wp_themeSkin .mceStatusbar div { + float: right; +} + +.wp_themeSkin .mceStatusbar a.mceResize { + display: block; + float: right; + background: url("../js/tinymce/themes/advanced/img/icons.gif") -800px 0; + width: 20px; + height: 20px; + cursor: se-resize; +} + +.rtl .wp_themeSkin .mceStatusbar a.mceResize { + float: left; +} + +.wp_themeSkin .mceStatusbar a:hover { + text-decoration: underline; +} + +.wp_themeSkin table.mceToolbar { + margin: 0 6px 2px; +} + +.wp_themeSkin table.mceToolbar :active, +.wp_themeSkin table.mceToolbar :focus, +.wp_themeSkin table.mceToolbar:focus, +.wp_themeSkin span.mceSeparator:focus { + outline: none; +} + +.wp_themeSkin #content_toolbar1 { + margin-top: 2px; +} + +.wp_themeSkin .mceToolbar .mceToolbarEndListBox span { + display: none; +} + +.wp_themeSkin span.mceIcon, +.wp_themeSkin img.mceIcon { + display: block; + width: 20px; + height: 20px; +} + +.wp_themeSkin .mceIcon { + background: url("../js/tinymce/themes/advanced/img/icons.gif") no-repeat 20px 20px; +} + +/* Button */ +.wp_themeSkin .mceButton { + display: block; + width: 20px; + height: 20px; + cursor: default; + padding: 1px 2px; + margin: 1px; + -webkit-border-radius: 2px; + border-radius: 2px; +} + +.wp_themeSkin a.mceButtonEnabled:hover { + background-image: inherit 0 -10px; +} + +.wp_themeSkin .mceOldBoxModel a.mceButton span, .wp_themeSkin .mceOldBoxModel a.mceButton img { + margin: 0 0 0 1px; +} + +.wp_themeSkin .mceButtonDisabled .mceIcon { + opacity: 0.2; + filter: alpha(opacity=20); +} + +/* Separator */ +.wp_themeSkin .mceSeparator { + display: none; +} + +/* ListBox */ +.wp_themeSkin .mceListBox, +.wp_themeSkin .mceListBox a { + display: block; +} + +.wp_themeSkin .mceListBox .mceText { + padding: 1px 4px 1px 5px; + width: 70px; + text-align: left; + text-decoration: none; + -webkit-border-bottom-left-radius: 2px; + -webkit-border-top-left-radius: 2px; + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; + font-family: sans-serif; + font-size: 12px; + height: 20px; + line-height: 20px; + overflow: hidden; +} + +.wp_themeSkin .mceListBox { + margin: 1px; + direction: ltr; + background-color: #fff; + border: 1px solid #ddd; + -webkit-box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .2); + box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .2); +} + +.wp_themeSkin .mceListBox .mceOpen { + width: 12px; + height: 20px; + border-collapse: separate; + padding: 1px; + -webkit-border-bottom-left-radius: 0; + -webkit-border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.wp_themeSkin .mceListBox .mceFirst a { + border-style: solid; + border-width: 1px; + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} + +.wp_themeSkin .mceListBoxMenu .mce_formatPreview { + line-height: normal; +} + +.wp_themeSkin .mceListBox .mceOpen, +.wp_themeSkin .mceListBoxHover .mceOpen, +.wp_themeSkin .mceListBoxSelected .mceOpen, +.wp_themeSkin table.mceListBoxEnabled .mceOpen { + background-image: url("../images/down_arrow.gif"); + background-position: 3px 1px; + background-repeat: no-repeat; +} + +.wp_themeSkin .mceListBoxDisabled .mceText { + color: gray; +} + +.wp_themeSkin .mceListBoxMenu { + overflow: auto; + overflow-x: hidden; +} + +.wp_themeSkin .mceOldBoxModel .mceListBox .mceText { + height: 22px; +} + +.wp_themeSkin select.mceListBox { + font-family: sans-serif; + font-size: 12px; + border-color: #b2b2b2; + background-color: #fff; +} + +/* SplitButton */ +.wp_themeSkin .mceSplitButton a, +.wp_themeSkin .mceSplitButton span { + display: block; + height: 20px; +} + +.wp_themeSkin .mceSplitButton { + display: block; + direction: ltr; +} + +.wp_themeSkin table.mceSplitButton td { + padding: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; +} + +.wp_themeSkin table.mceSplitButton:hover td { + background-image: inherit 0 -10px; +} + +.wp_themeSkin .mceSplitButton a.mceAction { + height: 20px; + width: 20px; + padding: 1px 2px; + border-right: 0 none; +} + +.wp_themeSkin .mceSplitButton span.mceAction { + background-image: url("../js/tinymce/themes/advanced/img/icons.gif"); + background-repeat: no-repeat; + background-color: transparent; + width: 20px; +} + +.wp_themeSkin .mceSplitButton a.mceOpen { + width: 11px; + height: 20px; + background-position: 0px 2px; + background-repeat: no-repeat; + padding: 1px 0; +} + +.wp_themeSkin .mceSplitButton span.mceOpen { + display: none; +} + +.wp_themeSkin .mceSplitButtonDisabled .mceAction { + opacity: 0.3; + filter: alpha(opacity=30); +} + +.wp_themeSkin .mceListBox a.mceText, +.wp_themeSkin .mceSplitButton a.mceAction { + -webkit-border-bottom-left-radius: 2px; + -webkit-border-top-left-radius: 2px; + border-bottom-left-radius: 2px; + border-top-left-radius: 2px; +} + +.wp_themeSkin .mceSplitButton a.mceOpen, +.wp_themeSkin .mceListBox a.mceOpen { + -webkit-border-bottom-right-radius: 2px; + -webkit-border-top-right-radius: 2px; + border-bottom-right-radius: 2px; + border-top-right-radius: 2px; +} + +.wp_themeSkin span.mce_undo, +.wp_themeSkin span.mce_redo, +.wp_themeSkin span.mce_bullist, +.wp_themeSkin span.mce_numlist, +.wp_themeSkin span.mce_blockquote, +.wp_themeSkin span.mce_charmap, +.wp_themeSkin span.mce_bold, +.wp_themeSkin span.mce_italic, +.wp_themeSkin span.mce_underline, +.wp_themeSkin span.mce_justifyleft, +.wp_themeSkin span.mce_justifyright, +.wp_themeSkin span.mce_justifycenter, +.wp_themeSkin span.mce_justifyfull, +.wp_themeSkin span.mce_indent, +.wp_themeSkin span.mce_outdent, +.wp_themeSkin span.mce_link, +.wp_themeSkin span.mce_unlink, +.wp_themeSkin span.mce_help, +.wp_themeSkin span.mce_removeformat, +.wp_themeSkin span.mce_fullscreen, +.wp_themeSkin span.mce_wp_fullscreen, +.wp_themeSkin span.mce_media, +.wp_themeSkin span.mce_pastetext, +.wp_themeSkin span.mce_pasteword, +.wp_themeSkin span.mce_wp_help, +.wp_themeSkin span.mce_wp_adv, +.wp_themeSkin span.mce_wp_more, +.wp_themeSkin span.mce_strikethrough, +.wp_themeSkin span.mce_spellchecker, +.wp_themeSkin span.mce_forecolor, +.wp_themeSkin .mce_forecolorpicker, +.wp_themeSkin .mceSplitButton .mce_spellchecker span.mce_spellchecker, +.wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor, +.wp_themeSkin .mceSplitButton span.mce_numlist, +.wp_themeSkin .mceSplitButton span.mce_bullist { + background-image: url('../images/wpicons.png?ver=20120720'); +} + +/* ColorSplitButton */ +.wp_themeSkin div.mceColorSplitMenu table { + background-color: #ebebeb; + border-color: #bbb; +} + +.wp_themeSkin .mceColorSplitMenu td { + padding: 2px; +} + +.wp_themeSkin .mceColorSplitMenu a { + display: block; + width: 9px; + height: 9px; + overflow: hidden; + border-color: #B2B2B2; +} + +.wp_themeSkin .mceColorSplitMenu td.mceMoreColors { + padding: 1px 3px 1px 1px; +} + +.wp_themeSkin .mceColorSplitMenu a.mceMoreColors { + width: 100%; + height: auto; + text-align: center; + font-family: Tahoma,Verdana,Arial,Helvetica; + font-size: 11px; + line-height: 20px; + border-color: #fff; +} + +.wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover {} +.wp_themeSkin a.mceMoreColors:hover {} +.wp_themeSkin .mceColorPreview { + margin: -5px 0 0 2px; + width: 16px; + height: 4px; + overflow: hidden; +} + +/* Menu */ +.wp_themeSkin .mceMenu { + position: absolute; + left: 0; + top: 0; + z-index: 1000; + border-color: #ddd; + direction: ltr; +} + +.wp_themeSkin .mceNoIcons span.mceIcon { + width: 0; +} + +.wp_themeSkin .mceNoIcons a .mceText { + padding-left: 10px; +} + +.wp_themeSkin .mceMenu table { + background-color: #ebeaeb; +} + +.wp_themeSkin .mceMenu a, +.wp_themeSkin .mceMenu span, +.wp_themeSkin .mceMenu { + display: block; +} + +.wp_themeSkin .mceMenu td { + height: 20px;overflow: hidden; +} + +.wp_themeSkin .mceMenu a { + position: relative; + padding: 3px 0 4px 0; + text-decoration: none !important; +} + +.wp_themeSkin .mceMenu .mceText { + position: relative; + display: block; + font-family: Tahoma,Verdana,Arial,Helvetica; + cursor: default; + margin: 0; + padding: 0 25px; + color: #000; +} + +.wp_themeSkin .mceMenu span.mceText, .wp_themeSkin .mceMenu .mcePreview { + font-size: 12px; +} + +.wp_themeSkin .mceMenu pre.mceText { + font-family: Monospace; +} + +.wp_themeSkin .mceMenu .mceIcon { + position: absolute; + top: 0; + left: 0; + width: 22px; +} + +.wp_themeSkin .mceMenu .mceMenuItemEnabled a:hover, +.wp_themeSkin .mceMenu .mceMenuItemActive { + background-color: #f5f5f5; +} + +.wp_themeSkin td.mceMenuItemSeparator { + height: 1px; + background-color: #aaa; +} + +.wp_themeSkin .mceMenuItemTitle a { + border-top: 0; + border-right: 0; + border-left: 0; + border-bottom: 1px solid #aaa; + text-decoration: none !important; + background-color: #ccc; +} + +.wp_themeSkin .mceMenuItemTitle span.mceText { + font-weight: bold; + padding-left: 4px; + color: #000; +} + +.wp_themeSkin .mceMenuItemSelected .mceIcon { + background: url("../js/tinymce/themes/advanced/skins/default/img/menu_check.gif"); + color: #888; +} + +.wp_themeSkin .mceNoIcons .mceMenuItemSelected a { + background: url("../js/tinymce/themes/advanced/skins/default/img/menu_arrow.gif") no-repeat -6px center; +} + +.wp_themeSkin .mceMenu span.mceMenuLine { + display: none; +} + +.wp_themeSkin .mceMenuItemSub a { + background: url("../js/tinymce/themes/advanced/skins/default/img/menu_arrow.gif") no-repeat top right; +} + +/* Progress,Resize */ +.wp_themeSkin .mceBlocker { + position: absolute; + left: 0; + top: 0; + z-index: 1000; + opacity: 0.5; + filter: alpha(opacity=50); + background: #FFF; +} + +.wp_themeSkin .mceProgress { + position: absolute; + left: 0; + top: 0; + z-index: 1001; + background: url("../js/tinymce/themes/advanced/skins/default/img/progress.gif") no-repeat; + width: 32px; + height: 32px; + margin: -16px 0 0 -16px; +} + +.wp_themeSkin .mcePlaceHolder { + border: 1px dotted gray; +} + +/* Rtl */ +.mceRtl .mceListBox .mceText { + text-align: right; + padding: 0 4px 0 0; +} + +.mceRtl .mceMenuItem .mceText { + text-align: right; +} + +/* Formats */ +.wp_themeSkin .mce_p span.mceText {} +.wp_themeSkin .mce_address span.mceText { + font-style: italic; +} + +.wp_themeSkin .mce_pre span.mceText { + font-family: monospace; +} + +.wp_themeSkin .mce_h1 span.mceText { + font-weight: bolder; + font-size: 18px; +} + +.wp_themeSkin .mce_h2 span.mceText { + font-weight: bolder; + font-size: 16px; +} + +.wp_themeSkin .mce_h3 span.mceText { + font-weight: bolder; + font-size: 14px; +} + +.wp_themeSkin .mce_h4 span.mceText { + font-weight: bolder; + font-size: 12px; +} + +.wp_themeSkin .mce_h5 span.mceText { + font-weight: bolder; + font-size: 11px; +} + +.wp_themeSkin .mce_h6 span.mceText { + font-weight: bolder; + font-size: 10px; +} + +/* Theme */ +.wp_themeSkin span.mce_undo {background-position:-500px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_undo, +.wp_themeSkin .mceButtonActive span.mce_undo {background-position:-500px 0} + +.wp_themeSkin span.mce_redo {background-position:-480px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_redo, +.wp_themeSkin .mceButtonActive span.mce_redo {background-position:-480px 0} + +.wp_themeSkin span.mce_bullist {background-position:-40px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_bullist, +.wp_themeSkin .mceButtonActive span.mce_bullist, +.wp_themeSkin .mceSplitButton:hover span.mce_bullist {background-position:-40px 0} + +.wp_themeSkin span.mce_numlist {background-position:-60px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_numlist, +.wp_themeSkin .mceButtonActive span.mce_numlist, +.wp_themeSkin .mceSplitButton:hover span.mce_numlist {background-position:-60px 0} + +.wp_themeSkin span.mce_blockquote {background-position:-80px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_blockquote, +.wp_themeSkin .mceButtonActive span.mce_blockquote {background-position:-80px 0} + +.wp_themeSkin span.mce_charmap {background-position:-420px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_charmap, +.wp_themeSkin .mceButtonActive span.mce_charmap {background-position:-420px 0} + +.wp_themeSkin span.mce_bold {background-position:0 -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_bold, +.wp_themeSkin .mceButtonActive span.mce_bold {background-position:0 0} + +.wp_themeSkin span.mce_italic {background-position:-20px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_italic, +.wp_themeSkin .mceButtonActive span.mce_italic {background-position:-20px 0} + +.wp_themeSkin span.mce_underline {background-position:-280px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_underline, +.wp_themeSkin .mceButtonActive span.mce_underline {background-position:-280px 0} + +.wp_themeSkin span.mce_justifyleft {background-position:-100px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_justifyleft, +.wp_themeSkin .mceButtonActive span.mce_justifyleft {background-position:-100px 0} + +.wp_themeSkin span.mce_justifyright {background-position:-140px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_justifyright, +.wp_themeSkin .mceButtonActive span.mce_justifyright {background-position:-140px 0} + +.wp_themeSkin span.mce_justifycenter {background-position:-120px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_justifycenter, +.wp_themeSkin .mceButtonActive span.mce_justifycenter {background-position:-120px 0} + +.wp_themeSkin span.mce_justifyfull {background-position:-300px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_justifyfull, +.wp_themeSkin .mceButtonActive span.mce_justifyfull {background-position:-300px 0} + +.wp_themeSkin span.mce_indent {background-position:-460px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_indent, +.wp_themeSkin .mceButtonActive span.mce_indent {background-position:-460px 0} + +.wp_themeSkin span.mce_outdent {background-position:-440px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_outdent, +.wp_themeSkin .mceButtonActive span.mce_outdent {background-position:-440px 0} + +.wp_themeSkin span.mce_link {background-position:-160px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_link, +.wp_themeSkin .mceButtonActive span.mce_link {background-position:-160px 0} + +.wp_themeSkin span.mce_unlink {background-position:-180px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_unlink, +.wp_themeSkin .mceButtonActive span.mce_unlink {background-position:-180px 0} + +.wp_themeSkin span.mce_help {background-position:-520px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_help, +.wp_themeSkin .mceButtonActive span.mce_help {background-position:-520px 0} + +.wp_themeSkin span.mce_removeformat {background-position:-380px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_removeformat, +.wp_themeSkin .mceButtonActive span.mce_removeformat {background-position:-380px 0} + +.wp_themeSkin span.mce_strikethrough {background-position:-540px -20px;} +.wp_themeSkin .mceButtonEnabled:hover span.mce_strikethrough, +.wp_themeSkin .mceButtonActive span.mce_strikethrough {background-position:-540px 0} + +.wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor {background-position:-320px -20px} +.wp_themeSkin .mceSplitButtonEnabled:hover span.mce_forecolor, +.wp_themeSkin .mceSplitButtonSelected span.mce_forecolor {background-position:-320px 0} + +.wp_themeSkin .mce_forecolorpicker {background-position:-320px -20px} + +/* Plugins in WP */ +.wp_themeSkin span.mce_fullscreen {background-position:-240px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_fullscreen, +.wp_themeSkin .mceButtonActive span.mce_fullscreen {background-position:-240px 0} + +.wp_themeSkin span.mce_wp_fullscreen {background-position:-240px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_fullscreen, +.wp_themeSkin .mceButtonActive span.mce_wp_fullscreen {background-position:-240px 0} + +.wp_themeSkin span.mce_media {background-position:-400px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_media, +.wp_themeSkin .mceButtonActive span.mce_media {background-position:-400px 0} + +.wp_themeSkin span.mce_pastetext {background-position:-340px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_pastetext, +.wp_themeSkin .mceButtonActive span.mce_pastetext {background-position:-340px 0} + +.wp_themeSkin span.mce_pasteword {background-position:-360px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_pasteword, +.wp_themeSkin .mceButtonActive span.mce_pasteword {background-position:-360px 0} + +.wp_themeSkin span.mce_spellchecker {background-position:-220px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_spellchecker, +.wp_themeSkin .mceSplitButtonEnabled:hover span.mce_spellchecker, +.wp_themeSkin .mceButtonActive span.mce_spellchecker, +.wp_themeSkin .mceSplitButtonSelected span.mce_spellchecker {background-position:-220px 0} + +.wp_themeSkin span.mce_wp_help {background-position:-520px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_help, +.wp_themeSkin .mceButtonActive span.mce_wp_help {background-position:-520px 0} + +.wp_themeSkin span.mce_wp_adv {background-position:-260px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_adv, +.wp_themeSkin .mceButtonActive span.mce_wp_adv {background-position:-260px 0} + +.wp_themeSkin span.mce_wp_more {background-position:-200px -20px} +.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_more, +.wp_themeSkin .mceButtonActive span.mce_wp_more {background-position:-200px 0} + +/* Default icons */ +.wp_themeSkin span.mce_cleanup {background-position:-380px -20px} +.wp_themeSkin span.mce_anchor {background-position:-200px 0} +.wp_themeSkin span.mce_sub {background-position:-600px 0} +.wp_themeSkin span.mce_sup {background-position:-620px 0} +.wp_themeSkin span.mce_newdocument {background-position:-520px 0} +.wp_themeSkin span.mce_image {background-position:-380px 0} +.wp_themeSkin span.mce_code {background-position:-260px 0} +.wp_themeSkin span.mce_hr {background-position:-360px 0} +.wp_themeSkin span.mce_visualaid {background-position:-660px 0} +.wp_themeSkin span.mce_paste {background-position:-560px 0} +.wp_themeSkin span.mce_copy {background-position:-700px 0} +.wp_themeSkin span.mce_cut {background-position:-680px 0} +.wp_themeSkin .mce_backcolor span.mceAction {background-position:-760px 0} +.wp_themeSkin .mce_backcolorpicker {background-position:-760px 0} + +/* Plugins */ +.wp_themeSkin span.mce_advhr {background-position:-0px -20px} +.wp_themeSkin span.mce_ltr {background-position:-20px -20px} +.wp_themeSkin span.mce_rtl {background-position:-40px -20px} +.wp_themeSkin span.mce_emotions {background-position:-60px -20px} +.wp_themeSkin span.mce_fullpage {background-position:-80px -20px} +.wp_themeSkin span.mce_iespell {background-position:-120px -20px} +.wp_themeSkin span.mce_insertdate {background-position:-140px -20px} +.wp_themeSkin span.mce_inserttime {background-position:-160px -20px} +.wp_themeSkin span.mce_absolute {background-position:-180px -20px} +.wp_themeSkin span.mce_backward {background-position:-200px -20px} +.wp_themeSkin span.mce_forward {background-position:-220px -20px} +.wp_themeSkin span.mce_insert_layer {background-position:-240px -20px} +.wp_themeSkin span.mce_insertlayer {background-position:-260px -20px} +.wp_themeSkin span.mce_movebackward {background-position:-280px -20px} +.wp_themeSkin span.mce_moveforward {background-position:-300px -20px} +.wp_themeSkin span.mce_nonbreaking {background-position:-340px -20px} +.wp_themeSkin span.mce_selectall {background-position:-400px -20px} +.wp_themeSkin span.mce_preview {background-position:-420px -20px} +.wp_themeSkin span.mce_print {background-position:-440px -20px} +.wp_themeSkin span.mce_cancel {background-position:-460px -20px} +.wp_themeSkin span.mce_save {background-position:-480px -20px} +.wp_themeSkin span.mce_replace {background-position:-500px -20px} +.wp_themeSkin span.mce_search {background-position:-520px -20px} +.wp_themeSkin span.mce_styleprops {background-position:-560px -20px} +.wp_themeSkin span.mce_table {background-position:-580px -20px} +.wp_themeSkin span.mce_cell_props {background-position:-600px -20px} +.wp_themeSkin span.mce_delete_table {background-position:-620px -20px} +.wp_themeSkin span.mce_delete_col {background-position:-640px -20px} +.wp_themeSkin span.mce_delete_row {background-position:-660px -20px} +.wp_themeSkin span.mce_col_after {background-position:-680px -20px} +.wp_themeSkin span.mce_col_before {background-position:-700px -20px} +.wp_themeSkin span.mce_row_after {background-position:-720px -20px} +.wp_themeSkin span.mce_row_before {background-position:-740px -20px} +.wp_themeSkin span.mce_merge_cells {background-position:-760px -20px} +.wp_themeSkin span.mce_table_props {background-position:-980px -20px} +.wp_themeSkin span.mce_row_props {background-position:-780px -20px} +.wp_themeSkin span.mce_split_cells {background-position:-800px -20px} +.wp_themeSkin span.mce_template {background-position:-820px -20px} +.wp_themeSkin span.mce_visualchars {background-position:-840px -20px} +.wp_themeSkin span.mce_abbr {background-position:-860px -20px} +.wp_themeSkin span.mce_acronym {background-position:-880px -20px} +.wp_themeSkin span.mce_attribs {background-position:-900px -20px} +.wp_themeSkin span.mce_cite {background-position:-920px -20px} +.wp_themeSkin span.mce_del {background-position:-940px -20px} +.wp_themeSkin span.mce_ins {background-position:-960px -20px} +.wp_themeSkin span.mce_pagebreak {background-position:0 -40px} +.wp_themeSkin span.mce_restoredraft {background-position:-20px -40px} +.wp_themeSkin span.mce_visualblocks {background-position: -40px -40px} + +/* border */ +.wp_themeSkin .mceExternalToolbar, +.wp_themeSkin .mceButton, +.wp_themeSkin a.mceButtonEnabled:hover, +.wp_themeSkin a.mceButtonActive, +.wp_themeSkin a.mceButtonSelected, +.wp_themeSkin .mceListBox .mceText, +.wp_themeSkin .mceListBox .mceOpen, +.wp_themeSkin select.mceListBox, +.wp_themeSkin .mceSplitButton a.mceAction, +.wp_themeSkin .mceSplitButton a.mceOpen, +.wp_themeSkin .mceSplitButton a.mceOpen:hover, +.wp_themeSkin .mceSplitButtonSelected a.mceOpen, +.wp_themeSkin table.mceSplitButtonEnabled:hover a.mceAction, +.wp_themeSkin .mceSplitButton a.mceAction:hover, +.wp_themeSkin div.mceColorSplitMenu table, +.wp_themeSkin .mceColorSplitMenu a, +.wp_themeSkin .mceColorSplitMenu a.mceMoreColors, +.wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover, +.wp_themeSkin a.mceMoreColors:hover, +.wp_themeSkin .mceMenu { + border-style: solid; + border-width: 1px; +} +.wp_themeSkin .mceListBox .mceText { + border-right: 0 none; +} +.wp_themeSkin iframe { + background: transparent; +} + +.wp_themeSkin .mceButton { + border-color: transparent; +} + +.wp_themeSkin .mceListBox .mceText, +.wp_themeSkin .mceListBox .mceOpen { + border-color: transparent; +} + +.wp_themeSkin a.mceButtonEnabled:hover, +.wp_themeSkin table.mceSplitButton:hover { + border-color: #bbb; + background: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, from(#e5e5e5), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #e5e5e5, #fff); + background-image: -moz-linear-gradient(bottom, #e5e5e5, #fff); + background-image: -o-linear-gradient(bottom, #e5e5e5, #fff); + background-image: linear-gradient(to top, #e5e5e5, #fff); +} + +.wp_themeSkin a.mceButton:active, +.wp_themeSkin a.mceButtonEnabled:active, +.wp_themeSkin a.mceButtonSelected:active, +.wp_themeSkin a.mceButtonActive, +.wp_themeSkin a.mceButtonActive:active, +.wp_themeSkin a.mceButtonActive:hover, +.wp_themeSkin .mceSplitButtonSelected table, +.wp_themeSkin .mceSplitButtonSelected table:hover { + outline: none; + border-color: #999 #ccc #ccc #999; + background: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, from(#f6f6f6), to(#e3e3e3)); + background-image: -webkit-linear-gradient(bottom, #f6f6f6, #e3e3e3); + background-image: -moz-linear-gradient(bottom, #f6f6f6, #e3e3e3); + background-image: -o-linear-gradient(bottom, #f6f6f6, #e3e3e3); + background-image: linear-gradient(to top, #f6f6f6, #e3e3e3); +} + +.wp_themeSkin .mceSplitButtonSelected table a.mceOpen, +.wp_themeSkin .mceSplitButtonSelected table a.mceAction { + border-color: #999 #ccc #ccc #999; +} + +.wp_themeSkin .mceButtonDisabled { + border-color: transparent; +} + +.wp_themeSkin .mceListBox .mceOpen { + border-left: 0; +} + +.wp_themeSkin .mceListBoxEnabled:hover, +.wp_themeSkin .mceListBoxEnabled:active, +.wp_themeSkin .mceListBoxHover, +.wp_themeSkin .mceListBoxHover:active, +.wp_themeSkin .mceListBoxSelected { + -webkit-box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .3); + box-shadow: inset 0 1px 1px -1px rgba(0, 0, 0, .3); + border-color: #bbb; +} + +/* SplitButton */ +.wp_themeSkin .mceSplitButton .mceLast span.mceOpen .mceIconOnly { + display: block; +} + +.wp_themeSkin .mceSplitButton a.mceAction, +.wp_themeSkin .mceSplitButton a.mceOpen { + border-color: transparent; +} + +.wp_themeSkin .mceSplitButton:hover a { + border-color: #bbb; +} + +.wp_themeSkin .mceSplitButtonEnabled a.mceOpen, +.wp_themeSkin .mceSplitButtonSelected a.mceOpen, +.wp_themeSkin .mceSplitButtonActive a.mceOpen, +.wp_themeSkin .mceSplitButtonEnabled:hover a.mceOpen { + background-image: url("../images/down_arrow.gif"); + background-position: 1px 2px; + background-repeat: no-repeat; + border-left: 0; +} + +.wp_themeSkin .mceSplitButtonActive td { + -webkit-border-radius: 3px; + border-radius: 3px; +} + +.wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover { + border-color: #0A246A; + background-color: #B6BDD2; +} + +.wp_themeSkin a.mceMoreColors:hover { + border-color: #0A246A; +} + +.wp_themeSkin .mceMenuItemDisabled .mceText { + color: #888; +} + +#mceModalBlocker { + background: #000; +} + +/* WP specific */ +.wp-editor-wrap { + position: relative; +} + +.wp-editor-area { + font-family: Consolas, Monaco, monospace; + padding: 10px; + margin: 1px 0 0; + line-height: 150%; + border: 0 none; + outline: none; + display: block; + resize: vertical; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.wp-editor-tools { + height: 30px; + padding: 0 10px 0 0; +} + +.rtl .wp-editor-tools { + padding: 0 0 0 10px; +} + +.wp-editor-container { + border-width: 1px; + border-style: solid; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-color: #ccc #ccc #dfdfdf; +} + +.wp-editor-container textarea.wp-editor-area { + width: 100%; + margin: 0; + -webkit-box-shadow: none; + box-shadow: none; +} + +.quicktags-toolbar, +.wp_themeSkin tr.mceFirst td.mceToolbar { + border-bottom: 1px solid #d1d1d1; + background: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, from(#e5e5e5), to(#f4f4f4)); + background-image: -webkit-linear-gradient(bottom, #e5e5e5, #f4f4f4); + background-image: -moz-linear-gradient(bottom, #e5e5e5, #f4f4f4); + background-image: -o-linear-gradient(bottom, #e5e5e5, #f4f4f4); + background-image: linear-gradient(to top, #e5e5e5, #f4f4f4); +} + +.wp-switch-editor { + height: 18px; + font: 13px/18px Arial,Helvetica,sans-serif normal; + margin: 5px 5px 0 0; + padding: 4px 5px 2px; + float: right; + cursor: pointer; + border-width: 1px; + border-style: solid; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + background-color: #f1f1f1; + border-color: #dfdfdf #dfdfdf #ccc; + color: #999; +} + +html[dir="rtl"] .wp-switch-editor { + float: left; +} + +.wp-switch-editor:active { + background-color: #f1f1f1; +} + +.wp-switch-editor:hover { + text-decoration: none !important; +} + +.js .tmce-active .wp-editor-area { + color: white; +} + +.tmce-active .quicktags-toolbar { + display: none; +} + +.tmce-active .switch-tmce, +.html-active .switch-html { + border-color: #ccc #ccc #f4f4f4; + background-color: #f4f4f4; + color: #555; +} + +.wp-media-buttons .button { + margin-right: 5px; +} + +.rtl .wp-media-buttons .button { + margin-right: 0; + margin-left: 5px; +} + +.wp-media-buttons .insert-media { + padding-left: 0.4em; +} + +.rtl .wp-media-buttons .insert-media { + padding-left: 10px; + padding-right: 0.4em; +} + +.wp-media-buttons a { + text-decoration: none; + color: #464646; + font-size: 12px; +} + +.wp-media-buttons img { + padding: 0 4px; + vertical-align: middle; +} + +.wp-media-buttons span.wp-media-buttons-icon { + display: inline-block; + width: 16px; + height: 16px; + vertical-align: text-top; + margin: 0 2px; +} + +.wp-media-buttons .add_media span.wp-media-buttons-icon { + background: url('../../wp-admin/images/media-button.png') no-repeat top left; +} + +.quicktags-toolbar { + border-bottom-style: solid; + border-bottom-width: 1px; + -webkit-border-top-right-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; + padding: 2px 8px 0; + min-height: 29px; +} + +.quicktags-toolbar > div { + padding: 2px 4px 0; +} + +.quicktags-toolbar input { + margin: 2px 1px 4px; + line-height: 18px; + display: inline-block; + min-width: 26px; + padding: 2px 4px; + font: 12px/18px Arial, Helvetica, sans-serif normal; + color: #464646; + border: 1px solid #c3c3c3; + -webkit-border-radius: 3px; + border-radius: 3px; + background: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, from(#e3e3e3), to(#fff)); + background-image: -webkit-linear-gradient(bottom, #e3e3e3, #fff); + background-image: -moz-linear-gradient(bottom, #e3e3e3, #fff); + background-image: -o-linear-gradient(bottom, #e3e3e3, #fff); + background-image: linear-gradient(to top, #e3e3e3, #fff); +} + +.quicktags-toolbar input:hover { + border-color: #aaa; + background: #ddd; +} + +.quicktags-toolbar input[value="link"] { + text-decoration: underline; +} + +.quicktags-toolbar input[value="del"] { + text-decoration: line-through; +} + +.quicktags-toolbar input[value="i"] { + font-style: italic; +} + +.quicktags-toolbar input[value="b"] { + font-weight: bold; +} + +#wp_editbtns, +#wp_gallerybtns { + padding: 2px; + position: absolute; + display: none; + z-index: 155000; +} + +#wp_editimgbtn, +#wp_delimgbtn, +#wp_editgallery, +#wp_delgallery { + border-color: #999; + background-color: #eee; + margin: 2px; + padding: 2px; + border-width: 1px; + border-style: solid; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +#wp_editimgbtn:hover, +#wp_delimgbtn:hover, +#wp_editgallery:hover, +#wp_delgallery:hover { + border-color: #555; + background-color: #ccc; +} + +/*------------------------------------------------------------------------------ + wp-link +------------------------------------------------------------------------------*/ + +#wp-link { + background-color: #F5F5F5; + line-height: 1.4em; + font-size: 12px; +} + +#wp-link ol, +#wp-link ul { + list-style: none; + margin: 0; + padding: 0; +} + +#wp-link input[type="text"] { + -webkit-box-sizing: border-box; +} + +#wp-link input[type="text"], +#wp-link textarea { + border-width: 1px; + border-style: solid; + -webkit-border-radius: 4px; + border-radius: 4px; + font-size: 12px; + margin: 1px; + padding: 3px; +} + +#wp-link #link-options { + padding: 10px 0 14px; + border-bottom: 1px solid #dfdfdf; + margin: 0 6px 14px; +} + +#wp-link p.howto { + margin: 3px; +} + +#wp-link #internal-toggle { + display: inline-block; + cursor: pointer; + padding-left: 18px; +} + +#wp-link .toggle-arrow { + background: transparent url( '../images/toggle-arrow.png' ) top left no-repeat; + height: 23px; + line-height: 23px; +} + +#wp-link .toggle-arrow-active { + background-position: center left; +} + +#wp-link label input[type="text"] { + width: 360px; + margin-top: 5px; +} + +#wp-link #link-options label span, +#wp-link #search-panel label span.search-label { + display: inline-block; + width: 80px; + text-align: right; + padding-right: 5px; +} + +#wp-link .link-search-field { + float: left; + width: 220px; +} + +#wp-link .link-search-wrapper { + margin: 5px 6px 9px; + display: block; + overflow: hidden; +} + +#wp-link .link-search-wrapper span { + float: left; + margin-top: 4px; +} + +#wp-link .link-search-wrapper .spinner { + display: none; + vertical-align: text-bottom; +} + +#wp-link .link-target { + width: auto; + padding: 3px 0 0; + margin: 0 0 0 87px; + font-size: 11px; +} + +#wp-link .query-results { + border: 1px #dfdfdf solid; + margin: 0 5px 5px; + background: #fff; + height: 185px; + overflow: auto; + position: relative; +} + +#wp-link li, +#wp-link .query-notice { + clear: both; + margin-bottom: 0; + border-bottom: 1px solid #f1f1f1; + color: #333; + padding: 4px 6px; + cursor: pointer; + position: relative; +} + +#wp-link li:hover { + background: #eaf2fa; + color: #151515; +} + +#wp-link li.unselectable { + border-bottom: 1px solid #dfdfdf; +} + +#wp-link li.unselectable:hover { + background: #fff; + cursor: auto; + color: #333; +} + +#wp-link li.selected { + background: #ddd; + color: #333; +} + +#wp-link li.selected .item-title { + font-weight: bold; +} + +#wp-link .item-title { + display: inline-block; + width: 80%; +} + +#wp-link .item-info { + text-transform: uppercase; + color: #666; + font-size: 11px; + position: absolute; + right: 5px; + top: 4px; + bottom: 0; +} + +#wp-link #search-results { + display: none; +} + +#wp-link #search-panel { + float: left; + width: 100%; +} + +#wp-link .river-waiting { + display: none; + padding: 10px 0; +} + +#wp-link .river-waiting .spinner { + margin: 0 auto; + display: block; +} + +#wp-link .submitbox { + padding: 5px 10px; + font-size: 11px; + overflow: auto; + height: 29px; +} + +#wp-link-cancel { + line-height: 25px; + float: left; +} + +#wp-link-update { + line-height: 23px; + float: right; +} + +/*! + * jQuery UI CSS Framework 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + + +/*! + * jQuery UI Resizable 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} + +/*! + * jQuery UI Dialog 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 21px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} + +/* WP jQuery Dialog Theme */ +.wp-dialog { + padding: 0; + z-index: 300002; + border: 1px solid #999; + -webkit-box-shadow: 0px 0px 16px rgba( 0,0,0,0.3 ); + box-shadow: 0px 0px 16px rgba( 0,0,0,0.3 ); + background-color: #f5f5f5; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; +} + +.wp-dialog .ui-dialog-title { + display: block; + text-align: center; + padding: 1px 0 2px; +} + +.wp-dialog .ui-dialog-titlebar { + padding: 0 1em; + background-color: #444; + font-weight: bold; + font-size: 11px; + line-height: 18px; + color: #e5e5e5; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} + +.wp-dialog .ui-dialog-content { + padding: 0; +} + +.wp-dialog .ui-dialog-titlebar-close { + cursor: pointer; + -webkit-appearance: none; + border: 0; + width: 29px; + height: 16px; + top: 13px; + right: 6px; + background: url('../js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif') no-repeat -87px -16px; +} + +.wp-dialog .ui-dialog-titlebar-close .ui-button-text { + display: none; +} + +.wp-dialog .ui-dialog-titlebar-close:hover, +.wp-dialog .ui-dialog-titlebar-close:focus { + background-position: -87px -32px; +} + +.ui-widget-overlay { + z-index: 300001; + background-color: #000; + opacity: 0.6; + filter: alpha(opacity=60); +} + +.rtl .wp-dialog .ui-dialog-titlebar-close { + right: auto; + left: 6px; +} + +/* +RTL +*/ +.rtl #wp-link #internal-toggle { + padding-right: 18px; + padding-left: 0; +} + +.rtl #wp-link #link-options label span, +.rtl #wp-link #search-panel label span.search-label { + text-align: left; + padding-right: 0; + padding-left: 5px; +} + +.rtl #wp-link #link-options label #url-field { + direction: ltr; +} + +.rtl #wp-link .link-search-field, +.rtl #wp-link .link-search-wrapper span { + float: right; +} + +.rtl #wp-link .link-target { + margin-right: 87px; + margin-left: 0; +} + +.rtl #wp-link .item-info { + left: 5px; + right: auto; + top: 4px; + bottom: 0; +} + +.rtl #wp-link #search-panel { + float: right; +} + +.rtl #wp-link-cancel { + float: right; +} + +.rtl #wp-link-update { + float: left; +} + +.rtl #wp-link .toggle-arrow { + background-position: top right; +} + +.rtl #wp-link .toggle-arrow-active { + background-position: center right; +} + +.rtl .wp_themeSkin .mceListBox .mceText { + text-align: right; +} + +.rtl .wp_themeSkin .mceNoIcons a .mceText { + padding-right: 10px; + padding-left: 25px; +} + +.rtl .mceListBoxMenu.mceNoIcons { + direction: rtl; +} + +.clearlooks2 .mceFocus .mceTop .mceLeft { + background: #444444; + border-left: 1px solid #999; + border-top: 1px solid #999; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; +} + +.clearlooks2 .mceFocus .mceTop .mceRight { + background: #444444; + border-right: 1px solid #999; + border-top: 1px solid #999; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} + +.clearlooks2 .mceMiddle .mceLeft { + background: #f1f1f1; + border-left: 1px solid #999; +} + +.clearlooks2 .mceMiddle .mceRight { + background: #f1f1f1; + border-right: 1px solid #999; +} + +.clearlooks2 .mceBottom { + background: #f1f1f1; + border-bottom: 1px solid #999; +} + +.clearlooks2 .mceBottom .mceLeft { + background: #f1f1f1; + border-bottom: 1px solid #999; + border-left: 1px solid #999; +} + +.clearlooks2 .mceBottom .mceCenter { + background: #f1f1f1; + border-bottom: 1px solid #999; +} + +.clearlooks2 .mceBottom .mceRight { + background: #f1f1f1; + border-bottom: 1px solid #999; + border-right: 1px solid #999; +} + +.clearlooks2 .mceFocus .mceTop span { + color: #e5e5e5; +} + + +/* Distraction Free Writing mode + * =Overlay Styles +-------------------------------------------------------------- */ +.fullscreen-overlay { + z-index: 149999; + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + filter: inherit; +} + +.fullscreen-active .fullscreen-overlay, +.fullscreen-active #wp-fullscreen-body { + display: block; +} + +.fullscreen-fader { + z-index: 200000; +} + +.fullscreen-active .fullscreen-fader { + display: none; +} + +/* =Overlay Body +-------------------------------------------------------------- */ +#wp-fullscreen-body { + width: 100%; + z-index: 150005; + display: none; + position: absolute; + top: 0; + left: 0; + font-size: 12px; +} + +#wp-fullscreen-wrap { + margin: 0 auto 50px; + position: relative; + padding-top: 60px; +} + +#wp-fullscreen-title { + font-size: 1.7em; + line-height: 100%; + outline: medium none; + padding: 6px 7px; + width: 100%; + margin-bottom: 30px; + -webkit-box-shadow: none; + box-shadow: none; +} + +#wp-fullscreen-container { + padding: 4px 10px 50px; +} + +#wp-fullscreen-title, +#wp-fullscreen-container { + -webkit-border-radius: 0; + border-radius: 0; + border: 1px dashed transparent; + background: transparent; + -moz-transition-property: border-color; + -moz-transition-duration: 0.6s; + -webkit-transition-property: border-color; + -webkit-transition-duration: 0.6s; + -o-transition-property: border-color; + -o-transition-duration: 0.6s; + transition-property: border-color; + transition-duration: 0.6s; +} + +#wp_mce_fullscreen { + width: 100%; + min-height: 300px; + border: 0; + background: transparent; + font-family: Consolas, Monaco, monospace; + line-height: 1.6em; + padding: 0; + overflow-y: hidden; + outline: none; + resize: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +#wp-fullscreen-tagline { + color: #BBBBBB; + font-size: 18px; + float: right; + padding-top: 5px; +} + +/* =Top bar +-------------------------------------------------------------- */ +#fullscreen-topbar { + position: fixed; + top: 0; + left: 0; + z-index: 150050; + border-bottom-style: solid; + border-bottom-width: 1px; + min-width: 800px; + width: 100%; + height: 40px; +} + +#wp-fullscreen-toolbar { + padding: 6px 10px 0; + clear: both; + max-width: 1100px; + min-width: 820px; + margin: 0 auto; +} + +#wp-fullscreen-mode-bar, +#wp-fullscreen-button-bar, +#wp-fullscreen-close, +#wp-fullscreen-count { + float: left; +} + +#wp-fullscreen-save { + float: right; + padding: 2px 2px 0 5px; +} + +#wp-fullscreen-count, +#wp-fullscreen-close { + padding-top: 5px; +} + +#wp-fullscreen-central-toolbar { + margin: auto; + padding: 0; +} + +#wp-fullscreen-buttons > div { + float: left; +} + +#wp-fullscreen-mode-bar { + padding: 1px 14px 0 0; +} + +#wp-fullscreen-modes a { + display: block; + font-size: 11px; + text-decoration: none; + float: left; + margin: 1px 0 0 0; + padding: 2px 6px 2px; + border-width: 1px 1px 1px 0; + border-style: solid; + border-color: #bbb; + color: #777; + text-shadow: 0 1px 0 #fff; + background-color: #f4f4f4; + background: #f4f4f4; + background-image: -webkit-gradient(linear, left bottom, left top, from(#e4e4e4), to(#f9f9f9)); + background-image: -webkit-linear-gradient(bottom, #e4e4e4, #f9f9f9); + background-image: -moz-linear-gradient(bottom, #e4e4e4, #f9f9f9); + background-image: -o-linear-gradient(bottom, #e4e4e4, #f9f9f9); + background-image: linear-gradient(to top, #e4e4e4, #f9f9f9); +} + +#wp-fullscreen-modes a:hover, +.wp-html-mode #wp-fullscreen-modes a:last-child, +.wp-tmce-mode #wp-fullscreen-modes a:first-child { + color: #333; + border-color: #999; + background: #eee; + background-image: -webkit-gradient(linear, left top, left bottom, from(#e4e4e4), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #e4e4e4, #f9f9f9); + background-image: -moz-linear-gradient(top, #e4e4e4, #f9f9f9); + background-image: -o-linear-gradient(top, #e4e4e4, #f9f9f9); + background-image: linear-gradient(to bottom, #e4e4e4, #f9f9f9); +} + +#wp-fullscreen-modes a:first-child { + border-width: 1px; + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +#wp-fullscreen-modes a:last-child { + -webkit-border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +#wp-fullscreen-buttons .active a { + background: inherit; +} + +#wp-fullscreen-buttons .hidden { + display: none; +} + +#wp-fullscreen-buttons .disabled { + opacity: 0.5; +} + +.wp-html-mode #wp-fullscreen-buttons div { + display: none; +} + +.wp-html-mode #wp-fullscreen-buttons div.wp-fullscreen-both { + display: block; +} + +#fullscreen-topbar.fullscreen-make-sticky { + display: block !important; +} + +#wp-fullscreen-save img { + vertical-align: middle; +} + +#wp-fullscreen-save img, +#wp-fullscreen-save span { + padding-right: 4px; + display: none; +} + +#wp-fullscreen-buttons #wp_fs_image span.mce_image { + background-image: url('../../wp-admin/images/media-button.png'); + background-position: 2px 2px; +} + +/* =Thickbox Adjustments +-------------------------------------------------------------- */ +.fullscreen-active #TB_overlay { + z-index: 150100; +} + +.fullscreen-active #TB_window { + z-index: 150102; +} + +/* =TinyMCE Adjustments +-------------------------------------------------------------- */ +#wp_mce_fullscreen_ifr { + background: transparent; +} + +#wp_mce_fullscreen_parent #wp_mce_fullscreen_tbl tr.mceFirst { + display : none; +} + +#wp-fullscreen-container .wp_themeSkin table td { + vertical-align: top; +} + +/* Colors */ +.fullscreen-overlay { + background: #fff; +} + +.wp-fullscreen-focus #wp-fullscreen-title, +.wp-fullscreen-focus #wp-fullscreen-container { + border-color: #ccc; +} + +#fullscreen-topbar { + border-bottom-color: #DFDFDF; + background: #f1f1f1; + background-image: -webkit-gradient(linear, left bottom, left top, from(#ececec), to(#f9f9f9)); + background-image: -webkit-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: -moz-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: -o-linear-gradient(bottom, #ececec, #f9f9f9); + background-image: linear-gradient(to top, #ececec, #f9f9f9); +} + +#mce_fullscreen_container { + background: #fff; + /* Fix for the default fullscreen plugin for the media modal */ + z-index: 110000 !important; +} + +/* =CSS 3 transitions +-------------------------------------------------------------- */ + +.fade-1000, +.fade-600, +.fade-400, +.fade-300 { + opacity: 0; + -moz-transition-property: opacity; + -webkit-transition-property: opacity; + -o-transition-property: opacity; + transition-property: opacity; +} + +.fade-1000 { + -moz-transition-duration: 1s; + -webkit-transition-duration: 1s; + -o-transition-duration: 1s; + transition-duration: 1s; +} + +.fade-600 { + -moz-transition-duration: 0.6s; + -webkit-transition-duration: 0.6s; + -o-transition-duration: 0.6s; + transition-duration: 0.6s; +} + +.fade-400 { + -moz-transition-duration: 0.4s; + -webkit-transition-duration: 0.4s; + -o-transition-duration: 0.4s; + transition-duration: 0.4s; +} + +.fade-300 { + -moz-transition-duration: 0.3s; + -webkit-transition-duration: 0.3s; + -o-transition-duration: 0.3s; + transition-duration: 0.3s; +} + +.fade-trigger { + opacity: 1; +} + +/* Distraction Free Writing - RTL + * =Overlay Styles +-------------------------------------------------------------- */ + +/* No RTL for now, this space intentionally left blank */ + +/* =Overlay Body +-------------------------------------------------------------- */ +.rtl #wp-fullscreen-tagline { + float: left; +} + +/* =Top bar +-------------------------------------------------------------- */ +.rtl #fullscreen-topbar { + left:auto; + right: 0; +} + +.rtl #wp-fullscreen-mode-bar, +.rtl #wp-fullscreen-button-bar, +.rtl #wp-fullscreen-close, +.rtl #wp-fullscreen-count { + float: right; +} + +.rtl #wp-fullscreen-save { + float: left; +} + +.rtl #wp-fullscreen-save { + padding: 2px 5px 0 2px; +} + +.rtl #wp-fullscreen-buttons > div { + float: right; +} + +.rtl #wp-fullscreen-mode-bar { + padding: 1px 0 0 14px; +} + +.rtl #wp-fullscreen-modes a { + float: right; + border-width: 1px 0 1px 1px; +} + +.rtl #wp-fullscreen-modes a:first-child { + -webkit-border-top-left-radius: 0; + -webkit-border-top-right-radius: 3px; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 3px; + border-width: 1px; + border-top-left-radius: 0; + border-top-right-radius: 3px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 3px; +} + +.rtl #wp-fullscreen-modes a:last-child { + -webkit-border-top-right-radius: 0; + -webkit-border-top-left-radius: 3px; + -webkit-border-bottom-right-radius: 0; + -webkit-border-bottom-left-radius: 3px; + border-top-right-radius: 0; + border-top-left-radius: 3px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 3px; +} + +.rtl #wp-fullscreen-save img, +.rtl #wp-fullscreen-save span { + padding-right: 0; + padding-left: 4px; +} + +/* =Thickbox Adjustments +-------------------------------------------------------------- */ +/* No RTL for now, this space intentionally left blank */ + + +/* =TinyMCE Adjustments +-------------------------------------------------------------- */ +/* No RTL for now, this space intentionally left blank */ + + +/* HiDPI */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + .wp_themeSkin span.mce_undo, + .wp_themeSkin span.mce_redo, + .wp_themeSkin span.mce_bullist, + .wp_themeSkin span.mce_numlist, + .wp_themeSkin span.mce_blockquote, + .wp_themeSkin span.mce_charmap, + .wp_themeSkin span.mce_bold, + .wp_themeSkin span.mce_italic, + .wp_themeSkin span.mce_underline, + .wp_themeSkin span.mce_justifyleft, + .wp_themeSkin span.mce_justifyright, + .wp_themeSkin span.mce_justifycenter, + .wp_themeSkin span.mce_justifyfull, + .wp_themeSkin span.mce_indent, + .wp_themeSkin span.mce_outdent, + .wp_themeSkin span.mce_link, + .wp_themeSkin span.mce_unlink, + .wp_themeSkin span.mce_help, + .wp_themeSkin span.mce_removeformat, + .wp_themeSkin span.mce_fullscreen, + .wp_themeSkin span.mce_wp_fullscreen, + .wp_themeSkin span.mce_media, + .wp_themeSkin span.mce_pastetext, + .wp_themeSkin span.mce_pasteword, + .wp_themeSkin span.mce_wp_help, + .wp_themeSkin span.mce_wp_adv, + .wp_themeSkin span.mce_wp_more, + .wp_themeSkin span.mce_strikethrough, + .wp_themeSkin span.mce_spellchecker, + .wp_themeSkin span.mce_forecolor, + .wp_themeSkin .mce_forecolorpicker, + .wp_themeSkin .mceSplitButton .mce_spellchecker span.mce_spellchecker, + .wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor, + .wp_themeSkin .mceSplitButton span.mce_numlist, + .wp_themeSkin .mceSplitButton span.mce_bullist { + background-image: url('../images/wpicons-2x.png?ver=20120720'); + background-size: 560px 40px; + } + + .wp-media-buttons .add_media span.wp-media-buttons-icon, + #wp-fullscreen-buttons #wp_fs_image span.mce_image { + background-image: url('../../wp-admin/images/media-button-2x.png'); + background-size: 16px 16px; + } + + .wp_themeSkin .mceListBox .mceOpen, + .wp_themeSkin .mceListBoxHover .mceOpen, + .wp_themeSkin .mceListBoxSelected .mceOpen, + .wp_themeSkin table.mceListBoxEnabled .mceOpen { + background-image: url('../images/down_arrow-2x.gif'); + background-size: 10px 20px; + } + + .wp_themeSkin .mceSplitButtonEnabled a.mceOpen, + .wp_themeSkin .mceSplitButtonSelected a.mceOpen, + .wp_themeSkin .mceSplitButtonActive a.mceOpen, + .wp_themeSkin .mceSplitButtonEnabled:hover a.mceOpen { + background-image: url('../images/down_arrow-2x.gif'); + background-size: 10px 20px; + } + + #wp-link .toggle-arrow { + background: transparent url('../images/toggle-arrow-2x.png') top left no-repeat; + background-size: 19px 69px; + } +} diff --git a/sources/wp-includes/css/editor.min.css b/sources/wp-includes/css/editor.min.css new file mode 100644 index 0000000..a7f64b3 --- /dev/null +++ b/sources/wp-includes/css/editor.min.css @@ -0,0 +1,28 @@ +.wp_themeSkin table,.wp_themeSkin tbody,.wp_themeSkin a,.wp_themeSkin img,.wp_themeSkin tr,.wp_themeSkin div,.wp_themeSkin td,.wp_themeSkin iframe,.wp_themeSkin span,.wp_themeSkin *,.wp_themeSkin .mceText{border:0;margin:0;padding:0;white-space:nowrap;text-decoration:none;font-weight:400;cursor:default;vertical-align:baseline;width:auto;border-collapse:separate}.wp_themeSkin a:hover,.wp_themeSkin a:link,.wp_themeSkin a:visited,.wp_themeSkin a:active{text-decoration:none;font-weight:400;cursor:default}.wp_themeSkin table td{vertical-align:middle}.wp_themeSkin *,.wp_themeSkin a:hover,.wp_themeSkin a:link,.wp_themeSkin a:visited,.wp_themeSkin a:active{color:#555}.wp_themeSkin table{}.wp_themeSkin iframe{display:block}.wp_themeSkin #mce_fullscreen_ifr{background-color:#fff}.wp_themeSkin .mceToolbar{padding:1px}.wp_themeSkin .mceExternalToolbar{position:absolute;border-bottom:0;display:none}.wp_themeSkin .mceExternalToolbar td.mceToolbar{padding-right:13px}.wp_themeSkin .mceExternalClose{position:absolute;top:3px;right:3px;width:7px;height:7px;background:url(../js/tinymce/themes/advanced/img/icons.gif) -820px 0}.wp_themeSkin table.mceToolbar,.wp_themeSkin tr.mceFirst .mceToolbar tr td,.wp_themeSkin tr.mceLast .mceToolbar tr td{border:0;margin:0;padding:0}.wp_themeSkin table.mceLayout{border:0}.wp_themeSkin .mceStatusbar{display:block;font-family:sans-serif;font-size:12px;line-height:16px;padding:0 0 0 8px;overflow:visible;height:20px;border-top:1px solid #dfdfdf;color:#000;background-color:#f5f5f5}.rtl .wp_themeSkin .mceStatusbar{padding:0 8px 0 0}.wp_themeSkin .mceStatusbar *{color:#555}.wp_themeSkin .mceStatusbar div{float:left;padding:2px}.rtl .wp_themeSkin .mceStatusbar div{float:right}.wp_themeSkin .mceStatusbar a.mceResize{display:block;float:right;background:url(../js/tinymce/themes/advanced/img/icons.gif) -800px 0;width:20px;height:20px;cursor:se-resize}.rtl .wp_themeSkin .mceStatusbar a.mceResize{float:left}.wp_themeSkin .mceStatusbar a:hover{text-decoration:underline}.wp_themeSkin table.mceToolbar{margin:0 6px 2px}.wp_themeSkin table.mceToolbar :active,.wp_themeSkin table.mceToolbar :focus,.wp_themeSkin table.mceToolbar:focus,.wp_themeSkin span.mceSeparator:focus{outline:0}.wp_themeSkin #content_toolbar1{margin-top:2px}.wp_themeSkin .mceToolbar .mceToolbarEndListBox span{display:none}.wp_themeSkin span.mceIcon,.wp_themeSkin img.mceIcon{display:block;width:20px;height:20px}.wp_themeSkin .mceIcon{background:url(../js/tinymce/themes/advanced/img/icons.gif) no-repeat 20px 20px}.wp_themeSkin .mceButton{display:block;width:20px;height:20px;cursor:default;padding:1px 2px;margin:1px;-webkit-border-radius:2px;border-radius:2px}.wp_themeSkin a.mceButtonEnabled:hover{background-image:inherit 0 -10px}.wp_themeSkin .mceOldBoxModel a.mceButton span,.wp_themeSkin .mceOldBoxModel a.mceButton img{margin:0 0 0 1px}.wp_themeSkin .mceButtonDisabled .mceIcon{opacity:.2;filter:alpha(opacity=20)}.wp_themeSkin .mceSeparator{display:none}.wp_themeSkin .mceListBox,.wp_themeSkin .mceListBox a{display:block}.wp_themeSkin .mceListBox .mceText{padding:1px 4px 1px 5px;width:70px;text-align:left;text-decoration:none;-webkit-border-bottom-left-radius:2px;-webkit-border-top-left-radius:2px;border-bottom-left-radius:2px;border-top-left-radius:2px;font-family:sans-serif;font-size:12px;height:20px;line-height:20px;overflow:hidden}.wp_themeSkin .mceListBox{margin:1px;direction:ltr;background-color:#fff;border:1px solid #ddd;-webkit-box-shadow:inset 0 1px 1px -1px rgba(0,0,0,.2);box-shadow:inset 0 1px 1px -1px rgba(0,0,0,.2)}.wp_themeSkin .mceListBox .mceOpen{width:12px;height:20px;border-collapse:separate;padding:1px;-webkit-border-bottom-left-radius:0;-webkit-border-top-left-radius:0;border-bottom-left-radius:0;border-top-left-radius:0}.wp_themeSkin .mceListBox .mceFirst a{border-style:solid;border-width:1px;border-bottom-right-radius:2px;border-top-right-radius:2px}.wp_themeSkin .mceListBoxMenu .mce_formatPreview{line-height:normal}.wp_themeSkin .mceListBox .mceOpen,.wp_themeSkin .mceListBoxHover .mceOpen,.wp_themeSkin .mceListBoxSelected .mceOpen,.wp_themeSkin table.mceListBoxEnabled .mceOpen{background-image:url(../images/down_arrow.gif);background-position:3px 1px;background-repeat:no-repeat}.wp_themeSkin .mceListBoxDisabled .mceText{color:gray}.wp_themeSkin .mceListBoxMenu{overflow:auto;overflow-x:hidden}.wp_themeSkin .mceOldBoxModel .mceListBox .mceText{height:22px}.wp_themeSkin select.mceListBox{font-family:sans-serif;font-size:12px;border-color:#b2b2b2;background-color:#fff}.wp_themeSkin .mceSplitButton a,.wp_themeSkin .mceSplitButton span{display:block;height:20px}.wp_themeSkin .mceSplitButton{display:block;direction:ltr}.wp_themeSkin table.mceSplitButton td{padding:2px;-webkit-border-radius:2px;border-radius:2px}.wp_themeSkin table.mceSplitButton:hover td{background-image:inherit 0 -10px}.wp_themeSkin .mceSplitButton a.mceAction{height:20px;width:20px;padding:1px 2px;border-right:0 none}.wp_themeSkin .mceSplitButton span.mceAction{background-image:url(../js/tinymce/themes/advanced/img/icons.gif);background-repeat:no-repeat;background-color:transparent;width:20px}.wp_themeSkin .mceSplitButton a.mceOpen{width:11px;height:20px;background-position:0 2px;background-repeat:no-repeat;padding:1px 0}.wp_themeSkin .mceSplitButton span.mceOpen{display:none}.wp_themeSkin .mceSplitButtonDisabled .mceAction{opacity:.3;filter:alpha(opacity=30)}.wp_themeSkin .mceListBox a.mceText,.wp_themeSkin .mceSplitButton a.mceAction{-webkit-border-bottom-left-radius:2px;-webkit-border-top-left-radius:2px;border-bottom-left-radius:2px;border-top-left-radius:2px}.wp_themeSkin .mceSplitButton a.mceOpen,.wp_themeSkin .mceListBox a.mceOpen{-webkit-border-bottom-right-radius:2px;-webkit-border-top-right-radius:2px;border-bottom-right-radius:2px;border-top-right-radius:2px}.wp_themeSkin span.mce_undo,.wp_themeSkin span.mce_redo,.wp_themeSkin span.mce_bullist,.wp_themeSkin span.mce_numlist,.wp_themeSkin span.mce_blockquote,.wp_themeSkin span.mce_charmap,.wp_themeSkin span.mce_bold,.wp_themeSkin span.mce_italic,.wp_themeSkin span.mce_underline,.wp_themeSkin span.mce_justifyleft,.wp_themeSkin span.mce_justifyright,.wp_themeSkin span.mce_justifycenter,.wp_themeSkin span.mce_justifyfull,.wp_themeSkin span.mce_indent,.wp_themeSkin span.mce_outdent,.wp_themeSkin span.mce_link,.wp_themeSkin span.mce_unlink,.wp_themeSkin span.mce_help,.wp_themeSkin span.mce_removeformat,.wp_themeSkin span.mce_fullscreen,.wp_themeSkin span.mce_wp_fullscreen,.wp_themeSkin span.mce_media,.wp_themeSkin span.mce_pastetext,.wp_themeSkin span.mce_pasteword,.wp_themeSkin span.mce_wp_help,.wp_themeSkin span.mce_wp_adv,.wp_themeSkin span.mce_wp_more,.wp_themeSkin span.mce_strikethrough,.wp_themeSkin span.mce_spellchecker,.wp_themeSkin span.mce_forecolor,.wp_themeSkin .mce_forecolorpicker,.wp_themeSkin .mceSplitButton .mce_spellchecker span.mce_spellchecker,.wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor,.wp_themeSkin .mceSplitButton span.mce_numlist,.wp_themeSkin .mceSplitButton span.mce_bullist{background-image:url(../images/wpicons.png?ver=20120720)}.wp_themeSkin div.mceColorSplitMenu table{background-color:#ebebeb;border-color:#bbb}.wp_themeSkin .mceColorSplitMenu td{padding:2px}.wp_themeSkin .mceColorSplitMenu a{display:block;width:9px;height:9px;overflow:hidden;border-color:#B2B2B2}.wp_themeSkin .mceColorSplitMenu td.mceMoreColors{padding:1px 3px 1px 1px}.wp_themeSkin .mceColorSplitMenu a.mceMoreColors{width:100%;height:auto;text-align:center;font-family:Tahoma,Verdana,Arial,Helvetica;font-size:11px;line-height:20px;border-color:#fff}.wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover{}.wp_themeSkin a.mceMoreColors:hover{}.wp_themeSkin .mceColorPreview{margin:-5px 0 0 2px;width:16px;height:4px;overflow:hidden}.wp_themeSkin .mceMenu{position:absolute;left:0;top:0;z-index:1000;border-color:#ddd;direction:ltr}.wp_themeSkin .mceNoIcons span.mceIcon{width:0}.wp_themeSkin .mceNoIcons a .mceText{padding-left:10px}.wp_themeSkin .mceMenu table{background-color:#ebeaeb}.wp_themeSkin .mceMenu a,.wp_themeSkin .mceMenu span,.wp_themeSkin .mceMenu{display:block}.wp_themeSkin .mceMenu td{height:20px;overflow:hidden}.wp_themeSkin .mceMenu a{position:relative;padding:3px 0 4px;text-decoration:none!important}.wp_themeSkin .mceMenu .mceText{position:relative;display:block;font-family:Tahoma,Verdana,Arial,Helvetica;cursor:default;margin:0;padding:0 25px;color:#000}.wp_themeSkin .mceMenu span.mceText,.wp_themeSkin .mceMenu .mcePreview{font-size:12px}.wp_themeSkin .mceMenu pre.mceText{font-family:Monospace}.wp_themeSkin .mceMenu .mceIcon{position:absolute;top:0;left:0;width:22px}.wp_themeSkin .mceMenu .mceMenuItemEnabled a:hover,.wp_themeSkin .mceMenu .mceMenuItemActive{background-color:#f5f5f5}.wp_themeSkin td.mceMenuItemSeparator{height:1px;background-color:#aaa}.wp_themeSkin .mceMenuItemTitle a{border-top:0;border-right:0;border-left:0;border-bottom:1px solid #aaa;text-decoration:none!important;background-color:#ccc}.wp_themeSkin .mceMenuItemTitle span.mceText{font-weight:700;padding-left:4px;color:#000}.wp_themeSkin .mceMenuItemSelected .mceIcon{background:url(../js/tinymce/themes/advanced/skins/default/img/menu_check.gif);color:#888}.wp_themeSkin .mceNoIcons .mceMenuItemSelected a{background:url(../js/tinymce/themes/advanced/skins/default/img/menu_arrow.gif) no-repeat -6px center}.wp_themeSkin .mceMenu span.mceMenuLine{display:none}.wp_themeSkin .mceMenuItemSub a{background:url(../js/tinymce/themes/advanced/skins/default/img/menu_arrow.gif) no-repeat top right}.wp_themeSkin .mceBlocker{position:absolute;left:0;top:0;z-index:1000;opacity:.5;filter:alpha(opacity=50);background:#FFF}.wp_themeSkin .mceProgress{position:absolute;left:0;top:0;z-index:1001;background:url(../js/tinymce/themes/advanced/skins/default/img/progress.gif) no-repeat;width:32px;height:32px;margin:-16px 0 0 -16px}.wp_themeSkin .mcePlaceHolder{border:1px dotted gray}.mceRtl .mceListBox .mceText{text-align:right;padding:0 4px 0 0}.mceRtl .mceMenuItem .mceText{text-align:right}.wp_themeSkin .mce_p span.mceText{}.wp_themeSkin .mce_address span.mceText{font-style:italic}.wp_themeSkin .mce_pre span.mceText{font-family:monospace}.wp_themeSkin .mce_h1 span.mceText{font-weight:bolder;font-size:18px}.wp_themeSkin .mce_h2 span.mceText{font-weight:bolder;font-size:16px}.wp_themeSkin .mce_h3 span.mceText{font-weight:bolder;font-size:14px}.wp_themeSkin .mce_h4 span.mceText{font-weight:bolder;font-size:12px}.wp_themeSkin .mce_h5 span.mceText{font-weight:bolder;font-size:11px}.wp_themeSkin .mce_h6 span.mceText{font-weight:bolder;font-size:10px}.wp_themeSkin span.mce_undo{background-position:-500px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_undo,.wp_themeSkin .mceButtonActive span.mce_undo{background-position:-500px 0}.wp_themeSkin span.mce_redo{background-position:-480px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_redo,.wp_themeSkin .mceButtonActive span.mce_redo{background-position:-480px 0}.wp_themeSkin span.mce_bullist{background-position:-40px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_bullist,.wp_themeSkin .mceButtonActive span.mce_bullist,.wp_themeSkin .mceSplitButton:hover span.mce_bullist{background-position:-40px 0}.wp_themeSkin span.mce_numlist{background-position:-60px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_numlist,.wp_themeSkin .mceButtonActive span.mce_numlist,.wp_themeSkin .mceSplitButton:hover span.mce_numlist{background-position:-60px 0}.wp_themeSkin span.mce_blockquote{background-position:-80px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_blockquote,.wp_themeSkin .mceButtonActive span.mce_blockquote{background-position:-80px 0}.wp_themeSkin span.mce_charmap{background-position:-420px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_charmap,.wp_themeSkin .mceButtonActive span.mce_charmap{background-position:-420px 0}.wp_themeSkin span.mce_bold{background-position:0 -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_bold,.wp_themeSkin .mceButtonActive span.mce_bold{background-position:0 0}.wp_themeSkin span.mce_italic{background-position:-20px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_italic,.wp_themeSkin .mceButtonActive span.mce_italic{background-position:-20px 0}.wp_themeSkin span.mce_underline{background-position:-280px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_underline,.wp_themeSkin .mceButtonActive span.mce_underline{background-position:-280px 0}.wp_themeSkin span.mce_justifyleft{background-position:-100px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_justifyleft,.wp_themeSkin .mceButtonActive span.mce_justifyleft{background-position:-100px 0}.wp_themeSkin span.mce_justifyright{background-position:-140px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_justifyright,.wp_themeSkin .mceButtonActive span.mce_justifyright{background-position:-140px 0}.wp_themeSkin span.mce_justifycenter{background-position:-120px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_justifycenter,.wp_themeSkin .mceButtonActive span.mce_justifycenter{background-position:-120px 0}.wp_themeSkin span.mce_justifyfull{background-position:-300px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_justifyfull,.wp_themeSkin .mceButtonActive span.mce_justifyfull{background-position:-300px 0}.wp_themeSkin span.mce_indent{background-position:-460px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_indent,.wp_themeSkin .mceButtonActive span.mce_indent{background-position:-460px 0}.wp_themeSkin span.mce_outdent{background-position:-440px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_outdent,.wp_themeSkin .mceButtonActive span.mce_outdent{background-position:-440px 0}.wp_themeSkin span.mce_link{background-position:-160px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_link,.wp_themeSkin .mceButtonActive span.mce_link{background-position:-160px 0}.wp_themeSkin span.mce_unlink{background-position:-180px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_unlink,.wp_themeSkin .mceButtonActive span.mce_unlink{background-position:-180px 0}.wp_themeSkin span.mce_help{background-position:-520px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_help,.wp_themeSkin .mceButtonActive span.mce_help{background-position:-520px 0}.wp_themeSkin span.mce_removeformat{background-position:-380px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_removeformat,.wp_themeSkin .mceButtonActive span.mce_removeformat{background-position:-380px 0}.wp_themeSkin span.mce_strikethrough{background-position:-540px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_strikethrough,.wp_themeSkin .mceButtonActive span.mce_strikethrough{background-position:-540px 0}.wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor{background-position:-320px -20px}.wp_themeSkin .mceSplitButtonEnabled:hover span.mce_forecolor,.wp_themeSkin .mceSplitButtonSelected span.mce_forecolor{background-position:-320px 0}.wp_themeSkin .mce_forecolorpicker{background-position:-320px -20px}.wp_themeSkin span.mce_fullscreen{background-position:-240px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_fullscreen,.wp_themeSkin .mceButtonActive span.mce_fullscreen{background-position:-240px 0}.wp_themeSkin span.mce_wp_fullscreen{background-position:-240px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_fullscreen,.wp_themeSkin .mceButtonActive span.mce_wp_fullscreen{background-position:-240px 0}.wp_themeSkin span.mce_media{background-position:-400px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_media,.wp_themeSkin .mceButtonActive span.mce_media{background-position:-400px 0}.wp_themeSkin span.mce_pastetext{background-position:-340px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_pastetext,.wp_themeSkin .mceButtonActive span.mce_pastetext{background-position:-340px 0}.wp_themeSkin span.mce_pasteword{background-position:-360px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_pasteword,.wp_themeSkin .mceButtonActive span.mce_pasteword{background-position:-360px 0}.wp_themeSkin span.mce_spellchecker{background-position:-220px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_spellchecker,.wp_themeSkin .mceSplitButtonEnabled:hover span.mce_spellchecker,.wp_themeSkin .mceButtonActive span.mce_spellchecker,.wp_themeSkin .mceSplitButtonSelected span.mce_spellchecker{background-position:-220px 0}.wp_themeSkin span.mce_wp_help{background-position:-520px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_help,.wp_themeSkin .mceButtonActive span.mce_wp_help{background-position:-520px 0}.wp_themeSkin span.mce_wp_adv{background-position:-260px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_adv,.wp_themeSkin .mceButtonActive span.mce_wp_adv{background-position:-260px 0}.wp_themeSkin span.mce_wp_more{background-position:-200px -20px}.wp_themeSkin .mceButtonEnabled:hover span.mce_wp_more,.wp_themeSkin .mceButtonActive span.mce_wp_more{background-position:-200px 0}.wp_themeSkin span.mce_cleanup{background-position:-380px -20px}.wp_themeSkin span.mce_anchor{background-position:-200px 0}.wp_themeSkin span.mce_sub{background-position:-600px 0}.wp_themeSkin span.mce_sup{background-position:-620px 0}.wp_themeSkin span.mce_newdocument{background-position:-520px 0}.wp_themeSkin span.mce_image{background-position:-380px 0}.wp_themeSkin span.mce_code{background-position:-260px 0}.wp_themeSkin span.mce_hr{background-position:-360px 0}.wp_themeSkin span.mce_visualaid{background-position:-660px 0}.wp_themeSkin span.mce_paste{background-position:-560px 0}.wp_themeSkin span.mce_copy{background-position:-700px 0}.wp_themeSkin span.mce_cut{background-position:-680px 0}.wp_themeSkin .mce_backcolor span.mceAction{background-position:-760px 0}.wp_themeSkin .mce_backcolorpicker{background-position:-760px 0}.wp_themeSkin span.mce_advhr{background-position:-0px -20px}.wp_themeSkin span.mce_ltr{background-position:-20px -20px}.wp_themeSkin span.mce_rtl{background-position:-40px -20px}.wp_themeSkin span.mce_emotions{background-position:-60px -20px}.wp_themeSkin span.mce_fullpage{background-position:-80px -20px}.wp_themeSkin span.mce_iespell{background-position:-120px -20px}.wp_themeSkin span.mce_insertdate{background-position:-140px -20px}.wp_themeSkin span.mce_inserttime{background-position:-160px -20px}.wp_themeSkin span.mce_absolute{background-position:-180px -20px}.wp_themeSkin span.mce_backward{background-position:-200px -20px}.wp_themeSkin span.mce_forward{background-position:-220px -20px}.wp_themeSkin span.mce_insert_layer{background-position:-240px -20px}.wp_themeSkin span.mce_insertlayer{background-position:-260px -20px}.wp_themeSkin span.mce_movebackward{background-position:-280px -20px}.wp_themeSkin span.mce_moveforward{background-position:-300px -20px}.wp_themeSkin span.mce_nonbreaking{background-position:-340px -20px}.wp_themeSkin span.mce_selectall{background-position:-400px -20px}.wp_themeSkin span.mce_preview{background-position:-420px -20px}.wp_themeSkin span.mce_print{background-position:-440px -20px}.wp_themeSkin span.mce_cancel{background-position:-460px -20px}.wp_themeSkin span.mce_save{background-position:-480px -20px}.wp_themeSkin span.mce_replace{background-position:-500px -20px}.wp_themeSkin span.mce_search{background-position:-520px -20px}.wp_themeSkin span.mce_styleprops{background-position:-560px -20px}.wp_themeSkin span.mce_table{background-position:-580px -20px}.wp_themeSkin span.mce_cell_props{background-position:-600px -20px}.wp_themeSkin span.mce_delete_table{background-position:-620px -20px}.wp_themeSkin span.mce_delete_col{background-position:-640px -20px}.wp_themeSkin span.mce_delete_row{background-position:-660px -20px}.wp_themeSkin span.mce_col_after{background-position:-680px -20px}.wp_themeSkin span.mce_col_before{background-position:-700px -20px}.wp_themeSkin span.mce_row_after{background-position:-720px -20px}.wp_themeSkin span.mce_row_before{background-position:-740px -20px}.wp_themeSkin span.mce_merge_cells{background-position:-760px -20px}.wp_themeSkin span.mce_table_props{background-position:-980px -20px}.wp_themeSkin span.mce_row_props{background-position:-780px -20px}.wp_themeSkin span.mce_split_cells{background-position:-800px -20px}.wp_themeSkin span.mce_template{background-position:-820px -20px}.wp_themeSkin span.mce_visualchars{background-position:-840px -20px}.wp_themeSkin span.mce_abbr{background-position:-860px -20px}.wp_themeSkin span.mce_acronym{background-position:-880px -20px}.wp_themeSkin span.mce_attribs{background-position:-900px -20px}.wp_themeSkin span.mce_cite{background-position:-920px -20px}.wp_themeSkin span.mce_del{background-position:-940px -20px}.wp_themeSkin span.mce_ins{background-position:-960px -20px}.wp_themeSkin span.mce_pagebreak{background-position:0 -40px}.wp_themeSkin span.mce_restoredraft{background-position:-20px -40px}.wp_themeSkin span.mce_visualblocks{background-position:-40px -40px}.wp_themeSkin .mceExternalToolbar,.wp_themeSkin .mceButton,.wp_themeSkin a.mceButtonEnabled:hover,.wp_themeSkin a.mceButtonActive,.wp_themeSkin a.mceButtonSelected,.wp_themeSkin .mceListBox .mceText,.wp_themeSkin .mceListBox .mceOpen,.wp_themeSkin select.mceListBox,.wp_themeSkin .mceSplitButton a.mceAction,.wp_themeSkin .mceSplitButton a.mceOpen,.wp_themeSkin .mceSplitButton a.mceOpen:hover,.wp_themeSkin .mceSplitButtonSelected a.mceOpen,.wp_themeSkin table.mceSplitButtonEnabled:hover a.mceAction,.wp_themeSkin .mceSplitButton a.mceAction:hover,.wp_themeSkin div.mceColorSplitMenu table,.wp_themeSkin .mceColorSplitMenu a,.wp_themeSkin .mceColorSplitMenu a.mceMoreColors,.wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover,.wp_themeSkin a.mceMoreColors:hover,.wp_themeSkin .mceMenu{border-style:solid;border-width:1px}.wp_themeSkin .mceListBox .mceText{border-right:0 none}.wp_themeSkin iframe{background:transparent}.wp_themeSkin .mceButton{border-color:transparent}.wp_themeSkin .mceListBox .mceText,.wp_themeSkin .mceListBox .mceOpen{border-color:transparent}.wp_themeSkin a.mceButtonEnabled:hover,.wp_themeSkin table.mceSplitButton:hover{border-color:#bbb;background:#eee;background-image:-webkit-gradient(linear,left bottom,left top,from(#e5e5e5),to(#fff));background-image:-webkit-linear-gradient(bottom,#e5e5e5,#fff);background-image:-moz-linear-gradient(bottom,#e5e5e5,#fff);background-image:-o-linear-gradient(bottom,#e5e5e5,#fff);background-image:linear-gradient(to top,#e5e5e5,#fff)}.wp_themeSkin a.mceButton:active,.wp_themeSkin a.mceButtonEnabled:active,.wp_themeSkin a.mceButtonSelected:active,.wp_themeSkin a.mceButtonActive,.wp_themeSkin a.mceButtonActive:active,.wp_themeSkin a.mceButtonActive:hover,.wp_themeSkin .mceSplitButtonSelected table,.wp_themeSkin .mceSplitButtonSelected table:hover{outline:0;border-color:#999 #ccc #ccc #999;background:#eee;background-image:-webkit-gradient(linear,left bottom,left top,from(#f6f6f6),to(#e3e3e3));background-image:-webkit-linear-gradient(bottom,#f6f6f6,#e3e3e3);background-image:-moz-linear-gradient(bottom,#f6f6f6,#e3e3e3);background-image:-o-linear-gradient(bottom,#f6f6f6,#e3e3e3);background-image:linear-gradient(to top,#f6f6f6,#e3e3e3)}.wp_themeSkin .mceSplitButtonSelected table a.mceOpen,.wp_themeSkin .mceSplitButtonSelected table a.mceAction{border-color:#999 #ccc #ccc #999}.wp_themeSkin .mceButtonDisabled{border-color:transparent}.wp_themeSkin .mceListBox .mceOpen{border-left:0}.wp_themeSkin .mceListBoxEnabled:hover,.wp_themeSkin .mceListBoxEnabled:active,.wp_themeSkin .mceListBoxHover,.wp_themeSkin .mceListBoxHover:active,.wp_themeSkin .mceListBoxSelected{-webkit-box-shadow:inset 0 1px 1px -1px rgba(0,0,0,.3);box-shadow:inset 0 1px 1px -1px rgba(0,0,0,.3);border-color:#bbb}.wp_themeSkin .mceSplitButton .mceLast span.mceOpen .mceIconOnly{display:block}.wp_themeSkin .mceSplitButton a.mceAction,.wp_themeSkin .mceSplitButton a.mceOpen{border-color:transparent}.wp_themeSkin .mceSplitButton:hover a{border-color:#bbb}.wp_themeSkin .mceSplitButtonEnabled a.mceOpen,.wp_themeSkin .mceSplitButtonSelected a.mceOpen,.wp_themeSkin .mceSplitButtonActive a.mceOpen,.wp_themeSkin .mceSplitButtonEnabled:hover a.mceOpen{background-image:url(../images/down_arrow.gif);background-position:1px 2px;background-repeat:no-repeat;border-left:0}.wp_themeSkin .mceSplitButtonActive td{-webkit-border-radius:3px;border-radius:3px}.wp_themeSkin .mceColorSplitMenu a.mceMoreColors:hover{border-color:#0A246A;background-color:#B6BDD2}.wp_themeSkin a.mceMoreColors:hover{border-color:#0A246A}.wp_themeSkin .mceMenuItemDisabled .mceText{color:#888}#mceModalBlocker{background:#000}.wp-editor-wrap{position:relative}.wp-editor-area{font-family:Consolas,Monaco,monospace;padding:10px;margin:1px 0 0;line-height:150%;border:0 none;outline:0;display:block;resize:vertical;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.wp-editor-tools{height:30px;padding:0 10px 0 0}.rtl .wp-editor-tools{padding:0 0 0 10px}.wp-editor-container{border-width:1px;border-style:solid;-webkit-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;border-top-right-radius:3px;border-top-left-radius:3px;border-color:#ccc #ccc #dfdfdf}.wp-editor-container textarea.wp-editor-area{width:100%;margin:0;-webkit-box-shadow:none;box-shadow:none}.quicktags-toolbar,.wp_themeSkin tr.mceFirst td.mceToolbar{border-bottom:1px solid #d1d1d1;background:#eee;background-image:-webkit-gradient(linear,left bottom,left top,from(#e5e5e5),to(#f4f4f4));background-image:-webkit-linear-gradient(bottom,#e5e5e5,#f4f4f4);background-image:-moz-linear-gradient(bottom,#e5e5e5,#f4f4f4);background-image:-o-linear-gradient(bottom,#e5e5e5,#f4f4f4);background-image:linear-gradient(to top,#e5e5e5,#f4f4f4)}.wp-switch-editor{height:18px;font:13px/18px Arial,Helvetica,sans-serif normal;margin:5px 5px 0 0;padding:4px 5px 2px;float:right;cursor:pointer;border-width:1px;border-style:solid;-webkit-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;border-top-right-radius:3px;border-top-left-radius:3px;background-color:#f1f1f1;border-color:#dfdfdf #dfdfdf #ccc;color:#999}html[dir=rtl] .wp-switch-editor{float:left}.wp-switch-editor:active{background-color:#f1f1f1}.wp-switch-editor:hover{text-decoration:none!important}.js .tmce-active .wp-editor-area{color:#fff}.tmce-active .quicktags-toolbar{display:none}.tmce-active .switch-tmce,.html-active .switch-html{border-color:#ccc #ccc #f4f4f4;background-color:#f4f4f4;color:#555}.wp-media-buttons .button{margin-right:5px}.rtl .wp-media-buttons .button{margin-right:0;margin-left:5px}.wp-media-buttons .insert-media{padding-left:.4em}.rtl .wp-media-buttons .insert-media{padding-left:10px;padding-right:.4em}.wp-media-buttons a{text-decoration:none;color:#464646;font-size:12px}.wp-media-buttons img{padding:0 4px;vertical-align:middle}.wp-media-buttons span.wp-media-buttons-icon{display:inline-block;width:16px;height:16px;vertical-align:text-top;margin:0 2px}.wp-media-buttons .add_media span.wp-media-buttons-icon{background:url(../../wp-admin/images/media-button.png) no-repeat top left}.quicktags-toolbar{border-bottom-style:solid;border-bottom-width:1px;-webkit-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;border-top-right-radius:3px;border-top-left-radius:3px;padding:2px 8px 0;min-height:29px}.quicktags-toolbar>div{padding:2px 4px 0}.quicktags-toolbar input{margin:2px 1px 4px;line-height:18px;display:inline-block;min-width:26px;padding:2px 4px;font:12px/18px Arial,Helvetica,sans-serif normal;color:#464646;border:1px solid #c3c3c3;-webkit-border-radius:3px;border-radius:3px;background:#eee;background-image:-webkit-gradient(linear,left bottom,left top,from(#e3e3e3),to(#fff));background-image:-webkit-linear-gradient(bottom,#e3e3e3,#fff);background-image:-moz-linear-gradient(bottom,#e3e3e3,#fff);background-image:-o-linear-gradient(bottom,#e3e3e3,#fff);background-image:linear-gradient(to top,#e3e3e3,#fff)}.quicktags-toolbar input:hover{border-color:#aaa;background:#ddd}.quicktags-toolbar input[value=link]{text-decoration:underline}.quicktags-toolbar input[value=del]{text-decoration:line-through}.quicktags-toolbar input[value="i"]{font-style:italic}.quicktags-toolbar input[value="b"]{font-weight:700}#wp_editbtns,#wp_gallerybtns{padding:2px;position:absolute;display:none;z-index:155000}#wp_editimgbtn,#wp_delimgbtn,#wp_editgallery,#wp_delgallery{border-color:#999;background-color:#eee;margin:2px;padding:2px;border-width:1px;border-style:solid;-webkit-border-radius:3px;border-radius:3px}#wp_editimgbtn:hover,#wp_delimgbtn:hover,#wp_editgallery:hover,#wp_delgallery:hover{border-color:#555;background-color:#ccc}#wp-link{background-color:#F5F5F5;line-height:1.4em;font-size:12px}#wp-link ol,#wp-link ul{list-style:none;margin:0;padding:0}#wp-link input[type=text]{-webkit-box-sizing:border-box}#wp-link input[type=text],#wp-link textarea{border-width:1px;border-style:solid;-webkit-border-radius:4px;border-radius:4px;font-size:12px;margin:1px;padding:3px}#wp-link #link-options{padding:10px 0 14px;border-bottom:1px solid #dfdfdf;margin:0 6px 14px}#wp-link p.howto{margin:3px}#wp-link #internal-toggle{display:inline-block;cursor:pointer;padding-left:18px}#wp-link .toggle-arrow{background:transparent url( '../images/toggle-arrow.png' ) top left no-repeat;height:23px;line-height:23px}#wp-link .toggle-arrow-active{background-position:center left}#wp-link label input[type=text]{width:360px;margin-top:5px}#wp-link #link-options label span,#wp-link #search-panel label span.search-label{display:inline-block;width:80px;text-align:right;padding-right:5px}#wp-link .link-search-field{float:left;width:220px}#wp-link .link-search-wrapper{margin:5px 6px 9px;display:block;overflow:hidden}#wp-link .link-search-wrapper span{float:left;margin-top:4px}#wp-link .link-search-wrapper .spinner{display:none;vertical-align:text-bottom}#wp-link .link-target{width:auto;padding:3px 0 0;margin:0 0 0 87px;font-size:11px}#wp-link .query-results{border:1px #dfdfdf solid;margin:0 5px 5px;background:#fff;height:185px;overflow:auto;position:relative}#wp-link li,#wp-link .query-notice{clear:both;margin-bottom:0;border-bottom:1px solid #f1f1f1;color:#333;padding:4px 6px;cursor:pointer;position:relative}#wp-link li:hover{background:#eaf2fa;color:#151515}#wp-link li.unselectable{border-bottom:1px solid #dfdfdf}#wp-link li.unselectable:hover{background:#fff;cursor:auto;color:#333}#wp-link li.selected{background:#ddd;color:#333}#wp-link li.selected .item-title{font-weight:700}#wp-link .item-title{display:inline-block;width:80%}#wp-link .item-info{text-transform:uppercase;color:#666;font-size:11px;position:absolute;right:5px;top:4px;bottom:0}#wp-link #search-results{display:none}#wp-link #search-panel{float:left;width:100%}#wp-link .river-waiting{display:none;padding:10px 0}#wp-link .river-waiting .spinner{margin:0 auto;display:block}#wp-link .submitbox{padding:5px 10px;font-size:11px;overflow:auto;height:29px}#wp-link-cancel{line-height:25px;float:left}#wp-link-update{line-height:23px;float:right}/*! + * jQuery UI CSS Framework 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}/*! + * jQuery UI Resizable 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}/*! + * jQuery UI Dialog 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:0 0;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.wp-dialog{padding:0;z-index:300002;border:1px solid #999;-webkit-box-shadow:0 0 16px rgba(0,0,0,.3);box-shadow:0 0 16px rgba(0,0,0,.3);background-color:#f5f5f5;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px}.wp-dialog .ui-dialog-title{display:block;text-align:center;padding:1px 0 2px}.wp-dialog .ui-dialog-titlebar{padding:0 1em;background-color:#444;font-weight:700;font-size:11px;line-height:18px;color:#e5e5e5;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.wp-dialog .ui-dialog-content{padding:0}.wp-dialog .ui-dialog-titlebar-close{cursor:pointer;-webkit-appearance:none;border:0;width:29px;height:16px;top:13px;right:6px;background:url(../js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif) no-repeat -87px -16px}.wp-dialog .ui-dialog-titlebar-close .ui-button-text{display:none}.wp-dialog .ui-dialog-titlebar-close:hover,.wp-dialog .ui-dialog-titlebar-close:focus{background-position:-87px -32px}.ui-widget-overlay{z-index:300001;background-color:#000;opacity:.6;filter:alpha(opacity=60)}.rtl .wp-dialog .ui-dialog-titlebar-close{right:auto;left:6px}.rtl #wp-link #internal-toggle{padding-right:18px;padding-left:0}.rtl #wp-link #link-options label span,.rtl #wp-link #search-panel label span.search-label{text-align:left;padding-right:0;padding-left:5px}.rtl #wp-link #link-options label #url-field{direction:ltr}.rtl #wp-link .link-search-field,.rtl #wp-link .link-search-wrapper span{float:right}.rtl #wp-link .link-target{margin-right:87px;margin-left:0}.rtl #wp-link .item-info{left:5px;right:auto;top:4px;bottom:0}.rtl #wp-link #search-panel{float:right}.rtl #wp-link-cancel{float:right}.rtl #wp-link-update{float:left}.rtl #wp-link .toggle-arrow{background-position:top right}.rtl #wp-link .toggle-arrow-active{background-position:center right}.rtl .wp_themeSkin .mceListBox .mceText{text-align:right}.rtl .wp_themeSkin .mceNoIcons a .mceText{padding-right:10px;padding-left:25px}.rtl .mceListBoxMenu.mceNoIcons{direction:rtl}.clearlooks2 .mceFocus .mceTop .mceLeft{background:#444;border-left:1px solid #999;border-top:1px solid #999;-webkit-border-top-left-radius:3px;border-top-left-radius:3px}.clearlooks2 .mceFocus .mceTop .mceRight{background:#444;border-right:1px solid #999;border-top:1px solid #999;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.clearlooks2 .mceMiddle .mceLeft{background:#f1f1f1;border-left:1px solid #999}.clearlooks2 .mceMiddle .mceRight{background:#f1f1f1;border-right:1px solid #999}.clearlooks2 .mceBottom{background:#f1f1f1;border-bottom:1px solid #999}.clearlooks2 .mceBottom .mceLeft{background:#f1f1f1;border-bottom:1px solid #999;border-left:1px solid #999}.clearlooks2 .mceBottom .mceCenter{background:#f1f1f1;border-bottom:1px solid #999}.clearlooks2 .mceBottom .mceRight{background:#f1f1f1;border-bottom:1px solid #999;border-right:1px solid #999}.clearlooks2 .mceFocus .mceTop span{color:#e5e5e5}.fullscreen-overlay{z-index:149999;display:none;position:fixed;top:0;bottom:0;left:0;right:0;filter:inherit}.fullscreen-active .fullscreen-overlay,.fullscreen-active #wp-fullscreen-body{display:block}.fullscreen-fader{z-index:200000}.fullscreen-active .fullscreen-fader{display:none}#wp-fullscreen-body{width:100%;z-index:150005;display:none;position:absolute;top:0;left:0;font-size:12px}#wp-fullscreen-wrap{margin:0 auto 50px;position:relative;padding-top:60px}#wp-fullscreen-title{font-size:1.7em;line-height:100%;outline:medium none;padding:6px 7px;width:100%;margin-bottom:30px;-webkit-box-shadow:none;box-shadow:none}#wp-fullscreen-container{padding:4px 10px 50px}#wp-fullscreen-title,#wp-fullscreen-container{-webkit-border-radius:0;border-radius:0;border:1px dashed transparent;background:transparent;-moz-transition-property:border-color;-moz-transition-duration:.6s;-webkit-transition-property:border-color;-webkit-transition-duration:.6s;-o-transition-property:border-color;-o-transition-duration:.6s;transition-property:border-color;transition-duration:.6s}#wp_mce_fullscreen{width:100%;min-height:300px;border:0;background:transparent;font-family:Consolas,Monaco,monospace;line-height:1.6em;padding:0;overflow-y:hidden;outline:0;resize:none;-webkit-box-shadow:none;box-shadow:none}#wp-fullscreen-tagline{color:#BBB;font-size:18px;float:right;padding-top:5px}#fullscreen-topbar{position:fixed;top:0;left:0;z-index:150050;border-bottom-style:solid;border-bottom-width:1px;min-width:800px;width:100%;height:40px}#wp-fullscreen-toolbar{padding:6px 10px 0;clear:both;max-width:1100px;min-width:820px;margin:0 auto}#wp-fullscreen-mode-bar,#wp-fullscreen-button-bar,#wp-fullscreen-close,#wp-fullscreen-count{float:left}#wp-fullscreen-save{float:right;padding:2px 2px 0 5px}#wp-fullscreen-count,#wp-fullscreen-close{padding-top:5px}#wp-fullscreen-central-toolbar{margin:auto;padding:0}#wp-fullscreen-buttons>div{float:left}#wp-fullscreen-mode-bar{padding:1px 14px 0 0}#wp-fullscreen-modes a{display:block;font-size:11px;text-decoration:none;float:left;margin:1px 0 0;padding:2px 6px;border-width:1px 1px 1px 0;border-style:solid;border-color:#bbb;color:#777;text-shadow:0 1px 0 #fff;background-color:#f4f4f4;background:#f4f4f4;background-image:-webkit-gradient(linear,left bottom,left top,from(#e4e4e4),to(#f9f9f9));background-image:-webkit-linear-gradient(bottom,#e4e4e4,#f9f9f9);background-image:-moz-linear-gradient(bottom,#e4e4e4,#f9f9f9);background-image:-o-linear-gradient(bottom,#e4e4e4,#f9f9f9);background-image:linear-gradient(to top,#e4e4e4,#f9f9f9)}#wp-fullscreen-modes a:hover,.wp-html-mode #wp-fullscreen-modes a:last-child,.wp-tmce-mode #wp-fullscreen-modes a:first-child{color:#333;border-color:#999;background:#eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#e4e4e4),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#e4e4e4,#f9f9f9);background-image:-moz-linear-gradient(top,#e4e4e4,#f9f9f9);background-image:-o-linear-gradient(top,#e4e4e4,#f9f9f9);background-image:linear-gradient(to bottom,#e4e4e4,#f9f9f9)}#wp-fullscreen-modes a:first-child{border-width:1px;-webkit-border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-top-left-radius:3px;border-bottom-left-radius:3px}#wp-fullscreen-modes a:last-child{-webkit-border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px}#wp-fullscreen-buttons .active a{background:inherit}#wp-fullscreen-buttons .hidden{display:none}#wp-fullscreen-buttons .disabled{opacity:.5}.wp-html-mode #wp-fullscreen-buttons div{display:none}.wp-html-mode #wp-fullscreen-buttons div.wp-fullscreen-both{display:block}#fullscreen-topbar.fullscreen-make-sticky{display:block!important}#wp-fullscreen-save img{vertical-align:middle}#wp-fullscreen-save img,#wp-fullscreen-save span{padding-right:4px;display:none}#wp-fullscreen-buttons #wp_fs_image span.mce_image{background-image:url(../../wp-admin/images/media-button.png);background-position:2px 2px}.fullscreen-active #TB_overlay{z-index:150100}.fullscreen-active #TB_window{z-index:150102}#wp_mce_fullscreen_ifr{background:transparent}#wp_mce_fullscreen_parent #wp_mce_fullscreen_tbl tr.mceFirst{display:none}#wp-fullscreen-container .wp_themeSkin table td{vertical-align:top}.fullscreen-overlay{background:#fff}.wp-fullscreen-focus #wp-fullscreen-title,.wp-fullscreen-focus #wp-fullscreen-container{border-color:#ccc}#fullscreen-topbar{border-bottom-color:#DFDFDF;background:#f1f1f1;background-image:-webkit-gradient(linear,left bottom,left top,from(#ececec),to(#f9f9f9));background-image:-webkit-linear-gradient(bottom,#ececec,#f9f9f9);background-image:-moz-linear-gradient(bottom,#ececec,#f9f9f9);background-image:-o-linear-gradient(bottom,#ececec,#f9f9f9);background-image:linear-gradient(to top,#ececec,#f9f9f9)}#mce_fullscreen_container{background:#fff;z-index:110000!important}.fade-1000,.fade-600,.fade-400,.fade-300{opacity:0;-moz-transition-property:opacity;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.fade-1000{-moz-transition-duration:1s;-webkit-transition-duration:1s;-o-transition-duration:1s;transition-duration:1s}.fade-600{-moz-transition-duration:.6s;-webkit-transition-duration:.6s;-o-transition-duration:.6s;transition-duration:.6s}.fade-400{-moz-transition-duration:.4s;-webkit-transition-duration:.4s;-o-transition-duration:.4s;transition-duration:.4s}.fade-300{-moz-transition-duration:.3s;-webkit-transition-duration:.3s;-o-transition-duration:.3s;transition-duration:.3s}.fade-trigger{opacity:1}.rtl #wp-fullscreen-tagline{float:left}.rtl #fullscreen-topbar{left:auto;right:0}.rtl #wp-fullscreen-mode-bar,.rtl #wp-fullscreen-button-bar,.rtl #wp-fullscreen-close,.rtl #wp-fullscreen-count{float:right}.rtl #wp-fullscreen-save{float:left}.rtl #wp-fullscreen-save{padding:2px 5px 0 2px}.rtl #wp-fullscreen-buttons>div{float:right}.rtl #wp-fullscreen-mode-bar{padding:1px 0 0 14px}.rtl #wp-fullscreen-modes a{float:right;border-width:1px 0 1px 1px}.rtl #wp-fullscreen-modes a:first-child{-webkit-border-top-left-radius:0;-webkit-border-top-right-radius:3px;-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-radius:3px;border-width:1px;border-top-left-radius:0;border-top-right-radius:3px;border-bottom-left-radius:0;border-bottom-right-radius:3px}.rtl #wp-fullscreen-modes a:last-child{-webkit-border-top-right-radius:0;-webkit-border-top-left-radius:3px;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;border-top-right-radius:0;border-top-left-radius:3px;border-bottom-right-radius:0;border-bottom-left-radius:3px}.rtl #wp-fullscreen-save img,.rtl #wp-fullscreen-save span{padding-right:0;padding-left:4px}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.wp_themeSkin span.mce_undo,.wp_themeSkin span.mce_redo,.wp_themeSkin span.mce_bullist,.wp_themeSkin span.mce_numlist,.wp_themeSkin span.mce_blockquote,.wp_themeSkin span.mce_charmap,.wp_themeSkin span.mce_bold,.wp_themeSkin span.mce_italic,.wp_themeSkin span.mce_underline,.wp_themeSkin span.mce_justifyleft,.wp_themeSkin span.mce_justifyright,.wp_themeSkin span.mce_justifycenter,.wp_themeSkin span.mce_justifyfull,.wp_themeSkin span.mce_indent,.wp_themeSkin span.mce_outdent,.wp_themeSkin span.mce_link,.wp_themeSkin span.mce_unlink,.wp_themeSkin span.mce_help,.wp_themeSkin span.mce_removeformat,.wp_themeSkin span.mce_fullscreen,.wp_themeSkin span.mce_wp_fullscreen,.wp_themeSkin span.mce_media,.wp_themeSkin span.mce_pastetext,.wp_themeSkin span.mce_pasteword,.wp_themeSkin span.mce_wp_help,.wp_themeSkin span.mce_wp_adv,.wp_themeSkin span.mce_wp_more,.wp_themeSkin span.mce_strikethrough,.wp_themeSkin span.mce_spellchecker,.wp_themeSkin span.mce_forecolor,.wp_themeSkin .mce_forecolorpicker,.wp_themeSkin .mceSplitButton .mce_spellchecker span.mce_spellchecker,.wp_themeSkin .mceSplitButton .mce_forecolor span.mce_forecolor,.wp_themeSkin .mceSplitButton span.mce_numlist,.wp_themeSkin .mceSplitButton span.mce_bullist{background-image:url(../images/wpicons-2x.png?ver=20120720);background-size:560px 40px}.wp-media-buttons .add_media span.wp-media-buttons-icon,#wp-fullscreen-buttons #wp_fs_image span.mce_image{background-image:url(../../wp-admin/images/media-button-2x.png);background-size:16px 16px}.wp_themeSkin .mceListBox .mceOpen,.wp_themeSkin .mceListBoxHover .mceOpen,.wp_themeSkin .mceListBoxSelected .mceOpen,.wp_themeSkin table.mceListBoxEnabled .mceOpen{background-image:url(../images/down_arrow-2x.gif);background-size:10px 20px}.wp_themeSkin .mceSplitButtonEnabled a.mceOpen,.wp_themeSkin .mceSplitButtonSelected a.mceOpen,.wp_themeSkin .mceSplitButtonActive a.mceOpen,.wp_themeSkin .mceSplitButtonEnabled:hover a.mceOpen{background-image:url(../images/down_arrow-2x.gif);background-size:10px 20px}#wp-link .toggle-arrow{background:transparent url(../images/toggle-arrow-2x.png) top left no-repeat;background-size:19px 69px}} \ No newline at end of file diff --git a/sources/wp-includes/css/jquery-ui-dialog.css b/sources/wp-includes/css/jquery-ui-dialog.css new file mode 100644 index 0000000..9c75fbd --- /dev/null +++ b/sources/wp-includes/css/jquery-ui-dialog.css @@ -0,0 +1,307 @@ +/*! + * jQuery UI CSS Framework 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + + +/*! + * jQuery UI Resizable 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} + +/*! + * jQuery UI Dialog 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 21px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} + +/* WP jQuery Dialog Theme */ +.wp-dialog { + padding: 0; + z-index: 300002; + border: 1px solid #999; + -webkit-box-shadow: 0px 0px 16px rgba( 0,0,0,0.3 ); + box-shadow: 0px 0px 16px rgba( 0,0,0,0.3 ); + background-color: #f5f5f5; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; +} + +.wp-dialog .ui-dialog-title { + display: block; + text-align: center; + padding: 1px 0 2px; +} + +.wp-dialog .ui-dialog-titlebar { + padding: 0 1em; + background-color: #444; + font-weight: bold; + font-size: 11px; + line-height: 18px; + color: #e5e5e5; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; +} + +.wp-dialog .ui-dialog-content { + padding: 0; +} + +.wp-dialog .ui-dialog-titlebar-close { + cursor: pointer; + -webkit-appearance: none; + border: 0; + width: 29px; + height: 16px; + top: 13px; + right: 6px; + background: url('../js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif') no-repeat -87px -16px; +} + +.wp-dialog .ui-dialog-titlebar-close .ui-button-text { + display: none; +} + +.wp-dialog .ui-dialog-titlebar-close:hover, +.wp-dialog .ui-dialog-titlebar-close:focus { + background-position: -87px -32px; +} + +.ui-widget-overlay { + z-index: 300001; + background-color: #000; + opacity: 0.6; + filter: alpha(opacity=60); +} diff --git a/sources/wp-includes/css/jquery-ui-dialog.min.css b/sources/wp-includes/css/jquery-ui-dialog.min.css new file mode 100644 index 0000000..78c6f31 --- /dev/null +++ b/sources/wp-includes/css/jquery-ui-dialog.min.css @@ -0,0 +1,28 @@ +/*! + * jQuery UI CSS Framework 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}/*! + * jQuery UI Resizable 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}/*! + * jQuery UI Dialog 1.10.1 + * http://jqueryui.com + * + * Copyright 2013 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:0 0;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.wp-dialog{padding:0;z-index:300002;border:1px solid #999;-webkit-box-shadow:0 0 16px rgba(0,0,0,.3);box-shadow:0 0 16px rgba(0,0,0,.3);background-color:#f5f5f5;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px}.wp-dialog .ui-dialog-title{display:block;text-align:center;padding:1px 0 2px}.wp-dialog .ui-dialog-titlebar{padding:0 1em;background-color:#444;font-weight:700;font-size:11px;line-height:18px;color:#e5e5e5;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.wp-dialog .ui-dialog-content{padding:0}.wp-dialog .ui-dialog-titlebar-close{cursor:pointer;-webkit-appearance:none;border:0;width:29px;height:16px;top:13px;right:6px;background:url(../js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif) no-repeat -87px -16px}.wp-dialog .ui-dialog-titlebar-close .ui-button-text{display:none}.wp-dialog .ui-dialog-titlebar-close:hover,.wp-dialog .ui-dialog-titlebar-close:focus{background-position:-87px -32px}.ui-widget-overlay{z-index:300001;background-color:#000;opacity:.6;filter:alpha(opacity=60)} \ No newline at end of file diff --git a/sources/wp-includes/css/media-views-rtl.css b/sources/wp-includes/css/media-views-rtl.css new file mode 100644 index 0000000..f260bb2 --- /dev/null +++ b/sources/wp-includes/css/media-views-rtl.css @@ -0,0 +1,312 @@ +/** + * Modal + */ +.media-modal-close { + right: auto; + left: 7px; +} + +/** + * Toolbar + */ +.media-toolbar-primary { + float: left; +} + +.media-toolbar-secondary { + float: right; +} + +.media-toolbar-primary > .media-button, +.media-toolbar-primary > .media-button-group { + margin-left: 0; + margin-right: 10px; + float: right; +} + +.media-toolbar-secondary > .media-button, +.media-toolbar-secondary > .media-button-group { + margin-right: 0; + margin-left: 10px; + float: right; +} + +/** + * Sidebar + */ +.media-sidebar { + right: auto; + left: 0; + border-left: 0; + border-right: 1px solid #dfdfdf; +} + +.media-sidebar .setting { + float: right; +} + +.media-sidebar .setting .link-to-custom { + direction: ltr; +} + +.media-sidebar .setting span { + margin-right: 0; + margin-left: 4%; +} + +.media-sidebar .setting span, +.compat-item label span { + float: right; + text-align: left; +} + +.media-sidebar .setting input, +.media-sidebar .setting textarea { + float: left; +} + +.compat-item { + float: right; +} + +.compat-item .label { + margin-right: 0; + margin-left: 4%; + float: right; + text-align: left; +} + +.compat-item .field { + float: left; + padding-right: 0; + padding-left: 1px; +} + +/** + * Menu + */ +.media-menu { + border-right: 0; + border-left: 1px solid #d9d9d9; + box-shadow: inset 6px 0 6px -6px rgba( 0, 0, 0, 0.2 ) +} + +/** + * Router + */ +.media-router > a { + float: right; + border-right: 0; + border-left: 1px solid #dfdfdf; +} +.media-router > a:last-child { + border-left: 0; +} + +/** + * Frame + */ +.media-frame-menu { + left: auto; + right: 0; +} + +.media-frame-title, +.media-frame-router, +.media-frame-content, +.media-frame-toolbar { + left: 0; + right: 200px; +} + +.media-frame.hide-menu .media-frame-title, +.media-frame.hide-menu .media-frame-router, +.media-frame.hide-menu .media-frame-toolbar, +.media-frame.hide-menu .media-frame-content { + right: 0; +} + +.media-frame.hide-menu .media-frame-menu { + left: auto; + right: -200px; +} + +/** + * Attachment Browser Filters + */ +.media-frame select.attachment-filters { + margin-right: 0; + margin-left: 10px; +} + +/** + * Search + */ +.media-toolbar-secondary .search { + margin-right: 0; + margin-left: 16px; +} + +/** + * Attachments + */ +.attachments { + padding-right: 0; + padding-left: 16px; +} + +/** + * Attachment + */ +.attachment { + float: right; +} + +.attachment .thumbnail { + left: auto; + right: 0; +} + +.attachment .close { + right: auto; + left: 5px; +} + +.attachment .check { + right: auto; + left: -7px; +} + +/** + * Attachments Browser + */ +.attachments-browser .media-toolbar { + right: 0; + left: 300px; +} + +.attachments-browser .attachments, +.attachments-browser .uploader-inline { + right: 0; + left: 300px; +} + + +/** + * Progress Bar + */ +.attachment-preview .media-progress-bar { + left: auto; + right: 15%; +} + +.media-sidebar .media-uploader-status .upload-dismiss-errors { + right: auto; + left: 0; +} + +.upload-errors .upload-error-label { + margin-right: 0; + margin-left: 8px; + float: right; + margin-top: -3px; +} + +/** + * Selection + */ +.media-selection { + right: 0; + left: 350px; + padding: 0 16px 0 0; +} + +.media-selection .selection-info { + margin-right: 0; + margin-left: 10px; +} + +.media-selection .selection-info a { + float: right; + border-right: 0; + border-left: 1px solid #dfdfdf; + margin: 1px -8px 1px 8px; +} + +.media-selection .selection-info a:last-child { + border-right: 1px; + border-left: 0; + margin-left: 0; + margin-right: -8px; +} + +.media-selection:after { + right: auto; + left: 0; + background-image: -webkit-gradient(linear, left top, right top, from( rgba( 255, 255, 255, 1 ) ), to( rgba( 255, 255, 255, 0 ) )); + background-image: -webkit-linear-gradient(left, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); + background-image: -moz-linear-gradient(left, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); + background-image: -o-linear-gradient(left, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); + background-image: linear-gradient(to right, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); +} + +/** + * Attachment Details + */ +.attachment-info .thumbnail { + float: right; + margin-right: 0; + margin-left: 10px; +} + +.attachment-info .details { + float: right; +} + +/** + * Attachment Display Settings + */ +.attachment-display-settings { + float: right; +} + +/** + * Embed from URL + */ +.embed-url span { + display: block; + padding: 4px 2px 6px 0; +} + +.media-embed .thumbnail { + float: right; +} + +.media-embed .setting { + float: right; +} + +.media-frame .embed-url input, +.media-frame .link-to-custom { + direction: ltr; +} + +/** + * Responsive layout + */ +@media only screen and (max-width: 900px) { + .media-frame-title, + .media-frame-router, + .media-frame-content, + .media-frame-toolbar { + left: 0; + right: 140px; + } + + .attachments-browser .attachments, + .attachments-browser .uploader-inline, + .attachments-browser .media-toolbar { + right: 0; + left: 180px; + } +} diff --git a/sources/wp-includes/css/media-views-rtl.min.css b/sources/wp-includes/css/media-views-rtl.min.css new file mode 100644 index 0000000..c7b75bb --- /dev/null +++ b/sources/wp-includes/css/media-views-rtl.min.css @@ -0,0 +1 @@ +.media-modal-close{right:auto;left:7px}.media-toolbar-primary{float:left}.media-toolbar-secondary{float:right}.media-toolbar-primary>.media-button,.media-toolbar-primary>.media-button-group{margin-left:0;margin-right:10px;float:right}.media-toolbar-secondary>.media-button,.media-toolbar-secondary>.media-button-group{margin-right:0;margin-left:10px;float:right}.media-sidebar{right:auto;left:0;border-left:0;border-right:1px solid #dfdfdf}.media-sidebar .setting{float:right}.media-sidebar .setting .link-to-custom{direction:ltr}.media-sidebar .setting span{margin-right:0;margin-left:4%}.media-sidebar .setting span,.compat-item label span{float:right;text-align:left}.media-sidebar .setting input,.media-sidebar .setting textarea{float:left}.compat-item{float:right}.compat-item .label{margin-right:0;margin-left:4%;float:right;text-align:left}.compat-item .field{float:left;padding-right:0;padding-left:1px}.media-menu{border-right:0;border-left:1px solid #d9d9d9;box-shadow:inset 6px 0 6px -6px rgba(0,0,0,.2)}.media-router>a{float:right;border-right:0;border-left:1px solid #dfdfdf}.media-router>a:last-child{border-left:0}.media-frame-menu{left:auto;right:0}.media-frame-title,.media-frame-router,.media-frame-content,.media-frame-toolbar{left:0;right:200px}.media-frame.hide-menu .media-frame-title,.media-frame.hide-menu .media-frame-router,.media-frame.hide-menu .media-frame-toolbar,.media-frame.hide-menu .media-frame-content{right:0}.media-frame.hide-menu .media-frame-menu{left:auto;right:-200px}.media-frame select.attachment-filters{margin-right:0;margin-left:10px}.media-toolbar-secondary .search{margin-right:0;margin-left:16px}.attachments{padding-right:0;padding-left:16px}.attachment{float:right}.attachment .thumbnail{left:auto;right:0}.attachment .close{right:auto;left:5px}.attachment .check{right:auto;left:-7px}.attachments-browser .media-toolbar{right:0;left:300px}.attachments-browser .attachments,.attachments-browser .uploader-inline{right:0;left:300px}.attachment-preview .media-progress-bar{left:auto;right:15%}.media-sidebar .media-uploader-status .upload-dismiss-errors{right:auto;left:0}.upload-errors .upload-error-label{margin-right:0;margin-left:8px;float:right;margin-top:-3px}.media-selection{right:0;left:350px;padding:0 16px 0 0}.media-selection .selection-info{margin-right:0;margin-left:10px}.media-selection .selection-info a{float:right;border-right:0;border-left:1px solid #dfdfdf;margin:1px -8px 1px 8px}.media-selection .selection-info a:last-child{border-right:1px;border-left:0;margin-left:0;margin-right:-8px}.media-selection:after{right:auto;left:0;background-image:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,1)),to(rgba(255,255,255,0)));background-image:-webkit-linear-gradient(left,rgba(255,255,255,1),rgba(255,255,255,0));background-image:-moz-linear-gradient(left,rgba(255,255,255,1),rgba(255,255,255,0));background-image:-o-linear-gradient(left,rgba(255,255,255,1),rgba(255,255,255,0));background-image:linear-gradient(to right,rgba(255,255,255,1),rgba(255,255,255,0))}.attachment-info .thumbnail{float:right;margin-right:0;margin-left:10px}.attachment-info .details{float:right}.attachment-display-settings{float:right}.embed-url span{display:block;padding:4px 2px 6px 0}.media-embed .thumbnail{float:right}.media-embed .setting{float:right}.media-frame .embed-url input,.media-frame .link-to-custom{direction:ltr}@media only screen and (max-width:900px){.media-frame-title,.media-frame-router,.media-frame-content,.media-frame-toolbar{left:0;right:140px}.attachments-browser .attachments,.attachments-browser .uploader-inline,.attachments-browser .media-toolbar{right:0;left:180px}} \ No newline at end of file diff --git a/sources/wp-includes/css/media-views.css b/sources/wp-includes/css/media-views.css new file mode 100644 index 0000000..4306156 --- /dev/null +++ b/sources/wp-includes/css/media-views.css @@ -0,0 +1,1673 @@ +/** + * Base Styles + */ +.media-modal, +.media-frame { + font-family: sans-serif; + font-size: 12px; +} + +.media-frame input, +.media-frame textarea { + padding: 6px 8px; + line-height: 16px; +} + +.media-frame select, +.wp-admin .media-frame select { + line-height: 28px; + margin-top: 3px; +} + +.media-frame a { + border-bottom: none; + color: #21759b; +} + +.media-frame a:hover { + color: #d54e21; +} + +.media-frame a.button { + color: #333; +} + +.media-frame a.button:hover { + color: #222; +} + +.media-frame a.button-primary, +.media-frame a.button-primary:hover { + color: #fff; +} + +.media-frame input[type="text"], +.media-frame input[type="password"], +.media-frame input[type="number"], +.media-frame input[type="search"], +.media-frame input[type="email"], +.media-frame input[type="url"], +.media-frame textarea, +.media-frame select { + font-family: sans-serif; + font-size: 12px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; /* ie8 only */ + box-sizing: border-box; + -webkit-border-radius: 3px; + border-radius: 3px; + border-width: 1px; + border-style: solid; + border-color: #dfdfdf; +} + +.media-frame select { + height: 24px; + padding: 2px; +} + +.media-frame input:disabled, +.media-frame textarea:disabled, +.media-frame input[readonly], +.media-frame textarea[readonly] { + background-color: #eee; +} + +.media-frame input[type="search"] { + -webkit-appearance: textfield; +} + +.media-frame :-moz-placeholder { + color: #a9a9a9; +} + +/* Enable draggable on IE10 touch events until it's rolled into jQuery UI core */ +.ui-sortable, +.ui-draggable { + -ms-touch-action: none; +} + +/** + * Modal + */ +.media-modal { + position: fixed; + top: 30px; + left: 30px; + right: 30px; + bottom: 30px; + z-index: 160000; +} + +.media-modal-backdrop { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + min-height: 360px; + background: #000; + opacity: 0.7; + z-index: 159900; +} + +.media-modal-close { + position: absolute; + top: 7px; + right: 7px; + width: 30px; + height: 30px; + z-index: 1000; +} +.media-modal-close span { + display: block; + margin: 8px auto 0; + width: 15px; + height: 15px; + background-position: -100px 0; +} + +.media-modal-close:active { + outline: 0; +} + +.media-modal-content { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: auto; + min-height: 300px; + background: #fff; +} + +.media-modal-icon { + background-image: url(../images/uploader-icons.png); + background-repeat: no-repeat; +} + +/** + * Toolbar + */ +.media-toolbar { + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 100; + height: 60px; + padding: 0 16px; + border: 0 solid #dfdfdf; + overflow: hidden; +} + +.media-toolbar-primary { + float: right; + height: 100%; +} + +.media-toolbar-secondary { + float: left; + height: 100%; +} + +.media-toolbar-primary > .media-button, +.media-toolbar-primary > .media-button-group { + margin-left: 10px; + float: left; + margin-top: 15px; +} + +.media-toolbar-secondary > .media-button, +.media-toolbar-secondary > .media-button-group { + margin-right: 10px; + float: left; + margin-top: 15px; +} + +/** + * Sidebar + */ +.media-sidebar { + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 267px; + padding: 0 16px 24px; + z-index: 75; + background: #f5f5f5; + border-left: 1px solid #dfdfdf; + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +.hide-toolbar .media-sidebar { + bottom: 0; +} + +.media-sidebar .sidebar-title { + font-weight: 200; + font-size: 20px; + margin: 0; + padding: 12px 10px 10px; + line-height: 28px; +} + +.media-sidebar .sidebar-content { + padding: 0 10px; + margin-bottom: 130px; +} + +.media-sidebar .search { + display: block; + width: 100%; +} + +.media-sidebar h3 { + position: relative; + font-weight: bold; + text-transform: uppercase; + font-size: 12px; + color: #777; + text-shadow: 0 1px 0 #fff; + margin: 24px 0 8px; +} + +.media-sidebar .setting { + display: block; + float: left; + width: 100%; + margin: 1px 0; +} + +.media-sidebar .setting label { + display: block; +} + +.media-sidebar .setting .link-to-custom { + margin: 3px 0; +} + +.media-sidebar .setting span { + min-width: 30%; + margin-right: 4%; + font-size: 12px; +} + +.media-sidebar .setting select { + max-width: 65%; +} + +.media-sidebar .setting input[type="checkbox"] { + width: auto; + float: none; + margin-top: 8px; + padding: 0; +} + +.media-sidebar .setting span, +.compat-item label span { + float: left; + min-height: 22px; + padding-top: 8px; + line-height: 16px; + text-align: right; + font-weight: normal; + color: #999; + text-shadow: 0 1px 0 #fff; +} + +.media-sidebar .setting input, +.media-sidebar .setting textarea { + width: 65%; + float: right; +} + +.media-sidebar .setting textarea, +.compat-item .field textarea { + height: 62px; + resize: vertical; +} + +.media-sidebar select { + margin-top: 3px; +} + +.compat-item { + float: left; + width: 100%; + overflow: hidden; +} + +.compat-item table { + width: 100%; + table-layout: fixed; + border-spacing: 0; + border: 0; +} + +.compat-item tr { + padding: 2px 0; + display: block; + overflow: hidden; +} + +.compat-item .label, +.compat-item .field { + display: block; + margin: 0; + padding: 0; +} + +.compat-item .label { + min-width: 30%; + margin-right: 4%; + float: left; + text-align: right; +} + +.compat-item .label span { + display: block; + width: 100%; +} + +.compat-item .field { + float: right; + width: 65%; + padding-right: 1px; +} + +.compat-item .field input { + width: 100%; + margin: 0; +} + + +/** + * Menu + */ +.media-menu { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: 0; + padding: 16px 0; + border-right: 1px solid #d9d9d9; + box-shadow: inset -6px 0 6px -6px rgba( 0, 0, 0, 0.2 ); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.media-menu > a { + display: block; + position: relative; + padding: 4px 20px; + margin: 0; + line-height: 18px; + font-size: 14px; + color: #21759B; + text-shadow: 0 1px 0 #fff; + text-decoration: none; +} + +.media-menu > a:hover { + color: #21759B; + background: rgba( 0, 0, 0, 0.04 ); +} + +.media-menu > a:active { + outline: none; +} + +.media-menu .active, +.media-menu .active:hover { + color: #333; + font-weight: bold; +} + +.media-menu .separator { + height: 0; + margin: 12px 20px; + padding: 0; + border-top: 1px solid #dfdfdf; + border-bottom: 1px solid #fff; +} + +/** + * Menu + */ +.media-router { + position: relative; + padding: 0 6px; + margin: 0; + clear: both; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.media-router > a { + position: relative; + float: left; + padding: 2px 10px; + margin: 0; + height: 18px; + line-height: 18px; + font-size: 14px; + border-right: 1px solid #dfdfdf; + text-shadow: 0 1px 0 #fff; + text-decoration: none; +} + +.media-router > a:last-child { + border-right: 0; +} + +.media-router > a:active, +.media-router > a:focus { + outline: none; +} + +.media-router .active, +.media-router .active:hover { + color: #333; +} + +.media-router .active:after { + content: ''; + display: block; + margin: -100px auto 0; + width: 7px; + height: 7px; + background: #fff; + box-shadow: 1px 1px 1px rgba( 0, 0, 0, 0.2 ); + z-index: 300; + + -webkit-transform: rotate( 45deg ) translate( 75px, 75px ); + -moz-transform: rotate( 45deg ) translate( 75px, 75px ); + -ms-transform: rotate( 45deg ) translate( 75px, 75px ); + -o-transform: rotate( 45deg ) translate( 75px, 75px ); + transform: rotate( 45deg ) translate( 75px, 75px ); +} + +/** + * Frame + */ +.media-frame { + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.media-frame-menu { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 199px; + z-index: 150; +} + +.media-frame-title { + position: absolute; + top: 0; + left: 200px; + right: 0; + height: 45px; + z-index: 200; +} + +.media-frame-router { + position: absolute; + top: 45px; + left: 200px; + right: 0; + height: 30px; + z-index: 200; + border-bottom: 1px solid #dfdfdf; + box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); +} + +.media-frame-content { + position: absolute; + top: 75px; + left: 200px; + right: 0; + bottom: 61px; + height: auto; + width: auto; + margin: 0; + overflow: auto; +} + +.media-frame-toolbar { + position: absolute; + left: 200px; + right: 0; + bottom: 0; + height: 60px; + z-index: 100; + border: 0 solid #dfdfdf; + border-width: 1px 0 0 0; + box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.1 ); +} + +.media-frame.hide-menu .media-frame-title, +.media-frame.hide-menu .media-frame-router, +.media-frame.hide-menu .media-frame-toolbar, +.media-frame.hide-menu .media-frame-content { + left: 0; +} + +.media-frame.hide-menu .media-frame-menu { + left: -200px; +} + +.media-frame.hide-toolbar .media-frame-content { + bottom: 0; +} + +.media-frame.hide-toolbar .media-frame-toolbar { + bottom: -61px; +} + +.media-frame.hide-router .media-frame-content { + top: 45px; +} + +.media-frame.hide-router .media-frame-router { + display: none; +} + +.media-frame.hide-router .media-frame-title { + border-bottom: 1px solid #dfdfdf; + box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); +} + +.media-frame .media-toolbar .add-to-gallery { + display: none; +} + +.media-frame-title h1 { + padding: 0 16px; + font-size: 22px; + font-weight: 200; + line-height: 45px; + margin: 0; +} + +/** + * Iframes + */ +.media-frame .media-iframe { + overflow: hidden; +} + +.media-frame .media-iframe, +.media-frame .media-iframe iframe { + height: 100%; + width: 100%; + border: 0; +} + +/** + * Attachment Browser Filters + */ +.media-frame select.attachment-filters { + margin-top: 11px; + margin-right: 10px; +} + +/** + * Search + */ +.media-frame .search { + margin-top: 11px; + padding: 4px; + line-height: 18px; + font-size: 13px; + color: #464646; + font-family: sans-serif; + -webkit-appearance: none; +} + +.media-toolbar-secondary .search { + margin-right: 16px; +} + +/** + * Attachments + */ +.attachments { + margin: 0; + padding-right: 16px; + -webkit-overflow-scrolling: touch; +} + +/** + * Attachment + */ +.attachment { + position: relative; + float: left; + + padding: 0; + margin: 0 10px 20px; + color: #464646; + list-style: none; + text-align: center; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.selected.attachment { + box-shadow: + 0 0 0 1px #fff, + 0 0 0 3px #ccc; +} + +.details.attachment { + box-shadow: + 0 0 0 1px #fff, + 0 0 0 5px #1e8cbe; +} + +.attachment-preview { + position: relative; + width: 199px; + height: 199px; + box-shadow: + inset 0 0 15px rgba( 0, 0, 0, 0.1 ), + inset 0 0 0 1px rgba( 0, 0, 0, 0.05 ); + background: #eee; + cursor: pointer; +} + +.attachment .icon { + margin: 0 auto; + overflow: hidden; + padding-top: 20%; +} + +.attachment .thumbnail { + display: block; + position: absolute; + top: 0; + left: 0; + margin: 0 auto; + overflow: hidden; + max-width: 100%; + max-height: 100%; +} + +.attachment-preview .thumbnail:after { + content: ''; + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.1 ); + overflow: hidden; +} + +.attachment .thumbnail img { + top: 0; + left: 0; +} + +.attachment .thumbnail .centered { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + -webkit-transform: translate( 50%, 50% ); + -moz-transform: translate( 50%, 50% ); + -ms-transform: translate( 50%, 50% ); + -o-transform: translate( 50%, 50% ); + transform: translate( 50%, 50% ); +} + +.attachment .thumbnail .centered img { + -webkit-transform: translate( -50%, -50% ); + -moz-transform: translate( -50%, -50% ); + -ms-transform: translate( -50%, -50% ); + -o-transform: translate( -50%, -50% ); + transform: translate( -50%, -50% ); +} + +.attachment .filename { + position: absolute; + left: 0; + right: 0; + bottom: 0; + overflow: hidden; + max-height: 100%; + + word-wrap: break-word; + text-align: center; + font-weight: bold; + background: rgba( 255, 255, 255, 0.8 ); + box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.15 ); +} + +.attachment .filename div { + padding: 5px 10px; +} + +.attachment-preview .thumbnail { + width: 199px; + height: 199px; +} + +.attachment .thumbnail img { + position: absolute; +} + +.attachment .close { + display: none; + position: absolute; + top: 5px; + right: 5px; + height: 22px; + width: 22px; + padding: 0; + font-size: 20px; + line-height: 20px; + text-align: center; + text-decoration: none; + color: #464646; + background-color: #fff; + background-position: -96px 4px; + border-width: 0; + border-radius: 3px; + box-shadow: 0 0 0 1px rgba( 0, 0, 0, 0.3 ); +} + +.attachment .close:hover { + box-shadow: 0 0 0 1px rgba( 0, 0, 0, 0.6 ); +} + +.attachment:hover .close { + display: block; +} + +.attachment .check { + display: none; + height: 24px; + width: 24px; + position: absolute; + top: -7px; + right: -7px; + outline: none; + + border: 1px solid #fff; + border-radius: 3px; + box-shadow: 0 0 0 1px rgba( 0, 0, 0, 0.4 ); + + background: #f1f1f1; + background-image: -webkit-gradient(linear, left top, left bottom, from(#f1f1f1), to(#e1e1e1)); + background-image: -webkit-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image: -moz-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image: -o-linear-gradient(top, #f1f1f1, #e1e1e1); + background-image: linear-gradient(to bottom, #f1f1f1, #e1e1e1); +} + +.attachment .check div { + background-position: -1px 0; + height: 15px; + width: 15px; + margin: 5px; +} + +.attachment .check:hover div { + background-position: -40px 0; +} + +.attachment.selected .check { + display: block; +} + +.attachment.details .check { + box-shadow: 0 0 0 1px #1e8cbe; + + background: #1e8cbe; + background-image: -webkit-gradient(linear, left top, left bottom, from(#1e8cbe), to(#0074a2)); + background-image: -webkit-linear-gradient(top, #1e8cbe, #0074a2); + background-image: -moz-linear-gradient(top, #1e8cbe, #0074a2); + background-image: -o-linear-gradient(top, #1e8cbe, #0074a2); + background-image: linear-gradient(to bottom, #1e8cbe, #0074a2); +} + +.attachment.details .check div { + background-position: -21px 0; +} + +.attachment.details .check:hover div { + background-position: -60px 0; +} + +.media-frame .attachment .describe { + position: relative; + display: block; + width: 100%; + margin: -1px 0 0; + padding: 8px; + font-size: 12px; + border-radius: 0; +} + +/** + * Attachments Browser + */ +.media-frame .attachments-browser { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; +} + +.attachments-browser .media-toolbar { + right: 300px; + height: 50px; +} + +.attachments-browser .media-toolbar-primary > .media-button, +.attachments-browser .media-toolbar-primary > .media-button-group, +.attachments-browser .media-toolbar-secondary > .media-button, +.attachments-browser .media-toolbar-secondary > .media-button-group { + margin-top: 10px; +} + +.attachments-browser .attachments, +.attachments-browser .uploader-inline { + position: absolute; + top: 50px; + left: 0; + right: 300px; + bottom: 0; + overflow: auto; +} + +.attachments-browser .instructions { + display: inline-block; + margin-top: 16px; + line-height: 18px; + font-size: 13px; + color: #999; +} + +/** + * Progress Bar + */ +.media-progress-bar { + position: relative; + height: 10px; + width: 70%; + margin: 10px auto; + border-radius: 10px; + background: #dfdfdf; + background: rgba( 0, 0, 0, 0.1 ); +} + +.media-progress-bar div { + height: 10px; + min-width: 20px; + width: 0; + background: #aaa; + background: rgba( 0, 0, 0, 0.2 ); + border-radius: 10px; + -webkit-transition: width 300ms; + -moz-transition: width 300ms; + -ms-transition: width 300ms; + -o-transition: width 300ms; + transition: width 300ms; +} + +.media-uploader-status .media-progress-bar { + display: none; + width: 100%; +} + +.uploading.media-uploader-status .media-progress-bar { + display: block; +} + +.attachment-preview .media-progress-bar { + position: absolute; + top: 50%; + left: 15%; + width: 70%; + margin: -5px 0 0 0; +} + +.media-uploader-status { + position: relative; + margin: 0 auto; + padding-bottom: 10px; + max-width: 400px; +} + +.media-sidebar .media-uploader-status { + border-bottom: 1px solid #dfdfdf; + box-shadow: 0 1px 0 #fff; +} + +.uploader-inline .media-uploader-status h3 { + display: none; +} + +.media-uploader-status .upload-details { + display: none; + font-size: 12px; + color: #666; + text-shadow: 0 1px 0 #fff; +} + +.uploading.media-uploader-status .upload-details { + display: block; +} + +.media-uploader-status .upload-detail-separator { + padding: 0 4px; +} + +.media-uploader-status .upload-count { + color: #464646; +} + +.media-uploader-status .upload-dismiss-errors, +.media-uploader-status .upload-errors { + display: none; +} + +.errors.media-uploader-status .upload-dismiss-errors, +.errors.media-uploader-status .upload-errors { + display: block; +} + +.media-uploader-status .upload-dismiss-errors { + text-decoration: none; +} + +.media-sidebar .media-uploader-status .upload-dismiss-errors { + position: absolute; + top: 0; + right: 0; +} + +.upload-errors .upload-error { + margin: 8px auto 0 auto; + padding: 8px; + border: 1px #c00 solid; + background: #ffebe8; + border-radius: 3px; +} + +.upload-errors .upload-error-label { + padding: 2px 4px; + margin-right: 8px; + font-weight: bold; + color: #fff; + background: #e00; + background-image: -webkit-gradient(linear, left top, left bottom, from(#e00), to(#a00)); + background-image: -webkit-linear-gradient(top, #e00, #a00); + background-image: -moz-linear-gradient(top, #e00, #a00); + background-image: -o-linear-gradient(top, #e00, #a00); + background-image: linear-gradient(to bottom, #e00, #a00); + border-radius: 3px; +} + +.upload-errors .upload-error-message { + display: block; + padding-top: 8px; + color: #b44; + word-wrap: break-word; +} + +.uploader-window { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba( 0, 86, 132, 0.9 ); + + z-index: 250000; + display: none; + text-align: center; + opacity: 0; + + -webkit-transition: opacity 250ms; + -moz-transition: opacity 250ms; + -ms-transition: opacity 250ms; + -o-transition: opacity 250ms; + transition: opacity 250ms; +} + +.uploader-window-content { + position: absolute; + top: 10px; + left: 10px; + right: 10px; + bottom: 10px; + border: 1px dashed #fff; +} + +.uploader-window h3 { + position: absolute; + top: 50%; + left: 0; + right: 0; + -webkit-transform: translateY( -50% ); + -moz-transform: translateY( -50% ); + -ms-transform: translateY( -50% ); + -o-transform: translateY( -50% ); + transform: translateY( -50% ); + + font-size: 20px; + font-weight: 200; + color: #fff; + padding: 0; +} + +.uploader-window .media-progress-bar { + margin-top: 20px; + max-width: 300px; + background: transparent; + border-color: #fff; + display: none; +} + +.uploader-window .media-progress-bar div { + background: #fff; +} + +.uploading .uploader-window .media-progress-bar { + display: block; +} + +.media-frame .uploader-inline { + margin: 20px; + padding: 20px; + text-align: center; +} + +.uploader-inline-content { + position: absolute; + top: 30%; + left: 0; + right: 0; +} + +.uploader-inline-content .upload-ui { + margin: 4em 0; +} + +.uploader-inline-content .post-upload-ui { + margin-bottom: 2em; +} + +.uploader-inline .has-upload-message .upload-ui { + margin: 0 0 4em; +} + +.uploader-inline h3 { + font-size: 20px; + line-height: 28px; + font-weight: 200; + margin-bottom: 1.6em; +} + +.uploader-inline .has-upload-message .upload-instructions { + font-size: 14px; + color: #464646; + font-weight: normal; +} + +.uploader-inline .drop-instructions { + display: none; +} + +.supports-drag-drop .uploader-inline .drop-instructions { + display: block; +} + +.uploader-inline p { + font-size: 12px; +} + +.uploader-inline .media-progress-bar { + display: none; +} + +.uploading.uploader-inline .media-progress-bar { + display: block; +} + +.uploader-inline .browser { + display: inline-block !important; +} + +/** + * Selection + */ +.media-selection { + position: absolute; + top: 0; + left: 0; + right: 350px; + height: 60px; + padding: 0 0 0 16px; + overflow: hidden; + white-space: nowrap; +} + +.media-selection .selection-info { + display: inline-block; + font-size: 12px; + height: 60px; + margin-right: 10px; + vertical-align: top; +} + +.media-selection.empty, +.media-selection.editing { + display: none; +} + +.media-selection.one .edit-selection { + display: none; +} + +.media-selection .count { + display: block; + padding-top: 12px; + font-size: 14px; + line-height: 20px; + font-weight: bold; +} + +.media-selection .selection-info a { + display: block; + float: left; + padding: 1px 8px; + margin: 1px 8px 1px -8px; + line-height: 16px; + text-decoration: none; + border-right: 1px solid #dfdfdf; + color: #21759B; +} + +.media-selection .selection-info a:hover { + background: #21759B; + color: #fff; + border-color: transparent; +} + +.media-selection .selection-info a:last-child { + border-right: 0; + margin-right: 0; +} + +.media-selection .selection-info .clear-selection { + color: red; +} + +.media-selection .selection-info .clear-selection:hover { + background: red; +} + +.media-selection .selection-view { + display: inline-block; + vertical-align: top; +} + +.media-selection .attachments { + display: inline-block; + height: 48px; + margin-top: 5px; + overflow: hidden; + vertical-align: top; +} + +.media-selection .attachment .icon { + width: 50%; +} + +.attachment.selection.selected { + box-shadow: none; +} + +.attachment.selection.details { + box-shadow: + 0 0 0 1px #fff, + 0 0 0 4px #1e8cbe; +} + +.media-selection .attachment.selection.details { + box-shadow: + 0 0 0 1px #fff, + 0 0 0 3px #1e8cbe; +} + +.media-selection:after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 25px; + background-image: -webkit-gradient(linear, right top, left top, from( rgba( 255, 255, 255, 1 ) ), to( rgba( 255, 255, 255, 0 ) )); + background-image: -webkit-linear-gradient(right, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); + background-image: -moz-linear-gradient(right, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); + background-image: -o-linear-gradient(right, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); + background-image: linear-gradient(to left, rgba( 255, 255, 255, 1 ) , rgba( 255, 255, 255, 0 ) ); +} + +.media-selection .attachment .filename { + display: none; +} + +/** + * Spinner + */ + +.media-frame .spinner { + background: url(../images/wpspin.gif) no-repeat; + background-size: 16px 16px; + display: none; + opacity: 0.7; + filter: alpha(opacity=70); + width: 16px; + height: 16px; + margin: 0; +} + +.media-sidebar .settings-save-status { + background: #f5f5f5; + float: right; + text-transform: none; + z-index: 10; +} + +.media-sidebar .settings-save-status .spinner { + margin: 0 5px 0; +} + +.media-sidebar .settings-save-status .saved { + float: right; + display: none; +} + +.media-sidebar .save-waiting .settings-save-status .spinner, +.media-sidebar .save-complete .settings-save-status .saved { + display: block; +} + +/** + * Attachment Details + */ +.attachment-details { + position: relative; + overflow: auto; +} + +.attachment-info { + overflow: hidden; + min-height: 60px; + margin-bottom: 16px; + line-height: 18px; + color: #999; + border-bottom: 1px solid #e5e5e5; + box-shadow: 0 1px 0 #fff; + padding-bottom: 11px; +} + +.attachment-info .filename { + font-weight: bold; + color: #464646; + word-wrap: break-word; +} + +.attachment-info .thumbnail { + position: relative; + float: left; + max-width: 120px; + max-height: 120px; + margin-top: 5px; + margin-right: 10px; + margin-bottom: 5px; +} + +.uploading .attachment-info .thumbnail { + width: 120px; + height: 80px; + box-shadow: inset 0 0 15px rgba( 0, 0, 0, 0.1 ); +} + +.uploading .attachment-info .media-progress-bar { + margin-top: 35px; +} + +.attachment-info .thumbnail:after { + content: ''; + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.15 ); + overflow: hidden; +} + +.attachment-info .thumbnail img { + display: block; + max-width: 120px; + max-height: 120px; + margin: 0 auto; +} + +.attachment-info .details { + float: left; + font-size: 12px; + max-width: 100%; +} + +.attachment-info .edit-attachment, +.attachment-info .refresh-attachment, +.attachment-info .delete-attachment { + display: block; + text-decoration: none; + white-space: nowrap; +} + +.attachment-info .refresh-attachment, +.attachment-details.needs-refresh .attachment-info .edit-attachment { + display: none; +} + +.attachment-details.needs-refresh .attachment-info .refresh-attachment, +.attachment-info .edit-attachment { + display: block; +} + +.attachment-info .delete-attachment { + color: #bc0b0b; +} + +.attachment-info .delete-attachment:hover { + color: red; +} + +/** + * Attachment Display Settings + */ +.attachment-display-settings { + width: 100%; + float: left; + overflow: hidden; +} + +.attachment-display-settings h4 { + margin: 1.4em 0 0.4em; +} + +.gallery-settings { + overflow: hidden; +} + +/** + * Embed from URL + */ +.embed-url { + display: block; + position: relative; + padding: 0 16px 7px; + margin: 0; + z-index: 250; + background: #fff; + border-bottom: 1px solid #dfdfdf; + box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); + font-size: 18px; + font-weight: 200; +} + +.media-frame .embed-url input { + font-size: 18px; + padding: 12px 14px; + width: 100%; + min-width: 200px; + box-shadow: inset 2px 2px 4px -2px rgba( 0, 0, 0, 0.1 ); +} + +.media-frame .embed-url .spinner { + position: absolute; + top: 16px; + right: 26px; +} + +.media-frame .embed-loading .embed-url .spinner { + display: block; +} + +.embed-link-settings, +.embed-image-settings { + position: absolute; + background: #f5f5f5; + top: 57px; + left: 0; + right: 0; + bottom: 0; + padding: 16px 16px 32px; + overflow: auto; +} + +.media-embed .thumbnail { + max-width: 100%; + max-height: 200px; + position: relative; + float: left; +} + +.media-embed .thumbnail img { + max-height: 200px; + display: block; +} + +.media-embed .thumbnail:after { + content: ''; + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.1 ); + overflow: hidden; +} + +.media-embed .setting { + width: 100%; + margin-top: 10px; + float: left; + display: block; + clear: both; +} + +.media-embed .setting span { + display: block; + width: 200px; + font-size: 13px; + line-height: 24px; + color: #999; + text-shadow: 0 1px 0 #fff; +} + +.media-embed .setting .button-group { + margin: 2px 0; +} + +.media-embed .setting input, +.media-embed .setting textarea { + display: block; + width: 100%; + max-width: 400px; + margin: 1px 0; +} + +/** + * IE7 Fixes + */ +.ie7 .media-frame .attachments-browser { + position: static; +} + +.ie7 .media-frame .embed-url input { + margin-top: 4px; + width: 90%; +} + +.ie7 .compat-item { + width: 99%; +} + +.ie7 .attachment-display-settings { + width: auto; +} + +.ie7 .attachment-preview, +.ie7 .attachment-preview .thumbnail { + width: 120px; + height: 120px; +} + +.ie7 .media-frame .attachment .describe { + width: 102px; +} + +.ie7 .media-sidebar .setting select { + max-width: 55%; +} + +.ie7 .media-sidebar .setting input, +.ie7 .media-sidebar .setting textarea { + width: 55%; +} + +.ie7 .media-sidebar .setting .link-to-custom { + float: left; +} + +@media only screen and (max-width: 960px) { + .media-frame-content .media-toolbar-primary .search, + .media-frame-content .media-toolbar-secondary .attachment-filters { + max-width: 120px; + } +} + +/** + * Responsive layout + */ +@media only screen and (max-width: 900px) { + .media-frame-menu { + width: 139px; + } + + .media-menu > a { + padding: 4px 10px; + } + + .media-frame-title, + .media-frame-router, + .media-frame-content, + .media-frame-toolbar { + left: 140px; + } + + .media-sidebar { + width: 159px; + padding: 0 10px 24px; + } + + .attachments-browser .attachments, + .attachments-browser .uploader-inline, + .attachments-browser .media-toolbar { + right: 180px; + } + + .media-sidebar .setting input, + .media-sidebar .setting textarea, + .media-sidebar .setting span, + .compat-item label span { + float: none; + } + + .media-sidebar .setting span, + .compat-item label span { + text-align: inherit; + display: block; + min-height: 16px; + margin: 0; + padding: 8px 2px 0; + } + + .media-sidebar .setting input, + .media-sidebar .setting textarea, + .media-sidebar .setting select { + width: 98%; + max-width: none; + } + + .media-sidebar .setting select.columns { + width: auto; + } + + .media-frame input, + .media-frame textarea, + .media-frame .search { + padding: 3px 6px; + } + + .media-frame-content .attachment .icon { + top: 40%; + } + + .media-selection { + min-width: 120px; + } + + .media-selection:after { + background: none; + } + + .media-selection .attachments { + display: none; + } + + .media-menu .separator { + margin: 12px 10px; + } +} + +@media only screen and (max-width: 800px) { + .media-frame-content .media-toolbar .instructions { + display: none; + } +} + +@media only screen and (max-width: 680px) { + .media-frame-content .media-toolbar .search, + .media-frame-content .media-toolbar .attachment-filters { + max-width: 85px; + } +} + +/* Use the same min-width as in the admin */ +@media only screen and (max-width: 600px) { + .media-modal { + width: 540px; + position: absolute; + } + + .media-modal-backdrop { + width: 600px; + position: absolute; + } +} + +/** + * HiDPI Displays + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + .media-modal-icon { + background-image: url(../images/uploader-icons-2x.png); + background-size: 134px 15px; + } + + .media-frame .spinner { + background-image: url(../images/wpspin-2x.gif); + } +} \ No newline at end of file diff --git a/sources/wp-includes/css/media-views.min.css b/sources/wp-includes/css/media-views.min.css new file mode 100644 index 0000000..0176b6d --- /dev/null +++ b/sources/wp-includes/css/media-views.min.css @@ -0,0 +1 @@ +.media-modal,.media-frame{font-family:sans-serif;font-size:12px}.media-frame input,.media-frame textarea{padding:6px 8px;line-height:16px}.media-frame select,.wp-admin .media-frame select{line-height:28px;margin-top:3px}.media-frame a{border-bottom:0;color:#21759b}.media-frame a:hover{color:#d54e21}.media-frame a.button{color:#333}.media-frame a.button:hover{color:#222}.media-frame a.button-primary,.media-frame a.button-primary:hover{color:#fff}.media-frame input[type=text],.media-frame input[type=password],.media-frame input[type=number],.media-frame input[type=search],.media-frame input[type=email],.media-frame input[type=url],.media-frame textarea,.media-frame select{font-family:sans-serif;font-size:12px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:3px;border-radius:3px;border-width:1px;border-style:solid;border-color:#dfdfdf}.media-frame select{height:24px;padding:2px}.media-frame input:disabled,.media-frame textarea:disabled,.media-frame input[readonly],.media-frame textarea[readonly]{background-color:#eee}.media-frame input[type=search]{-webkit-appearance:textfield}.media-frame :-moz-placeholder{color:#a9a9a9}.ui-sortable,.ui-draggable{-ms-touch-action:none}.media-modal{position:fixed;top:30px;left:30px;right:30px;bottom:30px;z-index:160000}.media-modal-backdrop{position:fixed;top:0;left:0;right:0;bottom:0;min-height:360px;background:#000;opacity:.7;z-index:159900}.media-modal-close{position:absolute;top:7px;right:7px;width:30px;height:30px;z-index:1000}.media-modal-close span{display:block;margin:8px auto 0;width:15px;height:15px;background-position:-100px 0}.media-modal-close:active{outline:0}.media-modal-content{position:absolute;top:0;left:0;right:0;bottom:0;overflow:auto;min-height:300px;background:#fff}.media-modal-icon{background-image:url(../images/uploader-icons.png);background-repeat:no-repeat}.media-toolbar{position:absolute;top:0;left:0;right:0;z-index:100;height:60px;padding:0 16px;border:0 solid #dfdfdf;overflow:hidden}.media-toolbar-primary{float:right;height:100%}.media-toolbar-secondary{float:left;height:100%}.media-toolbar-primary>.media-button,.media-toolbar-primary>.media-button-group{margin-left:10px;float:left;margin-top:15px}.media-toolbar-secondary>.media-button,.media-toolbar-secondary>.media-button-group{margin-right:10px;float:left;margin-top:15px}.media-sidebar{position:absolute;top:0;right:0;bottom:0;width:267px;padding:0 16px 24px;z-index:75;background:#f5f5f5;border-left:1px solid #dfdfdf;overflow:auto;-webkit-overflow-scrolling:touch}.hide-toolbar .media-sidebar{bottom:0}.media-sidebar .sidebar-title{font-weight:200;font-size:20px;margin:0;padding:12px 10px 10px;line-height:28px}.media-sidebar .sidebar-content{padding:0 10px;margin-bottom:130px}.media-sidebar .search{display:block;width:100%}.media-sidebar h3{position:relative;font-weight:700;text-transform:uppercase;font-size:12px;color:#777;text-shadow:0 1px 0 #fff;margin:24px 0 8px}.media-sidebar .setting{display:block;float:left;width:100%;margin:1px 0}.media-sidebar .setting label{display:block}.media-sidebar .setting .link-to-custom{margin:3px 0}.media-sidebar .setting span{min-width:30%;margin-right:4%;font-size:12px}.media-sidebar .setting select{max-width:65%}.media-sidebar .setting input[type=checkbox]{width:auto;float:none;margin-top:8px;padding:0}.media-sidebar .setting span,.compat-item label span{float:left;min-height:22px;padding-top:8px;line-height:16px;text-align:right;font-weight:400;color:#999;text-shadow:0 1px 0 #fff}.media-sidebar .setting input,.media-sidebar .setting textarea{width:65%;float:right}.media-sidebar .setting textarea,.compat-item .field textarea{height:62px;resize:vertical}.media-sidebar select{margin-top:3px}.compat-item{float:left;width:100%;overflow:hidden}.compat-item table{width:100%;table-layout:fixed;border-spacing:0;border:0}.compat-item tr{padding:2px 0;display:block;overflow:hidden}.compat-item .label,.compat-item .field{display:block;margin:0;padding:0}.compat-item .label{min-width:30%;margin-right:4%;float:left;text-align:right}.compat-item .label span{display:block;width:100%}.compat-item .field{float:right;width:65%;padding-right:1px}.compat-item .field input{width:100%;margin:0}.media-menu{position:absolute;top:0;left:0;right:0;bottom:0;margin:0;padding:16px 0;border-right:1px solid #d9d9d9;box-shadow:inset -6px 0 6px -6px rgba(0,0,0,.2);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.media-menu>a{display:block;position:relative;padding:4px 20px;margin:0;line-height:18px;font-size:14px;color:#21759B;text-shadow:0 1px 0 #fff;text-decoration:none}.media-menu>a:hover{color:#21759B;background:rgba(0,0,0,.04)}.media-menu>a:active{outline:0}.media-menu .active,.media-menu .active:hover{color:#333;font-weight:700}.media-menu .separator{height:0;margin:12px 20px;padding:0;border-top:1px solid #dfdfdf;border-bottom:1px solid #fff}.media-router{position:relative;padding:0 6px;margin:0;clear:both;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.media-router>a{position:relative;float:left;padding:2px 10px;margin:0;height:18px;line-height:18px;font-size:14px;border-right:1px solid #dfdfdf;text-shadow:0 1px 0 #fff;text-decoration:none}.media-router>a:last-child{border-right:0}.media-router>a:active,.media-router>a:focus{outline:0}.media-router .active,.media-router .active:hover{color:#333}.media-router .active:after{content:'';display:block;margin:-100px auto 0;width:7px;height:7px;background:#fff;box-shadow:1px 1px 1px rgba(0,0,0,.2);z-index:300;-webkit-transform:rotate(45deg) translate(75px,75px);-moz-transform:rotate(45deg) translate(75px,75px);-ms-transform:rotate(45deg) translate(75px,75px);-o-transform:rotate(45deg) translate(75px,75px);transform:rotate(45deg) translate(75px,75px)}.media-frame{overflow:hidden;position:absolute;top:0;left:0;right:0;bottom:0}.media-frame-menu{position:absolute;top:0;left:0;bottom:0;width:199px;z-index:150}.media-frame-title{position:absolute;top:0;left:200px;right:0;height:45px;z-index:200}.media-frame-router{position:absolute;top:45px;left:200px;right:0;height:30px;z-index:200;border-bottom:1px solid #dfdfdf;box-shadow:0 4px 4px -4px rgba(0,0,0,.1)}.media-frame-content{position:absolute;top:75px;left:200px;right:0;bottom:61px;height:auto;width:auto;margin:0;overflow:auto}.media-frame-toolbar{position:absolute;left:200px;right:0;bottom:0;height:60px;z-index:100;border:0 solid #dfdfdf;border-width:1px 0 0;box-shadow:0 -4px 4px -4px rgba(0,0,0,.1)}.media-frame.hide-menu .media-frame-title,.media-frame.hide-menu .media-frame-router,.media-frame.hide-menu .media-frame-toolbar,.media-frame.hide-menu .media-frame-content{left:0}.media-frame.hide-menu .media-frame-menu{left:-200px}.media-frame.hide-toolbar .media-frame-content{bottom:0}.media-frame.hide-toolbar .media-frame-toolbar{bottom:-61px}.media-frame.hide-router .media-frame-content{top:45px}.media-frame.hide-router .media-frame-router{display:none}.media-frame.hide-router .media-frame-title{border-bottom:1px solid #dfdfdf;box-shadow:0 4px 4px -4px rgba(0,0,0,.1)}.media-frame .media-toolbar .add-to-gallery{display:none}.media-frame-title h1{padding:0 16px;font-size:22px;font-weight:200;line-height:45px;margin:0}.media-frame .media-iframe{overflow:hidden}.media-frame .media-iframe,.media-frame .media-iframe iframe{height:100%;width:100%;border:0}.media-frame select.attachment-filters{margin-top:11px;margin-right:10px}.media-frame .search{margin-top:11px;padding:4px;line-height:18px;font-size:13px;color:#464646;font-family:sans-serif;-webkit-appearance:none}.media-toolbar-secondary .search{margin-right:16px}.attachments{margin:0;padding-right:16px;-webkit-overflow-scrolling:touch}.attachment{position:relative;float:left;padding:0;margin:0 10px 20px;color:#464646;list-style:none;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.selected.attachment{box-shadow:0 0 0 1px #fff,0 0 0 3px #ccc}.details.attachment{box-shadow:0 0 0 1px #fff,0 0 0 5px #1e8cbe}.attachment-preview{position:relative;width:199px;height:199px;box-shadow:inset 0 0 15px rgba(0,0,0,.1),inset 0 0 0 1px rgba(0,0,0,.05);background:#eee;cursor:pointer}.attachment .icon{margin:0 auto;overflow:hidden;padding-top:20%}.attachment .thumbnail{display:block;position:absolute;top:0;left:0;margin:0 auto;overflow:hidden;max-width:100%;max-height:100%}.attachment-preview .thumbnail:after{content:'';display:block;position:absolute;top:0;left:0;right:0;bottom:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);overflow:hidden}.attachment .thumbnail img{top:0;left:0}.attachment .thumbnail .centered{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-transform:translate(50%,50%);-moz-transform:translate(50%,50%);-ms-transform:translate(50%,50%);-o-transform:translate(50%,50%);transform:translate(50%,50%)}.attachment .thumbnail .centered img{-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.attachment .filename{position:absolute;left:0;right:0;bottom:0;overflow:hidden;max-height:100%;word-wrap:break-word;text-align:center;font-weight:700;background:rgba(255,255,255,.8);box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}.attachment .filename div{padding:5px 10px}.attachment-preview .thumbnail{width:199px;height:199px}.attachment .thumbnail img{position:absolute}.attachment .close{display:none;position:absolute;top:5px;right:5px;height:22px;width:22px;padding:0;font-size:20px;line-height:20px;text-align:center;text-decoration:none;color:#464646;background-color:#fff;background-position:-96px 4px;border-width:0;border-radius:3px;box-shadow:0 0 0 1px rgba(0,0,0,.3)}.attachment .close:hover{box-shadow:0 0 0 1px rgba(0,0,0,.6)}.attachment:hover .close{display:block}.attachment .check{display:none;height:24px;width:24px;position:absolute;top:-7px;right:-7px;outline:0;border:1px solid #fff;border-radius:3px;box-shadow:0 0 0 1px rgba(0,0,0,.4);background:#f1f1f1;background-image:-webkit-gradient(linear,left top,left bottom,from(#f1f1f1),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#f1f1f1,#e1e1e1);background-image:-moz-linear-gradient(top,#f1f1f1,#e1e1e1);background-image:-o-linear-gradient(top,#f1f1f1,#e1e1e1);background-image:linear-gradient(to bottom,#f1f1f1,#e1e1e1)}.attachment .check div{background-position:-1px 0;height:15px;width:15px;margin:5px}.attachment .check:hover div{background-position:-40px 0}.attachment.selected .check{display:block}.attachment.details .check{box-shadow:0 0 0 1px #1e8cbe;background:#1e8cbe;background-image:-webkit-gradient(linear,left top,left bottom,from(#1e8cbe),to(#0074a2));background-image:-webkit-linear-gradient(top,#1e8cbe,#0074a2);background-image:-moz-linear-gradient(top,#1e8cbe,#0074a2);background-image:-o-linear-gradient(top,#1e8cbe,#0074a2);background-image:linear-gradient(to bottom,#1e8cbe,#0074a2)}.attachment.details .check div{background-position:-21px 0}.attachment.details .check:hover div{background-position:-60px 0}.media-frame .attachment .describe{position:relative;display:block;width:100%;margin:-1px 0 0;padding:8px;font-size:12px;border-radius:0}.media-frame .attachments-browser{position:relative;width:100%;height:100%;overflow:hidden}.attachments-browser .media-toolbar{right:300px;height:50px}.attachments-browser .media-toolbar-primary>.media-button,.attachments-browser .media-toolbar-primary>.media-button-group,.attachments-browser .media-toolbar-secondary>.media-button,.attachments-browser .media-toolbar-secondary>.media-button-group{margin-top:10px}.attachments-browser .attachments,.attachments-browser .uploader-inline{position:absolute;top:50px;left:0;right:300px;bottom:0;overflow:auto}.attachments-browser .instructions{display:inline-block;margin-top:16px;line-height:18px;font-size:13px;color:#999}.media-progress-bar{position:relative;height:10px;width:70%;margin:10px auto;border-radius:10px;background:#dfdfdf;background:rgba(0,0,0,.1)}.media-progress-bar div{height:10px;min-width:20px;width:0;background:#aaa;background:rgba(0,0,0,.2);border-radius:10px;-webkit-transition:width 300ms;-moz-transition:width 300ms;-ms-transition:width 300ms;-o-transition:width 300ms;transition:width 300ms}.media-uploader-status .media-progress-bar{display:none;width:100%}.uploading.media-uploader-status .media-progress-bar{display:block}.attachment-preview .media-progress-bar{position:absolute;top:50%;left:15%;width:70%;margin:-5px 0 0 0}.media-uploader-status{position:relative;margin:0 auto;padding-bottom:10px;max-width:400px}.media-sidebar .media-uploader-status{border-bottom:1px solid #dfdfdf;box-shadow:0 1px 0 #fff}.uploader-inline .media-uploader-status h3{display:none}.media-uploader-status .upload-details{display:none;font-size:12px;color:#666;text-shadow:0 1px 0 #fff}.uploading.media-uploader-status .upload-details{display:block}.media-uploader-status .upload-detail-separator{padding:0 4px}.media-uploader-status .upload-count{color:#464646}.media-uploader-status .upload-dismiss-errors,.media-uploader-status .upload-errors{display:none}.errors.media-uploader-status .upload-dismiss-errors,.errors.media-uploader-status .upload-errors{display:block}.media-uploader-status .upload-dismiss-errors{text-decoration:none}.media-sidebar .media-uploader-status .upload-dismiss-errors{position:absolute;top:0;right:0}.upload-errors .upload-error{margin:8px auto 0;padding:8px;border:1px #c00 solid;background:#ffebe8;border-radius:3px}.upload-errors .upload-error-label{padding:2px 4px;margin-right:8px;font-weight:700;color:#fff;background:#e00;background-image:-webkit-gradient(linear,left top,left bottom,from(#e00),to(#a00));background-image:-webkit-linear-gradient(top,#e00,#a00);background-image:-moz-linear-gradient(top,#e00,#a00);background-image:-o-linear-gradient(top,#e00,#a00);background-image:linear-gradient(to bottom,#e00,#a00);border-radius:3px}.upload-errors .upload-error-message{display:block;padding-top:8px;color:#b44;word-wrap:break-word}.uploader-window{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,86,132,.9);z-index:250000;display:none;text-align:center;opacity:0;-webkit-transition:opacity 250ms;-moz-transition:opacity 250ms;-ms-transition:opacity 250ms;-o-transition:opacity 250ms;transition:opacity 250ms}.uploader-window-content{position:absolute;top:10px;left:10px;right:10px;bottom:10px;border:1px dashed #fff}.uploader-window h3{position:absolute;top:50%;left:0;right:0;-webkit-transform:translateY(-50%);-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);font-size:20px;font-weight:200;color:#fff;padding:0}.uploader-window .media-progress-bar{margin-top:20px;max-width:300px;background:transparent;border-color:#fff;display:none}.uploader-window .media-progress-bar div{background:#fff}.uploading .uploader-window .media-progress-bar{display:block}.media-frame .uploader-inline{margin:20px;padding:20px;text-align:center}.uploader-inline-content{position:absolute;top:30%;left:0;right:0}.uploader-inline-content .upload-ui{margin:4em 0}.uploader-inline-content .post-upload-ui{margin-bottom:2em}.uploader-inline .has-upload-message .upload-ui{margin:0 0 4em}.uploader-inline h3{font-size:20px;line-height:28px;font-weight:200;margin-bottom:1.6em}.uploader-inline .has-upload-message .upload-instructions{font-size:14px;color:#464646;font-weight:400}.uploader-inline .drop-instructions{display:none}.supports-drag-drop .uploader-inline .drop-instructions{display:block}.uploader-inline p{font-size:12px}.uploader-inline .media-progress-bar{display:none}.uploading.uploader-inline .media-progress-bar{display:block}.uploader-inline .browser{display:inline-block!important}.media-selection{position:absolute;top:0;left:0;right:350px;height:60px;padding:0 0 0 16px;overflow:hidden;white-space:nowrap}.media-selection .selection-info{display:inline-block;font-size:12px;height:60px;margin-right:10px;vertical-align:top}.media-selection.empty,.media-selection.editing{display:none}.media-selection.one .edit-selection{display:none}.media-selection .count{display:block;padding-top:12px;font-size:14px;line-height:20px;font-weight:700}.media-selection .selection-info a{display:block;float:left;padding:1px 8px;margin:1px 8px 1px -8px;line-height:16px;text-decoration:none;border-right:1px solid #dfdfdf;color:#21759B}.media-selection .selection-info a:hover{background:#21759B;color:#fff;border-color:transparent}.media-selection .selection-info a:last-child{border-right:0;margin-right:0}.media-selection .selection-info .clear-selection{color:red}.media-selection .selection-info .clear-selection:hover{background:red}.media-selection .selection-view{display:inline-block;vertical-align:top}.media-selection .attachments{display:inline-block;height:48px;margin-top:5px;overflow:hidden;vertical-align:top}.media-selection .attachment .icon{width:50%}.attachment.selection.selected{box-shadow:none}.attachment.selection.details{box-shadow:0 0 0 1px #fff,0 0 0 4px #1e8cbe}.media-selection .attachment.selection.details{box-shadow:0 0 0 1px #fff,0 0 0 3px #1e8cbe}.media-selection:after{content:'';display:block;position:absolute;top:0;right:0;bottom:0;width:25px;background-image:-webkit-gradient(linear,right top,left top,from(rgba(255,255,255,1)),to(rgba(255,255,255,0)));background-image:-webkit-linear-gradient(right,rgba(255,255,255,1),rgba(255,255,255,0));background-image:-moz-linear-gradient(right,rgba(255,255,255,1),rgba(255,255,255,0));background-image:-o-linear-gradient(right,rgba(255,255,255,1),rgba(255,255,255,0));background-image:linear-gradient(to left,rgba(255,255,255,1),rgba(255,255,255,0))}.media-selection .attachment .filename{display:none}.media-frame .spinner{background:url(../images/wpspin.gif) no-repeat;background-size:16px 16px;display:none;opacity:.7;filter:alpha(opacity=70);width:16px;height:16px;margin:0}.media-sidebar .settings-save-status{background:#f5f5f5;float:right;text-transform:none;z-index:10}.media-sidebar .settings-save-status .spinner{margin:0 5px}.media-sidebar .settings-save-status .saved{float:right;display:none}.media-sidebar .save-waiting .settings-save-status .spinner,.media-sidebar .save-complete .settings-save-status .saved{display:block}.attachment-details{position:relative;overflow:auto}.attachment-info{overflow:hidden;min-height:60px;margin-bottom:16px;line-height:18px;color:#999;border-bottom:1px solid #e5e5e5;box-shadow:0 1px 0 #fff;padding-bottom:11px}.attachment-info .filename{font-weight:700;color:#464646;word-wrap:break-word}.attachment-info .thumbnail{position:relative;float:left;max-width:120px;max-height:120px;margin-top:5px;margin-right:10px;margin-bottom:5px}.uploading .attachment-info .thumbnail{width:120px;height:80px;box-shadow:inset 0 0 15px rgba(0,0,0,.1)}.uploading .attachment-info .media-progress-bar{margin-top:35px}.attachment-info .thumbnail:after{content:'';display:block;position:absolute;top:0;left:0;right:0;bottom:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15);overflow:hidden}.attachment-info .thumbnail img{display:block;max-width:120px;max-height:120px;margin:0 auto}.attachment-info .details{float:left;font-size:12px;max-width:100%}.attachment-info .edit-attachment,.attachment-info .refresh-attachment,.attachment-info .delete-attachment{display:block;text-decoration:none;white-space:nowrap}.attachment-info .refresh-attachment,.attachment-details.needs-refresh .attachment-info .edit-attachment{display:none}.attachment-details.needs-refresh .attachment-info .refresh-attachment,.attachment-info .edit-attachment{display:block}.attachment-info .delete-attachment{color:#bc0b0b}.attachment-info .delete-attachment:hover{color:red}.attachment-display-settings{width:100%;float:left;overflow:hidden}.attachment-display-settings h4{margin:1.4em 0 .4em}.gallery-settings{overflow:hidden}.embed-url{display:block;position:relative;padding:0 16px 7px;margin:0;z-index:250;background:#fff;border-bottom:1px solid #dfdfdf;box-shadow:0 4px 4px -4px rgba(0,0,0,.1);font-size:18px;font-weight:200}.media-frame .embed-url input{font-size:18px;padding:12px 14px;width:100%;min-width:200px;box-shadow:inset 2px 2px 4px -2px rgba(0,0,0,.1)}.media-frame .embed-url .spinner{position:absolute;top:16px;right:26px}.media-frame .embed-loading .embed-url .spinner{display:block}.embed-link-settings,.embed-image-settings{position:absolute;background:#f5f5f5;top:57px;left:0;right:0;bottom:0;padding:16px 16px 32px;overflow:auto}.media-embed .thumbnail{max-width:100%;max-height:200px;position:relative;float:left}.media-embed .thumbnail img{max-height:200px;display:block}.media-embed .thumbnail:after{content:'';display:block;position:absolute;top:0;left:0;right:0;bottom:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);overflow:hidden}.media-embed .setting{width:100%;margin-top:10px;float:left;display:block;clear:both}.media-embed .setting span{display:block;width:200px;font-size:13px;line-height:24px;color:#999;text-shadow:0 1px 0 #fff}.media-embed .setting .button-group{margin:2px 0}.media-embed .setting input,.media-embed .setting textarea{display:block;width:100%;max-width:400px;margin:1px 0}.ie7 .media-frame .attachments-browser{position:static}.ie7 .media-frame .embed-url input{margin-top:4px;width:90%}.ie7 .compat-item{width:99%}.ie7 .attachment-display-settings{width:auto}.ie7 .attachment-preview,.ie7 .attachment-preview .thumbnail{width:120px;height:120px}.ie7 .media-frame .attachment .describe{width:102px}.ie7 .media-sidebar .setting select{max-width:55%}.ie7 .media-sidebar .setting input,.ie7 .media-sidebar .setting textarea{width:55%}.ie7 .media-sidebar .setting .link-to-custom{float:left}@media only screen and (max-width:960px){.media-frame-content .media-toolbar-primary .search,.media-frame-content .media-toolbar-secondary .attachment-filters{max-width:120px}}@media only screen and (max-width:900px){.media-frame-menu{width:139px}.media-menu>a{padding:4px 10px}.media-frame-title,.media-frame-router,.media-frame-content,.media-frame-toolbar{left:140px}.media-sidebar{width:159px;padding:0 10px 24px}.attachments-browser .attachments,.attachments-browser .uploader-inline,.attachments-browser .media-toolbar{right:180px}.media-sidebar .setting input,.media-sidebar .setting textarea,.media-sidebar .setting span,.compat-item label span{float:none}.media-sidebar .setting span,.compat-item label span{text-align:inherit;display:block;min-height:16px;margin:0;padding:8px 2px 0}.media-sidebar .setting input,.media-sidebar .setting textarea,.media-sidebar .setting select{width:98%;max-width:none}.media-sidebar .setting select.columns{width:auto}.media-frame input,.media-frame textarea,.media-frame .search{padding:3px 6px}.media-frame-content .attachment .icon{top:40%}.media-selection{min-width:120px}.media-selection:after{background:0 0}.media-selection .attachments{display:none}.media-menu .separator{margin:12px 10px}}@media only screen and (max-width:800px){.media-frame-content .media-toolbar .instructions{display:none}}@media only screen and (max-width:680px){.media-frame-content .media-toolbar .search,.media-frame-content .media-toolbar .attachment-filters{max-width:85px}}@media only screen and (max-width:600px){.media-modal{width:540px;position:absolute}.media-modal-backdrop{width:600px;position:absolute}}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.media-modal-icon{background-image:url(../images/uploader-icons-2x.png);background-size:134px 15px}.media-frame .spinner{background-image:url(../images/wpspin-2x.gif)}} \ No newline at end of file diff --git a/sources/wp-includes/css/wp-auth-check.css b/sources/wp-includes/css/wp-auth-check.css new file mode 100644 index 0000000..f51017b --- /dev/null +++ b/sources/wp-includes/css/wp-auth-check.css @@ -0,0 +1,94 @@ +/*------------------------------------------------------------------------------ + Interim login dialog +------------------------------------------------------------------------------*/ + +#wp-auth-check-wrap.hidden { + display: none; +} + +#wp-auth-check-wrap #wp-auth-check-bg { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: #000; + opacity: 0.5; + filter: alpha(opacity=50); + z-index: 1000000; +} + +#wp-auth-check-wrap #wp-auth-check { + position: fixed; + left: 50%; + overflow: hidden; + top: 40px; + bottom: 20px; + max-height: 415px; + width: 380px; + margin: 0 0 0 -190px; + padding: 30px 0 0; + background-color: #fbfbfb; + -webkit-border-radius: 3px; + border-radius: 3px; + z-index: 1000001; +} + +#wp-auth-check-wrap.fallback #wp-auth-check { + max-height: 180px; + overflow: auto; +} + +#wp-auth-check-wrap #wp-auth-check-form { + background: url(../images/wpspin-2x.gif) no-repeat center center; + background-size: 16px 16px; + height: 100%; +} + +#wp-auth-check-wrap #wp-auth-check-form iframe { + height: 100%; + width: 100%; + overflow: auto; +} + +#wp-auth-check-wrap .wp-auth-check-close { + position: absolute; + top: 8px; + right: 8px; + height: 14px; + width: 14px; + cursor: pointer; + background-image: url(../images/uploader-icons.png); + background-repeat: no-repeat; + background-position: -100px 0; +} + +#wp-auth-check-wrap .wp-auth-check-close:focus { + outline: 1px dotted #888; +} + +#wp-auth-check-wrap .wp-auth-fallback-expired { + outline: 0; +} + +#wp-auth-check-wrap .wp-auth-fallback { + font-size: 14px; + line-height: 21px; + padding: 0 25px; + display: none; +} + +#wp-auth-check-wrap.fallback .wp-auth-fallback, +#wp-auth-check-wrap.fallback .wp-auth-check-close { + display: block; +} + +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + #wp-auth-check-wrap .wp-auth-check-close { + background-image: url(../images/uploader-icons-2x.png); + background-size: 134px 15px; + } +} diff --git a/sources/wp-includes/css/wp-auth-check.min.css b/sources/wp-includes/css/wp-auth-check.min.css new file mode 100644 index 0000000..734525c --- /dev/null +++ b/sources/wp-includes/css/wp-auth-check.min.css @@ -0,0 +1 @@ +#wp-auth-check-wrap.hidden{display:none}#wp-auth-check-wrap #wp-auth-check-bg{position:fixed;top:0;bottom:0;left:0;right:0;background:#000;opacity:.5;filter:alpha(opacity=50);z-index:1000000}#wp-auth-check-wrap #wp-auth-check{position:fixed;left:50%;overflow:hidden;top:40px;bottom:20px;max-height:415px;width:380px;margin:0 0 0 -190px;padding:30px 0 0;background-color:#fbfbfb;-webkit-border-radius:3px;border-radius:3px;z-index:1000001}#wp-auth-check-wrap.fallback #wp-auth-check{max-height:180px;overflow:auto}#wp-auth-check-wrap #wp-auth-check-form{background:url(../images/wpspin-2x.gif) no-repeat center center;background-size:16px 16px;height:100%}#wp-auth-check-wrap #wp-auth-check-form iframe{height:100%;width:100%;overflow:auto}#wp-auth-check-wrap .wp-auth-check-close{position:absolute;top:8px;right:8px;height:14px;width:14px;cursor:pointer;background-image:url(../images/uploader-icons.png);background-repeat:no-repeat;background-position:-100px 0}#wp-auth-check-wrap .wp-auth-check-close:focus{outline:1px dotted #888}#wp-auth-check-wrap .wp-auth-fallback-expired{outline:0}#wp-auth-check-wrap .wp-auth-fallback{font-size:14px;line-height:21px;padding:0 25px;display:none}#wp-auth-check-wrap.fallback .wp-auth-fallback,#wp-auth-check-wrap.fallback .wp-auth-check-close{display:block}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){#wp-auth-check-wrap .wp-auth-check-close{background-image:url(../images/uploader-icons-2x.png);background-size:134px 15px}} \ No newline at end of file diff --git a/sources/wp-includes/css/wp-pointer.css b/sources/wp-includes/css/wp-pointer.css new file mode 100644 index 0000000..c5566f3 --- /dev/null +++ b/sources/wp-includes/css/wp-pointer.css @@ -0,0 +1,228 @@ +.wp-pointer { +} + +.wp-pointer-content { + padding: 0 0 10px; + position: relative; + font-size: 13px; + + background: #fff; + border-style: solid; + border-width: 1px; + /* Fallback for non-rgba-compliant browsers */ + border-color: #dfdfdf; + /* Use rgba to look better against non-white backgrounds. */ + border-color: rgba(0,0,0,.125); + -webkit-border-radius: 3px; + border-radius: 3px; + + -webkit-box-shadow: 0 2px 4px rgba(0,0,0,.19); + box-shadow: 0 2px 4px rgba(0,0,0,.19); +} + +.wp-pointer-content h3 { + position: relative; + margin: 0 0 5px; + padding: 15px 18px 14px 60px; + line-height: 1.4em; + font-size: 14px; + color: #fff; + border-radius: 3px 3px 0 0; + text-shadow: 0 -1px 0 rgba(0,0,0,0.3); + background: #8cc1e9; + background-image: -webkit-gradient(linear, left bottom, left top, from(#72a7cf), to(#8cc1e9)); + background-image: -webkit-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -moz-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: -o-linear-gradient(bottom, #72a7cf, #8cc1e9); + background-image: linear-gradient(to top, #72a7cf, #8cc1e9); +} + +.wp-pointer-content h3:before { + position: absolute; + top: 0; + left: 15px; + content: ' '; + width: 36px; + height: 100%; + background: url('../images/icon-pointer-flag.png') 0 50% no-repeat; +} + +.wp-pointer-content p { + padding: 0 15px; +} + +.wp-pointer-buttons { + margin: 0; + padding: 5px 15px; + overflow: auto; +} + +.wp-pointer-buttons a { + float: right; + display: inline-block; + text-decoration: none; +} + +.wp-pointer-buttons a.close { + padding-left:3px; + position: relative; +} + +.wp-pointer-buttons a.close:before { + content: ' '; + width:10px; + height:100%; + position:absolute; + left:-10px; + background:url('../images/xit.gif') 0 50% no-repeat; +} + +.wp-pointer-buttons a.close:hover:before { + background-position:100% 50%; +} + +/* The arrow base class must take up no space, even with transparent borders. */ +.wp-pointer-arrow, +.wp-pointer-arrow-inner { + position: absolute; + width: 0; + height: 0; +} + +.wp-pointer-arrow { + z-index: 10; + background:url('../images/arrow-pointer-blue.png') 0 0 no-repeat; +} + +.wp-pointer-arrow-inner { + z-index: 20; +} + +/* Make Room for the Arrow! */ +.wp-pointer-top, +.wp-pointer-undefined { + padding-top: 13px; +} + +.wp-pointer-bottom { + padding-bottom: 13px; +} + +.wp-pointer-left { + padding-left: 13px; +} + +.wp-pointer-right { + padding-right: 13px; +} + +/* Base Size & Positioning */ +.wp-pointer-top .wp-pointer-arrow, +.wp-pointer-bottom .wp-pointer-arrow, +.wp-pointer-undefined .wp-pointer-arrow { + left: 50px; + width: 30px; + height: 14px; +} + +.wp-pointer-left .wp-pointer-arrow, +.wp-pointer-right .wp-pointer-arrow { + top: 50%; + margin-top: -15px; + width: 14px; + height: 30px; +} + +/* Arrow Sprite */ +.wp-pointer-top .wp-pointer-arrow, +.wp-pointer-undefined .wp-pointer-arrow { + top: 0; + background-position: 0 0; +} + +.wp-pointer-bottom .wp-pointer-arrow { + bottom: 0; + background-position: 0 -46px; +} + +.wp-pointer-left .wp-pointer-arrow { + left: 0; + background-position: 0 -15px; +} + +.wp-pointer-right .wp-pointer-arrow { + right:0; + background-position:-16px -15px; +} + +/* - RTL +------------------------------------------------------------------------------*/ + +.rtl .wp-pointer-content h3 { + padding-right: 60px; + padding-left: 18px; +} + +.rtl .wp-pointer-content h3:before { + right: 15px; +} + +.rtl .wp-pointer-buttons a { + float: left; +} + +.rtl .wp-pointer-buttons a.close { + padding-right:3px; + padding-left: 0; +} + +.rtl .wp-pointer-buttons a.close:before { + right:-10px; +} + +.rtl .wp-pointer-top .wp-pointer-arrow, +.rtl .wp-pointer-bottom .wp-pointer-arrow, +.rtl .wp-pointer-undefined .wp-pointer-arrow { + right: 50px; +} + +/** + * HiDPI Displays + */ +@media print, + (-o-min-device-pixel-ratio: 5/4), + (-webkit-min-device-pixel-ratio: 1.25), + (min-resolution: 120dpi) { + + .wp-pointer-buttons a.close:before { + background-image: url('../images/xit-2x.gif'); + background-size: 20px auto; + } + + .wp-pointer-content h3:before { + background-image: url('../images/icon-pointer-flag-2x.png'); + background-size: 36px auto; + } + + .wp-pointer-arrow { + background: url('../images/arrow-pointer-blue-2x.png') 0 0 no-repeat; + background-size: 30px 60px; + } + + .wp-pointer-top .wp-pointer-arrow, + .wp-pointer-undefined .wp-pointer-arrow { + background-position: 0 1px; + } + + .wp-pointer-bottom .wp-pointer-arrow { + background-position: 0 -47px; + } + + .wp-pointer-left .wp-pointer-arrow { + background-position: 1px -15px; + } + + .wp-pointer-right .wp-pointer-arrow { + background-position:-17px -15px; + } +} diff --git a/sources/wp-includes/css/wp-pointer.min.css b/sources/wp-includes/css/wp-pointer.min.css new file mode 100644 index 0000000..46f1cc3 --- /dev/null +++ b/sources/wp-includes/css/wp-pointer.min.css @@ -0,0 +1 @@ +.wp-pointer{}.wp-pointer-content{padding:0 0 10px;position:relative;font-size:13px;background:#fff;border-style:solid;border-width:1px;border-color:#dfdfdf;border-color:rgba(0,0,0,.125);-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.19);box-shadow:0 2px 4px rgba(0,0,0,.19)}.wp-pointer-content h3{position:relative;margin:0 0 5px;padding:15px 18px 14px 60px;line-height:1.4em;font-size:14px;color:#fff;border-radius:3px 3px 0 0;text-shadow:0 -1px 0 rgba(0,0,0,.3);background:#8cc1e9;background-image:-webkit-gradient(linear,left bottom,left top,from(#72a7cf),to(#8cc1e9));background-image:-webkit-linear-gradient(bottom,#72a7cf,#8cc1e9);background-image:-moz-linear-gradient(bottom,#72a7cf,#8cc1e9);background-image:-o-linear-gradient(bottom,#72a7cf,#8cc1e9);background-image:linear-gradient(to top,#72a7cf,#8cc1e9)}.wp-pointer-content h3:before{position:absolute;top:0;left:15px;content:' ';width:36px;height:100%;background:url(../images/icon-pointer-flag.png) 0 50% no-repeat}.wp-pointer-content p{padding:0 15px}.wp-pointer-buttons{margin:0;padding:5px 15px;overflow:auto}.wp-pointer-buttons a{float:right;display:inline-block;text-decoration:none}.wp-pointer-buttons a.close{padding-left:3px;position:relative}.wp-pointer-buttons a.close:before{content:' ';width:10px;height:100%;position:absolute;left:-10px;background:url(../images/xit.gif) 0 50% no-repeat}.wp-pointer-buttons a.close:hover:before{background-position:100% 50%}.wp-pointer-arrow,.wp-pointer-arrow-inner{position:absolute;width:0;height:0}.wp-pointer-arrow{z-index:10;background:url(../images/arrow-pointer-blue.png) 0 0 no-repeat}.wp-pointer-arrow-inner{z-index:20}.wp-pointer-top,.wp-pointer-undefined{padding-top:13px}.wp-pointer-bottom{padding-bottom:13px}.wp-pointer-left{padding-left:13px}.wp-pointer-right{padding-right:13px}.wp-pointer-top .wp-pointer-arrow,.wp-pointer-bottom .wp-pointer-arrow,.wp-pointer-undefined .wp-pointer-arrow{left:50px;width:30px;height:14px}.wp-pointer-left .wp-pointer-arrow,.wp-pointer-right .wp-pointer-arrow{top:50%;margin-top:-15px;width:14px;height:30px}.wp-pointer-top .wp-pointer-arrow,.wp-pointer-undefined .wp-pointer-arrow{top:0;background-position:0 0}.wp-pointer-bottom .wp-pointer-arrow{bottom:0;background-position:0 -46px}.wp-pointer-left .wp-pointer-arrow{left:0;background-position:0 -15px}.wp-pointer-right .wp-pointer-arrow{right:0;background-position:-16px -15px}.rtl .wp-pointer-content h3{padding-right:60px;padding-left:18px}.rtl .wp-pointer-content h3:before{right:15px}.rtl .wp-pointer-buttons a{float:left}.rtl .wp-pointer-buttons a.close{padding-right:3px;padding-left:0}.rtl .wp-pointer-buttons a.close:before{right:-10px}.rtl .wp-pointer-top .wp-pointer-arrow,.rtl .wp-pointer-bottom .wp-pointer-arrow,.rtl .wp-pointer-undefined .wp-pointer-arrow{right:50px}@media print,(-o-min-device-pixel-ratio:5/4),(-webkit-min-device-pixel-ratio:1.25),(min-resolution:120dpi){.wp-pointer-buttons a.close:before{background-image:url(../images/xit-2x.gif);background-size:20px auto}.wp-pointer-content h3:before{background-image:url(../images/icon-pointer-flag-2x.png);background-size:36px auto}.wp-pointer-arrow{background:url(../images/arrow-pointer-blue-2x.png) 0 0 no-repeat;background-size:30px 60px}.wp-pointer-top .wp-pointer-arrow,.wp-pointer-undefined .wp-pointer-arrow{background-position:0 1px}.wp-pointer-bottom .wp-pointer-arrow{background-position:0 -47px}.wp-pointer-left .wp-pointer-arrow{background-position:1px -15px}.wp-pointer-right .wp-pointer-arrow{background-position:-17px -15px}} \ No newline at end of file diff --git a/sources/wp-includes/date.php b/sources/wp-includes/date.php new file mode 100644 index 0000000..f41cae8 --- /dev/null +++ b/sources/wp-includes/date.php @@ -0,0 +1,447 @@ +', '>=', '<', '<=', 'IN', 'NOT IN', + * 'BETWEEN', 'NOT BETWEEN'. + * @type string $relation Optional. The boolean relationship between the date queryies. + * Default 'OR'. Accepts 'OR', 'AND'. + * @type array { + * @type string|array $before Optional. Date to retrieve posts before. Accepts strtotime()-compatible + * string, or array of 'year', 'month', 'day' values. { + * + * @type string $year The four-digit year. Default empty. Accepts any four-digit year. + * @type string $month Optional when passing array.The month of the year. + * Default (string:empty)|(array:1). Accepts numbers 1-12. + * @type string $day Optional when passing array.The day of the month. + * Default (string:empty)|(array:1). Accepts numbers 1-31. + * } + * @type string|array $after Optional. Date to retrieve posts before. Accepts strtotime()-compatible + * string, or array of 'year', 'month', 'day' values. { + * + * @type string $year The four-digit year. Default empty. Accepts any four-digit year. + * @type string $month Optional when passing array.The month of the year. + * Default (string:empty)|(array:12). Accepts numbers 1-12. + * @type string $day Optional when passing array.The day of the month. + * Default (string:empty)|(array:last day of month). Accepts numbers 1-31. + * } + * @type string $column Optional. Used to add a clause comparing a column other than the column + * specified in the top-level $column paramater. Default is the value + * of top-level $column. Accepts 'post_date', 'post_date_gmt', + * 'post_modified', 'post_modified_gmt', 'comment_date', 'comment_date_gmt'. + * @type string $compare Optional. The comparison operator. Default '='. Accepts '=', '!=', + * '>', '>=', '<', '<=', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. + * @type bool $inclusive Optional. Include results from dates specified in 'before' or 'after'. + * Default. Accepts. + * @type int $year Optional. The four-digit near number. Default empty. Accepts any + * four-digit year. + * @type int $month Optional. The two-digit month number. Default empty. Accepts numbers 1-12. + * @type int $week Optional. The week number of the year. Default empty. Accepts numbers 0-53. + * @type int $day Optional. The day of the month. Default empty. Accepts numbers 1-31. + * @type int $hour Optional. The hour of the day. Default empty. Accepts numbers 0-23. + * @type int $minute Optional. The minute of the hour. Default empty. Accepts numbers 0-60. + * @type int $second Optional. The second of the minute. Default empty. Accepts numbers 0-60. + * } + * } + * } + * @param array $default_column Optional. Default column to query against. Default 'post_date'. + * Accepts 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', + * 'comment_date', 'comment_date_gmt'. + */ + function __construct( $date_query, $default_column = 'post_date' ) { + if ( empty( $date_query ) || ! is_array( $date_query ) ) + return; + + if ( isset( $date_query['relation'] ) && strtoupper( $date_query['relation'] ) == 'OR' ) + $this->relation = 'OR'; + else + $this->relation = 'AND'; + + if ( ! empty( $date_query['column'] ) ) + $this->column = esc_sql( $date_query['column'] ); + else + $this->column = esc_sql( $default_column ); + + $this->column = $this->validate_column( $this->column ); + + $this->compare = $this->get_compare( $date_query ); + + // If an array of arrays wasn't passed, fix it + if ( ! isset( $date_query[0] ) ) + $date_query = array( $date_query ); + + $this->queries = array(); + foreach ( $date_query as $key => $query ) { + if ( ! is_array( $query ) ) + continue; + + $this->queries[$key] = $query; + } + } + + /** + * Determines and validates what comparison operator to use. + * + * @since 3.7.0 + * @access public + * + * @param array $query A date query or a date subquery + * @return string The comparison operator + */ + public function get_compare( $query ) { + if ( ! empty( $query['compare'] ) && in_array( $query['compare'], array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) + return strtoupper( $query['compare'] ); + + return $this->compare; + } + + /** + * Validates a column name parameter. + * + * @since 3.7.0 + * @access public + * + * @param string $column The user-supplied column name. + * @return string A validated column name value. + */ + public function validate_column( $column ) { + $valid_columns = array( + 'post_date', 'post_date_gmt', 'post_modified', + 'post_modified_gmt', 'comment_date', 'comment_date_gmt' + ); + /** + * Filter the list of valid date query columns. + * + * @since 3.7.0 + * + * @param array $valid_columns An array of valid date query columns. Defaults are 'post_date', 'post_date_gmt', + * 'post_modified', 'post_modified_gmt', 'comment_date', 'comment_date_gmt' + */ + if ( ! in_array( $column, apply_filters( 'date_query_valid_columns', $valid_columns ) ) ) + $column = 'post_date'; + + return $column; + } + + /** + * Turns an array of date query parameters into a MySQL string. + * + * @since 3.7.0 + * @access public + * + * @return string MySQL WHERE parameters + */ + public function get_sql() { + // The parts of the final query + $where = array(); + + foreach ( $this->queries as $key => $query ) { + $where_parts = $this->get_sql_for_subquery( $query ); + if ( $where_parts ) { + // Combine the parts of this subquery into a single string + $where[ $key ] = '( ' . implode( ' AND ', $where_parts ) . ' )'; + } + } + + // Combine the subquery strings into a single string + if ( $where ) + $where = ' AND ( ' . implode( " {$this->relation} ", $where ) . ' )'; + else + $where = ''; + + /** + * Filter the date query WHERE clause. + * + * @since 3.7.0 + * + * @param string $where WHERE clause of the date query. + * @param WP_Date_Query $this The WP_Date_Query instance. + */ + return apply_filters( 'get_date_sql', $where, $this ); + } + + /** + * Turns a single date subquery into pieces for a WHERE clause. + * + * @since 3.7.0 + * return array + */ + protected function get_sql_for_subquery( $query ) { + global $wpdb; + + // The sub-parts of a $where part + $where_parts = array(); + + $column = ( ! empty( $query['column'] ) ) ? esc_sql( $query['column'] ) : $this->column; + + $column = $this->validate_column( $column ); + + $compare = $this->get_compare( $query ); + + $lt = '<'; + $gt = '>'; + if ( ! empty( $query['inclusive'] ) ) { + $lt .= '='; + $gt .= '='; + } + + // Range queries + if ( ! empty( $query['after'] ) ) + $where_parts[] = $wpdb->prepare( "$column $gt %s", $this->build_mysql_datetime( $query['after'], true ) ); + + if ( ! empty( $query['before'] ) ) + $where_parts[] = $wpdb->prepare( "$column $lt %s", $this->build_mysql_datetime( $query['before'], false ) ); + + // Specific value queries + + if ( isset( $query['year'] ) && $value = $this->build_value( $compare, $query['year'] ) ) + $where_parts[] = "YEAR( $column ) $compare $value"; + + if ( isset( $query['month'] ) && $value = $this->build_value( $compare, $query['month'] ) ) + $where_parts[] = "MONTH( $column ) $compare $value"; + + // Legacy + if ( isset( $query['monthnum'] ) && $value = $this->build_value( $compare, $query['monthnum'] ) ) + $where_parts[] = "MONTH( $column ) $compare $value"; + + if ( isset( $query['week'] ) && false !== ( $value = $this->build_value( $compare, $query['week'] ) ) ) + $where_parts[] = _wp_mysql_week( $column ) . " $compare $value"; + + // Legacy + if ( isset( $query['w'] ) && false !== ( $value = $this->build_value( $compare, $query['w'] ) ) ) + $where_parts[] = _wp_mysql_week( $column ) . " $compare $value"; + + if ( isset( $query['dayofyear'] ) && $value = $this->build_value( $compare, $query['dayofyear'] ) ) + $where_parts[] = "DAYOFYEAR( $column ) $compare $value"; + + if ( isset( $query['day'] ) && $value = $this->build_value( $compare, $query['day'] ) ) + $where_parts[] = "DAYOFMONTH( $column ) $compare $value"; + + if ( isset( $query['dayofweek'] ) && $value = $this->build_value( $compare, $query['dayofweek'] ) ) + $where_parts[] = "DAYOFWEEK( $column ) $compare $value"; + + if ( isset( $query['hour'] ) || isset( $query['minute'] ) || isset( $query['second'] ) ) { + // Avoid notices + foreach ( array( 'hour', 'minute', 'second' ) as $unit ) { + if ( ! isset( $query[$unit] ) ) { + $query[$unit] = null; + } + } + + if ( $time_query = $this->build_time_query( $column, $compare, $query['hour'], $query['minute'], $query['second'] ) ) { + $where_parts[] = $time_query; + } + } + + return $where_parts; + } + + /** + * Builds and validates a value string based on the comparison operator. + * + * @since 3.7.0 + * @access public + * + * @param string $compare The compare operator to use + * @param string|array $value The value + * @return string|int|false The value to be used in SQL or false on error. + */ + public function build_value( $compare, $value ) { + if ( ! isset( $value ) ) + return false; + + switch ( $compare ) { + case 'IN': + case 'NOT IN': + return '(' . implode( ',', array_map( 'intval', (array) $value ) ) . ')'; + + case 'BETWEEN': + case 'NOT BETWEEN': + if ( ! is_array( $value ) || 2 != count( $value ) || ! isset( $value[0] ) || ! isset( $value[1] ) ) + $value = array( $value, $value ); + + $value = array_map( 'intval', $value ); + + return $value[0] . ' AND ' . $value[1]; + + default; + return (int) $value; + } + } + + /** + * Builds a MySQL format date/time based on some query parameters. + * + * You can pass an array of values (year, month, etc.) with missing parameter values being defaulted to + * either the maximum or minimum values (controlled by the $default_to parameter). Alternatively you can + * pass a string that that will be run through strtotime(). + * + * @since 3.7.0 + * @access public + * + * @param string|array $datetime An array of parameters or a strotime() string + * @param string $default_to Controls what values default to if they are missing from $datetime. Pass "min" or "max". + * @return string|false A MySQL format date/time or false on failure + */ + public function build_mysql_datetime( $datetime, $default_to_max = false ) { + $now = current_time( 'timestamp' ); + + if ( ! is_array( $datetime ) ) { + // @todo Timezone issues here possibly + return gmdate( 'Y-m-d H:i:s', strtotime( $datetime, $now ) ); + } + + $datetime = array_map( 'absint', $datetime ); + + if ( ! isset( $datetime['year'] ) ) + $datetime['year'] = gmdate( 'Y', $now ); + + if ( ! isset( $datetime['month'] ) ) + $datetime['month'] = ( $default_to_max ) ? 12 : 1; + + if ( ! isset( $datetime['day'] ) ) + $datetime['day'] = ( $default_to_max ) ? (int) date( 't', mktime( 0, 0, 0, $datetime['month'], 1, $datetime['year'] ) ) : 1; + + if ( ! isset( $datetime['hour'] ) ) + $datetime['hour'] = ( $default_to_max ) ? 23 : 0; + + if ( ! isset( $datetime['minute'] ) ) + $datetime['minute'] = ( $default_to_max ) ? 59 : 0; + + if ( ! isset( $datetime['second'] ) ) + $datetime['second'] = ( $default_to_max ) ? 59 : 0; + + return sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $datetime['year'], $datetime['month'], $datetime['day'], $datetime['hour'], $datetime['minute'], $datetime['second'] ); + } + + /** + * Builds a query string for comparing time values (hour, minute, second). + * + * If just hour, minute, or second is set than a normal comparison will be done. + * However if multiple values are passed, a pseudo-decimal time will be created + * in order to be able to accurately compare against. + * + * @since 3.7.0 + * @access public + * + * @param string $column The column to query against. Needs to be pre-validated! + * @param string $compare The comparison operator. Needs to be pre-validated! + * @param int|null $hour Optional. An hour value (0-23). + * @param int|null $minute Optional. A minute value (0-59). + * @param int|null $second Optional. A second value (0-59). + * @return string|false A query part or false on failure. + */ + public function build_time_query( $column, $compare, $hour = null, $minute = null, $second = null ) { + global $wpdb; + + // Have to have at least one + if ( ! isset( $hour ) && ! isset( $minute ) && ! isset( $second ) ) + return false; + + // Complex combined queries aren't supported for multi-value queries + if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) { + $return = array(); + + if ( isset( $hour ) && false !== ( $value = $this->build_value( $compare, $hour ) ) ) + $return[] = "HOUR( $column ) $compare $value"; + + if ( isset( $minute ) && false !== ( $value = $this->build_value( $compare, $minute ) ) ) + $return[] = "MINUTE( $column ) $compare $value"; + + if ( isset( $second ) && false !== ( $value = $this->build_value( $compare, $second ) ) ) + $return[] = "SECOND( $column ) $compare $value"; + + return implode( ' AND ', $return ); + } + + // Cases where just one unit is set + if ( isset( $hour ) && ! isset( $minute ) && ! isset( $second ) && false !== ( $value = $this->build_value( $compare, $hour ) ) ) { + return "HOUR( $column ) $compare $value"; + } elseif ( ! isset( $hour ) && isset( $minute ) && ! isset( $second ) && false !== ( $value = $this->build_value( $compare, $minute ) ) ) { + return "MINUTE( $column ) $compare $value"; + } elseif ( ! isset( $hour ) && ! isset( $minute ) && isset( $second ) && false !== ( $value = $this->build_value( $compare, $second ) ) ) { + return "SECOND( $column ) $compare $value"; + } + + // Single units were already handled. Since hour & second isn't allowed, minute must to be set. + if ( ! isset( $minute ) ) + return false; + + $format = $time = ''; + + // Hour + if ( $hour ) { + $format .= '%H.'; + $time .= sprintf( '%02d', $hour ) . '.'; + } else { + $format .= '0.'; + $time .= '0.'; + } + + // Minute + $format .= '%i'; + $time .= sprintf( '%02d', $minute ); + + if ( isset( $second ) ) { + $format .= '%s'; + $time .= sprintf( '%02d', $second ); + } + + return $wpdb->prepare( "DATE_FORMAT( $column, %s ) $compare %f", $format, $time ); + } +} diff --git a/sources/wp-includes/default-constants.php b/sources/wp-includes/default-constants.php new file mode 100644 index 0000000..7326d6c --- /dev/null +++ b/sources/wp-includes/default-constants.php @@ -0,0 +1,316 @@ + 'widget_pages', 'description' => __( 'Your site’s WordPress Pages') ); + parent::__construct('pages', __('Pages'), $widget_ops); + } + + function widget( $args, $instance ) { + extract( $args ); + + $title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Pages' ) : $instance['title'], $instance, $this->id_base); + $sortby = empty( $instance['sortby'] ) ? 'menu_order' : $instance['sortby']; + $exclude = empty( $instance['exclude'] ) ? '' : $instance['exclude']; + + if ( $sortby == 'menu_order' ) + $sortby = 'menu_order, post_title'; + + $out = wp_list_pages( apply_filters('widget_pages_args', array('title_li' => '', 'echo' => 0, 'sort_column' => $sortby, 'exclude' => $exclude) ) ); + + if ( !empty( $out ) ) { + echo $before_widget; + if ( $title) + echo $before_title . $title . $after_title; + ?> +
      + +
    + 'post_title', 'title' => '', 'exclude' => '') ); + $title = esc_attr( $instance['title'] ); + $exclude = esc_attr( $instance['exclude'] ); + ?> +

    +

    + + +

    +

    + +
    + +

    + __( "Your blogroll" ) ); + parent::__construct('links', __('Links'), $widget_ops); + } + + function widget( $args, $instance ) { + extract($args, EXTR_SKIP); + + $show_description = isset($instance['description']) ? $instance['description'] : false; + $show_name = isset($instance['name']) ? $instance['name'] : false; + $show_rating = isset($instance['rating']) ? $instance['rating'] : false; + $show_images = isset($instance['images']) ? $instance['images'] : true; + $category = isset($instance['category']) ? $instance['category'] : false; + $orderby = isset( $instance['orderby'] ) ? $instance['orderby'] : 'name'; + $order = $orderby == 'rating' ? 'DESC' : 'ASC'; + $limit = isset( $instance['limit'] ) ? $instance['limit'] : -1; + + $before_widget = preg_replace('/id="[^"]*"/','id="%id"', $before_widget); + wp_list_bookmarks(apply_filters('widget_links_args', array( + 'title_before' => $before_title, 'title_after' => $after_title, + 'category_before' => $before_widget, 'category_after' => $after_widget, + 'show_images' => $show_images, 'show_description' => $show_description, + 'show_name' => $show_name, 'show_rating' => $show_rating, + 'category' => $category, 'class' => 'linkcat widget', + 'orderby' => $orderby, 'order' => $order, + 'limit' => $limit, + ))); + } + + function update( $new_instance, $old_instance ) { + $new_instance = (array) $new_instance; + $instance = array( 'images' => 0, 'name' => 0, 'description' => 0, 'rating' => 0 ); + foreach ( $instance as $field => $val ) { + if ( isset($new_instance[$field]) ) + $instance[$field] = 1; + } + + $instance['orderby'] = 'name'; + if ( in_array( $new_instance['orderby'], array( 'name', 'rating', 'id', 'rand' ) ) ) + $instance['orderby'] = $new_instance['orderby']; + + $instance['category'] = intval( $new_instance['category'] ); + $instance['limit'] = ! empty( $new_instance['limit'] ) ? intval( $new_instance['limit'] ) : -1; + + return $instance; + } + + function form( $instance ) { + + //Defaults + $instance = wp_parse_args( (array) $instance, array( 'images' => true, 'name' => true, 'description' => false, 'rating' => false, 'category' => false, 'orderby' => 'name', 'limit' => -1 ) ); + $link_cats = get_terms( 'link_category' ); + if ( ! $limit = intval( $instance['limit'] ) ) + $limit = -1; +?> +

    + + + + +

    +

    + id="get_field_id('images'); ?>" name="get_field_name('images'); ?>" /> +
    + id="get_field_id('name'); ?>" name="get_field_name('name'); ?>" /> +
    + id="get_field_id('description'); ?>" name="get_field_name('description'); ?>" /> +
    + id="get_field_id('rating'); ?>" name="get_field_name('rating'); ?>" /> + +

    +

    + + +

    + 'widget_search', 'description' => __( "A search form for your site") ); + parent::__construct('search', __('Search'), $widget_ops); + } + + function widget( $args, $instance ) { + extract($args); + $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base ); + + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; + + // Use current theme search form if it exists + get_search_form(); + + echo $after_widget; + } + + function form( $instance ) { + $instance = wp_parse_args( (array) $instance, array( 'title' => '') ); + $title = $instance['title']; +?> +

    + '')); + $instance['title'] = strip_tags($new_instance['title']); + return $instance; + } + +} + +/** + * Archives widget class + * + * @since 2.8.0 + */ +class WP_Widget_Archives extends WP_Widget { + + function __construct() { + $widget_ops = array('classname' => 'widget_archive', 'description' => __( 'A monthly archive of your site’s posts') ); + parent::__construct('archives', __('Archives'), $widget_ops); + } + + function widget( $args, $instance ) { + extract($args); + $c = ! empty( $instance['count'] ) ? '1' : '0'; + $d = ! empty( $instance['dropdown'] ) ? '1' : '0'; + $title = apply_filters('widget_title', empty($instance['title']) ? __('Archives') : $instance['title'], $instance, $this->id_base); + + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; + + if ( $d ) { +?> + + +
      + 'monthly', 'show_post_count' => $c))); ?> +
    + '', 'count' => 0, 'dropdown' => '') ); + $instance['title'] = strip_tags($new_instance['title']); + $instance['count'] = $new_instance['count'] ? 1 : 0; + $instance['dropdown'] = $new_instance['dropdown'] ? 1 : 0; + + return $instance; + } + + function form( $instance ) { + $instance = wp_parse_args( (array) $instance, array( 'title' => '', 'count' => 0, 'dropdown' => '') ); + $title = strip_tags($instance['title']); + $count = $instance['count'] ? 'checked="checked"' : ''; + $dropdown = $instance['dropdown'] ? 'checked="checked"' : ''; +?> +

    +

    + id="get_field_id('dropdown'); ?>" name="get_field_name('dropdown'); ?>" /> +
    + id="get_field_id('count'); ?>" name="get_field_name('count'); ?>" /> +

    + 'widget_meta', 'description' => __( "Log in/out, admin, feed and WordPress links") ); + parent::__construct('meta', __('Meta'), $widget_ops); + } + + function widget( $args, $instance ) { + extract($args); + $title = apply_filters('widget_title', empty($instance['title']) ? __('Meta') : $instance['title'], $instance, $this->id_base); + + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; +?> +
      + +
    • +
    • RSS'); ?>
    • +
    • RSS'); ?>
    • + %s', + esc_url( __( 'http://wordpress.org/' ) ), + esc_attr__( 'Powered by WordPress, state-of-the-art semantic personal publishing platform.' ), + _x( 'WordPress.org', 'meta widget link text' ) + ) ); ?> + +
    + '' ) ); + $title = strip_tags($instance['title']); +?> +

    + 'widget_calendar', 'description' => __( 'A calendar of your site’s posts') ); + parent::__construct('calendar', __('Calendar'), $widget_ops); + } + + function widget( $args, $instance ) { + extract($args); + $title = apply_filters('widget_title', empty($instance['title']) ? '' : $instance['title'], $instance, $this->id_base); + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; + echo '
    '; + get_calendar(); + echo '
    '; + echo $after_widget; + } + + function update( $new_instance, $old_instance ) { + $instance = $old_instance; + $instance['title'] = strip_tags($new_instance['title']); + + return $instance; + } + + function form( $instance ) { + $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) ); + $title = strip_tags($instance['title']); +?> +

    +

    + 'widget_text', 'description' => __('Arbitrary text or HTML')); + $control_ops = array('width' => 400, 'height' => 350); + parent::__construct('text', __('Text'), $widget_ops, $control_ops); + } + + function widget( $args, $instance ) { + extract($args); + $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base ); + $text = apply_filters( 'widget_text', empty( $instance['text'] ) ? '' : $instance['text'], $instance ); + echo $before_widget; + if ( !empty( $title ) ) { echo $before_title . $title . $after_title; } ?> +
    + '', 'text' => '' ) ); + $title = strip_tags($instance['title']); + $text = esc_textarea($instance['text']); +?> +

    +

    + + + +

    /> 

    + 'widget_categories', 'description' => __( "A list or dropdown of categories" ) ); + parent::__construct('categories', __('Categories'), $widget_ops); + } + + function widget( $args, $instance ) { + extract( $args ); + + $title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Categories' ) : $instance['title'], $instance, $this->id_base); + $c = ! empty( $instance['count'] ) ? '1' : '0'; + $h = ! empty( $instance['hierarchical'] ) ? '1' : '0'; + $d = ! empty( $instance['dropdown'] ) ? '1' : '0'; + + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; + + $cat_args = array('orderby' => 'name', 'show_count' => $c, 'hierarchical' => $h); + + if ( $d ) { + $cat_args['show_option_none'] = __('Select Category'); + wp_dropdown_categories(apply_filters('widget_categories_dropdown_args', $cat_args)); +?> + + + + +
      + +
    + '') ); + $title = esc_attr( $instance['title'] ); + $count = isset($instance['count']) ? (bool) $instance['count'] :false; + $hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false; + $dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false; +?> +

    +

    + +

    /> +
    + + /> +
    + + /> +

    + 'widget_recent_entries', 'description' => __( "The most recent posts on your site") ); + parent::__construct('recent-posts', __('Recent Posts'), $widget_ops); + $this->alt_option_name = 'widget_recent_entries'; + + add_action( 'save_post', array($this, 'flush_widget_cache') ); + add_action( 'deleted_post', array($this, 'flush_widget_cache') ); + add_action( 'switch_theme', array($this, 'flush_widget_cache') ); + } + + function widget($args, $instance) { + $cache = wp_cache_get('widget_recent_posts', 'widget'); + + if ( !is_array($cache) ) + $cache = array(); + + if ( ! isset( $args['widget_id'] ) ) + $args['widget_id'] = $this->id; + + if ( isset( $cache[ $args['widget_id'] ] ) ) { + echo $cache[ $args['widget_id'] ]; + return; + } + + ob_start(); + extract($args); + + $title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Recent Posts' ); + $title = apply_filters( 'widget_title', $title, $instance, $this->id_base ); + $number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 10; + if ( ! $number ) + $number = 10; + $show_date = isset( $instance['show_date'] ) ? $instance['show_date'] : false; + + $r = new WP_Query( apply_filters( 'widget_posts_args', array( 'posts_per_page' => $number, 'no_found_rows' => true, 'post_status' => 'publish', 'ignore_sticky_posts' => true ) ) ); + if ($r->have_posts()) : +?> + + +
      + have_posts() ) : $r->the_post(); ?> +
    • + + + + +
    • + +
    + +flush_widget_cache(); + + $alloptions = wp_cache_get( 'alloptions', 'options' ); + if ( isset($alloptions['widget_recent_entries']) ) + delete_option('widget_recent_entries'); + + return $instance; + } + + function flush_widget_cache() { + wp_cache_delete('widget_recent_posts', 'widget'); + } + + function form( $instance ) { + $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : ''; + $number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5; + $show_date = isset( $instance['show_date'] ) ? (bool) $instance['show_date'] : false; +?> +

    +

    + +

    +

    + +

    id="get_field_id( 'show_date' ); ?>" name="get_field_name( 'show_date' ); ?>" /> +

    + 'widget_recent_comments', 'description' => __( 'The most recent comments' ) ); + parent::__construct('recent-comments', __('Recent Comments'), $widget_ops); + $this->alt_option_name = 'widget_recent_comments'; + + if ( is_active_widget(false, false, $this->id_base) ) + add_action( 'wp_head', array($this, 'recent_comments_style') ); + + add_action( 'comment_post', array($this, 'flush_widget_cache') ); + add_action( 'edit_comment', array($this, 'flush_widget_cache') ); + add_action( 'transition_comment_status', array($this, 'flush_widget_cache') ); + } + + function recent_comments_style() { + if ( ! current_theme_supports( 'widgets' ) // Temp hack #14876 + || ! apply_filters( 'show_recent_comments_widget_style', true, $this->id_base ) ) + return; + ?> + +id; + + if ( isset( $cache[ $args['widget_id'] ] ) ) { + echo $cache[ $args['widget_id'] ]; + return; + } + + extract($args, EXTR_SKIP); + $output = ''; + + $title = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Recent Comments' ); + $title = apply_filters( 'widget_title', $title, $instance, $this->id_base ); + $number = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5; + if ( ! $number ) + $number = 5; + + $comments = get_comments( apply_filters( 'widget_comments_args', array( 'number' => $number, 'status' => 'approve', 'post_status' => 'publish' ) ) ); + $output .= $before_widget; + if ( $title ) + $output .= $before_title . $title . $after_title; + + $output .= '
      '; + if ( $comments ) { + // Prime cache for associated posts. (Prime post term cache if we need it for permalinks.) + $post_ids = array_unique( wp_list_pluck( $comments, 'comment_post_ID' ) ); + _prime_post_caches( $post_ids, strpos( get_option( 'permalink_structure' ), '%category%' ), false ); + + foreach ( (array) $comments as $comment) { + $output .= '
    • ' . /* translators: comments widget: 1: comment author, 2: post link */ sprintf(_x('%1$s on %2$s', 'widgets'), get_comment_author_link(), '' . get_the_title($comment->comment_post_ID) . '') . '
    • '; + } + } + $output .= '
    '; + $output .= $after_widget; + + echo $output; + $cache[$args['widget_id']] = $output; + wp_cache_set('widget_recent_comments', $cache, 'widget'); + } + + function update( $new_instance, $old_instance ) { + $instance = $old_instance; + $instance['title'] = strip_tags($new_instance['title']); + $instance['number'] = absint( $new_instance['number'] ); + $this->flush_widget_cache(); + + $alloptions = wp_cache_get( 'alloptions', 'options' ); + if ( isset($alloptions['widget_recent_comments']) ) + delete_option('widget_recent_comments'); + + return $instance; + } + + function form( $instance ) { + $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : ''; + $number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5; +?> +

    +

    + +

    +

    + __('Entries from any RSS or Atom feed') ); + $control_ops = array( 'width' => 400, 'height' => 200 ); + parent::__construct( 'rss', __('RSS'), $widget_ops, $control_ops ); + } + + function widget($args, $instance) { + + if ( isset($instance['error']) && $instance['error'] ) + return; + + extract($args, EXTR_SKIP); + + $url = ! empty( $instance['url'] ) ? $instance['url'] : ''; + while ( stristr($url, 'http') != $url ) + $url = substr($url, 1); + + if ( empty($url) ) + return; + + // self-url destruction sequence + if ( in_array( untrailingslashit( $url ), array( site_url(), home_url() ) ) ) + return; + + $rss = fetch_feed($url); + $title = $instance['title']; + $desc = ''; + $link = ''; + + if ( ! is_wp_error($rss) ) { + $desc = esc_attr(strip_tags(@html_entity_decode($rss->get_description(), ENT_QUOTES, get_option('blog_charset')))); + if ( empty($title) ) + $title = esc_html(strip_tags($rss->get_title())); + $link = esc_url(strip_tags($rss->get_permalink())); + while ( stristr($link, 'http') != $link ) + $link = substr($link, 1); + } + + if ( empty($title) ) + $title = empty($desc) ? __('Unknown Feed') : $desc; + + $title = apply_filters('widget_title', $title, $instance, $this->id_base); + $url = esc_url(strip_tags($url)); + $icon = includes_url('images/rss.png'); + if ( $title ) + $title = "RSS $title"; + + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; + wp_widget_rss_output( $rss, $instance ); + echo $after_widget; + + if ( ! is_wp_error($rss) ) + $rss->__destruct(); + unset($rss); + } + + function update($new_instance, $old_instance) { + $testurl = ( isset( $new_instance['url'] ) && ( !isset( $old_instance['url'] ) || ( $new_instance['url'] != $old_instance['url'] ) ) ); + return wp_widget_rss_process( $new_instance, $testurl ); + } + + function form($instance) { + + if ( empty($instance) ) + $instance = array( 'title' => '', 'url' => '', 'items' => 10, 'error' => false, 'show_summary' => 0, 'show_author' => 0, 'show_date' => 0 ); + $instance['number'] = $this->number; + + wp_widget_rss_form( $instance ); + } +} + +/** + * Display the RSS entries in a list. + * + * @since 2.5.0 + * + * @param string|array|object $rss RSS url. + * @param array $args Widget arguments. + */ +function wp_widget_rss_output( $rss, $args = array() ) { + if ( is_string( $rss ) ) { + $rss = fetch_feed($rss); + } elseif ( is_array($rss) && isset($rss['url']) ) { + $args = $rss; + $rss = fetch_feed($rss['url']); + } elseif ( !is_object($rss) ) { + return; + } + + if ( is_wp_error($rss) ) { + if ( is_admin() || current_user_can('manage_options') ) + echo '

    ' . sprintf( __('RSS Error: %s'), $rss->get_error_message() ) . '

    '; + return; + } + + $default_args = array( 'show_author' => 0, 'show_date' => 0, 'show_summary' => 0 ); + $args = wp_parse_args( $args, $default_args ); + extract( $args, EXTR_SKIP ); + + $items = (int) $items; + if ( $items < 1 || 20 < $items ) + $items = 10; + $show_summary = (int) $show_summary; + $show_author = (int) $show_author; + $show_date = (int) $show_date; + + if ( !$rss->get_item_quantity() ) { + echo '
    • ' . __( 'An error has occurred, which probably means the feed is down. Try again later.' ) . '
    '; + $rss->__destruct(); + unset($rss); + return; + } + + echo '
      '; + foreach ( $rss->get_items(0, $items) as $item ) { + $link = $item->get_link(); + while ( stristr($link, 'http') != $link ) + $link = substr($link, 1); + $link = esc_url(strip_tags($link)); + $title = esc_attr(strip_tags($item->get_title())); + if ( empty($title) ) + $title = __('Untitled'); + + $desc = str_replace( array("\n", "\r"), ' ', esc_attr( strip_tags( @html_entity_decode( $item->get_description(), ENT_QUOTES, get_option('blog_charset') ) ) ) ); + $excerpt = wp_html_excerpt( $desc, 360 ); + + // Append ellipsis. Change existing [...] to […]. + if ( '[...]' == substr( $excerpt, -5 ) ) + $excerpt = substr( $excerpt, 0, -5 ) . '[…]'; + elseif ( '[…]' != substr( $excerpt, -10 ) && $desc != $excerpt ) + $excerpt .= ' […]'; + + $excerpt = esc_html( $excerpt ); + + if ( $show_summary ) { + $summary = "
      $excerpt
      "; + } else { + $summary = ''; + } + + $date = ''; + if ( $show_date ) { + $date = $item->get_date( 'U' ); + + if ( $date ) { + $date = ' ' . date_i18n( get_option( 'date_format' ), $date ) . ''; + } + } + + $author = ''; + if ( $show_author ) { + $author = $item->get_author(); + if ( is_object($author) ) { + $author = $author->get_name(); + $author = ' ' . esc_html( strip_tags( $author ) ) . ''; + } + } + + if ( $link == '' ) { + echo "
    • $title{$date}{$summary}{$author}
    • "; + } else { + echo "
    • $title{$date}{$summary}{$author}
    • "; + } + } + echo '
    '; + $rss->__destruct(); + unset($rss); +} + +/** + * Display RSS widget options form. + * + * The options for what fields are displayed for the RSS form are all booleans + * and are as follows: 'url', 'title', 'items', 'show_summary', 'show_author', + * 'show_date'. + * + * @since 2.5.0 + * + * @param array|string $args Values for input fields. + * @param array $inputs Override default display options. + */ +function wp_widget_rss_form( $args, $inputs = null ) { + + $default_inputs = array( 'url' => true, 'title' => true, 'items' => true, 'show_summary' => true, 'show_author' => true, 'show_date' => true ); + $inputs = wp_parse_args( $inputs, $default_inputs ); + extract( $args ); + extract( $inputs, EXTR_SKIP ); + + $number = esc_attr( $number ); + $title = esc_attr( $title ); + $url = esc_url( $url ); + $items = (int) $items; + if ( $items < 1 || 20 < $items ) + $items = 10; + $show_summary = (int) $show_summary; + $show_author = (int) $show_author; + $show_date = (int) $show_date; + + if ( !empty($error) ) + echo '

    ' . sprintf( __('RSS Error: %s'), $error) . '

    '; + + if ( $inputs['url'] ) : +?> +

    +

    + +

    +

    + +

    +

    + +

    /> +

    + +

    /> +

    + +

    /> +

    + + +get_error_message(); + } else { + $link = esc_url(strip_tags($rss->get_permalink())); + while ( stristr($link, 'http') != $link ) + $link = substr($link, 1); + + $rss->__destruct(); + unset($rss); + } + } + + return compact( 'title', 'url', 'link', 'items', 'error', 'show_summary', 'show_author', 'show_date' ); +} + +/** + * Tag cloud widget class + * + * @since 2.8.0 + */ +class WP_Widget_Tag_Cloud extends WP_Widget { + + function __construct() { + $widget_ops = array( 'description' => __( "Your most used tags in cloud format") ); + parent::__construct('tag_cloud', __('Tag Cloud'), $widget_ops); + } + + function widget( $args, $instance ) { + extract($args); + $current_taxonomy = $this->_get_current_taxonomy($instance); + if ( !empty($instance['title']) ) { + $title = $instance['title']; + } else { + if ( 'post_tag' == $current_taxonomy ) { + $title = __('Tags'); + } else { + $tax = get_taxonomy($current_taxonomy); + $title = $tax->labels->name; + } + } + $title = apply_filters('widget_title', $title, $instance, $this->id_base); + + echo $before_widget; + if ( $title ) + echo $before_title . $title . $after_title; + echo '
    '; + wp_tag_cloud( apply_filters('widget_tag_cloud_args', array('taxonomy' => $current_taxonomy) ) ); + echo "
    \n"; + echo $after_widget; + } + + function update( $new_instance, $old_instance ) { + $instance['title'] = strip_tags(stripslashes($new_instance['title'])); + $instance['taxonomy'] = stripslashes($new_instance['taxonomy']); + return $instance; + } + + function form( $instance ) { + $current_taxonomy = $this->_get_current_taxonomy($instance); +?> +

    +

    +

    +

    __('Use this widget to add one of your custom menus as a widget.') ); + parent::__construct( 'nav_menu', __('Custom Menu'), $widget_ops ); + } + + function widget($args, $instance) { + // Get menu + $nav_menu = ! empty( $instance['nav_menu'] ) ? wp_get_nav_menu_object( $instance['nav_menu'] ) : false; + + if ( !$nav_menu ) + return; + + $instance['title'] = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base ); + + echo $args['before_widget']; + + if ( !empty($instance['title']) ) + echo $args['before_title'] . $instance['title'] . $args['after_title']; + + wp_nav_menu( array( 'fallback_cb' => '', 'menu' => $nav_menu ) ); + + echo $args['after_widget']; + } + + function update( $new_instance, $old_instance ) { + $instance['title'] = strip_tags( stripslashes($new_instance['title']) ); + $instance['nav_menu'] = (int) $new_instance['nav_menu']; + return $instance; + } + + function form( $instance ) { + $title = isset( $instance['title'] ) ? $instance['title'] : ''; + $nav_menu = isset( $instance['nav_menu'] ) ? $instance['nav_menu'] : ''; + + // Get menus + $menus = wp_get_nav_menus( array( 'orderby' => 'name' ) ); + + // If no menus exists, direct the user to go and create some. + if ( !$menus ) { + echo '

    '. sprintf( __('No menus have been created yet. Create some.'), admin_url('nav-menus.php') ) .'

    '; + return; + } + ?> +

    + + +

    +

    + + +

    + $post->ID, + 'Author_ID' => $post->post_author, + 'Date' => $post->post_date, + 'Content' => $post->post_content, + 'Excerpt' => $post->post_excerpt, + 'Title' => $post->post_title, + 'Category' => $post->post_category, + 'post_status' => $post->post_status, + 'comment_status' => $post->comment_status, + 'ping_status' => $post->ping_status, + 'post_password' => $post->post_password, + 'to_ping' => $post->to_ping, + 'pinged' => $post->pinged, + 'post_type' => $post->post_type, + 'post_name' => $post->post_name + ); + + return $postdata; +} + +/** + * Sets up the WordPress Loop. + * + * @since 1.0.1 + * @deprecated 1.5 + * @deprecated Use The Loop - {@link http://codex.wordpress.org/The_Loop Use new WordPress Loop} + */ +function start_wp() { + global $wp_query; + + _deprecated_function( __FUNCTION__, '1.5', __('new WordPress Loop') ); + + // Since the old style loop is being used, advance the query iterator here. + $wp_query->next_post(); + + setup_postdata( get_post() ); +} + +/** + * Return or Print Category ID. + * + * @since 0.71 + * @deprecated 0.71 + * @deprecated use get_the_category() + * @see get_the_category() + * + * @param bool $echo + * @return null|int + */ +function the_category_ID($echo = true) { + _deprecated_function( __FUNCTION__, '0.71', 'get_the_category()' ); + + // Grab the first cat in the list. + $categories = get_the_category(); + $cat = $categories[0]->term_id; + + if ( $echo ) + echo $cat; + + return $cat; +} + +/** + * Print category with optional text before and after. + * + * @since 0.71 + * @deprecated 0.71 + * @deprecated use get_the_category_by_ID() + * @see get_the_category_by_ID() + * + * @param string $before + * @param string $after + */ +function the_category_head($before='', $after='') { + global $currentcat, $previouscat; + + _deprecated_function( __FUNCTION__, '0.71', 'get_the_category_by_ID()' ); + + // Grab the first cat in the list. + $categories = get_the_category(); + $currentcat = $categories[0]->category_id; + if ( $currentcat != $previouscat ) { + echo $before; + echo get_the_category_by_ID($currentcat); + echo $after; + $previouscat = $currentcat; + } +} + +/** + * Prints link to the previous post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use previous_post_link() + * @see previous_post_link() + * + * @param string $format + * @param string $previous + * @param string $title + * @param string $in_same_cat + * @param int $limitprev + * @param string $excluded_categories + */ +function previous_post($format='%', $previous='previous post: ', $title='yes', $in_same_cat='no', $limitprev=1, $excluded_categories='') { + + _deprecated_function( __FUNCTION__, '2.0', 'previous_post_link()' ); + + if ( empty($in_same_cat) || 'no' == $in_same_cat ) + $in_same_cat = false; + else + $in_same_cat = true; + + $post = get_previous_post($in_same_cat, $excluded_categories); + + if ( !$post ) + return; + + $string = ''.$previous; + if ( 'yes' == $title ) + $string .= apply_filters('the_title', $post->post_title, $post->ID); + $string .= ''; + $format = str_replace('%', $string, $format); + echo $format; +} + +/** + * Prints link to the next post. + * + * @since 0.71 + * @deprecated 2.0 + * @deprecated Use next_post_link() + * @see next_post_link() + * + * @param string $format + * @param string $next + * @param string $title + * @param string $in_same_cat + * @param int $limitnext + * @param string $excluded_categories + */ +function next_post($format='%', $next='next post: ', $title='yes', $in_same_cat='no', $limitnext=1, $excluded_categories='') { + _deprecated_function( __FUNCTION__, '2.0', 'next_post_link()' ); + + if ( empty($in_same_cat) || 'no' == $in_same_cat ) + $in_same_cat = false; + else + $in_same_cat = true; + + $post = get_next_post($in_same_cat, $excluded_categories); + + if ( !$post ) + return; + + $string = ''.$next; + if ( 'yes' == $title ) + $string .= apply_filters('the_title', $post->post_title, $post->ID); + $string .= ''; + $format = str_replace('%', $string, $format); + echo $format; +} + +/** + * Whether user can create a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $blog_id Not Used + * @param int $category_id Not Used + * @return bool + */ +function user_can_create_post($user_id, $blog_id = 1, $category_id = 'None') { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + $author_data = get_userdata($user_id); + return ($author_data->user_level > 1); +} + +/** + * Whether user can create a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $blog_id Not Used + * @param int $category_id Not Used + * @return bool + */ +function user_can_create_draft($user_id, $blog_id = 1, $category_id = 'None') { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + $author_data = get_userdata($user_id); + return ($author_data->user_level >= 1); +} + +/** + * Whether user can edit a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool + */ +function user_can_edit_post($user_id, $post_id, $blog_id = 1) { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + $author_data = get_userdata($user_id); + $post = get_post($post_id); + $post_author_data = get_userdata($post->post_author); + + if ( (($user_id == $post_author_data->ID) && !($post->post_status == 'publish' && $author_data->user_level < 2)) + || ($author_data->user_level > $post_author_data->user_level) + || ($author_data->user_level >= 10) ) { + return true; + } else { + return false; + } +} + +/** + * Whether user can delete a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool + */ +function user_can_delete_post($user_id, $post_id, $blog_id = 1) { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + // right now if one can edit, one can delete + return user_can_edit_post($user_id, $post_id, $blog_id); +} + +/** + * Whether user can set new posts' dates. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $blog_id Not Used + * @param int $category_id Not Used + * @return bool + */ +function user_can_set_post_date($user_id, $blog_id = 1, $category_id = 'None') { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + $author_data = get_userdata($user_id); + return (($author_data->user_level > 4) && user_can_create_post($user_id, $blog_id, $category_id)); +} + +/** + * Whether user can delete a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool returns true if $user_id can edit $post_id's date + */ +function user_can_edit_post_date($user_id, $post_id, $blog_id = 1) { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + $author_data = get_userdata($user_id); + return (($author_data->user_level > 4) && user_can_edit_post($user_id, $post_id, $blog_id)); +} + +/** + * Whether user can delete a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool returns true if $user_id can edit $post_id's comments + */ +function user_can_edit_post_comments($user_id, $post_id, $blog_id = 1) { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + // right now if one can edit a post, one can edit comments made on it + return user_can_edit_post($user_id, $post_id, $blog_id); +} + +/** + * Whether user can delete a post. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $post_id + * @param int $blog_id Not Used + * @return bool returns true if $user_id can delete $post_id's comments + */ +function user_can_delete_post_comments($user_id, $post_id, $blog_id = 1) { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + // right now if one can edit comments, one can delete comments + return user_can_edit_post_comments($user_id, $post_id, $blog_id); +} + +/** + * Can user can edit other user. + * + * @since 1.5 + * @deprecated 2.0 + * @deprecated Use current_user_can() + * @see current_user_can() + * + * @param int $user_id + * @param int $other_user + * @return bool + */ +function user_can_edit_user($user_id, $other_user) { + _deprecated_function( __FUNCTION__, '2.0', 'current_user_can()' ); + + $user = get_userdata($user_id); + $other = get_userdata($other_user); + if ( $user->user_level > $other->user_level || $user->user_level > 8 || $user->ID == $other->ID ) + return true; + else + return false; +} + +/** + * Gets the links associated with category $cat_name. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use get_bookmarks() + * @see get_bookmarks() + * + * @param string $cat_name Optional. The category name to use. If no match is found uses all. + * @param string $before Optional. The html to output before the link. + * @param string $after Optional. The html to output after the link. + * @param string $between Optional. The html to output between the link/image and its description. Not used if no image or $show_images is true. + * @param bool $show_images Optional. Whether to show images (if defined). + * @param string $orderby Optional. The order to output the links. E.g. 'id', 'name', 'url', 'description' or 'rating'. Or maybe owner. + * If you start the name with an underscore the order will be reversed. You can also specify 'rand' as the order which will return links in a + * random order. + * @param bool $show_description Optional. Whether to show the description if show_images=false/not defined. + * @param bool $show_rating Optional. Show rating stars/chars. + * @param int $limit Optional. Limit to X entries. If not specified, all entries are shown. + * @param int $show_updated Optional. Whether to show last updated timestamp + */ +function get_linksbyname($cat_name = "noname", $before = '', $after = '
    ', $between = " ", $show_images = true, $orderby = 'id', + $show_description = true, $show_rating = false, + $limit = -1, $show_updated = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmarks()' ); + + $cat_id = -1; + $cat = get_term_by('name', $cat_name, 'link_category'); + if ( $cat ) + $cat_id = $cat->term_id; + + get_links($cat_id, $before, $after, $between, $show_images, $orderby, $show_description, $show_rating, $limit, $show_updated); +} + +/** + * Gets the links associated with the named category. + * + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use wp_list_bookmarks() + * @see wp_list_bookmarks() + * + * @param string $category The category to use. + * @param string $args + * @return bool|null + */ +function wp_get_linksbyname($category, $args = '') { + _deprecated_function(__FUNCTION__, '2.1', 'wp_list_bookmarks()'); + + $defaults = array( + 'after' => '
    ', + 'before' => '', + 'categorize' => 0, + 'category_after' => '', + 'category_before' => '', + 'category_name' => $category, + 'show_description' => 1, + 'title_li' => '', + ); + + $r = wp_parse_args( $args, $defaults ); + + return wp_list_bookmarks($r); +} + +/** + * Gets an array of link objects associated with category $cat_name. + * + * + * $links = get_linkobjectsbyname('fred'); + * foreach ($links as $link) { + * echo '
  • '.$link->link_name.'
  • '; + * } + *
    + * + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use get_bookmarks() + * @see get_bookmarks() + * + * @param string $cat_name The category name to use. If no match is found uses all. + * @param string $orderby The order to output the links. E.g. 'id', 'name', 'url', 'description', or 'rating'. + * Or maybe owner. If you start the name with an underscore the order will be reversed. You can also + * specify 'rand' as the order which will return links in a random order. + * @param int $limit Limit to X entries. If not specified, all entries are shown. + * @return unknown + */ +function get_linkobjectsbyname($cat_name = "noname" , $orderby = 'name', $limit = -1) { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmarks()' ); + + $cat_id = -1; + $cat = get_term_by('name', $cat_name, 'link_category'); + if ( $cat ) + $cat_id = $cat->term_id; + + return get_linkobjects($cat_id, $orderby, $limit); +} + +/** + * Gets an array of link objects associated with category n. + * + * Usage: + * + * $links = get_linkobjects(1); + * if ($links) { + * foreach ($links as $link) { + * echo '
  • '.$link->link_name.'
    '.$link->link_description.'
  • '; + * } + * } + *
    + * + * Fields are: + *
      + *
    1. link_id
    2. + *
    3. link_url
    4. + *
    5. link_name
    6. + *
    7. link_image
    8. + *
    9. link_target
    10. + *
    11. link_category
    12. + *
    13. link_description
    14. + *
    15. link_visible
    16. + *
    17. link_owner
    18. + *
    19. link_rating
    20. + *
    21. link_updated
    22. + *
    23. link_rel
    24. + *
    25. link_notes
    26. + *
    + * + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use get_bookmarks() + * @see get_bookmarks() + * + * @param int $category The category to use. If no category supplied uses all + * @param string $orderby the order to output the links. E.g. 'id', 'name', 'url', + * 'description', or 'rating'. Or maybe owner. If you start the name with an + * underscore the order will be reversed. You can also specify 'rand' as the + * order which will return links in a random order. + * @param int $limit Limit to X entries. If not specified, all entries are shown. + * @return unknown + */ +function get_linkobjects($category = 0, $orderby = 'name', $limit = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmarks()' ); + + $links = get_bookmarks( array( 'category' => $category, 'orderby' => $orderby, 'limit' => $limit ) ) ; + + $links_array = array(); + foreach ($links as $link) + $links_array[] = $link; + + return $links_array; +} + +/** + * Gets the links associated with category 'cat_name' and display rating stars/chars. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use get_bookmarks() + * @see get_bookmarks() + * + * @param string $cat_name The category name to use. If no match is found uses all + * @param string $before The html to output before the link + * @param string $after The html to output after the link + * @param string $between The html to output between the link/image and its description. Not used if no image or show_images is true + * @param bool $show_images Whether to show images (if defined). + * @param string $orderby the order to output the links. E.g. 'id', 'name', 'url', + * 'description', or 'rating'. Or maybe owner. If you start the name with an + * underscore the order will be reversed. You can also specify 'rand' as the + * order which will return links in a random order. + * @param bool $show_description Whether to show the description if show_images=false/not defined + * @param int $limit Limit to X entries. If not specified, all entries are shown. + * @param int $show_updated Whether to show last updated timestamp + */ +function get_linksbyname_withrating($cat_name = "noname", $before = '', $after = '
    ', $between = " ", + $show_images = true, $orderby = 'id', $show_description = true, $limit = -1, $show_updated = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmarks()' ); + + get_linksbyname($cat_name, $before, $after, $between, $show_images, $orderby, $show_description, true, $limit, $show_updated); +} + +/** + * Gets the links associated with category n and display rating stars/chars. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use get_bookmarks() + * @see get_bookmarks() + * + * @param int $category The category to use. If no category supplied uses all + * @param string $before The html to output before the link + * @param string $after The html to output after the link + * @param string $between The html to output between the link/image and its description. Not used if no image or show_images == true + * @param bool $show_images Whether to show images (if defined). + * @param string $orderby The order to output the links. E.g. 'id', 'name', 'url', + * 'description', or 'rating'. Or maybe owner. If you start the name with an + * underscore the order will be reversed. You can also specify 'rand' as the + * order which will return links in a random order. + * @param bool $show_description Whether to show the description if show_images=false/not defined. + * @param string $limit Limit to X entries. If not specified, all entries are shown. + * @param int $show_updated Whether to show last updated timestamp + */ +function get_links_withrating($category = -1, $before = '', $after = '
    ', $between = " ", $show_images = true, + $orderby = 'id', $show_description = true, $limit = -1, $show_updated = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmarks()' ); + + get_links($category, $before, $after, $between, $show_images, $orderby, $show_description, true, $limit, $show_updated); +} + +/** + * Gets the auto_toggle setting. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated No alternative function available + * + * @param int $id The category to get. If no category supplied uses 0 + * @return int Only returns 0. + */ +function get_autotoggle($id = 0) { + _deprecated_function( __FUNCTION__, '2.1' ); + return 0; +} + +/** + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use wp_list_categories() + * @see wp_list_categories() + * + * @param int $optionall + * @param string $all + * @param string $sort_column + * @param string $sort_order + * @param string $file + * @param bool $list + * @param int $optiondates + * @param int $optioncount + * @param int $hide_empty + * @param int $use_desc_for_title + * @param bool $children + * @param int $child_of + * @param int $categories + * @param int $recurse + * @param string $feed + * @param string $feed_image + * @param string $exclude + * @param bool $hierarchical + * @return unknown + */ +function list_cats($optionall = 1, $all = 'All', $sort_column = 'ID', $sort_order = 'asc', $file = '', $list = true, $optiondates = 0, + $optioncount = 0, $hide_empty = 1, $use_desc_for_title = 1, $children=false, $child_of=0, $categories=0, + $recurse=0, $feed = '', $feed_image = '', $exclude = '', $hierarchical=false) { + _deprecated_function( __FUNCTION__, '2.1', 'wp_list_categories()' ); + + $query = compact('optionall', 'all', 'sort_column', 'sort_order', 'file', 'list', 'optiondates', 'optioncount', 'hide_empty', 'use_desc_for_title', 'children', + 'child_of', 'categories', 'recurse', 'feed', 'feed_image', 'exclude', 'hierarchical'); + return wp_list_cats($query); +} + +/** + * @since 1.2 + * @deprecated 2.1 + * @deprecated Use wp_list_categories() + * @see wp_list_categories() + * + * @param string|array $args + * @return unknown + */ +function wp_list_cats($args = '') { + _deprecated_function( __FUNCTION__, '2.1', 'wp_list_categories()' ); + + $r = wp_parse_args( $args ); + + // Map to new names. + if ( isset($r['optionall']) && isset($r['all'])) + $r['show_option_all'] = $r['all']; + if ( isset($r['sort_column']) ) + $r['orderby'] = $r['sort_column']; + if ( isset($r['sort_order']) ) + $r['order'] = $r['sort_order']; + if ( isset($r['optiondates']) ) + $r['show_last_update'] = $r['optiondates']; + if ( isset($r['optioncount']) ) + $r['show_count'] = $r['optioncount']; + if ( isset($r['list']) ) + $r['style'] = $r['list'] ? 'list' : 'break'; + $r['title_li'] = ''; + + return wp_list_categories($r); +} + +/** + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use wp_dropdown_categories() + * @see wp_dropdown_categories() + * + * @param int $optionall + * @param string $all + * @param string $orderby + * @param string $order + * @param int $show_last_update + * @param int $show_count + * @param int $hide_empty + * @param bool $optionnone + * @param int $selected + * @param int $exclude + * @return unknown + */ +function dropdown_cats($optionall = 1, $all = 'All', $orderby = 'ID', $order = 'asc', + $show_last_update = 0, $show_count = 0, $hide_empty = 1, $optionnone = false, + $selected = 0, $exclude = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'wp_dropdown_categories()' ); + + $show_option_all = ''; + if ( $optionall ) + $show_option_all = $all; + + $show_option_none = ''; + if ( $optionnone ) + $show_option_none = __('None'); + + $vars = compact('show_option_all', 'show_option_none', 'orderby', 'order', + 'show_last_update', 'show_count', 'hide_empty', 'selected', 'exclude'); + $query = add_query_arg($vars, ''); + return wp_dropdown_categories($query); +} + +/** + * @since 1.2 + * @deprecated 2.1 + * @deprecated Use wp_list_authors() + * @see wp_list_authors() + * + * @param bool $optioncount + * @param bool $exclude_admin + * @param bool $show_fullname + * @param bool $hide_empty + * @param string $feed + * @param string $feed_image + * @return unknown + */ +function list_authors($optioncount = false, $exclude_admin = true, $show_fullname = false, $hide_empty = true, $feed = '', $feed_image = '') { + _deprecated_function( __FUNCTION__, '2.1', 'wp_list_authors()' ); + + $args = compact('optioncount', 'exclude_admin', 'show_fullname', 'hide_empty', 'feed', 'feed_image'); + return wp_list_authors($args); +} + +/** + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use wp_get_post_categories() + * @see wp_get_post_categories() + * + * @param int $blogid Not Used + * @param int $post_ID + * @return unknown + */ +function wp_get_post_cats($blogid = '1', $post_ID = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'wp_get_post_categories()' ); + return wp_get_post_categories($post_ID); +} + +/** + * Sets the categories that the post id belongs to. + * + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use wp_set_post_categories() + * @see wp_set_post_categories() + * + * @param int $blogid Not used + * @param int $post_ID + * @param array $post_categories + * @return unknown + */ +function wp_set_post_cats($blogid = '1', $post_ID = 0, $post_categories = array()) { + _deprecated_function( __FUNCTION__, '2.1', 'wp_set_post_categories()' ); + return wp_set_post_categories($post_ID, $post_categories); +} + +/** + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use wp_get_archives() + * @see wp_get_archives() + * + * @param string $type + * @param string $limit + * @param string $format + * @param string $before + * @param string $after + * @param bool $show_post_count + * @return unknown + */ +function get_archives($type='', $limit='', $format='html', $before = '', $after = '', $show_post_count = false) { + _deprecated_function( __FUNCTION__, '2.1', 'wp_get_archives()' ); + $args = compact('type', 'limit', 'format', 'before', 'after', 'show_post_count'); + return wp_get_archives($args); +} + +/** + * Returns or Prints link to the author's posts. + * + * @since 1.2 + * @deprecated 2.1 + * @deprecated Use get_author_posts_url() + * @see get_author_posts_url() + * + * @param bool $echo + * @param int $author_id + * @param string $author_nicename Optional. + * @return string|null + */ +function get_author_link($echo, $author_id, $author_nicename = '') { + _deprecated_function( __FUNCTION__, '2.1', 'get_author_posts_url()' ); + + $link = get_author_posts_url($author_id, $author_nicename); + + if ( $echo ) + echo $link; + return $link; +} + +/** + * Print list of pages based on arguments. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use wp_link_pages() + * @see wp_link_pages() + * + * @param string $before + * @param string $after + * @param string $next_or_number + * @param string $nextpagelink + * @param string $previouspagelink + * @param string $pagelink + * @param string $more_file + * @return string + */ +function link_pages($before='
    ', $after='
    ', $next_or_number='number', $nextpagelink='next page', $previouspagelink='previous page', + $pagelink='%', $more_file='') { + _deprecated_function( __FUNCTION__, '2.1', 'wp_link_pages()' ); + + $args = compact('before', 'after', 'next_or_number', 'nextpagelink', 'previouspagelink', 'pagelink', 'more_file'); + return wp_link_pages($args); +} + +/** + * Get value based on option. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use get_option() + * @see get_option() + * + * @param string $option + * @return string + */ +function get_settings($option) { + _deprecated_function( __FUNCTION__, '2.1', 'get_option()' ); + + return get_option($option); +} + +/** + * Print the permalink of the current post in the loop. + * + * @since 0.71 + * @deprecated 1.2 + * @deprecated Use the_permalink() + * @see the_permalink() + */ +function permalink_link() { + _deprecated_function( __FUNCTION__, '1.2', 'the_permalink()' ); + the_permalink(); +} + +/** + * Print the permalink to the RSS feed. + * + * @since 0.71 + * @deprecated 2.3 + * @deprecated Use the_permalink_rss() + * @see the_permalink_rss() + * + * @param string $deprecated + */ +function permalink_single_rss($deprecated = '') { + _deprecated_function( __FUNCTION__, '2.3', 'the_permalink_rss()' ); + the_permalink_rss(); +} + +/** + * Gets the links associated with category. + * + * @see get_links() for argument information that can be used in $args + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use wp_list_bookmarks() + * @see wp_list_bookmarks() + * + * @param string $args a query string + * @return null|string + */ +function wp_get_links($args = '') { + _deprecated_function( __FUNCTION__, '2.1', 'wp_list_bookmarks()' ); + + if ( strpos( $args, '=' ) === false ) { + $cat_id = $args; + $args = add_query_arg( 'category', $cat_id, $args ); + } + + $defaults = array( + 'after' => '
    ', + 'before' => '', + 'between' => ' ', + 'categorize' => 0, + 'category' => '', + 'echo' => true, + 'limit' => -1, + 'orderby' => 'name', + 'show_description' => true, + 'show_images' => true, + 'show_rating' => false, + 'show_updated' => true, + 'title_li' => '', + ); + + $r = wp_parse_args( $args, $defaults ); + + return wp_list_bookmarks($r); +} + +/** + * Gets the links associated with category by id. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use get_bookmarks() + * @see get_bookmarks() + * + * @param int $category The category to use. If no category supplied uses all + * @param string $before the html to output before the link + * @param string $after the html to output after the link + * @param string $between the html to output between the link/image and its description. + * Not used if no image or show_images == true + * @param bool $show_images whether to show images (if defined). + * @param string $orderby the order to output the links. E.g. 'id', 'name', 'url', + * 'description', or 'rating'. Or maybe owner. If you start the name with an + * underscore the order will be reversed. You can also specify 'rand' as the order + * which will return links in a random order. + * @param bool $show_description whether to show the description if show_images=false/not defined. + * @param bool $show_rating show rating stars/chars + * @param int $limit Limit to X entries. If not specified, all entries are shown. + * @param int $show_updated whether to show last updated timestamp + * @param bool $echo whether to echo the results, or return them instead + * @return null|string + */ +function get_links($category = -1, $before = '', $after = '
    ', $between = ' ', $show_images = true, $orderby = 'name', + $show_description = true, $show_rating = false, $limit = -1, $show_updated = 1, $echo = true) { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmarks()' ); + + $order = 'ASC'; + if ( substr($orderby, 0, 1) == '_' ) { + $order = 'DESC'; + $orderby = substr($orderby, 1); + } + + if ( $category == -1 ) //get_bookmarks uses '' to signify all categories + $category = ''; + + $results = get_bookmarks(array('category' => $category, 'orderby' => $orderby, 'order' => $order, 'show_updated' => $show_updated, 'limit' => $limit)); + + if ( !$results ) + return; + + $output = ''; + + foreach ( (array) $results as $row ) { + if ( !isset($row->recently_updated) ) + $row->recently_updated = false; + $output .= $before; + if ( $show_updated && $row->recently_updated ) + $output .= get_option('links_recently_updated_prepend'); + $the_link = '#'; + if ( !empty($row->link_url) ) + $the_link = esc_url($row->link_url); + $rel = $row->link_rel; + if ( '' != $rel ) + $rel = ' rel="' . $rel . '"'; + + $desc = esc_attr(sanitize_bookmark_field('link_description', $row->link_description, $row->link_id, 'display')); + $name = esc_attr(sanitize_bookmark_field('link_name', $row->link_name, $row->link_id, 'display')); + $title = $desc; + + if ( $show_updated ) + if (substr($row->link_updated_f, 0, 2) != '00') + $title .= ' ('.__('Last updated') . ' ' . date(get_option('links_updated_date_format'), $row->link_updated_f + (get_option('gmt_offset') * HOUR_IN_SECONDS)) . ')'; + + if ( '' != $title ) + $title = ' title="' . $title . '"'; + + $alt = ' alt="' . $name . '"'; + + $target = $row->link_target; + if ( '' != $target ) + $target = ' target="' . $target . '"'; + + $output .= ''; + + if ( $row->link_image != null && $show_images ) { + if ( strpos($row->link_image, 'http') !== false ) + $output .= "link_image\" $alt $title />"; + else // If it's a relative path + $output .= "link_image\" $alt $title />"; + } else { + $output .= $name; + } + + $output .= ''; + + if ( $show_updated && $row->recently_updated ) + $output .= get_option('links_recently_updated_append'); + + if ( $show_description && '' != $desc ) + $output .= $between . $desc; + + if ($show_rating) { + $output .= $between . get_linkrating($row); + } + + $output .= "$after\n"; + } // end while + + if ( !$echo ) + return $output; + echo $output; +} + +/** + * Output entire list of links by category. + * + * Output a list of all links, listed by category, using the settings in + * $wpdb->linkcategories and output it as a nested HTML unordered list. + * + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use wp_list_bookmarks() + * @see wp_list_bookmarks() + * + * @param string $order Sort link categories by 'name' or 'id' + */ +function get_links_list($order = 'name') { + _deprecated_function( __FUNCTION__, '2.1', 'wp_list_bookmarks()' ); + + $order = strtolower($order); + + // Handle link category sorting + $direction = 'ASC'; + if ( '_' == substr($order,0,1) ) { + $direction = 'DESC'; + $order = substr($order,1); + } + + if ( !isset($direction) ) + $direction = ''; + + $cats = get_categories(array('type' => 'link', 'orderby' => $order, 'order' => $direction, 'hierarchical' => 0)); + + // Display each category + if ( $cats ) { + foreach ( (array) $cats as $cat ) { + // Handle each category. + + // Display the category name + echo '
  • ' . apply_filters('link_category', $cat->name ) . "

    \n\t
      \n"; + // Call get_links() with all the appropriate params + get_links($cat->term_id, '
    • ', "
    • ", "\n", true, 'name', false); + + // Close the last category + echo "\n\t
    \n
  • \n"; + } + } +} + +/** + * Show the link to the links popup and the number of links. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated {@internal Use function instead is unknown}} + * + * @param string $text the text of the link + * @param int $width the width of the popup window + * @param int $height the height of the popup window + * @param string $file the page to open in the popup window + * @param bool $count the number of links in the db + */ +function links_popup_script($text = 'Links', $width=400, $height=400, $file='links.all.php', $count = true) { + _deprecated_function( __FUNCTION__, '2.1' ); +} + +/** + * @since 1.0.1 + * @deprecated 2.1 + * @deprecated Use sanitize_bookmark_field() + * @see sanitize_bookmark_field() + * + * @param object $link + * @return unknown + */ +function get_linkrating($link) { + _deprecated_function( __FUNCTION__, '2.1', 'sanitize_bookmark_field()' ); + return sanitize_bookmark_field('link_rating', $link->link_rating, $link->link_id, 'display'); +} + +/** + * Gets the name of category by id. + * + * @since 0.71 + * @deprecated 2.1 + * @deprecated Use get_category() + * @see get_category() + * + * @param int $id The category to get. If no category supplied uses 0 + * @return string + */ +function get_linkcatname($id = 0) { + _deprecated_function( __FUNCTION__, '2.1', 'get_category()' ); + + $id = (int) $id; + + if ( empty($id) ) + return ''; + + $cats = wp_get_link_cats($id); + + if ( empty($cats) || ! is_array($cats) ) + return ''; + + $cat_id = (int) $cats[0]; // Take the first cat. + + $cat = get_category($cat_id); + return $cat->name; +} + +/** + * Print RSS comment feed link. + * + * @since 1.0.1 + * @deprecated 2.5 + * @deprecated Use post_comments_feed_link() + * @see post_comments_feed_link() + * + * @param string $link_text + */ +function comments_rss_link($link_text = 'Comments RSS') { + _deprecated_function( __FUNCTION__, '2.5', 'post_comments_feed_link()' ); + post_comments_feed_link($link_text); +} + +/** + * Print/Return link to category RSS2 feed. + * + * @since 1.2 + * @deprecated 2.5 + * @deprecated Use get_category_feed_link() + * @see get_category_feed_link() + * + * @param bool $echo + * @param int $cat_ID + * @return string|null + */ +function get_category_rss_link($echo = false, $cat_ID = 1) { + _deprecated_function( __FUNCTION__, '2.5', 'get_category_feed_link()' ); + + $link = get_category_feed_link($cat_ID, 'rss2'); + + if ( $echo ) + echo $link; + return $link; +} + +/** + * Print/Return link to author RSS feed. + * + * @since 1.2 + * @deprecated 2.5 + * @deprecated Use get_author_feed_link() + * @see get_author_feed_link() + * + * @param bool $echo + * @param int $author_id + * @return string|null + */ +function get_author_rss_link($echo = false, $author_id = 1) { + _deprecated_function( __FUNCTION__, '2.5', 'get_author_feed_link()' ); + + $link = get_author_feed_link($author_id); + if ( $echo ) + echo $link; + return $link; +} + +/** + * Return link to the post RSS feed. + * + * @since 1.5 + * @deprecated 2.2 + * @deprecated Use get_post_comments_feed_link() + * @see get_post_comments_feed_link() + * + * @return string + */ +function comments_rss() { + _deprecated_function( __FUNCTION__, '2.2', 'get_post_comments_feed_link()' ); + return esc_url( get_post_comments_feed_link() ); +} + +/** + * An alias of wp_create_user(). + * + * @since 2.0 + * @deprecated 2.0 + * @deprecated Use wp_create_user() + * @see wp_create_user() + * + * @param string $username The user's username. + * @param string $password The user's password. + * @param string $email The user's email (optional). + * @return int The new user's ID. + */ +function create_user($username, $password, $email) { + _deprecated_function( __FUNCTION__, '2.0', 'wp_create_user()' ); + return wp_create_user($username, $password, $email); +} + +/** + * Unused function. + * + * @deprecated 2.5 +*/ +function gzip_compression() { + _deprecated_function( __FUNCTION__, '2.5' ); + return false; +} + +/** + * Retrieve an array of comment data about comment $comment_ID. + * + * @since 0.71 + * @deprecated 2.7 + * @deprecated Use get_comment() + * @see get_comment() + * + * @param int $comment_ID The ID of the comment + * @param int $no_cache Whether to use the cache (cast to bool) + * @param bool $include_unapproved Whether to include unapproved comments + * @return array The comment data + */ +function get_commentdata( $comment_ID, $no_cache = 0, $include_unapproved = false ) { + _deprecated_function( __FUNCTION__, '2.7', 'get_comment()' ); + return get_comment($comment_ID, ARRAY_A); +} + +/** + * Retrieve the category name by the category ID. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use get_cat_name() + * @see get_cat_name() + * + * @param int $cat_ID Category ID + * @return string category name + */ +function get_catname( $cat_ID ) { + _deprecated_function( __FUNCTION__, '2.8', 'get_cat_name()' ); + return get_cat_name( $cat_ID ); +} + +/** + * Retrieve category children list separated before and after the term IDs. + * + * @since 1.2.0 + * @deprecated 2.8 + * @deprecated Use get_term_children() + * @see get_term_children() + * + * @param int $id Category ID to retrieve children. + * @param string $before Optional. Prepend before category term ID. + * @param string $after Optional, default is empty string. Append after category term ID. + * @param array $visited Optional. Category Term IDs that have already been added. + * @return string + */ +function get_category_children( $id, $before = '/', $after = '', $visited = array() ) { + _deprecated_function( __FUNCTION__, '2.8', 'get_term_children()' ); + if ( 0 == $id ) + return ''; + + $chain = ''; + /** TODO: consult hierarchy */ + $cat_ids = get_all_category_ids(); + foreach ( (array) $cat_ids as $cat_id ) { + if ( $cat_id == $id ) + continue; + + $category = get_category( $cat_id ); + if ( is_wp_error( $category ) ) + return $category; + if ( $category->parent == $id && !in_array( $category->term_id, $visited ) ) { + $visited[] = $category->term_id; + $chain .= $before.$category->term_id.$after; + $chain .= get_category_children( $category->term_id, $before, $after ); + } + } + return $chain; +} + +/** + * Retrieve the description of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('description') + * @see get_the_author_meta() + * + * @return string The author's description. + */ +function get_the_author_description() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'description\')' ); + return get_the_author_meta('description'); +} + +/** + * Display the description of the author of the current post. + * + * @since 1.0.0 + * @deprecated 2.8 + * @deprecated Use the_author_meta('description') + * @see the_author_meta() + */ +function the_author_description() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'description\')' ); + the_author_meta('description'); +} + +/** + * Retrieve the login name of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('login') + * @see get_the_author_meta() + * + * @return string The author's login name (username). + */ +function get_the_author_login() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'login\')' ); + return get_the_author_meta('login'); +} + +/** + * Display the login name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('login') + * @see the_author_meta() + */ +function the_author_login() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'login\')' ); + the_author_meta('login'); +} + +/** + * Retrieve the first name of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('first_name') + * @see get_the_author_meta() + * + * @return string The author's first name. + */ +function get_the_author_firstname() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'first_name\')' ); + return get_the_author_meta('first_name'); +} + +/** + * Display the first name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('first_name') + * @see the_author_meta() + */ +function the_author_firstname() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'first_name\')' ); + the_author_meta('first_name'); +} + +/** + * Retrieve the last name of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('last_name') + * @see get_the_author_meta() + * + * @return string The author's last name. + */ +function get_the_author_lastname() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'last_name\')' ); + return get_the_author_meta('last_name'); +} + +/** + * Display the last name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('last_name') + * @see the_author_meta() + */ +function the_author_lastname() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'last_name\')' ); + the_author_meta('last_name'); +} + +/** + * Retrieve the nickname of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('nickname') + * @see get_the_author_meta() + * + * @return string The author's nickname. + */ +function get_the_author_nickname() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'nickname\')' ); + return get_the_author_meta('nickname'); +} + +/** + * Display the nickname of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('nickname') + * @see the_author_meta() + */ +function the_author_nickname() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'nickname\')' ); + the_author_meta('nickname'); +} + +/** + * Retrieve the email of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('email') + * @see get_the_author_meta() + * + * @return string The author's username. + */ +function get_the_author_email() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'email\')' ); + return get_the_author_meta('email'); +} + +/** + * Display the email of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('email') + * @see the_author_meta() + */ +function the_author_email() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'email\')' ); + the_author_meta('email'); +} + +/** + * Retrieve the ICQ number of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('icq') + * @see get_the_author_meta() + * + * @return string The author's ICQ number. + */ +function get_the_author_icq() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'icq\')' ); + return get_the_author_meta('icq'); +} + +/** + * Display the ICQ number of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('icq') + * @see the_author_meta() + */ +function the_author_icq() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'icq\')' ); + the_author_meta('icq'); +} + +/** + * Retrieve the Yahoo! IM name of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('yim') + * @see get_the_author_meta() + * + * @return string The author's Yahoo! IM name. + */ +function get_the_author_yim() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'yim\')' ); + return get_the_author_meta('yim'); +} + +/** + * Display the Yahoo! IM name of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('yim') + * @see the_author_meta() + */ +function the_author_yim() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'yim\')' ); + the_author_meta('yim'); +} + +/** + * Retrieve the MSN address of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('msn') + * @see get_the_author_meta() + * + * @return string The author's MSN address. + */ +function get_the_author_msn() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'msn\')' ); + return get_the_author_meta('msn'); +} + +/** + * Display the MSN address of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('msn') + * @see the_author_meta() + */ +function the_author_msn() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'msn\')' ); + the_author_meta('msn'); +} + +/** + * Retrieve the AIM address of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('aim') + * @see get_the_author_meta() + * + * @return string The author's AIM address. + */ +function get_the_author_aim() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'aim\')' ); + return get_the_author_meta('aim'); +} + +/** + * Display the AIM address of the author of the current post. + * + * @since 0.71 + * @see the_author_meta() + * @deprecated 2.8 + * @deprecated Use the_author_meta('aim') + */ +function the_author_aim() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'aim\')' ); + the_author_meta('aim'); +} + +/** + * Retrieve the specified author's preferred display name. + * + * @since 1.0.0 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('display_name') + * @see get_the_author_meta() + * + * @param int $auth_id The ID of the author. + * @return string The author's display name. + */ +function get_author_name( $auth_id = false ) { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'display_name\')' ); + return get_the_author_meta('display_name', $auth_id); +} + +/** + * Retrieve the URL to the home page of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('url') + * @see get_the_author_meta() + * + * @return string The URL to the author's page. + */ +function get_the_author_url() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'url\')' ); + return get_the_author_meta('url'); +} + +/** + * Display the URL to the home page of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('url') + * @see the_author_meta() + */ +function the_author_url() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'url\')' ); + the_author_meta('url'); +} + +/** + * Retrieve the ID of the author of the current post. + * + * @since 1.5 + * @deprecated 2.8 + * @deprecated Use get_the_author_meta('ID') + * @see get_the_author_meta() + * + * @return int The author's ID. + */ +function get_the_author_ID() { + _deprecated_function( __FUNCTION__, '2.8', 'get_the_author_meta(\'ID\')' ); + return get_the_author_meta('ID'); +} + +/** + * Display the ID of the author of the current post. + * + * @since 0.71 + * @deprecated 2.8 + * @deprecated Use the_author_meta('ID') + * @see the_author_meta() +*/ +function the_author_ID() { + _deprecated_function( __FUNCTION__, '2.8', 'the_author_meta(\'ID\')' ); + the_author_meta('ID'); +} + +/** + * Display the post content for the feed. + * + * For encoding the html or the $encode_html parameter, there are three possible + * values. '0' will make urls footnotes and use make_url_footnote(). '1' will + * encode special characters and automatically display all of the content. The + * value of '2' will strip all HTML tags from the content. + * + * Also note that you cannot set the amount of words and not set the html + * encoding. If that is the case, then the html encoding will default to 2, + * which will strip all HTML tags. + * + * To restrict the amount of words of the content, you can use the cut + * parameter. If the content is less than the amount, then there won't be any + * dots added to the end. If there is content left over, then dots will be added + * and the rest of the content will be removed. + * + * @package WordPress + * @subpackage Feed + * @since 0.71 + * @uses apply_filters() Calls 'the_content_rss' on the content before processing. + * + * @deprecated 2.9.0 + * @deprecated Use the_content_feed() + * @see the_content_feed() + * + * @param string $more_link_text Optional. Text to display when more content is available but not displayed. + * @param int|bool $stripteaser Optional. Default is 0. + * @param string $more_file Optional. + * @param int $cut Optional. Amount of words to keep for the content. + * @param int $encode_html Optional. How to encode the content. + */ +function the_content_rss($more_link_text='(more...)', $stripteaser=0, $more_file='', $cut = 0, $encode_html = 0) { + _deprecated_function( __FUNCTION__, '2.9', 'the_content_feed' ); + $content = get_the_content($more_link_text, $stripteaser); + $content = apply_filters('the_content_rss', $content); + if ( $cut && !$encode_html ) + $encode_html = 2; + if ( 1== $encode_html ) { + $content = esc_html($content); + $cut = 0; + } elseif ( 0 == $encode_html ) { + $content = make_url_footnote($content); + } elseif ( 2 == $encode_html ) { + $content = strip_tags($content); + } + if ( $cut ) { + $blah = explode(' ', $content); + if ( count($blah) > $cut ) { + $k = $cut; + $use_dotdotdot = 1; + } else { + $k = count($blah); + $use_dotdotdot = 0; + } + + /** @todo Check performance, might be faster to use array slice instead. */ + for ( $i=0; $i<$k; $i++ ) + $excerpt .= $blah[$i].' '; + $excerpt .= ($use_dotdotdot) ? '...' : ''; + $content = $excerpt; + } + $content = str_replace(']]>', ']]>', $content); + echo $content; +} + +/** + * Strip HTML and put links at the bottom of stripped content. + * + * Searches for all of the links, strips them out of the content, and places + * them at the bottom of the content with numbers. + * + * @since 0.71 + * @deprecated 2.9.0 + * + * @param string $content Content to get links + * @return string HTML stripped out of content with links at the bottom. + */ +function make_url_footnote( $content ) { + _deprecated_function( __FUNCTION__, '2.9', '' ); + preg_match_all( '/(.+?)<\/a>/', $content, $matches ); + $links_summary = "\n"; + for ( $i=0; $ipost_type) || !$url = wp_get_attachment_url($_post->ID) ) + return __('Missing Attachment'); + + if ( $permalink ) + $url = get_attachment_link($_post->ID); + + $post_title = esc_attr($_post->post_title); + + $innerHTML = get_attachment_innerHTML($_post->ID, $fullsize, $max_dims); + return "$innerHTML"; +} + +/** + * Retrieve icon URL and Path. + * + * @since 2.1.0 + * @deprecated 2.5.0 + * @deprecated Use wp_get_attachment_image_src() + * @see wp_get_attachment_image_src() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional, default to false. Whether to have full image. + * @return array Icon URL and full path to file, respectively. + */ +function get_attachment_icon_src( $id = 0, $fullsize = false ) { + _deprecated_function( __FUNCTION__, '2.5', 'wp_get_attachment_image_src()' ); + $id = (int) $id; + if ( !$post = get_post($id) ) + return false; + + $file = get_attached_file( $post->ID ); + + if ( !$fullsize && $src = wp_get_attachment_thumb_url( $post->ID ) ) { + // We have a thumbnail desired, specified and existing + + $src_file = basename($src); + $class = 'attachmentthumb'; + } elseif ( wp_attachment_is_image( $post->ID ) ) { + // We have an image without a thumbnail + + $src = wp_get_attachment_url( $post->ID ); + $src_file = & $file; + $class = 'attachmentimage'; + } elseif ( $src = wp_mime_type_icon( $post->ID ) ) { + // No thumb, no image. We'll look for a mime-related icon instead. + + $icon_dir = apply_filters( 'icon_dir', get_template_directory() . '/images' ); + $src_file = $icon_dir . '/' . basename($src); + } + + if ( !isset($src) || !$src ) + return false; + + return array($src, $src_file); +} + +/** + * Retrieve HTML content of icon attachment image element. + * + * @since 2.0.0 + * @deprecated 2.5.0 + * @deprecated Use wp_get_attachment_image() + * @see wp_get_attachment_image() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional, default to false. Whether to have full size image. + * @param array $max_dims Optional. Dimensions of image. + * @return string HTML content. + */ +function get_attachment_icon( $id = 0, $fullsize = false, $max_dims = false ) { + _deprecated_function( __FUNCTION__, '2.5', 'wp_get_attachment_image()' ); + $id = (int) $id; + if ( !$post = get_post($id) ) + return false; + + if ( !$src = get_attachment_icon_src( $post->ID, $fullsize ) ) + return false; + + list($src, $src_file) = $src; + + // Do we need to constrain the image? + if ( ($max_dims = apply_filters('attachment_max_dims', $max_dims)) && file_exists($src_file) ) { + + $imagesize = getimagesize($src_file); + + if (($imagesize[0] > $max_dims[0]) || $imagesize[1] > $max_dims[1] ) { + $actual_aspect = $imagesize[0] / $imagesize[1]; + $desired_aspect = $max_dims[0] / $max_dims[1]; + + if ( $actual_aspect >= $desired_aspect ) { + $height = $actual_aspect * $max_dims[0]; + $constraint = "width='{$max_dims[0]}' "; + $post->iconsize = array($max_dims[0], $height); + } else { + $width = $max_dims[1] / $actual_aspect; + $constraint = "height='{$max_dims[1]}' "; + $post->iconsize = array($width, $max_dims[1]); + } + } else { + $post->iconsize = array($imagesize[0], $imagesize[1]); + $constraint = ''; + } + } else { + $constraint = ''; + } + + $post_title = esc_attr($post->post_title); + + $icon = "$post_title"; + + return apply_filters( 'attachment_icon', $icon, $post->ID ); +} + +/** + * Retrieve HTML content of image element. + * + * @since 2.0.0 + * @deprecated 2.5.0 + * @deprecated Use wp_get_attachment_image() + * @see wp_get_attachment_image() + * + * @param int $id Optional. Post ID. + * @param bool $fullsize Optional, default to false. Whether to have full size image. + * @param array $max_dims Optional. Dimensions of image. + * @return string + */ +function get_attachment_innerHTML($id = 0, $fullsize = false, $max_dims = false) { + _deprecated_function( __FUNCTION__, '2.5', 'wp_get_attachment_image()' ); + $id = (int) $id; + if ( !$post = get_post($id) ) + return false; + + if ( $innerHTML = get_attachment_icon($post->ID, $fullsize, $max_dims)) + return $innerHTML; + + $innerHTML = esc_attr($post->post_title); + + return apply_filters('attachment_innerHTML', $innerHTML, $post->ID); +} + +/** + * Retrieve bookmark data based on ID. + * + * @since 2.0.0 + * @deprecated 2.1.0 + * @deprecated Use get_bookmark() + * @see get_bookmark() + * + * @param int $bookmark_id ID of link + * @param string $output OBJECT, ARRAY_N, or ARRAY_A + * @return object|array + */ +function get_link($bookmark_id, $output = OBJECT, $filter = 'raw') { + _deprecated_function( __FUNCTION__, '2.1', 'get_bookmark()' ); + return get_bookmark($bookmark_id, $output, $filter); +} + +/** + * Performs esc_url() for database or redirect usage. + * + * @since 2.3.1 + * @deprecated 2.8.0 + * @deprecated Use esc_url_raw() + * @see esc_url_raw() + * + * @param string $url The URL to be cleaned. + * @param array $protocols An array of acceptable protocols. + * @return string The cleaned URL. + */ +function sanitize_url( $url, $protocols = null ) { + _deprecated_function( __FUNCTION__, '2.8', 'esc_url_raw()' ); + return esc_url_raw( $url, $protocols ); +} + +/** + * Checks and cleans a URL. + * + * A number of characters are removed from the URL. If the URL is for displaying + * (the default behaviour) ampersands are also replaced. The 'clean_url' filter + * is applied to the returned cleaned URL. + * + * @since 1.2.0 + * @deprecated 3.0.0 + * @deprecated Use esc_url() + * @see Alias for esc_url() + * + * @param string $url The URL to be cleaned. + * @param array $protocols Optional. An array of acceptable protocols. + * @param string $context Optional. How the URL will be used. Default is 'display'. + * @return string The cleaned $url after the 'clean_url' filter is applied. + */ +function clean_url( $url, $protocols = null, $context = 'display' ) { + if ( $context == 'db' ) + _deprecated_function( 'clean_url( $context = \'db\' )', '3.0', 'esc_url_raw()' ); + else + _deprecated_function( __FUNCTION__, '3.0', 'esc_url()' ); + return esc_url( $url, $protocols, $context ); +} + +/** + * Escape single quotes, specialchar double quotes, and fix line endings. + * + * The filter 'js_escape' is also applied by esc_js() + * + * @since 2.0.4 + * @deprecated 2.8.0 + * @deprecated Use esc_js() + * @see esc_js() + * + * @param string $text The text to be escaped. + * @return string Escaped text. + */ +function js_escape( $text ) { + _deprecated_function( __FUNCTION__, '2.8', 'esc_js()' ); + return esc_js( $text ); +} + +/** + * Escaping for HTML blocks. + * + * @deprecated 2.8.0 + * @deprecated Use esc_html() + * @see esc_html() + */ +function wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { + _deprecated_function( __FUNCTION__, '2.8', 'esc_html()' ); + if ( func_num_args() > 1 ) { // Maintain backwards compat for people passing additional args + $args = func_get_args(); + return call_user_func_array( '_wp_specialchars', $args ); + } else { + return esc_html( $string ); + } +} + +/** + * Escaping for HTML attributes. + * + * @since 2.0.6 + * @deprecated 2.8.0 + * @deprecated Use esc_attr() + * @see esc_attr() + * + * @param string $text + * @return string + */ +function attribute_escape( $text ) { + _deprecated_function( __FUNCTION__, '2.8', 'esc_attr()' ); + return esc_attr( $text ); +} + +/** + * Register widget for sidebar with backwards compatibility. + * + * Allows $name to be an array that accepts either three elements to grab the + * first element and the third for the name or just uses the first element of + * the array for the name. + * + * Passes to {@link wp_register_sidebar_widget()} after argument list and + * backwards compatibility is complete. + * + * @since 2.2.0 + * @deprecated 2.8.0 + * @deprecated Use wp_register_sidebar_widget() + * @see wp_register_sidebar_widget() + * + * @param string|int $name Widget ID. + * @param callback $output_callback Run when widget is called. + * @param string $classname Classname widget option. + * @param mixed $params,... Widget parameters. + */ +function register_sidebar_widget($name, $output_callback, $classname = '') { + _deprecated_function( __FUNCTION__, '2.8', 'wp_register_sidebar_widget()' ); + // Compat + if ( is_array($name) ) { + if ( count($name) == 3 ) + $name = sprintf($name[0], $name[2]); + else + $name = $name[0]; + } + + $id = sanitize_title($name); + $options = array(); + if ( !empty($classname) && is_string($classname) ) + $options['classname'] = $classname; + $params = array_slice(func_get_args(), 2); + $args = array($id, $name, $output_callback, $options); + if ( !empty($params) ) + $args = array_merge($args, $params); + + call_user_func_array('wp_register_sidebar_widget', $args); +} + +/** + * Alias of {@link wp_unregister_sidebar_widget()}. + * + * @since 2.2.0 + * @deprecated 2.8.0 + * @deprecated Use wp_unregister_sidebar_widget() + * @see wp_unregister_sidebar_widget() + * + * @param int|string $id Widget ID. + */ +function unregister_sidebar_widget($id) { + _deprecated_function( __FUNCTION__, '2.8', 'wp_unregister_sidebar_widget()' ); + return wp_unregister_sidebar_widget($id); +} + +/** + * Registers widget control callback for customizing options. + * + * Allows $name to be an array that accepts either three elements to grab the + * first element and the third for the name or just uses the first element of + * the array for the name. + * + * Passes to {@link wp_register_widget_control()} after the argument list has + * been compiled. + * + * @since 2.2.0 + * @deprecated 2.8.0 + * @deprecated Use wp_register_widget_control() + * @see wp_register_widget_control() + * + * @param int|string $name Sidebar ID. + * @param callback $control_callback Widget control callback to display and process form. + * @param int $width Widget width. + * @param int $height Widget height. + */ +function register_widget_control($name, $control_callback, $width = '', $height = '') { + _deprecated_function( __FUNCTION__, '2.8', 'wp_register_widget_control()' ); + // Compat + if ( is_array($name) ) { + if ( count($name) == 3 ) + $name = sprintf($name[0], $name[2]); + else + $name = $name[0]; + } + + $id = sanitize_title($name); + $options = array(); + if ( !empty($width) ) + $options['width'] = $width; + if ( !empty($height) ) + $options['height'] = $height; + $params = array_slice(func_get_args(), 4); + $args = array($id, $name, $control_callback, $options); + if ( !empty($params) ) + $args = array_merge($args, $params); + + call_user_func_array('wp_register_widget_control', $args); +} + +/** + * Alias of {@link wp_unregister_widget_control()}. + * + * @since 2.2.0 + * @deprecated 2.8.0 + * @deprecated Use wp_unregister_widget_control() + * @see wp_unregister_widget_control() + * + * @param int|string $id Widget ID. + */ +function unregister_widget_control($id) { + _deprecated_function( __FUNCTION__, '2.8', 'wp_unregister_widget_control()' ); + return wp_unregister_widget_control($id); +} + +/** + * Remove user meta data. + * + * @since 2.0.0 + * @deprecated 3.0.0 + * @deprecated Use delete_user_meta() + * @see delete_user_meta() + * + * @param int $user_id User ID. + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. + * @return bool True deletion completed and false if user_id is not a number. + */ +function delete_usermeta( $user_id, $meta_key, $meta_value = '' ) { + _deprecated_function( __FUNCTION__, '3.0', 'delete_user_meta()' ); + global $wpdb; + if ( !is_numeric( $user_id ) ) + return false; + $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); + + if ( is_array($meta_value) || is_object($meta_value) ) + $meta_value = serialize($meta_value); + $meta_value = trim( $meta_value ); + + $cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); + + if ( $cur && $cur->umeta_id ) + do_action( 'delete_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); + + if ( ! empty($meta_value) ) + $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s AND meta_value = %s", $user_id, $meta_key, $meta_value) ); + else + $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); + + clean_user_cache( $user_id ); + wp_cache_delete( $user_id, 'user_meta' ); + + if ( $cur && $cur->umeta_id ) + do_action( 'deleted_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); + + return true; +} + +/** + * Retrieve user metadata. + * + * If $user_id is not a number, then the function will fail over with a 'false' + * boolean return value. Other returned values depend on whether there is only + * one item to be returned, which be that single item type. If there is more + * than one metadata value, then it will be list of metadata values. + * + * @since 2.0.0 + * @deprecated 3.0.0 + * @deprecated Use get_user_meta() + * @see get_user_meta() + * + * @param int $user_id User ID + * @param string $meta_key Optional. Metadata key. + * @return mixed + */ +function get_usermeta( $user_id, $meta_key = '' ) { + _deprecated_function( __FUNCTION__, '3.0', 'get_user_meta()' ); + global $wpdb; + $user_id = (int) $user_id; + + if ( !$user_id ) + return false; + + if ( !empty($meta_key) ) { + $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); + $user = wp_cache_get($user_id, 'users'); + // Check the cached user object + if ( false !== $user && isset($user->$meta_key) ) + $metas = array($user->$meta_key); + else + $metas = $wpdb->get_col( $wpdb->prepare("SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); + } else { + $metas = $wpdb->get_col( $wpdb->prepare("SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d", $user_id) ); + } + + if ( empty($metas) ) { + if ( empty($meta_key) ) + return array(); + else + return ''; + } + + $metas = array_map('maybe_unserialize', $metas); + + if ( count($metas) == 1 ) + return $metas[0]; + else + return $metas; +} + +/** + * Update metadata of user. + * + * There is no need to serialize values, they will be serialized if it is + * needed. The metadata key can only be a string with underscores. All else will + * be removed. + * + * Will remove the metadata, if the meta value is empty. + * + * @since 2.0.0 + * @deprecated 3.0.0 + * @deprecated Use update_user_meta() + * @see update_user_meta() + * + * @param int $user_id User ID + * @param string $meta_key Metadata key. + * @param mixed $meta_value Metadata value. + * @return bool True on successful update, false on failure. + */ +function update_usermeta( $user_id, $meta_key, $meta_value ) { + _deprecated_function( __FUNCTION__, '3.0', 'update_user_meta()' ); + global $wpdb; + if ( !is_numeric( $user_id ) ) + return false; + $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); + + /** @todo Might need fix because usermeta data is assumed to be already escaped */ + if ( is_string($meta_value) ) + $meta_value = stripslashes($meta_value); + $meta_value = maybe_serialize($meta_value); + + if (empty($meta_value)) { + return delete_usermeta($user_id, $meta_key); + } + + $cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) ); + + if ( $cur ) + do_action( 'update_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); + + if ( !$cur ) + $wpdb->insert($wpdb->usermeta, compact('user_id', 'meta_key', 'meta_value') ); + else if ( $cur->meta_value != $meta_value ) + $wpdb->update($wpdb->usermeta, compact('meta_value'), compact('user_id', 'meta_key') ); + else + return false; + + clean_user_cache( $user_id ); + wp_cache_delete( $user_id, 'user_meta' ); + + if ( !$cur ) + do_action( 'added_usermeta', $wpdb->insert_id, $user_id, $meta_key, $meta_value ); + else + do_action( 'updated_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value ); + + return true; +} + +/** + * Get users for the blog. + * + * For setups that use the multi-blog feature. Can be used outside of the + * multi-blog feature. + * + * @since 2.2.0 + * @deprecated 3.1.0 + * @uses $wpdb WordPress database object for queries + * @uses $blog_id The Blog id of the blog for those that use more than one blog + * + * @param int $id Blog ID. + * @return array List of users that are part of that Blog ID + */ +function get_users_of_blog( $id = '' ) { + _deprecated_function( __FUNCTION__, '3.1', 'get_users()' ); + + global $wpdb, $blog_id; + if ( empty($id) ) + $id = (int) $blog_id; + $blog_prefix = $wpdb->get_blog_prefix($id); + $users = $wpdb->get_results( "SELECT user_id, user_id AS ID, user_login, display_name, user_email, meta_value FROM $wpdb->users, $wpdb->usermeta WHERE {$wpdb->users}.ID = {$wpdb->usermeta}.user_id AND meta_key = '{$blog_prefix}capabilities' ORDER BY {$wpdb->usermeta}.user_id" ); + return $users; +} + +/** + * Enable/disable automatic general feed link outputting. + * + * @since 2.8.0 + * @deprecated 3.0.0 + * @deprecated Use add_theme_support( 'automatic-feed-links' ) + * + * @param boolean $add Optional, default is true. Add or remove links. Defaults to true. + */ +function automatic_feed_links( $add = true ) { + _deprecated_function( __FUNCTION__, '3.0', "add_theme_support( 'automatic-feed-links' )" ); + + if ( $add ) + add_theme_support( 'automatic-feed-links' ); + else + remove_action( 'wp_head', 'feed_links_extra', 3 ); // Just do this yourself in 3.0+ +} + +/** + * Retrieve user data based on field. + * + * @since 1.5.0 + * @deprecated 3.0.0 + * @deprecated Use get_the_author_meta() + * @see get_the_author_meta() + */ +function get_profile( $field, $user = false ) { + _deprecated_function( __FUNCTION__, '3.0', 'get_the_author_meta()' ); + if ( $user ) { + $user = get_user_by( 'login', $user ); + $user = $user->ID; + } + return get_the_author_meta( $field, $user ); +} + +/** + * Number of posts user has written. + * + * @since 0.71 + * @deprecated 3.0.0 + * @deprecated Use count_user_posts() + * @see count_user_posts() + */ +function get_usernumposts( $userid ) { + _deprecated_function( __FUNCTION__, '3.0', 'count_user_posts()' ); + return count_user_posts( $userid ); +} + +/** + * Callback used to change %uXXXX to &#YYY; syntax + * + * @since 2.8.0 + * @access private + * @deprecated 3.0.0 + * + * @param array $matches Single Match + * @return string An HTML entity + */ +function funky_javascript_callback($matches) { + return "&#".base_convert($matches[1],16,10).";"; +} + +/** + * Fixes javascript bugs in browsers. + * + * Converts unicode characters to HTML numbered entities. + * + * @since 1.5.0 + * @uses $is_macIE + * @uses $is_winIE + * @deprecated 3.0.0 + * + * @param string $text Text to be made safe. + * @return string Fixed text. + */ +function funky_javascript_fix($text) { + _deprecated_function( __FUNCTION__, '3.0' ); + // Fixes for browsers' javascript bugs + global $is_macIE, $is_winIE; + + if ( $is_winIE || $is_macIE ) + $text = preg_replace_callback("/\%u([0-9A-F]{4,4})/", + "funky_javascript_callback", + $text); + + return $text; +} + +/** + * Checks that the taxonomy name exists. + * + * @since 2.3.0 + * @deprecated 3.0.0 + * @deprecated Use taxonomy_exists() + * @see taxonomy_exists() + * + * @param string $taxonomy Name of taxonomy object + * @return bool Whether the taxonomy exists. + */ +function is_taxonomy( $taxonomy ) { + _deprecated_function( __FUNCTION__, '3.0', 'taxonomy_exists()' ); + return taxonomy_exists( $taxonomy ); +} + +/** + * Check if Term exists. + * + * @since 2.3.0 + * @deprecated 3.0.0 + * @deprecated Use term_exists() + * @see term_exists() + * + * @param int|string $term The term to check + * @param string $taxonomy The taxonomy name to use + * @param int $parent ID of parent term under which to confine the exists search. + * @return mixed Get the term id or Term Object, if exists. + */ +function is_term( $term, $taxonomy = '', $parent = 0 ) { + _deprecated_function( __FUNCTION__, '3.0', 'term_exists()' ); + return term_exists( $term, $taxonomy, $parent ); +} + +/** + * Is the current admin page generated by a plugin? + * + * @since 1.5.0 + * @deprecated 3.1.0 + * @deprecated Use global $plugin_page and/or get_plugin_page_hookname() hooks. + * + * @global $plugin_page + * + * @return bool + */ +function is_plugin_page() { + _deprecated_function( __FUNCTION__, '3.1' ); + + global $plugin_page; + + if ( isset($plugin_page) ) + return true; + + return false; +} + +/** + * Update the categories cache. + * + * This function does not appear to be used anymore or does not appear to be + * needed. It might be a legacy function left over from when there was a need + * for updating the category cache. + * + * @since 1.5.0 + * @deprecated 3.1.0 + * + * @return bool Always return True + */ +function update_category_cache() { + _deprecated_function( __FUNCTION__, '3.1' ); + + return true; +} + +/** + * Check for PHP timezone support + * + * @since 2.9.0 + * @deprecated 3.2.0 + * + * @return bool + */ +function wp_timezone_supported() { + _deprecated_function( __FUNCTION__, '3.2' ); + + return true; +} + +/** + * Display editor: TinyMCE, HTML, or both. + * + * @since 2.1.0 + * @deprecated 3.3.0 + * @deprecated Use wp_editor() + * @see wp_editor() + * + * @param string $content Textarea content. + * @param string $id Optional, default is 'content'. HTML ID attribute value. + * @param string $prev_id Optional, not used + * @param bool $media_buttons Optional, default is true. Whether to display media buttons. + * @param int $tab_index Optional, not used + */ +function the_editor($content, $id = 'content', $prev_id = 'title', $media_buttons = true, $tab_index = 2, $extended = true) { + _deprecated_function( __FUNCTION__, '3.3', 'wp_editor()' ); + + wp_editor( $content, $id, array( 'media_buttons' => $media_buttons ) ); + return; +} + +/** + * Perform the query to get the $metavalues array(s) needed by _fill_user and _fill_many_users + * + * @since 3.0.0 + * @deprecated 3.3.0 + * + * @param array $ids User ID numbers list. + * @return array of arrays. The array is indexed by user_id, containing $metavalues object arrays. + */ +function get_user_metavalues($ids) { + _deprecated_function( __FUNCTION__, '3.3' ); + + $objects = array(); + + $ids = array_map('intval', $ids); + foreach ( $ids as $id ) + $objects[$id] = array(); + + $metas = update_meta_cache('user', $ids); + + foreach ( $metas as $id => $meta ) { + foreach ( $meta as $key => $metavalues ) { + foreach ( $metavalues as $value ) { + $objects[$id][] = (object)array( 'user_id' => $id, 'meta_key' => $key, 'meta_value' => $value); + } + } + } + + return $objects; +} + +/** + * Sanitize every user field. + * + * If the context is 'raw', then the user object or array will get minimal santization of the int fields. + * + * @since 2.3.0 + * @deprecated 3.3.0 + * + * @param object|array $user The User Object or Array + * @param string $context Optional, default is 'display'. How to sanitize user fields. + * @return object|array The now sanitized User Object or Array (will be the same type as $user) + */ +function sanitize_user_object($user, $context = 'display') { + _deprecated_function( __FUNCTION__, '3.3' ); + + if ( is_object($user) ) { + if ( !isset($user->ID) ) + $user->ID = 0; + if ( !is_a( $user, 'WP_User' ) ) { + $vars = get_object_vars($user); + foreach ( array_keys($vars) as $field ) { + if ( is_string($user->$field) || is_numeric($user->$field) ) + $user->$field = sanitize_user_field($field, $user->$field, $user->ID, $context); + } + } + $user->filter = $context; + } else { + if ( !isset($user['ID']) ) + $user['ID'] = 0; + foreach ( array_keys($user) as $field ) + $user[$field] = sanitize_user_field($field, $user[$field], $user['ID'], $context); + $user['filter'] = $context; + } + + return $user; +} + +/** + * Get boundary post relational link. + * + * Can either be start or end post relational link. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. + * @param bool $in_same_cat Optional. Whether link should be in a same category. + * @param string $excluded_categories Optional. Excluded categories IDs. + * @param bool $start Optional, default is true. Whether to display link to first or last post. + * @return string + */ +function get_boundary_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '', $start = true) { + _deprecated_function( __FUNCTION__, '3.3' ); + + $posts = get_boundary_post($in_same_cat, $excluded_categories, $start); + // If there is no post stop. + if ( empty($posts) ) + return; + + // Even though we limited get_posts to return only 1 item it still returns an array of objects. + $post = $posts[0]; + + if ( empty($post->post_title) ) + $post->post_title = $start ? __('First Post') : __('Last Post'); + + $date = mysql2date(get_option('date_format'), $post->post_date); + + $title = str_replace('%title', $post->post_title, $title); + $title = str_replace('%date', $date, $title); + $title = apply_filters('the_title', $title, $post->ID); + + $link = $start ? "\n"; + + $boundary = $start ? 'start' : 'end'; + return apply_filters( "{$boundary}_post_rel_link", $link ); +} + +/** + * Display relational link for the first post. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. + * @param bool $in_same_cat Optional. Whether link should be in a same category. + * @param string $excluded_categories Optional. Excluded categories IDs. + */ +function start_post_rel_link($title = '%title', $in_same_cat = false, $excluded_categories = '') { + _deprecated_function( __FUNCTION__, '3.3' ); + + echo get_boundary_post_rel_link($title, $in_same_cat, $excluded_categories, true); +} + +/** + * Get site index relational link. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @return string + */ +function get_index_rel_link() { + _deprecated_function( __FUNCTION__, '3.3' ); + + $link = "\n"; + return apply_filters( "index_rel_link", $link ); +} + +/** + * Display relational link for the site index. + * + * @since 2.8.0 + * @deprecated 3.3.0 + */ +function index_rel_link() { + _deprecated_function( __FUNCTION__, '3.3' ); + + echo get_index_rel_link(); +} + +/** + * Get parent post relational link. + * + * @since 2.8.0 + * @deprecated 3.3.0 + * + * @param string $title Optional. Link title format. + * @return string + */ +function get_parent_post_rel_link($title = '%title') { + _deprecated_function( __FUNCTION__, '3.3' ); + + if ( ! empty( $GLOBALS['post'] ) && ! empty( $GLOBALS['post']->post_parent ) ) + $post = get_post($GLOBALS['post']->post_parent); + + if ( empty($post) ) + return; + + $date = mysql2date(get_option('date_format'), $post->post_date); + + $title = str_replace('%title', $post->post_title, $title); + $title = str_replace('%date', $date, $title); + $title = apply_filters('the_title', $title, $post->ID); + + $link = "\n"; + + return apply_filters( "parent_post_rel_link", $link ); +} + +/** + * Display relational link for parent item + * + * @since 2.8.0 + * @deprecated 3.3.0 + */ +function parent_post_rel_link($title = '%title') { + _deprecated_function( __FUNCTION__, '3.3' ); + + echo get_parent_post_rel_link($title); +} + +/** + * Add the "Dashboard"/"Visit Site" menu. + * + * @since 3.2.0 + * @deprecated 3.3.0 + */ +function wp_admin_bar_dashboard_view_site_menu( $wp_admin_bar ) { + _deprecated_function( __FUNCTION__, '3.3' ); + + $user_id = get_current_user_id(); + + if ( 0 != $user_id ) { + if ( is_admin() ) + $wp_admin_bar->add_menu( array( 'id' => 'view-site', 'title' => __( 'Visit Site' ), 'href' => home_url() ) ); + elseif ( is_multisite() ) + $wp_admin_bar->add_menu( array( 'id' => 'dashboard', 'title' => __( 'Dashboard' ), 'href' => get_dashboard_url( $user_id ) ) ); + else + $wp_admin_bar->add_menu( array( 'id' => 'dashboard', 'title' => __( 'Dashboard' ), 'href' => admin_url() ) ); + } +} + +/** + * Checks if the current user belong to a given blog. + * + * @since MU + * @deprecated 3.3.0 + * @deprecated Use is_user_member_of_blog() + * @see is_user_member_of_blog() + * + * @param int $blog_id Blog ID + * @return bool True if the current users belong to $blog_id, false if not. + */ +function is_blog_user( $blog_id = 0 ) { + _deprecated_function( __FUNCTION__, '3.3', 'is_user_member_of_blog()' ); + + return is_user_member_of_blog( get_current_user_id(), $blog_id ); +} + +/** + * Open the file handle for debugging. + * + * @since 0.71 + * @deprecated Use error_log() + * @link http://www.php.net/manual/en/function.error-log.php + * @deprecated 3.4.0 + */ +function debug_fopen( $filename, $mode ) { + _deprecated_function( __FUNCTION__, 'error_log()' ); + return false; +} + +/** + * Write contents to the file used for debugging. + * + * @since 0.71 + * @deprecated Use error_log() instead. + * @link http://www.php.net/manual/en/function.error-log.php + * @deprecated 3.4.0 + */ +function debug_fwrite( $fp, $string ) { + _deprecated_function( __FUNCTION__, 'error_log()' ); + if ( ! empty( $GLOBALS['debug'] ) ) + error_log( $string ); +} + +/** + * Close the debugging file handle. + * + * @since 0.71 + * @deprecated Use error_log() + * @link http://www.php.net/manual/en/function.error-log.php + * @deprecated 3.4.0 + */ +function debug_fclose( $fp ) { + _deprecated_function( __FUNCTION__, 'error_log()' ); +} + +/** + * Retrieve list of themes with theme data in theme directory. + * + * The theme is broken, if it doesn't have a parent theme and is missing either + * style.css and, or index.php. If the theme has a parent theme then it is + * broken, if it is missing style.css; index.php is optional. + * + * @since 1.5.0 + * @deprecated 3.4.0 + * @deprecated Use wp_get_themes() + * @see wp_get_themes() + * + * @return array Theme list with theme data. + */ +function get_themes() { + _deprecated_function( __FUNCTION__, '3.4', 'wp_get_themes()' ); + + global $wp_themes; + if ( isset( $wp_themes ) ) + return $wp_themes; + + $themes = wp_get_themes(); + $wp_themes = array(); + + foreach ( $themes as $theme ) { + $name = $theme->get('Name'); + if ( isset( $wp_themes[ $name ] ) ) + $wp_themes[ $name . '/' . $theme->get_stylesheet() ] = $theme; + else + $wp_themes[ $name ] = $theme; + } + + return $wp_themes; +} + +/** + * Retrieve theme data. + * + * @since 1.5.0 + * @deprecated 3.4.0 + * @deprecated Use wp_get_theme() + * @see wp_get_theme() + * + * @param string $theme Theme name. + * @return array|null Null, if theme name does not exist. Theme data, if exists. + */ +function get_theme( $theme ) { + _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme( $stylesheet )' ); + + $themes = get_themes(); + if ( is_array( $themes ) && array_key_exists( $theme, $themes ) ) + return $themes[ $theme ]; + return null; +} + +/** + * Retrieve current theme name. + * + * @since 1.5.0 + * @deprecated 3.4.0 + * @deprecated Use (string) wp_get_theme() + * @see wp_get_theme() + * + * @return string + */ +function get_current_theme() { + _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme()' ); + + if ( $theme = get_option( 'current_theme' ) ) + return $theme; + + return wp_get_theme()->get('Name'); +} + +/** + * Accepts matches array from preg_replace_callback in wpautop() or a string. + * + * Ensures that the contents of a <
    >...<
    > HTML block are not + * converted into paragraphs or line-breaks. + * + * @since 1.2.0 + * @deprecated 3.4.0 + * + * @param array|string $matches The array or string + * @return string The pre block without paragraph/line-break conversion. + */ +function clean_pre($matches) { + _deprecated_function( __FUNCTION__, '3.4' ); + + if ( is_array($matches) ) + $text = $matches[1] . $matches[2] . ""; + else + $text = $matches; + + $text = str_replace(array('
    ', '
    ', '
    '), array('', '', ''), $text); + $text = str_replace('

    ', "\n", $text); + $text = str_replace('

    ', '', $text); + + return $text; +} + + +/** + * Add callbacks for image header display. + * + * @since 2.1.0 + * @deprecated 3.4.0 + * @deprecated Use add_theme_support('custom-header', $args) + * @see add_theme_support() + * + * @param callback $wp_head_callback Call on 'wp_head' action. + * @param callback $admin_head_callback Call on custom header administration screen. + * @param callback $admin_preview_callback Output a custom header image div on the custom header administration screen. Optional. + */ +function add_custom_image_header( $wp_head_callback, $admin_head_callback, $admin_preview_callback = '' ) { + _deprecated_function( __FUNCTION__, '3.4', 'add_theme_support( \'custom-header\', $args )' ); + $args = array( + 'wp-head-callback' => $wp_head_callback, + 'admin-head-callback' => $admin_head_callback, + ); + if ( $admin_preview_callback ) + $args['admin-preview-callback'] = $admin_preview_callback; + return add_theme_support( 'custom-header', $args ); +} + +/** + * Remove image header support. + * + * @since 3.1.0 + * @deprecated 3.4.0 + * @deprecated Use remove_theme_support('custom-header') + * @see remove_theme_support() + * + * @return bool Whether support was removed. + */ +function remove_custom_image_header() { + _deprecated_function( __FUNCTION__, '3.4', 'remove_theme_support( \'custom-header\' )' ); + return remove_theme_support( 'custom-header' ); +} + +/** + * Add callbacks for background image display. + * + * @since 3.0.0 + * @deprecated 3.4.0 + * @deprecated Use add_theme_support('custom-background, $args) + * @see add_theme_support() + * + * @param callback $wp_head_callback Call on 'wp_head' action. + * @param callback $admin_head_callback Call on custom background administration screen. + * @param callback $admin_preview_callback Output a custom background image div on the custom background administration screen. Optional. + */ +function add_custom_background( $wp_head_callback = '', $admin_head_callback = '', $admin_preview_callback = '' ) { + _deprecated_function( __FUNCTION__, '3.4', 'add_theme_support( \'custom-background\', $args )' ); + $args = array(); + if ( $wp_head_callback ) + $args['wp-head-callback'] = $wp_head_callback; + if ( $admin_head_callback ) + $args['admin-head-callback'] = $admin_head_callback; + if ( $admin_preview_callback ) + $args['admin-preview-callback'] = $admin_preview_callback; + return add_theme_support( 'custom-background', $args ); +} + +/** + * Remove custom background support. + * + * @since 3.1.0 + * @see add_custom_background() + * + * @return bool Whether support was removed. + */ +function remove_custom_background() { + _deprecated_function( __FUNCTION__, '3.4', 'remove_theme_support( \'custom-background\' )' ); + return remove_theme_support( 'custom-background' ); +} + +/** + * Retrieve theme data from parsed theme file. + * + * @since 1.5.0 + * @deprecated 3.4.0 + * @deprecated Use wp_get_theme() + * @see wp_get_theme() + * + * @param string $theme_file Theme file path. + * @return array Theme data. + */ +function get_theme_data( $theme_file ) { + _deprecated_function( __FUNCTION__, '3.4', 'wp_get_theme()' ); + $theme = new WP_Theme( basename( dirname( $theme_file ) ), dirname( dirname( $theme_file ) ) ); + + $theme_data = array( + 'Name' => $theme->get('Name'), + 'URI' => $theme->display('ThemeURI', true, false), + 'Description' => $theme->display('Description', true, false), + 'Author' => $theme->display('Author', true, false), + 'AuthorURI' => $theme->display('AuthorURI', true, false), + 'Version' => $theme->get('Version'), + 'Template' => $theme->get('Template'), + 'Status' => $theme->get('Status'), + 'Tags' => $theme->get('Tags'), + 'Title' => $theme->get('Name'), + 'AuthorName' => $theme->get('Author'), + ); + + foreach ( apply_filters( 'extra_theme_headers', array() ) as $extra_header ) { + if ( ! isset( $theme_data[ $extra_header ] ) ) + $theme_data[ $extra_header ] = $theme->get( $extra_header ); + } + + return $theme_data; +} + +/** + * Alias of update_post_cache(). + * + * @see update_post_cache() Posts and pages are the same, alias is intentional + * + * @since 1.5.1 + * @deprecated 3.4.0 + * + * @param array $pages list of page objects + */ +function update_page_cache( &$pages ) { + _deprecated_function( __FUNCTION__, '3.4', 'update_post_cache()' ); + + update_post_cache( $pages ); +} + +/** + * Will clean the page in the cache. + * + * Clean (read: delete) page from cache that matches $id. Will also clean cache + * associated with 'all_page_ids' and 'get_pages'. + * + * @since 2.0.0 + * @deprecated 3.4.0 + * + * @uses do_action() Will call the 'clean_page_cache' hook action. + * + * @param int $id Page ID to clean + */ +function clean_page_cache( $id ) { + _deprecated_function( __FUNCTION__, '3.4', 'clean_post_cache()' ); + + clean_post_cache( $id ); +} + +/** + * Retrieve nonce action "Are you sure" message. + * + * Deprecated in 3.4.1 and 3.5.0. Backported to 3.3.3. + * + * @since 2.0.4 + * @deprecated 3.4.1 + * @deprecated Use wp_nonce_ays() + * @see wp_nonce_ays() + * + * @param string $action Nonce action. + * @return string Are you sure message. + */ +function wp_explain_nonce( $action ) { + _deprecated_function( __FUNCTION__, '3.4.1', 'wp_nonce_ays()' ); + return __( 'Are you sure you want to do this?' ); +} + +/** + * Display "sticky" CSS class, if a post is sticky. + * + * @since 2.7.0 + * @deprecated 3.5.0 + * @deprecated Use post_class() + * @see post_class() + * + * @param int $post_id An optional post ID. + */ +function sticky_class( $post_id = null ) { + _deprecated_function( __FUNCTION__, '3.5', 'post_class()' ); + if ( is_sticky( $post_id ) ) + echo ' sticky'; +} + +/** + * Retrieve post ancestors. + * + * This is no longer needed as WP_Post lazy-loads the ancestors + * property with get_post_ancestors(). + * + * @since 2.3.4 + * @deprecated 3.5.0 + * @see get_post_ancestors() + */ +function _get_post_ancestors( &$post ) { + _deprecated_function( __FUNCTION__, '3.5' ); +} + +/** + * Load an image from a string, if PHP supports it. + * + * @since 2.1.0 + * @deprecated 3.5.0 + * @see wp_get_image_editor() + * + * @param string $file Filename of the image to load. + * @return resource The resulting image resource on success, Error string on failure. + */ +function wp_load_image( $file ) { + _deprecated_function( __FUNCTION__, '3.5', 'wp_get_image_editor()' ); + + if ( is_numeric( $file ) ) + $file = get_attached_file( $file ); + + if ( ! is_file( $file ) ) + return sprintf(__('File “%s” doesn’t exist?'), $file); + + if ( ! function_exists('imagecreatefromstring') ) + return __('The GD image library is not installed.'); + + // Set artificially high because GD uses uncompressed images in memory + @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + $image = imagecreatefromstring( file_get_contents( $file ) ); + + if ( !is_resource( $image ) ) + return sprintf(__('File “%s” is not an image.'), $file); + + return $image; +} + +/** + * Scale down an image to fit a particular size and save a new copy of the image. + * + * The PNG transparency will be preserved using the function, as well as the + * image type. If the file going in is PNG, then the resized image is going to + * be PNG. The only supported image types are PNG, GIF, and JPEG. + * + * Some functionality requires API to exist, so some PHP version may lose out + * support. This is not the fault of WordPress (where functionality is + * downgraded, not actual defects), but of your PHP version. + * + * @since 2.5.0 + * @deprecated 3.5.0 + * @see wp_get_image_editor() + * + * @param string $file Image file path. + * @param int $max_w Maximum width to resize to. + * @param int $max_h Maximum height to resize to. + * @param bool $crop Optional. Whether to crop image or resize. + * @param string $suffix Optional. File suffix. + * @param string $dest_path Optional. New image file path. + * @param int $jpeg_quality Optional, default is 90. Image quality percentage. + * @return mixed WP_Error on failure. String with new destination path. + */ +function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) { + _deprecated_function( __FUNCTION__, '3.5', 'wp_get_image_editor()' ); + + $editor = wp_get_image_editor( $file ); + if ( is_wp_error( $editor ) ) + return $editor; + $editor->set_quality( $jpeg_quality ); + + $resized = $editor->resize( $max_w, $max_h, $crop ); + if ( is_wp_error( $resized ) ) + return $resized; + + $dest_file = $editor->generate_filename( $suffix, $dest_path ); + $saved = $editor->save( $dest_file ); + + if ( is_wp_error( $saved ) ) + return $saved; + + return $dest_file; +} + +/** + * Retrieve a single post, based on post ID. + * + * Has categories in 'post_category' property or key. Has tags in 'tags_input' + * property or key. + * + * @since 1.0.0 + * @deprecated 3.5.0 + * @see get_post() + * + * @param int $postid Post ID. + * @param string $mode How to return result, either OBJECT, ARRAY_N, or ARRAY_A. + * @return object|array Post object or array holding post contents and information + */ +function wp_get_single_post( $postid = 0, $mode = OBJECT ) { + _deprecated_function( __FUNCTION__, '3.5', 'get_post()' ); + return get_post( $postid, $mode ); +} + +/** + * Check that the user login name and password is correct. + * + * @since 0.71 + * @deprecated 3.5.0 + * @deprecated Use wp_authenticate() + * @see wp_authenticate() + * + * @param string $user_login User name. + * @param string $user_pass User password. + * @return bool False if does not authenticate, true if username and password authenticates. + */ +function user_pass_ok($user_login, $user_pass) { + _deprecated_function( __FUNCTION__, '3.5', 'wp_authenticate()' ); + $user = wp_authenticate( $user_login, $user_pass ); + if ( is_wp_error( $user ) ) + return false; + + return true; +} + +/** + * Callback formerly fired on the save_post hook. No longer needed. + * + * @since 2.3.0 + * @deprecated 3.5.0 + */ +function _save_post_hook() {} + +/** + * Check if the installed version of GD supports particular image type + * + * @since 2.9.0 + * @deprecated 3.5.0 + * @see wp_image_editor_supports() + * + * @param string $mime_type + * @return bool + */ +function gd_edit_image_support($mime_type) { + _deprecated_function( __FUNCTION__, '3.5', 'wp_image_editor_supports()' ); + + if ( function_exists('imagetypes') ) { + switch( $mime_type ) { + case 'image/jpeg': + return (imagetypes() & IMG_JPG) != 0; + case 'image/png': + return (imagetypes() & IMG_PNG) != 0; + case 'image/gif': + return (imagetypes() & IMG_GIF) != 0; + } + } else { + switch( $mime_type ) { + case 'image/jpeg': + return function_exists('imagecreatefromjpeg'); + case 'image/png': + return function_exists('imagecreatefrompng'); + case 'image/gif': + return function_exists('imagecreatefromgif'); + } + } + return false; +} + +/** + * Converts an integer byte value to a shorthand byte value. + * + * @since 2.3.0 + * @deprecated 3.6.0 + * @deprecated Use size_format() + * + * @param int $bytes An integer byte value. + * @return string A shorthand byte value. + */ +function wp_convert_bytes_to_hr( $bytes ) { + _deprecated_function( __FUNCTION__, '3.6', 'size_format()' ); + + $units = array( 0 => 'B', 1 => 'kB', 2 => 'MB', 3 => 'GB', 4 => 'TB' ); + $log = log( $bytes, 1024 ); + $power = (int) $log; + $size = pow( 1024, $log - $power ); + + if ( ! is_nan( $size ) && array_key_exists( $power, $units ) ) { + $unit = $units[ $power ]; + } else { + $size = $bytes; + $unit = $units[0]; + } + + return $size . $unit; +} + +/** + * Formerly used internally to tidy up the search terms. + * + * @access private + * @since 2.9.0 + * @deprecated 3.7.0 + */ +function _search_terms_tidy( $t ) { + _deprecated_function( __FUNCTION__, '3.7' ); + return trim( $t, "\"'\n\r " ); +} diff --git a/sources/wp-includes/feed-atom-comments.php b/sources/wp-includes/feed-atom-comments.php new file mode 100644 index 0000000..a7777f1 --- /dev/null +++ b/sources/wp-includes/feed-atom-comments.php @@ -0,0 +1,87 @@ +'; +?> + +> + <?php + if ( is_singular() ) + printf( ent2ncr( __( 'Comments on %s' ) ), get_the_title_rss() ); + elseif ( is_search() ) + printf( ent2ncr( __( 'Comments for %1$s searching on %2$s' ) ), get_bloginfo_rss( 'name' ), get_search_query() ); + else + printf( ent2ncr( __( 'Comments for %s' ) ), get_bloginfo_rss( 'name' ) . get_wp_title_rss() ); + ?> + + + + + + + + + + + + + + + + + + +comment_post_ID ); +?> + + <?php + if ( !is_singular() ) { + $title = get_the_title($comment_post->ID); + /** This filter is documented in wp-includes/feed.php */ + $title = apply_filters( 'the_title_rss', $title ); + printf(ent2ncr(__('Comment on %1$s by %2$s')), $title, get_comment_author_rss()); + } else { + printf(ent2ncr(__('By: %s')), get_comment_author_rss()); + } + ?> + + + + + ' . get_comment_author_url() . ''; ?> + + + + + + + + ]]> + + ]]> +comment_parent == 0 ) : // This comment is top level ?> + +comment_parent); + // The rel attribute below and the id tag above should be GUIDs, but WP doesn't create them for comments (unlike posts). Either way, it's more important that they both use the same system +?> + +comment_ID, $comment_post->ID); +?> + + + diff --git a/sources/wp-includes/feed-atom.php b/sources/wp-includes/feed-atom.php new file mode 100644 index 0000000..666b52d --- /dev/null +++ b/sources/wp-includes/feed-atom.php @@ -0,0 +1,83 @@ +'; ?> + + > + <?php bloginfo_rss('name'); wp_title_rss(); ?> + + + + + + + + + + + + + + + + + <![CDATA[<?php the_title_rss() ?>]]> + + + + + + ]]> + + ]]> + + + + + + + + diff --git a/sources/wp-includes/feed-rdf.php b/sources/wp-includes/feed-rdf.php new file mode 100644 index 0000000..d3503af --- /dev/null +++ b/sources/wp-includes/feed-rdf.php @@ -0,0 +1,77 @@ +'; ?> + +> +"> + <?php bloginfo_rss('name'); wp_title_rss(); ?> + + + + + + + + 2000-01-01T12:00+00:00 + + + + + + + + + + + + <?php the_title_rss() ?> + + post_date_gmt, false); ?> + ]]> + + + ]]> + + ]]> + ]]> + + + + + diff --git a/sources/wp-includes/feed-rss.php b/sources/wp-includes/feed-rss.php new file mode 100644 index 0000000..1650434 --- /dev/null +++ b/sources/wp-includes/feed-rss.php @@ -0,0 +1,46 @@ +'; ?> + + + <?php bloginfo_rss('name'); wp_title_rss(); ?> + + + + http://backend.userland.com/rss092 + + + + + + + <?php the_title_rss() ?> + ]]> + + + + + + diff --git a/sources/wp-includes/feed-rss2-comments.php b/sources/wp-includes/feed-rss2-comments.php new file mode 100644 index 0000000..a8a1c13 --- /dev/null +++ b/sources/wp-includes/feed-rss2-comments.php @@ -0,0 +1,94 @@ +'; +?> + + + +> + + <?php + if ( is_singular() ) + printf( ent2ncr( __( 'Comments on: %s' ) ), get_the_title_rss() ); + elseif ( is_search() ) + printf( ent2ncr( __( 'Comments for %1$s searching on %2$s' ) ), get_bloginfo_rss( 'name' ), get_search_query() ); + else + printf( ent2ncr( __( 'Comments for %s' ) ), get_bloginfo_rss( 'name' ) . get_wp_title_rss() ); + ?> + + + + + + + + + comment_post_ID ); + ?> + + <?php + if ( !is_singular() ) { + $title = get_the_title($comment_post->ID); + /** This filter is documented in wp-includes/feed.php */ + $title = apply_filters( 'the_title_rss', $title ); + printf(ent2ncr(__('Comment on %1$s by %2$s')), $title, get_comment_author_rss()); + } else { + printf(ent2ncr(__('By: %s')), get_comment_author_rss()); + } + ?> + + ]]> + + + + + ]]> + + ]]> + ]]> +comment_ID The ID of the comment being displayed. + * @param int $comment_post->ID The ID of the post the comment is connected to. + */ + do_action( 'commentrss2_item', $comment->comment_ID, $comment_post->ID ); +?> + + + + diff --git a/sources/wp-includes/feed-rss2.php b/sources/wp-includes/feed-rss2.php new file mode 100644 index 0000000..0ce4e6b --- /dev/null +++ b/sources/wp-includes/feed-rss2.php @@ -0,0 +1,105 @@ +'; ?> + + +> + + + <?php bloginfo_rss('name'); wp_title_rss(); ?> + + + + + + + + + + + + <?php the_title_rss() ?> + + + + ]]> + + + + + ]]> + + ]]> + + 0 ) : ?> + ]]> + + ]]> + + + + + + + + + + diff --git a/sources/wp-includes/feed.php b/sources/wp-includes/feed.php new file mode 100644 index 0000000..99e2286 --- /dev/null +++ b/sources/wp-includes/feed.php @@ -0,0 +1,552 @@ +get_error_message(); + $title = apply_filters( 'get_wp_title_rss', $title, $sep ); + return $title; +} + +/** + * Display the blog title for display of the feed title. + * + * @package WordPress + * @subpackage Feed + * @since 2.2.0 + * @uses apply_filters() Calls 'wp_title_rss' on the blog title. + * @see wp_title() $sep parameter usage. + * + * @param string $sep Optional. + */ +function wp_title_rss( $sep = '»' ) { + echo apply_filters( 'wp_title_rss', get_wp_title_rss( $sep ), $sep ); +} + +/** + * Retrieve the current post title for the feed. + * + * @package WordPress + * @subpackage Feed + * @since 2.0.0 + * @uses apply_filters() Calls 'the_title_rss' on the post title. + * + * @return string Current post title. + */ +function get_the_title_rss() { + $title = get_the_title(); + $title = apply_filters('the_title_rss', $title); + return $title; +} + +/** + * Display the post title in the feed. + * + * @package WordPress + * @subpackage Feed + * @since 0.71 + * @uses get_the_title_rss() Used to retrieve current post title. + */ +function the_title_rss() { + echo get_the_title_rss(); +} + +/** + * Retrieve the post content for feeds. + * + * @package WordPress + * @subpackage Feed + * @since 2.9.0 + * @uses apply_filters() Calls 'the_content_feed' on the content before processing. + * @see get_the_content() + * + * @param string $feed_type The type of feed. rss2 | atom | rss | rdf + * @return string The filtered content. + */ +function get_the_content_feed($feed_type = null) { + if ( !$feed_type ) + $feed_type = get_default_feed(); + + $content = apply_filters('the_content', get_the_content()); + $content = str_replace(']]>', ']]>', $content); + return apply_filters('the_content_feed', $content, $feed_type); +} + +/** + * Display the post content for feeds. + * + * @package WordPress + * @subpackage Feed + * @since 2.9.0 + * @uses apply_filters() Calls 'the_content_feed' on the content before processing. + * @see get_the_content() + * + * @param string $feed_type The type of feed. rss2 | atom | rss | rdf + */ +function the_content_feed($feed_type = null) { + echo get_the_content_feed($feed_type); +} + +/** + * Display the post excerpt for the feed. + * + * @package WordPress + * @subpackage Feed + * @since 0.71 + * @uses apply_filters() Calls 'the_excerpt_rss' hook on the excerpt. + */ +function the_excerpt_rss() { + $output = get_the_excerpt(); + echo apply_filters('the_excerpt_rss', $output); +} + +/** + * Display the permalink to the post for use in feeds. + * + * @package WordPress + * @subpackage Feed + * @since 2.3.0 + * @uses apply_filters() Call 'the_permalink_rss' on the post permalink + */ +function the_permalink_rss() { + echo esc_url( apply_filters('the_permalink_rss', get_permalink() )); +} + +/** + * Outputs the link to the comments for the current post in an xml safe way + * + * @since 3.0.0 + * @return none + */ +function comments_link_feed() { + echo esc_url( apply_filters( 'comments_link_feed', get_comments_link() ) ); +} + +/** + * Display the feed GUID for the current comment. + * + * @package WordPress + * @subpackage Feed + * @since 2.5.0 + * + * @param int|object $comment_id Optional comment object or id. Defaults to global comment object. + */ +function comment_guid($comment_id = null) { + echo esc_url( get_comment_guid($comment_id) ); +} + +/** + * Retrieve the feed GUID for the current comment. + * + * @package WordPress + * @subpackage Feed + * @since 2.5.0 + * + * @param int|object $comment_id Optional comment object or id. Defaults to global comment object. + * @return bool|string false on failure or guid for comment on success. + */ +function get_comment_guid($comment_id = null) { + $comment = get_comment($comment_id); + + if ( !is_object($comment) ) + return false; + + return get_the_guid($comment->comment_post_ID) . '#comment-' . $comment->comment_ID; +} + +/** + * Display the link to the comments. + * + * @since 1.5.0 + */ +function comment_link() { + echo esc_url( apply_filters( 'comment_link', get_comment_link() ) ); +} + +/** + * Retrieve the current comment author for use in the feeds. + * + * @package WordPress + * @subpackage Feed + * @since 2.0.0 + * @uses apply_filters() Calls 'comment_author_rss' hook on comment author. + * @uses get_comment_author() + * + * @return string Comment Author + */ +function get_comment_author_rss() { + return apply_filters('comment_author_rss', get_comment_author() ); +} + +/** + * Display the current comment author in the feed. + * + * @package WordPress + * @subpackage Feed + * @since 1.0.0 + */ +function comment_author_rss() { + echo get_comment_author_rss(); +} + +/** + * Display the current comment content for use in the feeds. + * + * @package WordPress + * @subpackage Feed + * @since 1.0.0 + * @uses apply_filters() Calls 'comment_text_rss' filter on comment content. + * @uses get_comment_text() + */ +function comment_text_rss() { + $comment_text = get_comment_text(); + $comment_text = apply_filters('comment_text_rss', $comment_text); + echo $comment_text; +} + +/** + * Retrieve all of the post categories, formatted for use in feeds. + * + * All of the categories for the current post in the feed loop, will be + * retrieved and have feed markup added, so that they can easily be added to the + * RSS2, Atom, or RSS1 and RSS0.91 RDF feeds. + * + * @package WordPress + * @subpackage Feed + * @since 2.1.0 + * @uses apply_filters() + * + * @param string $type Optional, default is the type returned by get_default_feed(). + * @return string All of the post categories for displaying in the feed. + */ +function get_the_category_rss($type = null) { + if ( empty($type) ) + $type = get_default_feed(); + $categories = get_the_category(); + $tags = get_the_tags(); + $the_list = ''; + $cat_names = array(); + + $filter = 'rss'; + if ( 'atom' == $type ) + $filter = 'raw'; + + if ( !empty($categories) ) foreach ( (array) $categories as $category ) { + $cat_names[] = sanitize_term_field('name', $category->name, $category->term_id, 'category', $filter); + } + + if ( !empty($tags) ) foreach ( (array) $tags as $tag ) { + $cat_names[] = sanitize_term_field('name', $tag->name, $tag->term_id, 'post_tag', $filter); + } + + $cat_names = array_unique($cat_names); + + foreach ( $cat_names as $cat_name ) { + if ( 'rdf' == $type ) + $the_list .= "\t\t\n"; + elseif ( 'atom' == $type ) + $the_list .= sprintf( '', esc_attr( apply_filters( 'get_bloginfo_rss', get_bloginfo( 'url' ) ) ), esc_attr( $cat_name ) ); + else + $the_list .= "\t\t\n"; + } + + return apply_filters('the_category_rss', $the_list, $type); +} + +/** + * Display the post categories in the feed. + * + * @package WordPress + * @subpackage Feed + * @since 0.71 + * @see get_the_category_rss() For better explanation. + * + * @param string $type Optional, default is the type returned by get_default_feed(). + */ +function the_category_rss($type = null) { + echo get_the_category_rss($type); +} + +/** + * Display the HTML type based on the blog setting. + * + * The two possible values are either 'xhtml' or 'html'. + * + * @package WordPress + * @subpackage Feed + * @since 2.2.0 + */ +function html_type_rss() { + $type = get_bloginfo('html_type'); + if (strpos($type, 'xhtml') !== false) + $type = 'xhtml'; + else + $type = 'html'; + echo $type; +} + +/** + * Display the rss enclosure for the current post. + * + * Uses the global $post to check whether the post requires a password and if + * the user has the password for the post. If not then it will return before + * displaying. + * + * Also uses the function get_post_custom() to get the post's 'enclosure' + * metadata field and parses the value to display the enclosure(s). The + * enclosure(s) consist of enclosure HTML tag(s) with a URI and other + * attributes. + * + * @package WordPress + * @subpackage Template + * @since 1.5.0 + * @uses apply_filters() Calls 'rss_enclosure' hook on rss enclosure. + * @uses get_post_custom() To get the current post enclosure metadata. + */ +function rss_enclosure() { + if ( post_password_required() ) + return; + + foreach ( (array) get_post_custom() as $key => $val) { + if ($key == 'enclosure') { + foreach ( (array) $val as $enc ) { + $enclosure = explode("\n", $enc); + + // only get the first element, e.g. audio/mpeg from 'audio/mpeg mpga mp2 mp3' + $t = preg_split('/[ \t]/', trim($enclosure[2]) ); + $type = $t[0]; + + echo apply_filters('rss_enclosure', '' . "\n"); + } + } + } +} + +/** + * Display the atom enclosure for the current post. + * + * Uses the global $post to check whether the post requires a password and if + * the user has the password for the post. If not then it will return before + * displaying. + * + * Also uses the function get_post_custom() to get the post's 'enclosure' + * metadata field and parses the value to display the enclosure(s). The + * enclosure(s) consist of link HTML tag(s) with a URI and other attributes. + * + * @package WordPress + * @subpackage Template + * @since 2.2.0 + * @uses apply_filters() Calls 'atom_enclosure' hook on atom enclosure. + * @uses get_post_custom() To get the current post enclosure metadata. + */ +function atom_enclosure() { + if ( post_password_required() ) + return; + + foreach ( (array) get_post_custom() as $key => $val ) { + if ($key == 'enclosure') { + foreach ( (array) $val as $enc ) { + $enclosure = explode("\n", $enc); + echo apply_filters('atom_enclosure', '' . "\n"); + } + } + } +} + +/** + * Determine the type of a string of data with the data formatted. + * + * Tell whether the type is text, html, or xhtml, per RFC 4287 section 3.1. + * + * In the case of WordPress, text is defined as containing no markup, + * xhtml is defined as "well formed", and html as tag soup (i.e., the rest). + * + * Container div tags are added to xhtml values, per section 3.1.1.3. + * + * @link http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.3.1 + * + * @package WordPress + * @subpackage Feed + * @since 2.5 + * + * @param string $data Input string + * @return array array(type, value) + */ +function prep_atom_text_construct($data) { + if (strpos($data, '<') === false && strpos($data, '&') === false) { + return array('text', $data); + } + + $parser = xml_parser_create(); + xml_parse($parser, '
    ' . $data . '
    ', true); + $code = xml_get_error_code($parser); + xml_parser_free($parser); + + if (!$code) { + if (strpos($data, '<') === false) { + return array('text', $data); + } else { + $data = "
    $data
    "; + return array('xhtml', $data); + } + } + + if (strpos($data, ']]>') == false) { + return array('html', ""); + } else { + return array('html', htmlspecialchars($data)); + } +} + +/** + * Display the link for the currently displayed feed in a XSS safe way. + * + * Generate a correct link for the atom:self element. + * + * @package WordPress + * @subpackage Feed + * @since 2.5 + */ +function self_link() { + $host = @parse_url(home_url()); + echo esc_url( apply_filters( 'self_link', set_url_scheme( 'http://' . $host['host'] . wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ); +} + +/** + * Return the content type for specified feed type. + * + * @package WordPress + * @subpackage Feed + * @since 2.8.0 + */ +function feed_content_type( $type = '' ) { + if ( empty($type) ) + $type = get_default_feed(); + + $types = array( + 'rss' => 'application/rss+xml', + 'rss2' => 'application/rss+xml', + 'rss-http' => 'text/xml', + 'atom' => 'application/atom+xml', + 'rdf' => 'application/rdf+xml' + ); + + $content_type = ( !empty($types[$type]) ) ? $types[$type] : 'application/octet-stream'; + + return apply_filters( 'feed_content_type', $content_type, $type ); +} + +/** + * Build SimplePie object based on RSS or Atom feed from URL. + * + * @since 2.8 + * + * @param mixed $url URL of feed to retrieve. If an array of URLs, the feeds are merged + * using SimplePie's multifeed feature. + * See also {@link ​http://simplepie.org/wiki/faq/typical_multifeed_gotchas} + * + * @return WP_Error|SimplePie WP_Error object on failure or SimplePie object on success + */ +function fetch_feed( $url ) { + require_once( ABSPATH . WPINC . '/class-feed.php' ); + + $feed = new SimplePie(); + + $feed->set_sanitize_class( 'WP_SimplePie_Sanitize_KSES' ); + // We must manually overwrite $feed->sanitize because SimplePie's + // constructor sets it before we have a chance to set the sanitization class + $feed->sanitize = new WP_SimplePie_Sanitize_KSES(); + + $feed->set_cache_class( 'WP_Feed_Cache' ); + $feed->set_file_class( 'WP_SimplePie_File' ); + + $feed->set_feed_url( $url ); + $feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) ); + do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) ); + $feed->init(); + $feed->handle_content_type(); + + if ( $feed->error() ) + return new WP_Error( 'simplepie-error', $feed->error() ); + + return $feed; +} diff --git a/sources/wp-includes/formatting.php b/sources/wp-includes/formatting.php new file mode 100644 index 0000000..904c99b --- /dev/null +++ b/sources/wp-includes/formatting.php @@ -0,0 +1,3433 @@ + + * 'cause today's effort makes it worth tomorrow's "holiday"... + *
    + * Becomes: + * + * ’cause today’s effort makes it worth tomorrow’s “holiday”… + * + * Code within certain html blocks are skipped. + * + * @since 0.71 + * @uses $wp_cockneyreplace Array of formatted entities for certain common phrases + * + * @param string $text The text to be formatted + * @return string The string replaced with html entities + */ +function wptexturize($text) { + global $wp_cockneyreplace; + static $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements, + $default_no_texturize_tags, $default_no_texturize_shortcodes; + + // No need to set up these static variables more than once + if ( ! isset( $static_characters ) ) { + /* translators: opening curly double quote */ + $opening_quote = _x( '“', 'opening curly double quote' ); + /* translators: closing curly double quote */ + $closing_quote = _x( '”', 'closing curly double quote' ); + + /* translators: apostrophe, for example in 'cause or can't */ + $apos = _x( '’', 'apostrophe' ); + + /* translators: prime, for example in 9' (nine feet) */ + $prime = _x( '′', 'prime' ); + /* translators: double prime, for example in 9" (nine inches) */ + $double_prime = _x( '″', 'double prime' ); + + /* translators: opening curly single quote */ + $opening_single_quote = _x( '‘', 'opening curly single quote' ); + /* translators: closing curly single quote */ + $closing_single_quote = _x( '’', 'closing curly single quote' ); + + /* translators: en dash */ + $en_dash = _x( '–', 'en dash' ); + /* translators: em dash */ + $em_dash = _x( '—', 'em dash' ); + + $default_no_texturize_tags = array('pre', 'code', 'kbd', 'style', 'script', 'tt'); + $default_no_texturize_shortcodes = array('code'); + + // if a plugin has provided an autocorrect array, use it + if ( isset($wp_cockneyreplace) ) { + $cockney = array_keys($wp_cockneyreplace); + $cockneyreplace = array_values($wp_cockneyreplace); + } elseif ( "'" != $apos ) { // Only bother if we're doing a replacement. + $cockney = array( "'tain't", "'twere", "'twas", "'tis", "'twill", "'til", "'bout", "'nuff", "'round", "'cause" ); + $cockneyreplace = array( $apos . "tain" . $apos . "t", $apos . "twere", $apos . "twas", $apos . "tis", $apos . "twill", $apos . "til", $apos . "bout", $apos . "nuff", $apos . "round", $apos . "cause" ); + } else { + $cockney = $cockneyreplace = array(); + } + + $static_characters = array_merge( array( '---', ' -- ', '--', ' - ', 'xn–', '...', '``', '\'\'', ' (tm)' ), $cockney ); + $static_replacements = array_merge( array( $em_dash, ' ' . $em_dash . ' ', $en_dash, ' ' . $en_dash . ' ', 'xn--', '…', $opening_quote, $closing_quote, ' ™' ), $cockneyreplace ); + + $dynamic = array(); + if ( "'" != $apos ) { + $dynamic[ '/\'(\d\d(?:’|\')?s)/' ] = $apos . '$1'; // '99's + $dynamic[ '/\'(\d)/' ] = $apos . '$1'; // '99 + } + if ( "'" != $opening_single_quote ) + $dynamic[ '/(\s|\A|[([{<]|")\'/' ] = '$1' . $opening_single_quote; // opening single quote, even after (, {, <, [ + if ( '"' != $double_prime ) + $dynamic[ '/(\d)"/' ] = '$1' . $double_prime; // 9" (double prime) + if ( "'" != $prime ) + $dynamic[ '/(\d)\'/' ] = '$1' . $prime; // 9' (prime) + if ( "'" != $apos ) + $dynamic[ '/(\S)\'([^\'\s])/' ] = '$1' . $apos . '$2'; // apostrophe in a word + if ( '"' != $opening_quote ) + $dynamic[ '/(\s|\A|[([{<])"(?!\s)/' ] = '$1' . $opening_quote . '$2'; // opening double quote, even after (, {, <, [ + if ( '"' != $closing_quote ) + $dynamic[ '/"(\s|\S|\Z)/' ] = $closing_quote . '$1'; // closing double quote + if ( "'" != $closing_single_quote ) + $dynamic[ '/\'([\s.]|\Z)/' ] = $closing_single_quote . '$1'; // closing single quote + + $dynamic[ '/\b(\d+)x(\d+)\b/' ] = '$1×$2'; // 9x9 (times) + + $dynamic_characters = array_keys( $dynamic ); + $dynamic_replacements = array_values( $dynamic ); + } + + // Transform into regexp sub-expression used in _wptexturize_pushpop_element + // Must do this every time in case plugins use these filters in a context sensitive manner + $no_texturize_tags = '(' . implode('|', apply_filters('no_texturize_tags', $default_no_texturize_tags) ) . ')'; + $no_texturize_shortcodes = '(' . implode('|', apply_filters('no_texturize_shortcodes', $default_no_texturize_shortcodes) ) . ')'; + + $no_texturize_tags_stack = array(); + $no_texturize_shortcodes_stack = array(); + + $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE); + + foreach ( $textarr as &$curl ) { + if ( empty( $curl ) ) + continue; + + // Only call _wptexturize_pushpop_element if first char is correct tag opening + $first = $curl[0]; + if ( '<' === $first ) { + _wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>'); + } elseif ( '[' === $first ) { + _wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']'); + } elseif ( empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack) ) { + // This is not a tag, nor is the texturization disabled static strings + $curl = str_replace($static_characters, $static_replacements, $curl); + // regular expressions + $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl); + } + $curl = preg_replace('/&([^#])(?![a-zA-Z1-4]{1,8};)/', '&$1', $curl); + } + return implode( '', $textarr ); +} + +/** + * Search for disabled element tags. Push element to stack on tag open and pop + * on tag close. Assumes first character of $text is tag opening. + * + * @since 2.9.0 + * @access private + * + * @param string $text Text to check. First character is assumed to be $opening + * @param array $stack Array used as stack of opened tag elements + * @param string $disabled_elements Tags to match against formatted as regexp sub-expression + * @param string $opening Tag opening character, assumed to be 1 character long + * @param string $closing Tag closing character + */ +function _wptexturize_pushpop_element($text, &$stack, $disabled_elements, $opening = '<', $closing = '>') { + // Check if it is a closing tag -- otherwise assume opening tag + if (strncmp($opening . '/', $text, 2)) { + // Opening? Check $text+1 against disabled elements + if (preg_match('/^' . $disabled_elements . '\b/', substr($text, 1), $matches)) { + /* + * This disables texturize until we find a closing tag of our type + * (e.g.
    ) even if there was invalid nesting before that
    +			 *
    +			 * Example: in the case 
    sadsadasd"baba"
    + * "baba" won't be texturize + */ + + array_push($stack, $matches[1]); + } + } else { + // Closing? Check $text+2 against disabled elements + $c = preg_quote($closing, '/'); + if (preg_match('/^' . $disabled_elements . $c . '/', substr($text, 2), $matches)) { + $last = array_pop($stack); + + // Make sure it matches the opening tag + if ($last != $matches[1]) + array_push($stack, $last); + } + } +} + +/** + * Replaces double line-breaks with paragraph elements. + * + * A group of regex replaces used to identify text formatted with newlines and + * replace double line-breaks with HTML paragraph tags. The remaining + * line-breaks after conversion become <
    > tags, unless $br is set to '0' + * or 'false'. + * + * @since 0.71 + * + * @param string $pee The text which has to be formatted. + * @param bool $br Optional. If set, this will convert all remaining line-breaks after paragraphing. Default true. + * @return string Text which has been converted into correct paragraph tags. + */ +function wpautop($pee, $br = true) { + $pre_tags = array(); + + if ( trim($pee) === '' ) + return ''; + + $pee = $pee . "\n"; // just to make things a little easier, pad the end + + if ( strpos($pee, '', $pee ); + $last_pee = array_pop($pee_parts); + $pee = ''; + $i = 0; + + foreach ( $pee_parts as $pee_part ) { + $start = strpos($pee_part, ''; + + $pee .= substr( $pee_part, 0, $start ) . $name; + $i++; + } + + $pee .= $last_pee; + } + + $pee = preg_replace('|
    \s*
    |', "\n\n", $pee); + // Space things out a little + $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|noscript|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)'; + $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee); + $pee = preg_replace('!()!', "$1\n\n", $pee); + $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines + if ( strpos($pee, ']*)>\s*|', "", $pee); // no pee inside object/embed + $pee = preg_replace('|\s*\s*|', '', $pee); + } + $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates + // make paragraphs, including one at the end + $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY); + $pee = ''; + foreach ( $pees as $tinkle ) + $pee .= '

    ' . trim($tinkle, "\n") . "

    \n"; + $pee = preg_replace('|

    \s*

    |', '', $pee); // under certain strange conditions it could create a P of entirely whitespace + $pee = preg_replace('!

    ([^<]+)!', "

    $1

    ", $pee); + $pee = preg_replace('!

    \s*(]*>)\s*

    !', "$1", $pee); // don't pee all over a tag + $pee = preg_replace("|

    (|", "$1", $pee); // problem with nested lists + $pee = preg_replace('|

    ]*)>|i', "

    ", $pee); + $pee = str_replace('

    ', '

    ', $pee); + $pee = preg_replace('!

    \s*(]*>)!', "$1", $pee); + $pee = preg_replace('!(]*>)\s*

    !', "$1", $pee); + if ( $br ) { + $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee); + $pee = preg_replace('|(?)\s*\n|', "
    \n", $pee); // optionally make line breaks + $pee = str_replace('', "\n", $pee); + } + $pee = preg_replace('!(]*>)\s*
    !', "$1", $pee); + $pee = preg_replace('!
    (\s*]*>)!', '$1', $pee); + $pee = preg_replace( "|\n

    $|", '

    ', $pee ); + + if ( !empty($pre_tags) ) + $pee = str_replace(array_keys($pre_tags), array_values($pre_tags), $pee); + + return $pee; +} + +/** + * Newline preservation help function for wpautop + * + * @since 3.1.0 + * @access private + * + * @param array $matches preg_replace_callback matches array + * @return string + */ +function _autop_newline_preservation_helper( $matches ) { + return str_replace("\n", "", $matches[0]); +} + +/** + * Don't auto-p wrap shortcodes that stand alone + * + * Ensures that shortcodes are not wrapped in <

    >...<

    >. + * + * @since 2.9.0 + * + * @param string $pee The content. + * @return string The filtered content. + */ +function shortcode_unautop( $pee ) { + global $shortcode_tags; + + if ( empty( $shortcode_tags ) || !is_array( $shortcode_tags ) ) { + return $pee; + } + + $tagregexp = join( '|', array_map( 'preg_quote', array_keys( $shortcode_tags ) ) ); + + $pattern = + '/' + . '

    ' // Opening paragraph + . '\\s*+' // Optional leading whitespace + . '(' // 1: The shortcode + . '\\[' // Opening bracket + . "($tagregexp)" // 2: Shortcode name + . '(?![\\w-])' // Not followed by word character or hyphen + // Unroll the loop: Inside the opening shortcode tag + . '[^\\]\\/]*' // Not a closing bracket or forward slash + . '(?:' + . '\\/(?!\\])' // A forward slash not followed by a closing bracket + . '[^\\]\\/]*' // Not a closing bracket or forward slash + . ')*?' + . '(?:' + . '\\/\\]' // Self closing tag and closing bracket + . '|' + . '\\]' // Closing bracket + . '(?:' // Unroll the loop: Optionally, anything between the opening and closing shortcode tags + . '[^\\[]*+' // Not an opening bracket + . '(?:' + . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag + . '[^\\[]*+' // Not an opening bracket + . ')*+' + . '\\[\\/\\2\\]' // Closing shortcode tag + . ')?' + . ')' + . ')' + . '\\s*+' // optional trailing whitespace + . '<\\/p>' // closing paragraph + . '/s'; + + return preg_replace( $pattern, '$1', $pee ); +} + +/** + * Checks to see if a string is utf8 encoded. + * + * NOTE: This function checks for 5-Byte sequences, UTF8 + * has Bytes Sequences with a maximum length of 4. + * + * @author bmorel at ssi dot fr (modified) + * @since 1.2.1 + * + * @param string $str The string to be checked + * @return bool True if $str fits a UTF-8 model, false otherwise. + */ +function seems_utf8($str) { + $length = strlen($str); + for ($i=0; $i < $length; $i++) { + $c = ord($str[$i]); + if ($c < 0x80) $n = 0; # 0bbbbbbb + elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb + elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb + elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb + elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb + elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b + else return false; # Does not match any model + for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ? + if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80)) + return false; + } + } + return true; +} + +/** + * Converts a number of special characters into their HTML entities. + * + * Specifically deals with: &, <, >, ", and '. + * + * $quote_style can be set to ENT_COMPAT to encode " to + * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. + * + * @since 1.2.2 + * @access private + * + * @param string $string The text which is to be encoded. + * @param mixed $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Also compatible with old values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES. + * @param string $charset Optional. The character encoding of the string. Default is false. + * @param boolean $double_encode Optional. Whether to encode existing html entities. Default is false. + * @return string The encoded text with HTML entities. + */ +function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { + $string = (string) $string; + + if ( 0 === strlen( $string ) ) + return ''; + + // Don't bother if there are no specialchars - saves some processing + if ( ! preg_match( '/[&<>"\']/', $string ) ) + return $string; + + // Account for the previous behaviour of the function when the $quote_style is not an accepted value + if ( empty( $quote_style ) ) + $quote_style = ENT_NOQUOTES; + elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) + $quote_style = ENT_QUOTES; + + // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() + if ( ! $charset ) { + static $_charset; + if ( ! isset( $_charset ) ) { + $alloptions = wp_load_alloptions(); + $_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : ''; + } + $charset = $_charset; + } + + if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) + $charset = 'UTF-8'; + + $_quote_style = $quote_style; + + if ( $quote_style === 'double' ) { + $quote_style = ENT_COMPAT; + $_quote_style = ENT_COMPAT; + } elseif ( $quote_style === 'single' ) { + $quote_style = ENT_NOQUOTES; + } + + // Handle double encoding ourselves + if ( $double_encode ) { + $string = @htmlspecialchars( $string, $quote_style, $charset ); + } else { + // Decode & into & + $string = wp_specialchars_decode( $string, $_quote_style ); + + // Guarantee every &entity; is valid or re-encode the & + $string = wp_kses_normalize_entities( $string ); + + // Now re-encode everything except &entity; + $string = preg_split( '/(&#?x?[0-9a-z]+;)/i', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); + + for ( $i = 0; $i < count( $string ); $i += 2 ) + $string[$i] = @htmlspecialchars( $string[$i], $quote_style, $charset ); + + $string = implode( '', $string ); + } + + // Backwards compatibility + if ( 'single' === $_quote_style ) + $string = str_replace( "'", ''', $string ); + + return $string; +} + +/** + * Converts a number of HTML entities into their special characters. + * + * Specifically deals with: &, <, >, ", and '. + * + * $quote_style can be set to ENT_COMPAT to decode " entities, + * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded. + * + * @since 2.8.0 + * + * @param string $string The text which is to be decoded. + * @param mixed $quote_style Optional. Converts double quotes if set to ENT_COMPAT, both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. Also compatible with old _wp_specialchars() values; converting single quotes if set to 'single', double if set to 'double' or both if otherwise set. Default is ENT_NOQUOTES. + * @return string The decoded text without HTML entities. + */ +function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) { + $string = (string) $string; + + if ( 0 === strlen( $string ) ) { + return ''; + } + + // Don't bother if there are no entities - saves a lot of processing + if ( strpos( $string, '&' ) === false ) { + return $string; + } + + // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value + if ( empty( $quote_style ) ) { + $quote_style = ENT_NOQUOTES; + } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { + $quote_style = ENT_QUOTES; + } + + // More complete than get_html_translation_table( HTML_SPECIALCHARS ) + $single = array( ''' => '\'', ''' => '\'' ); + $single_preg = array( '/�*39;/' => ''', '/�*27;/i' => ''' ); + $double = array( '"' => '"', '"' => '"', '"' => '"' ); + $double_preg = array( '/�*34;/' => '"', '/�*22;/i' => '"' ); + $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' ); + $others_preg = array( '/�*60;/' => '<', '/�*62;/' => '>', '/�*38;/' => '&', '/�*26;/i' => '&' ); + + if ( $quote_style === ENT_QUOTES ) { + $translation = array_merge( $single, $double, $others ); + $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); + } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) { + $translation = array_merge( $double, $others ); + $translation_preg = array_merge( $double_preg, $others_preg ); + } elseif ( $quote_style === 'single' ) { + $translation = array_merge( $single, $others ); + $translation_preg = array_merge( $single_preg, $others_preg ); + } elseif ( $quote_style === ENT_NOQUOTES ) { + $translation = $others; + $translation_preg = $others_preg; + } + + // Remove zero padding on numeric entities + $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string ); + + // Replace characters according to translation table + return strtr( $string, $translation ); +} + +/** + * Checks for invalid UTF8 in a string. + * + * @since 2.8.0 + * + * @param string $string The text which is to be checked. + * @param boolean $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. + * @return string The checked text. + */ +function wp_check_invalid_utf8( $string, $strip = false ) { + $string = (string) $string; + + if ( 0 === strlen( $string ) ) { + return ''; + } + + // Store the site charset as a static to avoid multiple calls to get_option() + static $is_utf8; + if ( !isset( $is_utf8 ) ) { + $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); + } + if ( !$is_utf8 ) { + return $string; + } + + // Check for support for utf8 in the installed PCRE library once and store the result in a static + static $utf8_pcre; + if ( !isset( $utf8_pcre ) ) { + $utf8_pcre = @preg_match( '/^./u', 'a' ); + } + // We can't demand utf8 in the PCRE installation, so just return the string in those cases + if ( !$utf8_pcre ) { + return $string; + } + + // preg_match fails when it encounters invalid UTF8 in $string + if ( 1 === @preg_match( '/^./us', $string ) ) { + return $string; + } + + // Attempt to strip the bad chars if requested (not recommended) + if ( $strip && function_exists( 'iconv' ) ) { + return iconv( 'utf-8', 'utf-8', $string ); + } + + return ''; +} + +/** + * Encode the Unicode values to be used in the URI. + * + * @since 1.5.0 + * + * @param string $utf8_string + * @param int $length Max length of the string + * @return string String with Unicode encoded for URI. + */ +function utf8_uri_encode( $utf8_string, $length = 0 ) { + $unicode = ''; + $values = array(); + $num_octets = 1; + $unicode_length = 0; + + $string_length = strlen( $utf8_string ); + for ($i = 0; $i < $string_length; $i++ ) { + + $value = ord( $utf8_string[ $i ] ); + + if ( $value < 128 ) { + if ( $length && ( $unicode_length >= $length ) ) + break; + $unicode .= chr($value); + $unicode_length++; + } else { + if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3; + + $values[] = $value; + + if ( $length && ( $unicode_length + ($num_octets * 3) ) > $length ) + break; + if ( count( $values ) == $num_octets ) { + if ($num_octets == 3) { + $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]); + $unicode_length += 9; + } else { + $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]); + $unicode_length += 6; + } + + $values = array(); + $num_octets = 1; + } + } + } + + return $unicode; +} + +/** + * Converts all accent characters to ASCII characters. + * + * If there are no accent characters, then the string given is just returned. + * + * @since 1.2.1 + * + * @param string $string Text that might have accent characters + * @return string Filtered string with replaced "nice" characters. + */ +function remove_accents($string) { + if ( !preg_match('/[\x80-\xff]/', $string) ) + return $string; + + if (seems_utf8($string)) { + $chars = array( + // Decompositions for Latin-1 Supplement + chr(194).chr(170) => 'a', chr(194).chr(186) => 'o', + chr(195).chr(128) => 'A', chr(195).chr(129) => 'A', + chr(195).chr(130) => 'A', chr(195).chr(131) => 'A', + chr(195).chr(132) => 'A', chr(195).chr(133) => 'A', + chr(195).chr(134) => 'AE',chr(195).chr(135) => 'C', + chr(195).chr(136) => 'E', chr(195).chr(137) => 'E', + chr(195).chr(138) => 'E', chr(195).chr(139) => 'E', + chr(195).chr(140) => 'I', chr(195).chr(141) => 'I', + chr(195).chr(142) => 'I', chr(195).chr(143) => 'I', + chr(195).chr(144) => 'D', chr(195).chr(145) => 'N', + chr(195).chr(146) => 'O', chr(195).chr(147) => 'O', + chr(195).chr(148) => 'O', chr(195).chr(149) => 'O', + chr(195).chr(150) => 'O', chr(195).chr(153) => 'U', + chr(195).chr(154) => 'U', chr(195).chr(155) => 'U', + chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y', + chr(195).chr(158) => 'TH',chr(195).chr(159) => 's', + chr(195).chr(160) => 'a', chr(195).chr(161) => 'a', + chr(195).chr(162) => 'a', chr(195).chr(163) => 'a', + chr(195).chr(164) => 'a', chr(195).chr(165) => 'a', + chr(195).chr(166) => 'ae',chr(195).chr(167) => 'c', + chr(195).chr(168) => 'e', chr(195).chr(169) => 'e', + chr(195).chr(170) => 'e', chr(195).chr(171) => 'e', + chr(195).chr(172) => 'i', chr(195).chr(173) => 'i', + chr(195).chr(174) => 'i', chr(195).chr(175) => 'i', + chr(195).chr(176) => 'd', chr(195).chr(177) => 'n', + chr(195).chr(178) => 'o', chr(195).chr(179) => 'o', + chr(195).chr(180) => 'o', chr(195).chr(181) => 'o', + chr(195).chr(182) => 'o', chr(195).chr(184) => 'o', + chr(195).chr(185) => 'u', chr(195).chr(186) => 'u', + chr(195).chr(187) => 'u', chr(195).chr(188) => 'u', + chr(195).chr(189) => 'y', chr(195).chr(190) => 'th', + chr(195).chr(191) => 'y', chr(195).chr(152) => 'O', + // Decompositions for Latin Extended-A + chr(196).chr(128) => 'A', chr(196).chr(129) => 'a', + chr(196).chr(130) => 'A', chr(196).chr(131) => 'a', + chr(196).chr(132) => 'A', chr(196).chr(133) => 'a', + chr(196).chr(134) => 'C', chr(196).chr(135) => 'c', + chr(196).chr(136) => 'C', chr(196).chr(137) => 'c', + chr(196).chr(138) => 'C', chr(196).chr(139) => 'c', + chr(196).chr(140) => 'C', chr(196).chr(141) => 'c', + chr(196).chr(142) => 'D', chr(196).chr(143) => 'd', + chr(196).chr(144) => 'D', chr(196).chr(145) => 'd', + chr(196).chr(146) => 'E', chr(196).chr(147) => 'e', + chr(196).chr(148) => 'E', chr(196).chr(149) => 'e', + chr(196).chr(150) => 'E', chr(196).chr(151) => 'e', + chr(196).chr(152) => 'E', chr(196).chr(153) => 'e', + chr(196).chr(154) => 'E', chr(196).chr(155) => 'e', + chr(196).chr(156) => 'G', chr(196).chr(157) => 'g', + chr(196).chr(158) => 'G', chr(196).chr(159) => 'g', + chr(196).chr(160) => 'G', chr(196).chr(161) => 'g', + chr(196).chr(162) => 'G', chr(196).chr(163) => 'g', + chr(196).chr(164) => 'H', chr(196).chr(165) => 'h', + chr(196).chr(166) => 'H', chr(196).chr(167) => 'h', + chr(196).chr(168) => 'I', chr(196).chr(169) => 'i', + chr(196).chr(170) => 'I', chr(196).chr(171) => 'i', + chr(196).chr(172) => 'I', chr(196).chr(173) => 'i', + chr(196).chr(174) => 'I', chr(196).chr(175) => 'i', + chr(196).chr(176) => 'I', chr(196).chr(177) => 'i', + chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij', + chr(196).chr(180) => 'J', chr(196).chr(181) => 'j', + chr(196).chr(182) => 'K', chr(196).chr(183) => 'k', + chr(196).chr(184) => 'k', chr(196).chr(185) => 'L', + chr(196).chr(186) => 'l', chr(196).chr(187) => 'L', + chr(196).chr(188) => 'l', chr(196).chr(189) => 'L', + chr(196).chr(190) => 'l', chr(196).chr(191) => 'L', + chr(197).chr(128) => 'l', chr(197).chr(129) => 'L', + chr(197).chr(130) => 'l', chr(197).chr(131) => 'N', + chr(197).chr(132) => 'n', chr(197).chr(133) => 'N', + chr(197).chr(134) => 'n', chr(197).chr(135) => 'N', + chr(197).chr(136) => 'n', chr(197).chr(137) => 'N', + chr(197).chr(138) => 'n', chr(197).chr(139) => 'N', + chr(197).chr(140) => 'O', chr(197).chr(141) => 'o', + chr(197).chr(142) => 'O', chr(197).chr(143) => 'o', + chr(197).chr(144) => 'O', chr(197).chr(145) => 'o', + chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe', + chr(197).chr(148) => 'R',chr(197).chr(149) => 'r', + chr(197).chr(150) => 'R',chr(197).chr(151) => 'r', + chr(197).chr(152) => 'R',chr(197).chr(153) => 'r', + chr(197).chr(154) => 'S',chr(197).chr(155) => 's', + chr(197).chr(156) => 'S',chr(197).chr(157) => 's', + chr(197).chr(158) => 'S',chr(197).chr(159) => 's', + chr(197).chr(160) => 'S', chr(197).chr(161) => 's', + chr(197).chr(162) => 'T', chr(197).chr(163) => 't', + chr(197).chr(164) => 'T', chr(197).chr(165) => 't', + chr(197).chr(166) => 'T', chr(197).chr(167) => 't', + chr(197).chr(168) => 'U', chr(197).chr(169) => 'u', + chr(197).chr(170) => 'U', chr(197).chr(171) => 'u', + chr(197).chr(172) => 'U', chr(197).chr(173) => 'u', + chr(197).chr(174) => 'U', chr(197).chr(175) => 'u', + chr(197).chr(176) => 'U', chr(197).chr(177) => 'u', + chr(197).chr(178) => 'U', chr(197).chr(179) => 'u', + chr(197).chr(180) => 'W', chr(197).chr(181) => 'w', + chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y', + chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z', + chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z', + chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z', + chr(197).chr(190) => 'z', chr(197).chr(191) => 's', + // Decompositions for Latin Extended-B + chr(200).chr(152) => 'S', chr(200).chr(153) => 's', + chr(200).chr(154) => 'T', chr(200).chr(155) => 't', + // Euro Sign + chr(226).chr(130).chr(172) => 'E', + // GBP (Pound) Sign + chr(194).chr(163) => '', + // Vowels with diacritic (Vietnamese) + // unmarked + chr(198).chr(160) => 'O', chr(198).chr(161) => 'o', + chr(198).chr(175) => 'U', chr(198).chr(176) => 'u', + // grave accent + chr(225).chr(186).chr(166) => 'A', chr(225).chr(186).chr(167) => 'a', + chr(225).chr(186).chr(176) => 'A', chr(225).chr(186).chr(177) => 'a', + chr(225).chr(187).chr(128) => 'E', chr(225).chr(187).chr(129) => 'e', + chr(225).chr(187).chr(146) => 'O', chr(225).chr(187).chr(147) => 'o', + chr(225).chr(187).chr(156) => 'O', chr(225).chr(187).chr(157) => 'o', + chr(225).chr(187).chr(170) => 'U', chr(225).chr(187).chr(171) => 'u', + chr(225).chr(187).chr(178) => 'Y', chr(225).chr(187).chr(179) => 'y', + // hook + chr(225).chr(186).chr(162) => 'A', chr(225).chr(186).chr(163) => 'a', + chr(225).chr(186).chr(168) => 'A', chr(225).chr(186).chr(169) => 'a', + chr(225).chr(186).chr(178) => 'A', chr(225).chr(186).chr(179) => 'a', + chr(225).chr(186).chr(186) => 'E', chr(225).chr(186).chr(187) => 'e', + chr(225).chr(187).chr(130) => 'E', chr(225).chr(187).chr(131) => 'e', + chr(225).chr(187).chr(136) => 'I', chr(225).chr(187).chr(137) => 'i', + chr(225).chr(187).chr(142) => 'O', chr(225).chr(187).chr(143) => 'o', + chr(225).chr(187).chr(148) => 'O', chr(225).chr(187).chr(149) => 'o', + chr(225).chr(187).chr(158) => 'O', chr(225).chr(187).chr(159) => 'o', + chr(225).chr(187).chr(166) => 'U', chr(225).chr(187).chr(167) => 'u', + chr(225).chr(187).chr(172) => 'U', chr(225).chr(187).chr(173) => 'u', + chr(225).chr(187).chr(182) => 'Y', chr(225).chr(187).chr(183) => 'y', + // tilde + chr(225).chr(186).chr(170) => 'A', chr(225).chr(186).chr(171) => 'a', + chr(225).chr(186).chr(180) => 'A', chr(225).chr(186).chr(181) => 'a', + chr(225).chr(186).chr(188) => 'E', chr(225).chr(186).chr(189) => 'e', + chr(225).chr(187).chr(132) => 'E', chr(225).chr(187).chr(133) => 'e', + chr(225).chr(187).chr(150) => 'O', chr(225).chr(187).chr(151) => 'o', + chr(225).chr(187).chr(160) => 'O', chr(225).chr(187).chr(161) => 'o', + chr(225).chr(187).chr(174) => 'U', chr(225).chr(187).chr(175) => 'u', + chr(225).chr(187).chr(184) => 'Y', chr(225).chr(187).chr(185) => 'y', + // acute accent + chr(225).chr(186).chr(164) => 'A', chr(225).chr(186).chr(165) => 'a', + chr(225).chr(186).chr(174) => 'A', chr(225).chr(186).chr(175) => 'a', + chr(225).chr(186).chr(190) => 'E', chr(225).chr(186).chr(191) => 'e', + chr(225).chr(187).chr(144) => 'O', chr(225).chr(187).chr(145) => 'o', + chr(225).chr(187).chr(154) => 'O', chr(225).chr(187).chr(155) => 'o', + chr(225).chr(187).chr(168) => 'U', chr(225).chr(187).chr(169) => 'u', + // dot below + chr(225).chr(186).chr(160) => 'A', chr(225).chr(186).chr(161) => 'a', + chr(225).chr(186).chr(172) => 'A', chr(225).chr(186).chr(173) => 'a', + chr(225).chr(186).chr(182) => 'A', chr(225).chr(186).chr(183) => 'a', + chr(225).chr(186).chr(184) => 'E', chr(225).chr(186).chr(185) => 'e', + chr(225).chr(187).chr(134) => 'E', chr(225).chr(187).chr(135) => 'e', + chr(225).chr(187).chr(138) => 'I', chr(225).chr(187).chr(139) => 'i', + chr(225).chr(187).chr(140) => 'O', chr(225).chr(187).chr(141) => 'o', + chr(225).chr(187).chr(152) => 'O', chr(225).chr(187).chr(153) => 'o', + chr(225).chr(187).chr(162) => 'O', chr(225).chr(187).chr(163) => 'o', + chr(225).chr(187).chr(164) => 'U', chr(225).chr(187).chr(165) => 'u', + chr(225).chr(187).chr(176) => 'U', chr(225).chr(187).chr(177) => 'u', + chr(225).chr(187).chr(180) => 'Y', chr(225).chr(187).chr(181) => 'y', + // Vowels with diacritic (Chinese, Hanyu Pinyin) + chr(201).chr(145) => 'a', + // macron + chr(199).chr(149) => 'U', chr(199).chr(150) => 'u', + // acute accent + chr(199).chr(151) => 'U', chr(199).chr(152) => 'u', + // caron + chr(199).chr(141) => 'A', chr(199).chr(142) => 'a', + chr(199).chr(143) => 'I', chr(199).chr(144) => 'i', + chr(199).chr(145) => 'O', chr(199).chr(146) => 'o', + chr(199).chr(147) => 'U', chr(199).chr(148) => 'u', + chr(199).chr(153) => 'U', chr(199).chr(154) => 'u', + // grave accent + chr(199).chr(155) => 'U', chr(199).chr(156) => 'u', + ); + + // Used for locale-specific rules + $locale = get_locale(); + + if ( 'de_DE' == $locale ) { + $chars[ chr(195).chr(132) ] = 'Ae'; + $chars[ chr(195).chr(164) ] = 'ae'; + $chars[ chr(195).chr(150) ] = 'Oe'; + $chars[ chr(195).chr(182) ] = 'oe'; + $chars[ chr(195).chr(156) ] = 'Ue'; + $chars[ chr(195).chr(188) ] = 'ue'; + $chars[ chr(195).chr(159) ] = 'ss'; + } + + $string = strtr($string, $chars); + } else { + // Assume ISO-8859-1 if not UTF-8 + $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158) + .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194) + .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202) + .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210) + .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218) + .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227) + .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235) + .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243) + .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251) + .chr(252).chr(253).chr(255); + + $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy"; + + $string = strtr($string, $chars['in'], $chars['out']); + $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254)); + $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'); + $string = str_replace($double_chars['in'], $double_chars['out'], $string); + } + + return $string; +} + +/** + * Sanitizes a filename, replacing whitespace with dashes. + * + * Removes special characters that are illegal in filenames on certain + * operating systems and special characters requiring special escaping + * to manipulate at the command line. Replaces spaces and consecutive + * dashes with a single dash. Trims period, dash and underscore from beginning + * and end of filename. + * + * @since 2.1.0 + * + * @param string $filename The filename to be sanitized + * @return string The sanitized filename + */ +function sanitize_file_name( $filename ) { + $filename_raw = $filename; + $special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0)); + $special_chars = apply_filters('sanitize_file_name_chars', $special_chars, $filename_raw); + $filename = str_replace($special_chars, '', $filename); + $filename = preg_replace('/[\s-]+/', '-', $filename); + $filename = trim($filename, '.-_'); + + // Split the filename into a base and extension[s] + $parts = explode('.', $filename); + + // Return if only one extension + if ( count($parts) <= 2 ) + return apply_filters('sanitize_file_name', $filename, $filename_raw); + + // Process multiple extensions + $filename = array_shift($parts); + $extension = array_pop($parts); + $mimes = get_allowed_mime_types(); + + // Loop over any intermediate extensions. Munge them with a trailing underscore if they are a 2 - 5 character + // long alpha string not in the extension whitelist. + foreach ( (array) $parts as $part) { + $filename .= '.' . $part; + + if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) { + $allowed = false; + foreach ( $mimes as $ext_preg => $mime_match ) { + $ext_preg = '!^(' . $ext_preg . ')$!i'; + if ( preg_match( $ext_preg, $part ) ) { + $allowed = true; + break; + } + } + if ( !$allowed ) + $filename .= '_'; + } + } + $filename .= '.' . $extension; + + return apply_filters('sanitize_file_name', $filename, $filename_raw); +} + +/** + * Sanitizes a username, stripping out unsafe characters. + * + * Removes tags, octets, entities, and if strict is enabled, will only keep + * alphanumeric, _, space, ., -, @. After sanitizing, it passes the username, + * raw username (the username in the parameter), and the value of $strict as + * parameters for the 'sanitize_user' filter. + * + * @since 2.0.0 + * @uses apply_filters() Calls 'sanitize_user' hook on username, raw username, + * and $strict parameter. + * + * @param string $username The username to be sanitized. + * @param bool $strict If set limits $username to specific characters. Default false. + * @return string The sanitized username, after passing through filters. + */ +function sanitize_user( $username, $strict = false ) { + $raw_username = $username; + $username = wp_strip_all_tags( $username ); + $username = remove_accents( $username ); + // Kill octets + $username = preg_replace( '|%([a-fA-F0-9][a-fA-F0-9])|', '', $username ); + $username = preg_replace( '/&.+?;/', '', $username ); // Kill entities + + // If strict, reduce to ASCII for max portability. + if ( $strict ) + $username = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $username ); + + $username = trim( $username ); + // Consolidate contiguous whitespace + $username = preg_replace( '|\s+|', ' ', $username ); + + return apply_filters( 'sanitize_user', $username, $raw_username, $strict ); +} + +/** + * Sanitizes a string key. + * + * Keys are used as internal identifiers. Lowercase alphanumeric characters, dashes and underscores are allowed. + * + * @since 3.0.0 + * + * @param string $key String key + * @return string Sanitized key + */ +function sanitize_key( $key ) { + $raw_key = $key; + $key = strtolower( $key ); + $key = preg_replace( '/[^a-z0-9_\-]/', '', $key ); + return apply_filters( 'sanitize_key', $key, $raw_key ); +} + +/** + * Sanitizes a title, or returns a fallback title. + * + * Specifically, HTML and PHP tags are stripped. Further actions can be added + * via the plugin API. If $title is empty and $fallback_title is set, the latter + * will be used. + * + * @since 1.0.0 + * + * @param string $title The string to be sanitized. + * @param string $fallback_title Optional. A title to use if $title is empty. + * @param string $context Optional. The operation for which the string is sanitized + * @return string The sanitized string. + */ +function sanitize_title( $title, $fallback_title = '', $context = 'save' ) { + $raw_title = $title; + + if ( 'save' == $context ) + $title = remove_accents($title); + + $title = apply_filters('sanitize_title', $title, $raw_title, $context); + + if ( '' === $title || false === $title ) + $title = $fallback_title; + + return $title; +} + +/** + * Sanitizes a title with the 'query' context. + * + * Used for querying the database for a value from URL. + * + * @since 3.1.0 + * @uses sanitize_title() + * + * @param string $title The string to be sanitized. + * @return string The sanitized string. + */ +function sanitize_title_for_query( $title ) { + return sanitize_title( $title, '', 'query' ); +} + +/** + * Sanitizes a title, replacing whitespace and a few other characters with dashes. + * + * Limits the output to alphanumeric characters, underscore (_) and dash (-). + * Whitespace becomes a dash. + * + * @since 1.2.0 + * + * @param string $title The title to be sanitized. + * @param string $raw_title Optional. Not used. + * @param string $context Optional. The operation for which the string is sanitized. + * @return string The sanitized title. + */ +function sanitize_title_with_dashes( $title, $raw_title = '', $context = 'display' ) { + $title = strip_tags($title); + // Preserve escaped octets. + $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title); + // Remove percent signs that are not part of an octet. + $title = str_replace('%', '', $title); + // Restore octets. + $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title); + + if (seems_utf8($title)) { + if (function_exists('mb_strtolower')) { + $title = mb_strtolower($title, 'UTF-8'); + } + $title = utf8_uri_encode($title, 200); + } + + $title = strtolower($title); + $title = preg_replace('/&.+?;/', '', $title); // kill entities + $title = str_replace('.', '-', $title); + + if ( 'save' == $context ) { + // Convert nbsp, ndash and mdash to hyphens + $title = str_replace( array( '%c2%a0', '%e2%80%93', '%e2%80%94' ), '-', $title ); + + // Strip these characters entirely + $title = str_replace( array( + // iexcl and iquest + '%c2%a1', '%c2%bf', + // angle quotes + '%c2%ab', '%c2%bb', '%e2%80%b9', '%e2%80%ba', + // curly quotes + '%e2%80%98', '%e2%80%99', '%e2%80%9c', '%e2%80%9d', + '%e2%80%9a', '%e2%80%9b', '%e2%80%9e', '%e2%80%9f', + // copy, reg, deg, hellip and trade + '%c2%a9', '%c2%ae', '%c2%b0', '%e2%80%a6', '%e2%84%a2', + // acute accents + '%c2%b4', '%cb%8a', '%cc%81', '%cd%81', + // grave accent, macron, caron + '%cc%80', '%cc%84', '%cc%8c', + ), '', $title ); + + // Convert times to x + $title = str_replace( '%c3%97', 'x', $title ); + } + + $title = preg_replace('/[^%a-z0-9 _-]/', '', $title); + $title = preg_replace('/\s+/', '-', $title); + $title = preg_replace('|-+|', '-', $title); + $title = trim($title, '-'); + + return $title; +} + +/** + * Ensures a string is a valid SQL order by clause. + * + * Accepts one or more columns, with or without ASC/DESC, and also accepts + * RAND(). + * + * @since 2.5.1 + * + * @param string $orderby Order by string to be checked. + * @return string|bool Returns the order by clause if it is a match, false otherwise. + */ +function sanitize_sql_orderby( $orderby ){ + preg_match('/^\s*([a-z0-9_]+(\s+(ASC|DESC))?(\s*,\s*|\s*$))+|^\s*RAND\(\s*\)\s*$/i', $orderby, $obmatches); + if ( !$obmatches ) + return false; + return $orderby; +} + +/** + * Sanitizes an HTML classname to ensure it only contains valid characters. + * + * Strips the string down to A-Z,a-z,0-9,_,-. If this results in an empty + * string then it will return the alternative value supplied. + * + * @todo Expand to support the full range of CDATA that a class attribute can contain. + * + * @since 2.8.0 + * + * @param string $class The classname to be sanitized + * @param string $fallback Optional. The value to return if the sanitization end's up as an empty string. + * Defaults to an empty string. + * @return string The sanitized value + */ +function sanitize_html_class( $class, $fallback = '' ) { + //Strip out any % encoded octets + $sanitized = preg_replace( '|%[a-fA-F0-9][a-fA-F0-9]|', '', $class ); + + //Limit to A-Z,a-z,0-9,_,- + $sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $sanitized ); + + if ( '' == $sanitized ) + $sanitized = $fallback; + + return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback ); +} + +/** + * Converts a number of characters from a string. + * + * Metadata tags <> and <<category>> are removed, <<br>> and <<hr>> are + * converted into correct XHTML and Unicode characters are converted to the + * valid range. + * + * @since 0.71 + * + * @param string $content String of characters to be converted. + * @param string $deprecated Not used. + * @return string Converted string. + */ +function convert_chars($content, $deprecated = '') { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '0.71' ); + + // Translation of invalid Unicode references range to valid range + $wp_htmltranswinuni = array( + '€' => '€', // the Euro sign + '' => '', + '‚' => '‚', // these are Windows CP1252 specific characters + 'ƒ' => 'ƒ', // they would look weird on non-Windows browsers + '„' => '„', + '…' => '…', + '†' => '†', + '‡' => '‡', + 'ˆ' => 'ˆ', + '‰' => '‰', + 'Š' => 'Š', + '‹' => '‹', + 'Œ' => 'Œ', + '' => '', + 'Ž' => 'Ž', + '' => '', + '' => '', + '‘' => '‘', + '’' => '’', + '“' => '“', + '”' => '”', + '•' => '•', + '–' => '–', + '—' => '—', + '˜' => '˜', + '™' => '™', + 'š' => 'š', + '›' => '›', + 'œ' => 'œ', + '' => '', + 'ž' => 'ž', + 'Ÿ' => 'Ÿ' + ); + + // Remove metadata tags + $content = preg_replace('/<title>(.+?)<\/title>/','',$content); + $content = preg_replace('/<category>(.+?)<\/category>/','',$content); + + // Converts lone & characters into & (a.k.a. &) + $content = preg_replace('/&([^#])(?![a-z1-4]{1,8};)/i', '&$1', $content); + + // Fix Word pasting + $content = strtr($content, $wp_htmltranswinuni); + + // Just a little XHTML help + $content = str_replace('<br>', '<br />', $content); + $content = str_replace('<hr>', '<hr />', $content); + + return $content; +} + +/** + * Balances tags if forced to, or if the 'use_balanceTags' option is set to true. + * + * @since 0.71 + * + * @param string $text Text to be balanced + * @param bool $force If true, forces balancing, ignoring the value of the option. Default false. + * @return string Balanced text + */ +function balanceTags( $text, $force = false ) { + if ( $force || get_option('use_balanceTags') == 1 ) + return force_balance_tags( $text ); + else + return $text; +} + +/** + * Balances tags of string using a modified stack. + * + * @since 2.0.4 + * + * @author Leonard Lin <leonard@acm.org> + * @license GPL + * @copyright November 4, 2001 + * @version 1.1 + * @todo Make better - change loop condition to $text in 1.2 + * @internal Modified by Scott Reilly (coffee2code) 02 Aug 2004 + * 1.1 Fixed handling of append/stack pop order of end text + * Added Cleaning Hooks + * 1.0 First Version + * + * @param string $text Text to be balanced. + * @return string Balanced text. + */ +function force_balance_tags( $text ) { + $tagstack = array(); + $stacksize = 0; + $tagqueue = ''; + $newtext = ''; + // Known single-entity/self-closing tags + $single_tags = array( 'area', 'base', 'basefont', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param', 'source' ); + // Tags that can be immediately nested within themselves + $nestable_tags = array( 'blockquote', 'div', 'object', 'q', 'span' ); + + // WP bug fix for comments - in case you REALLY meant to type '< !--' + $text = str_replace('< !--', '< !--', $text); + // WP bug fix for LOVE <3 (and other situations with '<' before a number) + $text = preg_replace('#<([0-9]{1})#', '<$1', $text); + + while ( preg_match("/<(\/?[\w:]*)\s*([^>]*)>/", $text, $regex) ) { + $newtext .= $tagqueue; + + $i = strpos($text, $regex[0]); + $l = strlen($regex[0]); + + // clear the shifter + $tagqueue = ''; + // Pop or Push + if ( isset($regex[1][0]) && '/' == $regex[1][0] ) { // End Tag + $tag = strtolower(substr($regex[1],1)); + // if too many closing tags + if( $stacksize <= 0 ) { + $tag = ''; + // or close to be safe $tag = '/' . $tag; + } + // if stacktop value = tag close value then pop + else if ( $tagstack[$stacksize - 1] == $tag ) { // found closing tag + $tag = '</' . $tag . '>'; // Close Tag + // Pop + array_pop( $tagstack ); + $stacksize--; + } else { // closing tag not at top, search for it + for ( $j = $stacksize-1; $j >= 0; $j-- ) { + if ( $tagstack[$j] == $tag ) { + // add tag to tagqueue + for ( $k = $stacksize-1; $k >= $j; $k--) { + $tagqueue .= '</' . array_pop( $tagstack ) . '>'; + $stacksize--; + } + break; + } + } + $tag = ''; + } + } else { // Begin Tag + $tag = strtolower($regex[1]); + + // Tag Cleaning + + // If it's an empty tag "< >", do nothing + if ( '' == $tag ) { + // do nothing + } + // ElseIf it presents itself as a self-closing tag... + elseif ( substr( $regex[2], -1 ) == '/' ) { + // ...but it isn't a known single-entity self-closing tag, then don't let it be treated as such and + // immediately close it with a closing tag (the tag will encapsulate no text as a result) + if ( ! in_array( $tag, $single_tags ) ) + $regex[2] = trim( substr( $regex[2], 0, -1 ) ) . "></$tag"; + } + // ElseIf it's a known single-entity tag but it doesn't close itself, do so + elseif ( in_array($tag, $single_tags) ) { + $regex[2] .= '/'; + } + // Else it's not a single-entity tag + else { + // If the top of the stack is the same as the tag we want to push, close previous tag + if ( $stacksize > 0 && !in_array($tag, $nestable_tags) && $tagstack[$stacksize - 1] == $tag ) { + $tagqueue = '</' . array_pop( $tagstack ) . '>'; + $stacksize--; + } + $stacksize = array_push( $tagstack, $tag ); + } + + // Attributes + $attributes = $regex[2]; + if( ! empty( $attributes ) && $attributes[0] != '>' ) + $attributes = ' ' . $attributes; + + $tag = '<' . $tag . $attributes . '>'; + //If already queuing a close tag, then put this tag on, too + if ( !empty($tagqueue) ) { + $tagqueue .= $tag; + $tag = ''; + } + } + $newtext .= substr($text, 0, $i) . $tag; + $text = substr($text, $i + $l); + } + + // Clear Tag Queue + $newtext .= $tagqueue; + + // Add Remaining text + $newtext .= $text; + + // Empty Stack + while( $x = array_pop($tagstack) ) + $newtext .= '</' . $x . '>'; // Add remaining tags to close + + // WP fix for the bug with HTML comments + $newtext = str_replace("< !--","<!--",$newtext); + $newtext = str_replace("< !--","< !--",$newtext); + + return $newtext; +} + +/** + * Acts on text which is about to be edited. + * + * The $content is run through esc_textarea(), which uses htmlspecialchars() + * to convert special characters to HTML entities. If $richedit is set to true, + * it is simply a holder for the 'format_to_edit' filter. + * + * @since 0.71 + * + * @param string $content The text about to be edited. + * @param bool $richedit Whether the $content should not pass through htmlspecialchars(). Default false (meaning it will be passed). + * @return string The text after the filter (and possibly htmlspecialchars()) has been run. + */ +function format_to_edit( $content, $richedit = false ) { + $content = apply_filters( 'format_to_edit', $content ); + if ( ! $richedit ) + $content = esc_textarea( $content ); + return $content; +} + +/** + * Holder for the 'format_to_post' filter. + * + * @since 0.71 + * + * @param string $content The text to pass through the filter. + * @return string Text returned from the 'format_to_post' filter. + */ +function format_to_post($content) { + $content = apply_filters('format_to_post', $content); + return $content; +} + +/** + * Add leading zeros when necessary. + * + * If you set the threshold to '4' and the number is '10', then you will get + * back '0010'. If you set the threshold to '4' and the number is '5000', then you + * will get back '5000'. + * + * Uses sprintf to append the amount of zeros based on the $threshold parameter + * and the size of the number. If the number is large enough, then no zeros will + * be appended. + * + * @since 0.71 + * + * @param mixed $number Number to append zeros to if not greater than threshold. + * @param int $threshold Digit places number needs to be to not have zeros added. + * @return string Adds leading zeros to number if needed. + */ +function zeroise($number, $threshold) { + return sprintf('%0'.$threshold.'s', $number); +} + +/** + * Adds backslashes before letters and before a number at the start of a string. + * + * @since 0.71 + * + * @param string $string Value to which backslashes will be added. + * @return string String with backslashes inserted. + */ +function backslashit($string) { + if ( isset( $string[0] ) && $string[0] >= '0' && $string[0] <= '9' ) + $string = '\\\\' . $string; + return addcslashes( $string, 'A..Za..z' ); +} + +/** + * Appends a trailing slash. + * + * Will remove trailing slash if it exists already before adding a trailing + * slash. This prevents double slashing a string or path. + * + * The primary use of this is for paths and thus should be used for paths. It is + * not restricted to paths and offers no specific path support. + * + * @since 1.2.0 + * @uses untrailingslashit() Unslashes string if it was slashed already. + * + * @param string $string What to add the trailing slash to. + * @return string String with trailing slash added. + */ +function trailingslashit($string) { + return untrailingslashit($string) . '/'; +} + +/** + * Removes trailing slash if it exists. + * + * The primary use of this is for paths and thus should be used for paths. It is + * not restricted to paths and offers no specific path support. + * + * @since 2.2.0 + * + * @param string $string What to remove the trailing slash from. + * @return string String without the trailing slash. + */ +function untrailingslashit($string) { + return rtrim($string, '/'); +} + +/** + * Adds slashes to escape strings. + * + * Slashes will first be removed if magic_quotes_gpc is set, see {@link + * http://www.php.net/magic_quotes} for more details. + * + * @since 0.71 + * + * @param string $gpc The string returned from HTTP request data. + * @return string Returns a string escaped with slashes. + */ +function addslashes_gpc($gpc) { + if ( get_magic_quotes_gpc() ) + $gpc = stripslashes($gpc); + + return wp_slash($gpc); +} + +/** + * Navigates through an array and removes slashes from the values. + * + * If an array is passed, the array_map() function causes a callback to pass the + * value back to the function. The slashes from this value will removed. + * + * @since 2.0.0 + * + * @param mixed $value The value to be stripped. + * @return mixed Stripped value. + */ +function stripslashes_deep($value) { + if ( is_array($value) ) { + $value = array_map('stripslashes_deep', $value); + } elseif ( is_object($value) ) { + $vars = get_object_vars( $value ); + foreach ($vars as $key=>$data) { + $value->{$key} = stripslashes_deep( $data ); + } + } elseif ( is_string( $value ) ) { + $value = stripslashes($value); + } + + return $value; +} + +/** + * Navigates through an array and encodes the values to be used in a URL. + * + * + * @since 2.2.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 urlencode_deep($value) { + $value = is_array($value) ? array_map('urlencode_deep', $value) : urlencode($value); + return $value; +} + +/** + * Navigates through an array and raw encodes the values to be used in a URL. + * + * @since 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 ); +} + +/** + * Converts email addresses characters to HTML entities to block spam bots. + * + * @since 0.71 + * + * @param string $email_address Email address. + * @param int $hex_encoding Optional. Set to 1 to enable hex encoding. + * @return string Converted email address. + */ +function antispambot( $email_address, $hex_encoding = 0 ) { + $email_no_spam_address = ''; + for ( $i = 0; $i < strlen( $email_address ); $i++ ) { + $j = rand( 0, 1 + $hex_encoding ); + if ( $j == 0 ) { + $email_no_spam_address .= '&#' . ord( $email_address[$i] ) . ';'; + } elseif ( $j == 1 ) { + $email_no_spam_address .= $email_address[$i]; + } elseif ( $j == 2 ) { + $email_no_spam_address .= '%' . zeroise( dechex( ord( $email_address[$i] ) ), 2 ); + } + } + + $email_no_spam_address = str_replace( '@', '@', $email_no_spam_address ); + + return $email_no_spam_address; +} + +/** + * Callback to convert URI match to HTML A element. + * + * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link + * make_clickable()}. + * + * @since 2.3.2 + * @access private + * + * @param array $matches Single Regex Match. + * @return string HTML A element with URI address. + */ +function _make_url_clickable_cb($matches) { + $url = $matches[2]; + + if ( ')' == $matches[3] && strpos( $url, '(' ) ) { + // If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it, add the closing parenthesis to the URL. + // Then we can let the parenthesis balancer do its thing below. + $url .= $matches[3]; + $suffix = ''; + } else { + $suffix = $matches[3]; + } + + // Include parentheses in the URL only if paired + while ( substr_count( $url, '(' ) < substr_count( $url, ')' ) ) { + $suffix = strrchr( $url, ')' ) . $suffix; + $url = substr( $url, 0, strrpos( $url, ')' ) ); + } + + $url = esc_url($url); + if ( empty($url) ) + return $matches[0]; + + return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>" . $suffix; +} + +/** + * Callback to convert URL match to HTML A element. + * + * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link + * make_clickable()}. + * + * @since 2.3.2 + * @access private + * + * @param array $matches Single Regex Match. + * @return string HTML A element with URL address. + */ +function _make_web_ftp_clickable_cb($matches) { + $ret = ''; + $dest = $matches[2]; + $dest = 'http://' . $dest; + $dest = esc_url($dest); + if ( empty($dest) ) + return $matches[0]; + + // removed trailing [.,;:)] from URL + if ( in_array( substr($dest, -1), array('.', ',', ';', ':', ')') ) === true ) { + $ret = substr($dest, -1); + $dest = substr($dest, 0, strlen($dest)-1); + } + return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>$ret"; +} + +/** + * Callback to convert email address match to HTML A element. + * + * This function was backported from 2.5.0 to 2.3.2. Regex callback for {@link + * make_clickable()}. + * + * @since 2.3.2 + * @access private + * + * @param array $matches Single Regex Match. + * @return string HTML A element with email address. + */ +function _make_email_clickable_cb($matches) { + $email = $matches[2] . '@' . $matches[3]; + return $matches[1] . "<a href=\"mailto:$email\">$email</a>"; +} + +/** + * Convert plaintext URI to HTML links. + * + * Converts URI, www and ftp, and email addresses. Finishes by fixing links + * within links. + * + * @since 0.71 + * + * @param string $text Content to convert URIs. + * @return string Content with converted URIs. + */ +function make_clickable( $text ) { + $r = ''; + $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags + foreach ( $textarr as $piece ) { + if ( empty( $piece ) || ( $piece[0] == '<' && ! preg_match('|^<\s*[\w]{1,20}+://|', $piece) ) ) { + $r .= $piece; + continue; + } + + // Long strings might contain expensive edge cases ... + if ( 10000 < strlen( $piece ) ) { + // ... break it up + foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses + if ( 2101 < strlen( $chunk ) ) { + $r .= $chunk; // Too big, no whitespace: bail. + } else { + $r .= make_clickable( $chunk ); + } + } + } else { + $ret = " $piece "; // Pad with whitespace to simplify the regexes + + $url_clickable = '~ + ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation + ( # 2: URL + [\\w]{1,20}+:// # Scheme and hier-part prefix + (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long + [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character + (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character + [\'.,;:!?)] # Punctuation URL character + [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character + )* + ) + (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing) + ~xS'; // The regex is a non-anchored pattern and does not have a single fixed starting character. + // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. + + $ret = preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $ret ); + + $ret = preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret ); + $ret = preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret ); + + $ret = substr( $ret, 1, -1 ); // Remove our whitespace padding. + $r .= $ret; + } + } + + // Cleanup of accidental links within links + $r = preg_replace( '#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i', "$1$3</a>", $r ); + return $r; +} + +/** + * Breaks a string into chunks by splitting at whitespace characters. + * The length of each returned chunk is as close to the specified length goal as possible, + * with the caveat that each chunk includes its trailing delimiter. + * Chunks longer than the goal are guaranteed to not have any inner whitespace. + * + * Joining the returned chunks with empty delimiters reconstructs the input string losslessly. + * + * Input string must have no null characters (or eventual transformations on output chunks must not care about null characters) + * + * <code> + * _split_str_by_whitespace( "1234 67890 1234 67890a cd 1234 890 123456789 1234567890a 45678 1 3 5 7 90 ", 10 ) == + * array ( + * 0 => '1234 67890 ', // 11 characters: Perfect split + * 1 => '1234 ', // 5 characters: '1234 67890a' was too long + * 2 => '67890a cd ', // 10 characters: '67890a cd 1234' was too long + * 3 => '1234 890 ', // 11 characters: Perfect split + * 4 => '123456789 ', // 10 characters: '123456789 1234567890a' was too long + * 5 => '1234567890a ', // 12 characters: Too long, but no inner whitespace on which to split + * 6 => ' 45678 ', // 11 characters: Perfect split + * 7 => '1 3 5 7 9', // 9 characters: End of $string + * ); + * </code> + * + * @since 3.4.0 + * @access private + * + * @param string $string The string to split. + * @param int $goal The desired chunk length. + * @return array Numeric array of chunks. + */ +function _split_str_by_whitespace( $string, $goal ) { + $chunks = array(); + + $string_nullspace = strtr( $string, "\r\n\t\v\f ", "\000\000\000\000\000\000" ); + + while ( $goal < strlen( $string_nullspace ) ) { + $pos = strrpos( substr( $string_nullspace, 0, $goal + 1 ), "\000" ); + + if ( false === $pos ) { + $pos = strpos( $string_nullspace, "\000", $goal + 1 ); + if ( false === $pos ) { + break; + } + } + + $chunks[] = substr( $string, 0, $pos + 1 ); + $string = substr( $string, $pos + 1 ); + $string_nullspace = substr( $string_nullspace, $pos + 1 ); + } + + if ( $string ) { + $chunks[] = $string; + } + + return $chunks; +} + +/** + * Adds rel nofollow string to all HTML A elements in content. + * + * @since 1.5.0 + * + * @param string $text Content that may contain HTML A elements. + * @return string Converted content. + */ +function wp_rel_nofollow( $text ) { + // This is a pre save filter, so text is already escaped. + $text = stripslashes($text); + $text = preg_replace_callback('|<a (.+?)>|i', 'wp_rel_nofollow_callback', $text); + $text = wp_slash($text); + return $text; +} + +/** + * Callback to add rel=nofollow string to HTML A element. + * + * Will remove already existing rel="nofollow" and rel='nofollow' from the + * string to prevent from invalidating (X)HTML. + * + * @since 2.3.0 + * + * @param array $matches Single Match + * @return string HTML A Element with rel nofollow. + */ +function wp_rel_nofollow_callback( $matches ) { + $text = $matches[1]; + $text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text); + return "<a $text rel=\"nofollow\">"; +} + +/** + * Convert one smiley code to the icon graphic file equivalent. + * + * Callback handler for {@link convert_smilies()}. + * Looks up one smiley code in the $wpsmiliestrans global array and returns an + * <img> string for that smiley. + * + * @global array $wpsmiliestrans + * @since 2.8.0 + * + * @param array $matches Single match. Smiley code to convert to image. + * @return string Image string for smiley. + */ +function translate_smiley( $matches ) { + global $wpsmiliestrans; + + if ( count( $matches ) == 0 ) + return ''; + + $smiley = trim( reset( $matches ) ); + $img = $wpsmiliestrans[ $smiley ]; + $smiley_masked = esc_attr( $smiley ); + + $src_url = apply_filters( 'smilies_src', includes_url( "images/smilies/$img" ), $img, site_url() ); + + return " <img src='$src_url' alt='$smiley_masked' class='wp-smiley' /> "; +} + +/** + * Convert text equivalent of smilies to images. + * + * Will only convert smilies if the option 'use_smilies' is true and the global + * used in the function isn't empty. + * + * @since 0.71 + * @uses $wp_smiliessearch + * + * @param string $text Content to convert smilies from text. + * @return string Converted content with text smilies replaced with images. + */ +function convert_smilies($text) { + global $wp_smiliessearch; + $output = ''; + if ( get_option('use_smilies') && !empty($wp_smiliessearch) ) { + // HTML loop taken from texturize function, could possible be consolidated + $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE); // capture the tags as well as in between + $stop = count($textarr);// loop stuff + for ($i = 0; $i < $stop; $i++) { + $content = $textarr[$i]; + if ((strlen($content) > 0) && ('<' != $content[0])) { // If it's not a tag + $content = preg_replace_callback($wp_smiliessearch, 'translate_smiley', $content); + } + $output .= $content; + } + } else { + // return default text. + $output = $text; + } + return $output; +} + +/** + * Verifies that an email is valid. + * + * Does not grok i18n domains. Not RFC compliant. + * + * @since 0.71 + * + * @param string $email Email address to verify. + * @param boolean $deprecated Deprecated. + * @return string|bool Either false or the valid email address. + */ +function is_email( $email, $deprecated = false ) { + if ( ! empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '3.0' ); + + // Test for the minimum length the email can be + if ( strlen( $email ) < 3 ) { + return apply_filters( 'is_email', false, $email, 'email_too_short' ); + } + + // Test for an @ character after the first position + if ( strpos( $email, '@', 1 ) === false ) { + return apply_filters( 'is_email', false, $email, 'email_no_at' ); + } + + // Split out the local and domain parts + list( $local, $domain ) = explode( '@', $email, 2 ); + + // LOCAL PART + // Test for invalid characters + if ( !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local ) ) { + return apply_filters( 'is_email', false, $email, 'local_invalid_chars' ); + } + + // DOMAIN PART + // Test for sequences of periods + if ( preg_match( '/\.{2,}/', $domain ) ) { + return apply_filters( 'is_email', false, $email, 'domain_period_sequence' ); + } + + // Test for leading and trailing periods and whitespace + if ( trim( $domain, " \t\n\r\0\x0B." ) !== $domain ) { + return apply_filters( 'is_email', false, $email, 'domain_period_limits' ); + } + + // Split the domain into subs + $subs = explode( '.', $domain ); + + // Assume the domain will have at least two subs + if ( 2 > count( $subs ) ) { + return apply_filters( 'is_email', false, $email, 'domain_no_periods' ); + } + + // Loop through each sub + foreach ( $subs as $sub ) { + // Test for leading and trailing hyphens and whitespace + if ( trim( $sub, " \t\n\r\0\x0B-" ) !== $sub ) { + return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' ); + } + + // Test for invalid characters + if ( !preg_match('/^[a-z0-9-]+$/i', $sub ) ) { + return apply_filters( 'is_email', false, $email, 'sub_invalid_chars' ); + } + } + + // Congratulations your email made it! + return apply_filters( 'is_email', $email, $email, null ); +} + +/** + * Convert to ASCII from email subjects. + * + * @since 1.2.0 + * + * @param string $string Subject line + * @return string Converted string to ASCII + */ +function wp_iso_descrambler($string) { + /* this may only work with iso-8859-1, I'm afraid */ + if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) { + return $string; + } else { + $subject = str_replace('_', ' ', $matches[2]); + $subject = preg_replace_callback('#\=([0-9a-f]{2})#i', '_wp_iso_convert', $subject); + return $subject; + } +} + +/** + * Helper function to convert hex encoded chars to ASCII + * + * @since 3.1.0 + * @access private + * + * @param array $match The preg_replace_callback matches array + * @return array Converted chars + */ +function _wp_iso_convert( $match ) { + return chr( hexdec( strtolower( $match[1] ) ) ); +} + +/** + * Returns a date in the GMT equivalent. + * + * Requires and returns a date in the Y-m-d H:i:s format. If there is a + * timezone_string available, the date is assumed to be in that timezone, + * otherwise it simply subtracts the value of the 'gmt_offset' option. Return + * format can be overridden using the $format parameter. + * + * @since 1.2.0 + * + * @uses get_option() to retrieve the value of 'gmt_offset'. + * @param string $string The date to be converted. + * @param string $format The format string for the returned date (default is Y-m-d H:i:s) + * @return string GMT version of the date provided. + */ +function get_gmt_from_date( $string, $format = 'Y-m-d H:i:s' ) { + $tz = get_option( 'timezone_string' ); + if ( $tz ) { + $datetime = date_create( $string, new DateTimeZone( $tz ) ); + if ( ! $datetime ) + return gmdate( $format, 0 ); + $datetime->setTimezone( new DateTimeZone( 'UTC' ) ); + $string_gmt = $datetime->format( $format ); + } else { + if ( ! preg_match( '#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches ) ) + return gmdate( $format, 0 ); + $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); + $string_gmt = gmdate( $format, $string_time - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); + } + return $string_gmt; +} + +/** + * Converts a GMT date into the correct format for the blog. + * + * Requires and returns a date in the Y-m-d H:i:s format. If there is a + * timezone_string available, the returned date is in that timezone, otherwise + * it simply adds the value of gmt_offset. Return format can be overridden + * using the $format parameter + * + * @since 1.2.0 + * + * @param string $string The date to be converted. + * @param string $format The format string for the returned date (default is Y-m-d H:i:s) + * @return string Formatted date relative to the timezone / GMT offset. + */ +function get_date_from_gmt( $string, $format = 'Y-m-d H:i:s' ) { + $tz = get_option( 'timezone_string' ); + if ( $tz ) { + $datetime = date_create( $string, new DateTimeZone( 'UTC' ) ); + if ( ! $datetime ) + return date( $format, 0 ); + $datetime->setTimezone( new DateTimeZone( $tz ) ); + $string_localtime = $datetime->format( $format ); + } else { + if ( ! preg_match('#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches) ) + return date( $format, 0 ); + $string_time = gmmktime( $matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1] ); + $string_localtime = gmdate( $format, $string_time + get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); + } + return $string_localtime; +} + +/** + * Computes an offset in seconds from an iso8601 timezone. + * + * @since 1.5.0 + * + * @param string $timezone Either 'Z' for 0 offset or '±hhmm'. + * @return int|float The offset in seconds. + */ +function iso8601_timezone_to_offset($timezone) { + // $timezone is either 'Z' or '[+|-]hhmm' + if ($timezone == 'Z') { + $offset = 0; + } else { + $sign = (substr($timezone, 0, 1) == '+') ? 1 : -1; + $hours = intval(substr($timezone, 1, 2)); + $minutes = intval(substr($timezone, 3, 4)) / 60; + $offset = $sign * HOUR_IN_SECONDS * ($hours + $minutes); + } + return $offset; +} + +/** + * Converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]. + * + * @since 1.5.0 + * + * @param string $date_string Date and time in ISO 8601 format {@link http://en.wikipedia.org/wiki/ISO_8601}. + * @param string $timezone Optional. If set to GMT returns the time minus gmt_offset. Default is 'user'. + * @return string The date and time in MySQL DateTime format - Y-m-d H:i:s. + */ +function iso8601_to_datetime($date_string, $timezone = 'user') { + $timezone = strtolower($timezone); + + if ($timezone == 'gmt') { + + preg_match('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', $date_string, $date_bits); + + if (!empty($date_bits[7])) { // we have a timezone, so let's compute an offset + $offset = iso8601_timezone_to_offset($date_bits[7]); + } else { // we don't have a timezone, so we assume user local timezone (not server's!) + $offset = HOUR_IN_SECONDS * get_option('gmt_offset'); + } + + $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]); + $timestamp -= $offset; + + return gmdate('Y-m-d H:i:s', $timestamp); + + } else if ($timezone == 'user') { + return preg_replace('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', '$1-$2-$3 $4:$5:$6', $date_string); + } +} + +/** + * Adds a element attributes to open links in new windows. + * + * Comment text in popup windows should be filtered through this. Right now it's + * a moderately dumb function, ideally it would detect whether a target or rel + * attribute was already there and adjust its actions accordingly. + * + * @since 0.71 + * + * @param string $text Content to replace links to open in a new window. + * @return string Content that has filtered links. + */ +function popuplinks($text) { + $text = preg_replace('/<a (.+?)>/i', "<a $1 target='_blank' rel='external'>", $text); + return $text; +} + +/** + * Strips out all characters that are not allowable in an email. + * + * @since 1.5.0 + * + * @param string $email Email address to filter. + * @return string Filtered email address. + */ +function sanitize_email( $email ) { + // Test for the minimum length the email can be + if ( strlen( $email ) < 3 ) { + return apply_filters( 'sanitize_email', '', $email, 'email_too_short' ); + } + + // Test for an @ character after the first position + if ( strpos( $email, '@', 1 ) === false ) { + return apply_filters( 'sanitize_email', '', $email, 'email_no_at' ); + } + + // Split out the local and domain parts + list( $local, $domain ) = explode( '@', $email, 2 ); + + // LOCAL PART + // Test for invalid characters + $local = preg_replace( '/[^a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]/', '', $local ); + if ( '' === $local ) { + return apply_filters( 'sanitize_email', '', $email, 'local_invalid_chars' ); + } + + // DOMAIN PART + // Test for sequences of periods + $domain = preg_replace( '/\.{2,}/', '', $domain ); + if ( '' === $domain ) { + return apply_filters( 'sanitize_email', '', $email, 'domain_period_sequence' ); + } + + // Test for leading and trailing periods and whitespace + $domain = trim( $domain, " \t\n\r\0\x0B." ); + if ( '' === $domain ) { + return apply_filters( 'sanitize_email', '', $email, 'domain_period_limits' ); + } + + // Split the domain into subs + $subs = explode( '.', $domain ); + + // Assume the domain will have at least two subs + if ( 2 > count( $subs ) ) { + return apply_filters( 'sanitize_email', '', $email, 'domain_no_periods' ); + } + + // Create an array that will contain valid subs + $new_subs = array(); + + // Loop through each sub + foreach ( $subs as $sub ) { + // Test for leading and trailing hyphens + $sub = trim( $sub, " \t\n\r\0\x0B-" ); + + // Test for invalid characters + $sub = preg_replace( '/[^a-z0-9-]+/i', '', $sub ); + + // If there's anything left, add it to the valid subs + if ( '' !== $sub ) { + $new_subs[] = $sub; + } + } + + // If there aren't 2 or more valid subs + if ( 2 > count( $new_subs ) ) { + return apply_filters( 'sanitize_email', '', $email, 'domain_no_valid_subs' ); + } + + // Join valid subs into the new domain + $domain = join( '.', $new_subs ); + + // Put the email back together + $email = $local . '@' . $domain; + + // Congratulations your email made it! + return apply_filters( 'sanitize_email', $email, $email, null ); +} + +/** + * Determines the difference between two timestamps. + * + * The difference is returned in a human readable format such as "1 hour", + * "5 mins", "2 days". + * + * @since 1.5.0 + * + * @param int $from Unix timestamp from which the difference begins. + * @param int $to Optional. Unix timestamp to end the time difference. Default becomes time() if not set. + * @return string Human readable time difference. + */ +function human_time_diff( $from, $to = '' ) { + if ( empty( $to ) ) + $to = time(); + + $diff = (int) abs( $to - $from ); + + if ( $diff < HOUR_IN_SECONDS ) { + $mins = round( $diff / MINUTE_IN_SECONDS ); + if ( $mins <= 1 ) + $mins = 1; + /* translators: min=minute */ + $since = sprintf( _n( '%s min', '%s mins', $mins ), $mins ); + } elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) { + $hours = round( $diff / HOUR_IN_SECONDS ); + if ( $hours <= 1 ) + $hours = 1; + $since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours ); + } elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) { + $days = round( $diff / DAY_IN_SECONDS ); + if ( $days <= 1 ) + $days = 1; + $since = sprintf( _n( '%s day', '%s days', $days ), $days ); + } elseif ( $diff < 30 * DAY_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) { + $weeks = round( $diff / WEEK_IN_SECONDS ); + if ( $weeks <= 1 ) + $weeks = 1; + $since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks ); + } elseif ( $diff < YEAR_IN_SECONDS && $diff >= 30 * DAY_IN_SECONDS ) { + $months = round( $diff / ( 30 * DAY_IN_SECONDS ) ); + if ( $months <= 1 ) + $months = 1; + $since = sprintf( _n( '%s month', '%s months', $months ), $months ); + } elseif ( $diff >= YEAR_IN_SECONDS ) { + $years = round( $diff / YEAR_IN_SECONDS ); + if ( $years <= 1 ) + $years = 1; + $since = sprintf( _n( '%s year', '%s years', $years ), $years ); + } + + return $since; +} + +/** + * Generates an excerpt from the content, if needed. + * + * The excerpt word amount will be 55 words and if the amount is greater than + * that, then the string ' […]' will be appended to the excerpt. If the string + * is less than 55 words, then the content will be returned as is. + * + * The 55 word limit can be modified by plugins/themes using the excerpt_length filter + * The ' […]' string can be modified by plugins/themes using the excerpt_more filter + * + * @since 1.5.0 + * + * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated. + * @return string The excerpt. + */ +function wp_trim_excerpt($text = '') { + $raw_excerpt = $text; + if ( '' == $text ) { + $text = get_the_content(''); + + $text = strip_shortcodes( $text ); + + $text = apply_filters('the_content', $text); + $text = str_replace(']]>', ']]>', $text); + $excerpt_length = apply_filters('excerpt_length', 55); + $excerpt_more = apply_filters('excerpt_more', ' ' . '[…]'); + $text = wp_trim_words( $text, $excerpt_length, $excerpt_more ); + } + return apply_filters('wp_trim_excerpt', $text, $raw_excerpt); +} + +/** + * Trims text to a certain number of words. + * + * This function is localized. For languages that count 'words' by the individual + * character (such as East Asian languages), the $num_words argument will apply + * to the number of individual characters. + * + * @since 3.3.0 + * + * @param string $text Text to trim. + * @param int $num_words Number of words. Default 55. + * @param string $more Optional. What to append if $text needs to be trimmed. Default '…'. + * @return string Trimmed text. + */ +function wp_trim_words( $text, $num_words = 55, $more = null ) { + if ( null === $more ) + $more = __( '…' ); + $original_text = $text; + $text = wp_strip_all_tags( $text ); + /* translators: If your word count is based on single characters (East Asian characters), + enter 'characters'. Otherwise, enter 'words'. Do not translate into your own language. */ + if ( 'characters' == _x( 'words', 'word count: words or characters?' ) && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { + $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' ); + preg_match_all( '/./u', $text, $words_array ); + $words_array = array_slice( $words_array[0], 0, $num_words + 1 ); + $sep = ''; + } else { + $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY ); + $sep = ' '; + } + if ( count( $words_array ) > $num_words ) { + array_pop( $words_array ); + $text = implode( $sep, $words_array ); + $text = $text . $more; + } else { + $text = implode( $sep, $words_array ); + } + return apply_filters( 'wp_trim_words', $text, $num_words, $more, $original_text ); +} + +/** + * Converts named entities into numbered entities. + * + * @since 1.5.1 + * + * @param string $text The text within which entities will be converted. + * @return string Text with converted entities. + */ +function ent2ncr($text) { + + // Allow a plugin to short-circuit and override the mappings. + $filtered = apply_filters( 'pre_ent2ncr', null, $text ); + if( null !== $filtered ) + return $filtered; + + $to_ncr = array( + '"' => '"', + '&' => '&', + '<' => '<', + '>' => '>', + '|' => '|', + ' ' => ' ', + '¡' => '¡', + '¢' => '¢', + '£' => '£', + '¤' => '¤', + '¥' => '¥', + '¦' => '¦', + '&brkbar;' => '¦', + '§' => '§', + '¨' => '¨', + '¨' => '¨', + '©' => '©', + 'ª' => 'ª', + '«' => '«', + '¬' => '¬', + '­' => '­', + '®' => '®', + '¯' => '¯', + '&hibar;' => '¯', + '°' => '°', + '±' => '±', + '²' => '²', + '³' => '³', + '´' => '´', + 'µ' => 'µ', + '¶' => '¶', + '·' => '·', + '¸' => '¸', + '¹' => '¹', + 'º' => 'º', + '»' => '»', + '¼' => '¼', + '½' => '½', + '¾' => '¾', + '¿' => '¿', + 'À' => 'À', + 'Á' => 'Á', + 'Â' => 'Â', + 'Ã' => 'Ã', + 'Ä' => 'Ä', + 'Å' => 'Å', + 'Æ' => 'Æ', + 'Ç' => 'Ç', + 'È' => 'È', + 'É' => 'É', + 'Ê' => 'Ê', + 'Ë' => 'Ë', + 'Ì' => 'Ì', + 'Í' => 'Í', + 'Î' => 'Î', + 'Ï' => 'Ï', + 'Ð' => 'Ð', + 'Ñ' => 'Ñ', + 'Ò' => 'Ò', + 'Ó' => 'Ó', + 'Ô' => 'Ô', + 'Õ' => 'Õ', + 'Ö' => 'Ö', + '×' => '×', + 'Ø' => 'Ø', + 'Ù' => 'Ù', + 'Ú' => 'Ú', + 'Û' => 'Û', + 'Ü' => 'Ü', + 'Ý' => 'Ý', + 'Þ' => 'Þ', + 'ß' => 'ß', + 'à' => 'à', + 'á' => 'á', + 'â' => 'â', + 'ã' => 'ã', + 'ä' => 'ä', + 'å' => 'å', + 'æ' => 'æ', + 'ç' => 'ç', + 'è' => 'è', + 'é' => 'é', + 'ê' => 'ê', + 'ë' => 'ë', + 'ì' => 'ì', + 'í' => 'í', + 'î' => 'î', + 'ï' => 'ï', + 'ð' => 'ð', + 'ñ' => 'ñ', + 'ò' => 'ò', + 'ó' => 'ó', + 'ô' => 'ô', + 'õ' => 'õ', + 'ö' => 'ö', + '÷' => '÷', + 'ø' => 'ø', + 'ù' => 'ù', + 'ú' => 'ú', + 'û' => 'û', + 'ü' => 'ü', + 'ý' => 'ý', + 'þ' => 'þ', + 'ÿ' => 'ÿ', + 'Œ' => 'Œ', + 'œ' => 'œ', + 'Š' => 'Š', + 'š' => 'š', + 'Ÿ' => 'Ÿ', + 'ƒ' => 'ƒ', + 'ˆ' => 'ˆ', + '˜' => '˜', + 'Α' => 'Α', + 'Β' => 'Β', + 'Γ' => 'Γ', + 'Δ' => 'Δ', + 'Ε' => 'Ε', + 'Ζ' => 'Ζ', + 'Η' => 'Η', + 'Θ' => 'Θ', + 'Ι' => 'Ι', + 'Κ' => 'Κ', + 'Λ' => 'Λ', + 'Μ' => 'Μ', + 'Ν' => 'Ν', + 'Ξ' => 'Ξ', + 'Ο' => 'Ο', + 'Π' => 'Π', + 'Ρ' => 'Ρ', + 'Σ' => 'Σ', + 'Τ' => 'Τ', + 'Υ' => 'Υ', + 'Φ' => 'Φ', + 'Χ' => 'Χ', + 'Ψ' => 'Ψ', + 'Ω' => 'Ω', + 'α' => 'α', + 'β' => 'β', + 'γ' => 'γ', + 'δ' => 'δ', + 'ε' => 'ε', + 'ζ' => 'ζ', + 'η' => 'η', + 'θ' => 'θ', + 'ι' => 'ι', + 'κ' => 'κ', + 'λ' => 'λ', + 'μ' => 'μ', + 'ν' => 'ν', + 'ξ' => 'ξ', + 'ο' => 'ο', + 'π' => 'π', + 'ρ' => 'ρ', + 'ς' => 'ς', + 'σ' => 'σ', + 'τ' => 'τ', + 'υ' => 'υ', + 'φ' => 'φ', + 'χ' => 'χ', + 'ψ' => 'ψ', + 'ω' => 'ω', + 'ϑ' => 'ϑ', + 'ϒ' => 'ϒ', + 'ϖ' => 'ϖ', + ' ' => ' ', + ' ' => ' ', + ' ' => ' ', + '‌' => '‌', + '‍' => '‍', + '‎' => '‎', + '‏' => '‏', + '–' => '–', + '—' => '—', + '‘' => '‘', + '’' => '’', + '‚' => '‚', + '“' => '“', + '”' => '”', + '„' => '„', + '†' => '†', + '‡' => '‡', + '•' => '•', + '…' => '…', + '‰' => '‰', + '′' => '′', + '″' => '″', + '‹' => '‹', + '›' => '›', + '‾' => '‾', + '⁄' => '⁄', + '€' => '€', + 'ℑ' => 'ℑ', + '℘' => '℘', + 'ℜ' => 'ℜ', + '™' => '™', + 'ℵ' => 'ℵ', + '↵' => '↵', + '⇐' => '⇐', + '⇑' => '⇑', + '⇒' => '⇒', + '⇓' => '⇓', + '⇔' => '⇔', + '∀' => '∀', + '∂' => '∂', + '∃' => '∃', + '∅' => '∅', + '∇' => '∇', + '∈' => '∈', + '∉' => '∉', + '∋' => '∋', + '∏' => '∏', + '∑' => '∑', + '−' => '−', + '∗' => '∗', + '√' => '√', + '∝' => '∝', + '∞' => '∞', + '∠' => '∠', + '∧' => '∧', + '∨' => '∨', + '∩' => '∩', + '∪' => '∪', + '∫' => '∫', + '∴' => '∴', + '∼' => '∼', + '≅' => '≅', + '≈' => '≈', + '≠' => '≠', + '≡' => '≡', + '≤' => '≤', + '≥' => '≥', + '⊂' => '⊂', + '⊃' => '⊃', + '⊄' => '⊄', + '⊆' => '⊆', + '⊇' => '⊇', + '⊕' => '⊕', + '⊗' => '⊗', + '⊥' => '⊥', + '⋅' => '⋅', + '⌈' => '⌈', + '⌉' => '⌉', + '⌊' => '⌊', + '⌋' => '⌋', + '⟨' => '〈', + '⟩' => '〉', + '←' => '←', + '↑' => '↑', + '→' => '→', + '↓' => '↓', + '↔' => '↔', + '◊' => '◊', + '♠' => '♠', + '♣' => '♣', + '♥' => '♥', + '♦' => '♦' + ); + + return str_replace( array_keys($to_ncr), array_values($to_ncr), $text ); +} + +/** + * Formats text for the rich text editor. + * + * The filter 'richedit_pre' is applied here. If $text is empty the filter will + * be applied to an empty string. + * + * @since 2.0.0 + * + * @param string $text The text to be formatted. + * @return string The formatted text after filter is applied. + */ +function wp_richedit_pre($text) { + // Filtering a blank results in an annoying <br />\n + if ( empty($text) ) return apply_filters('richedit_pre', ''); + + $output = convert_chars($text); + $output = wpautop($output); + $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); + + return apply_filters('richedit_pre', $output); +} + +/** + * Formats text for the HTML editor. + * + * Unless $output is empty it will pass through htmlspecialchars before the + * 'htmledit_pre' filter is applied. + * + * @since 2.5.0 + * + * @param string $output The text to be formatted. + * @return string Formatted text after filter applied. + */ +function wp_htmledit_pre($output) { + if ( !empty($output) ) + $output = htmlspecialchars($output, ENT_NOQUOTES, get_option( 'blog_charset' ) ); // convert only < > & + + return apply_filters('htmledit_pre', $output); +} + +/** + * Perform a deep string replace operation to ensure the values in $search are no longer present + * + * Repeats the replacement operation until it no longer replaces anything so as to remove "nested" values + * e.g. $subject = '%0%0%0DDD', $search ='%0D', $result ='' rather than the '%0%0DD' that + * str_replace would return + * + * @since 2.8.1 + * @access private + * + * @param string|array $search The value being searched for, otherwise known as the needle. An array may be used to designate multiple needles. + * @param string $subject The string being searched and replaced on, otherwise known as the haystack. + * @return string The string with the replaced svalues. + */ +function _deep_replace( $search, $subject ) { + $subject = (string) $subject; + + $count = 1; + while ( $count ) { + $subject = str_replace( $search, '', $subject, $count ); + } + + return $subject; +} + +/** + * Escapes data for use in a MySQL query. + * + * Usually you should prepare queries using wpdb::prepare(). + * Sometimes, spot-escaping is required or useful. One example + * is preparing an array for use in an IN clause. + * + * @since 2.8.0 + * @param string|array $data Unescaped data + * @return string|array Escaped data + */ +function esc_sql( $data ) { + global $wpdb; + return $wpdb->_escape( $data ); +} + +/** + * Checks and cleans a URL. + * + * A number of characters are removed from the URL. If the URL is for displaying + * (the default behaviour) ampersands are also replaced. The 'clean_url' filter + * is applied to the returned cleaned URL. + * + * @since 2.8.0 + * @uses wp_kses_bad_protocol() To only permit protocols in the URL set + * via $protocols or the common ones set in the function. + * + * @param string $url The URL to be cleaned. + * @param array $protocols Optional. An array of acceptable protocols. + * Defaults to 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn' if not set. + * @param string $_context Private. Use esc_url_raw() for database usage. + * @return string The cleaned $url after the 'clean_url' filter is applied. + */ +function esc_url( $url, $protocols = null, $_context = 'display' ) { + $original_url = $url; + + if ( '' == $url ) + return $url; + $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url); + $strip = array('%0d', '%0a', '%0D', '%0A'); + $url = _deep_replace($strip, $url); + $url = str_replace(';//', '://', $url); + /* If the URL doesn't appear to contain a scheme, we + * presume it needs http:// appended (unless a relative + * link starting with /, # or ? or a php file). + */ + if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && + ! preg_match('/^[a-z0-9-]+?\.php/i', $url) ) + $url = 'http://' . $url; + + // Replace ampersands and single quotes only when displaying. + if ( 'display' == $_context ) { + $url = wp_kses_normalize_entities( $url ); + $url = str_replace( '&', '&', $url ); + $url = str_replace( "'", ''', $url ); + } + + if ( '/' === $url[0] ) { + $good_protocol_url = $url; + } else { + if ( ! is_array( $protocols ) ) + $protocols = wp_allowed_protocols(); + $good_protocol_url = wp_kses_bad_protocol( $url, $protocols ); + if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) + return ''; + } + + return apply_filters('clean_url', $good_protocol_url, $original_url, $_context); +} + +/** + * Performs esc_url() for database usage. + * + * @since 2.8.0 + * @uses esc_url() + * + * @param string $url The URL to be cleaned. + * @param array $protocols An array of acceptable protocols. + * @return string The cleaned URL. + */ +function esc_url_raw( $url, $protocols = null ) { + return esc_url( $url, $protocols, 'db' ); +} + +/** + * Convert entities, while preserving already-encoded entities. + * + * @link http://www.php.net/htmlentities Borrowed from the PHP Manual user notes. + * + * @since 1.2.2 + * + * @param string $myHTML The text to be converted. + * @return string Converted text. + */ +function htmlentities2($myHTML) { + $translation_table = get_html_translation_table( HTML_ENTITIES, ENT_QUOTES ); + $translation_table[chr(38)] = '&'; + return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,3};)/", "&", strtr($myHTML, $translation_table) ); +} + +/** + * Escape single quotes, htmlspecialchar " < > &, and fix line endings. + * + * Escapes text strings for echoing in JS. It is intended to be used for inline JS + * (in a tag attribute, for example onclick="..."). Note that the strings have to + * be in single quotes. The filter 'js_escape' is also applied here. + * + * @since 2.8.0 + * + * @param string $text The text to be escaped. + * @return string Escaped text. + */ +function esc_js( $text ) { + $safe_text = wp_check_invalid_utf8( $text ); + $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); + $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); + $safe_text = str_replace( "\r", '', $safe_text ); + $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); + return apply_filters( 'js_escape', $safe_text, $text ); +} + +/** + * Escaping for HTML blocks. + * + * @since 2.8.0 + * + * @param string $text + * @return string + */ +function esc_html( $text ) { + $safe_text = wp_check_invalid_utf8( $text ); + $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); + return apply_filters( 'esc_html', $safe_text, $text ); +} + +/** + * Escaping for HTML attributes. + * + * @since 2.8.0 + * + * @param string $text + * @return string + */ +function esc_attr( $text ) { + $safe_text = wp_check_invalid_utf8( $text ); + $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES ); + return apply_filters( 'attribute_escape', $safe_text, $text ); +} + +/** + * Escaping for textarea values. + * + * @since 3.1.0 + * + * @param string $text + * @return string + */ +function esc_textarea( $text ) { + $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); + return apply_filters( 'esc_textarea', $safe_text, $text ); +} + +/** + * Escape an HTML tag name. + * + * @since 2.5.0 + * + * @param string $tag_name + * @return string + */ +function tag_escape($tag_name) { + $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); + return apply_filters('tag_escape', $safe_tag, $tag_name); +} + +/** + * Escapes text for SQL LIKE special characters % and _. + * + * @since 2.5.0 + * + * @param string $text The text to be escaped. + * @return string text, safe for inclusion in LIKE query. + */ +function like_escape($text) { + return str_replace(array("%", "_"), array("\\%", "\\_"), $text); +} + +/** + * Convert full URL paths to absolute paths. + * + * Removes the http or https protocols and the domain. Keeps the path '/' at the + * beginning, so it isn't a true relative link, but from the web root base. + * + * @since 2.1.0 + * + * @param string $link Full URL path. + * @return string Absolute path. + */ +function wp_make_link_relative( $link ) { + return preg_replace( '|https?://[^/]+(/.*)|i', '$1', $link ); +} + +/** + * Sanitises various option values based on the nature of the option. + * + * This is basically a switch statement which will pass $value through a number + * of functions depending on the $option. + * + * @since 2.0.5 + * + * @param string $option The name of the option. + * @param string $value The unsanitised value. + * @return string Sanitized value. + */ +function sanitize_option($option, $value) { + + switch ( $option ) { + case 'admin_email' : + case 'new_admin_email' : + $value = sanitize_email( $value ); + if ( ! is_email( $value ) ) { + $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization + if ( function_exists( 'add_settings_error' ) ) + add_settings_error( $option, 'invalid_admin_email', __( 'The email address entered did not appear to be a valid email address. Please enter a valid email address.' ) ); + } + break; + + case 'thumbnail_size_w': + case 'thumbnail_size_h': + case 'medium_size_w': + case 'medium_size_h': + case 'large_size_w': + case 'large_size_h': + case 'mailserver_port': + case 'comment_max_links': + case 'page_on_front': + case 'page_for_posts': + case 'rss_excerpt_length': + case 'default_category': + case 'default_email_category': + case 'default_link_category': + case 'close_comments_days_old': + case 'comments_per_page': + case 'thread_comments_depth': + case 'users_can_register': + case 'start_of_week': + $value = absint( $value ); + break; + + case 'posts_per_page': + case 'posts_per_rss': + $value = (int) $value; + if ( empty($value) ) + $value = 1; + if ( $value < -1 ) + $value = abs($value); + break; + + case 'default_ping_status': + case 'default_comment_status': + // Options that if not there have 0 value but need to be something like "closed" + if ( $value == '0' || $value == '') + $value = 'closed'; + break; + + case 'blogdescription': + case 'blogname': + $value = wp_kses_post( $value ); + $value = esc_html( $value ); + break; + + case 'blog_charset': + $value = preg_replace('/[^a-zA-Z0-9_-]/', '', $value); // strips slashes + break; + + case 'blog_public': + // This is the value if the settings checkbox is not checked on POST. Don't rely on this. + if ( null === $value ) + $value = 1; + else + $value = intval( $value ); + break; + + case 'date_format': + case 'time_format': + case 'mailserver_url': + case 'mailserver_login': + case 'mailserver_pass': + case 'upload_path': + $value = strip_tags( $value ); + $value = wp_kses_data( $value ); + break; + + case 'ping_sites': + $value = explode( "\n", $value ); + $value = array_filter( array_map( 'trim', $value ) ); + $value = array_filter( array_map( 'esc_url_raw', $value ) ); + $value = implode( "\n", $value ); + break; + + case 'gmt_offset': + $value = preg_replace('/[^0-9:.-]/', '', $value); // strips slashes + break; + + case 'siteurl': + if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { + $value = esc_url_raw($value); + } else { + $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization + if ( function_exists('add_settings_error') ) + add_settings_error('siteurl', 'invalid_siteurl', __('The WordPress address you entered did not appear to be a valid URL. Please enter a valid URL.')); + } + break; + + case 'home': + if ( (bool)preg_match( '#http(s?)://(.+)#i', $value) ) { + $value = esc_url_raw($value); + } else { + $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization + if ( function_exists('add_settings_error') ) + add_settings_error('home', 'invalid_home', __('The Site address you entered did not appear to be a valid URL. Please enter a valid URL.')); + } + break; + + case 'WPLANG': + $allowed = get_available_languages(); + if ( ! in_array( $value, $allowed ) && ! empty( $value ) ) + $value = get_option( $option ); + break; + + case 'illegal_names': + if ( ! is_array( $value ) ) + $value = explode( ' ', $value ); + + $value = array_values( array_filter( array_map( 'trim', $value ) ) ); + + if ( ! $value ) + $value = ''; + break; + + case 'limited_email_domains': + case 'banned_email_domains': + if ( ! is_array( $value ) ) + $value = explode( "\n", $value ); + + $domains = array_values( array_filter( array_map( 'trim', $value ) ) ); + $value = array(); + + foreach ( $domains as $domain ) { + if ( ! preg_match( '/(--|\.\.)/', $domain ) && preg_match( '|^([a-zA-Z0-9-\.])+$|', $domain ) ) + $value[] = $domain; + } + if ( ! $value ) + $value = ''; + break; + + case 'timezone_string': + $allowed_zones = timezone_identifiers_list(); + if ( ! in_array( $value, $allowed_zones ) && ! empty( $value ) ) { + $value = get_option( $option ); // Resets option to stored value in the case of failed sanitization + if ( function_exists('add_settings_error') ) + add_settings_error('timezone_string', 'invalid_timezone_string', __('The timezone you have entered is not valid. Please select a valid timezone.') ); + } + break; + + case 'permalink_structure': + case 'category_base': + case 'tag_base': + $value = esc_url_raw( $value ); + $value = str_replace( 'http://', '', $value ); + break; + + case 'default_role' : + if ( ! get_role( $value ) && get_role( 'subscriber' ) ) + $value = 'subscriber'; + break; + } + + $value = apply_filters("sanitize_option_{$option}", $value, $option); + + return $value; +} + +/** + * Parses a string into variables to be stored in an array. + * + * Uses {@link http://www.php.net/parse_str parse_str()} and stripslashes if + * {@link http://www.php.net/magic_quotes magic_quotes_gpc} is on. + * + * @since 2.2.1 + * @uses apply_filters() for the 'wp_parse_str' filter. + * + * @param string $string The string to be parsed. + * @param array $array Variables will be stored in this array. + */ +function wp_parse_str( $string, &$array ) { + parse_str( $string, $array ); + if ( get_magic_quotes_gpc() ) + $array = stripslashes_deep( $array ); + $array = apply_filters( 'wp_parse_str', $array ); +} + +/** + * Convert lone less than signs. + * + * KSES already converts lone greater than signs. + * + * @uses wp_pre_kses_less_than_callback in the callback function. + * @since 2.3.0 + * + * @param string $text Text to be converted. + * @return string Converted text. + */ +function wp_pre_kses_less_than( $text ) { + return preg_replace_callback('%<[^>]*?((?=<)|>|$)%', 'wp_pre_kses_less_than_callback', $text); +} + +/** + * Callback function used by preg_replace. + * + * @uses esc_html to format the $matches text. + * @since 2.3.0 + * + * @param array $matches Populated by matches to preg_replace. + * @return string The text returned after esc_html if needed. + */ +function wp_pre_kses_less_than_callback( $matches ) { + if ( false === strpos($matches[0], '>') ) + return esc_html($matches[0]); + return $matches[0]; +} + +/** + * WordPress implementation of PHP sprintf() with filters. + * + * @since 2.5.0 + * @link http://www.php.net/sprintf + * + * @param string $pattern The string which formatted args are inserted. + * @param mixed $args,... Arguments to be formatted into the $pattern string. + * @return string The formatted string. + */ +function wp_sprintf( $pattern ) { + $args = func_get_args(); + $len = strlen($pattern); + $start = 0; + $result = ''; + $arg_index = 0; + while ( $len > $start ) { + // Last character: append and break + if ( strlen($pattern) - 1 == $start ) { + $result .= substr($pattern, -1); + break; + } + + // Literal %: append and continue + if ( substr($pattern, $start, 2) == '%%' ) { + $start += 2; + $result .= '%'; + continue; + } + + // Get fragment before next % + $end = strpos($pattern, '%', $start + 1); + if ( false === $end ) + $end = $len; + $fragment = substr($pattern, $start, $end - $start); + + // Fragment has a specifier + if ( $pattern[$start] == '%' ) { + // Find numbered arguments or take the next one in order + if ( preg_match('/^%(\d+)\$/', $fragment, $matches) ) { + $arg = isset($args[$matches[1]]) ? $args[$matches[1]] : ''; + $fragment = str_replace("%{$matches[1]}$", '%', $fragment); + } else { + ++$arg_index; + $arg = isset($args[$arg_index]) ? $args[$arg_index] : ''; + } + + // Apply filters OR sprintf + $_fragment = apply_filters( 'wp_sprintf', $fragment, $arg ); + if ( $_fragment != $fragment ) + $fragment = $_fragment; + else + $fragment = sprintf($fragment, strval($arg) ); + } + + // Append to result and move to next fragment + $result .= $fragment; + $start = $end; + } + return $result; +} + +/** + * Localize list items before the rest of the content. + * + * The '%l' must be at the first characters can then contain the rest of the + * content. The list items will have ', ', ', and', and ' and ' added depending + * on the amount of list items in the $args parameter. + * + * @since 2.5.0 + * + * @param string $pattern Content containing '%l' at the beginning. + * @param array $args List items to prepend to the content and replace '%l'. + * @return string Localized list items and rest of the content. + */ +function wp_sprintf_l($pattern, $args) { + // Not a match + if ( substr($pattern, 0, 2) != '%l' ) + return $pattern; + + // Nothing to work with + if ( empty($args) ) + return ''; + + // Translate and filter the delimiter set (avoid ampersands and entities here) + $l = apply_filters('wp_sprintf_l', array( + /* translators: used between list items, there is a space after the comma */ + 'between' => __(', '), + /* translators: used between list items, there is a space after the and */ + 'between_last_two' => __(', and '), + /* translators: used between only two list items, there is a space after the and */ + 'between_only_two' => __(' and '), + )); + + $args = (array) $args; + $result = array_shift($args); + if ( count($args) == 1 ) + $result .= $l['between_only_two'] . array_shift($args); + // Loop when more than two args + $i = count($args); + while ( $i ) { + $arg = array_shift($args); + $i--; + if ( 0 == $i ) + $result .= $l['between_last_two'] . $arg; + else + $result .= $l['between'] . $arg; + } + return $result . substr($pattern, 2); +} + +/** + * Safely extracts not more than the first $count characters from html string. + * + * UTF-8, tags and entities safe prefix extraction. Entities inside will *NOT* + * be counted as one character. For example & will be counted as 4, < as + * 3, etc. + * + * @since 2.5.0 + * + * @param string $str String to get the excerpt from. + * @param integer $count Maximum number of characters to take. + * @param string $more Optional. What to append if $str needs to be trimmed. Defaults to empty string. + * @return string The excerpt. + */ +function wp_html_excerpt( $str, $count, $more = null ) { + if ( null === $more ) + $more = ''; + $str = wp_strip_all_tags( $str, true ); + $excerpt = mb_substr( $str, 0, $count ); + // remove part of an entity at the end + $excerpt = preg_replace( '/&[^;\s]{0,6}$/', '', $excerpt ); + if ( $str != $excerpt ) + $excerpt = trim( $excerpt ) . $more; + return $excerpt; +} + +/** + * Add a Base url to relative links in passed content. + * + * By default it supports the 'src' and 'href' attributes. However this can be + * changed via the 3rd param. + * + * @since 2.7.0 + * + * @param string $content String to search for links in. + * @param string $base The base URL to prefix to links. + * @param array $attrs The attributes which should be processed. + * @return string The processed content. + */ +function links_add_base_url( $content, $base, $attrs = array('src', 'href') ) { + global $_links_add_base; + $_links_add_base = $base; + $attrs = implode('|', (array)$attrs); + return preg_replace_callback( "!($attrs)=(['\"])(.+?)\\2!i", '_links_add_base', $content ); +} + +/** + * Callback to add a base url to relative links in passed content. + * + * @since 2.7.0 + * @access private + * + * @param string $m The matched link. + * @return string The processed link. + */ +function _links_add_base($m) { + global $_links_add_base; + //1 = attribute name 2 = quotation mark 3 = URL + return $m[1] . '=' . $m[2] . + ( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols() ) ? + $m[3] : + path_join( $_links_add_base, $m[3] ) ) + . $m[2]; +} + +/** + * Adds a Target attribute to all links in passed content. + * + * This function by default only applies to <a> tags, however this can be + * modified by the 3rd param. + * + * <b>NOTE:</b> Any current target attributed will be stripped and replaced. + * + * @since 2.7.0 + * + * @param string $content String to search for links in. + * @param string $target The Target to add to the links. + * @param array $tags An array of tags to apply to. + * @return string The processed content. + */ +function links_add_target( $content, $target = '_blank', $tags = array('a') ) { + global $_links_add_target; + $_links_add_target = $target; + $tags = implode('|', (array)$tags); + return preg_replace_callback( "!<($tags)(.+?)>!i", '_links_add_target', $content ); +} + +/** + * Callback to add a target attribute to all links in passed content. + * + * @since 2.7.0 + * @access private + * + * @param string $m The matched link. + * @return string The processed link. + */ +function _links_add_target( $m ) { + global $_links_add_target; + $tag = $m[1]; + $link = preg_replace('|(target=([\'"])(.*?)\2)|i', '', $m[2]); + return '<' . $tag . $link . ' target="' . esc_attr( $_links_add_target ) . '">'; +} + +/** + * Normalize EOL characters and strip duplicate whitespace. + * + * @since 2.7.0 + * + * @param string $str The string to normalize. + * @return string The normalized string. + */ +function normalize_whitespace( $str ) { + $str = trim( $str ); + $str = str_replace( "\r", "\n", $str ); + $str = preg_replace( array( '/\n+/', '/[ \t]+/' ), array( "\n", ' ' ), $str ); + return $str; +} + +/** + * Properly strip all HTML tags including script and style + * + * @since 2.9.0 + * + * @param string $string String containing HTML tags + * @param bool $remove_breaks optional Whether to remove left over line breaks and white space chars + * @return string The processed string. + */ +function wp_strip_all_tags($string, $remove_breaks = false) { + $string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string ); + $string = strip_tags($string); + + if ( $remove_breaks ) + $string = preg_replace('/[\r\n\t ]+/', ' ', $string); + + return trim( $string ); +} + +/** + * Sanitize a string from user input or from the db + * + * check for invalid UTF-8, + * Convert single < characters to entity, + * strip all tags, + * remove line breaks, tabs and extra white space, + * strip octets. + * + * @since 2.9.0 + * + * @param string $str + * @return string + */ +function sanitize_text_field($str) { + $filtered = wp_check_invalid_utf8( $str ); + + if ( strpos($filtered, '<') !== false ) { + $filtered = wp_pre_kses_less_than( $filtered ); + // This will strip extra whitespace for us. + $filtered = wp_strip_all_tags( $filtered, true ); + } else { + $filtered = trim( preg_replace('/[\r\n\t ]+/', ' ', $filtered) ); + } + + $found = false; + while ( preg_match('/%[a-f0-9]{2}/i', $filtered, $match) ) { + $filtered = str_replace($match[0], '', $filtered); + $found = true; + } + + if ( $found ) { + // Strip out the whitespace that may now exist after removing the octets. + $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); + } + + return apply_filters('sanitize_text_field', $filtered, $str); +} + +/** + * i18n friendly version of basename() + * + * @since 3.1.0 + * + * @param string $path A path. + * @param string $suffix If the filename ends in suffix this will also be cut off. + * @return string + */ +function wp_basename( $path, $suffix = '' ) { + return urldecode( basename( str_replace( array( '%2F', '%5C' ), '/', urlencode( $path ) ), $suffix ) ); +} + +/** + * Forever eliminate "Wordpress" from the planet (or at least the little bit we can influence). + * + * Violating our coding standards for a good function name. + * + * @since 3.0.0 + */ +function capital_P_dangit( $text ) { + // Simple replacement for titles + if ( 'the_title' === current_filter() ) + return str_replace( 'Wordpress', 'WordPress', $text ); + // Still here? Use the more judicious replacement + static $dblq = false; + if ( false === $dblq ) + $dblq = _x( '“', 'opening curly double quote' ); + return str_replace( + array( ' Wordpress', '‘Wordpress', $dblq . 'Wordpress', '>Wordpress', '(Wordpress' ), + array( ' WordPress', '‘WordPress', $dblq . 'WordPress', '>WordPress', '(WordPress' ), + $text ); + +} + +/** + * Sanitize a mime type + * + * @since 3.1.3 + * + * @param string $mime_type Mime type + * @return string Sanitized mime type + */ +function sanitize_mime_type( $mime_type ) { + $sani_mime_type = preg_replace( '/[^-+*.a-zA-Z0-9\/]/', '', $mime_type ); + return apply_filters( 'sanitize_mime_type', $sani_mime_type, $mime_type ); +} + +/** + * Sanitize space or carriage return separated URLs that are used to send trackbacks. + * + * @since 3.4.0 + * + * @param string $to_ping Space or carriage return separated URLs + * @return string URLs starting with the http or https protocol, separated by a carriage return. + */ +function sanitize_trackback_urls( $to_ping ) { + $urls_to_ping = preg_split( '/[\r\n\t ]/', trim( $to_ping ), -1, PREG_SPLIT_NO_EMPTY ); + foreach ( $urls_to_ping as $k => $url ) { + if ( !preg_match( '#^https?://.#i', $url ) ) + unset( $urls_to_ping[$k] ); + } + $urls_to_ping = array_map( 'esc_url_raw', $urls_to_ping ); + $urls_to_ping = implode( "\n", $urls_to_ping ); + return apply_filters( 'sanitize_trackback_urls', $urls_to_ping, $to_ping ); +} + +/** + * Add slashes to a string or array of strings. + * + * This should be used when preparing data for core API that expects slashed data. + * This should not be used to escape data going directly into an SQL query. + * + * @since 3.6.0 + * + * @param string|array $value String or array of strings to slash. + * @return string|array Slashed $value + */ +function wp_slash( $value ) { + if ( is_array( $value ) ) { + foreach ( $value as $k => $v ) { + if ( is_array( $v ) ) { + $value[$k] = wp_slash( $v ); + } else { + $value[$k] = addslashes( $v ); + } + } + } else { + $value = addslashes( $value ); + } + + return $value; +} + +/** + * Remove slashes from a string or array of strings. + * + * This should be used to remove slashes from data passed to core API that + * expects data to be unslashed. + * + * @since 3.6.0 + * + * @param string|array $value String or array of strings to unslash. + * @return string|array Unslashed $value + */ +function wp_unslash( $value ) { + return stripslashes_deep( $value ); +} + +/** + * Extract and return the first URL from passed content. + * + * @since 3.6.0 + * + * @param string $content A string which might contain a URL. + * @return string The found URL. + */ +function get_url_in_content( $content ) { + if ( empty( $content ) ) + return ''; + + if ( preg_match( '/<a\s[^>]*?href=([\'"])(.+?)\1/is', $content, $matches ) ) + return esc_url_raw( $matches[2] ); + + return false; +} diff --git a/sources/wp-includes/functions.php b/sources/wp-includes/functions.php new file mode 100644 index 0000000..aea813b --- /dev/null +++ b/sources/wp-includes/functions.php @@ -0,0 +1,4206 @@ +<?php +/** + * Main WordPress API + * + * @package WordPress + */ + +require( ABSPATH . WPINC . '/option.php' ); + +/** + * Converts given date string into a different format. + * + * $format should be either a PHP date format string, e.g. 'U' for a Unix + * timestamp, or 'G' for a Unix timestamp assuming that $date is GMT. + * + * If $translate is true then the given date and format string will + * be passed to date_i18n() for translation. + * + * @since 0.71 + * + * @param string $format Format of the date to return. + * @param string $date Date string to convert. + * @param bool $translate Whether the return date should be translated. Default is true. + * @return string|int Formatted date string, or Unix timestamp. + */ +function mysql2date( $format, $date, $translate = true ) { + if ( empty( $date ) ) + return false; + + if ( 'G' == $format ) + return strtotime( $date . ' +0000' ); + + $i = strtotime( $date ); + + if ( 'U' == $format ) + return $i; + + if ( $translate ) + return date_i18n( $format, $i ); + else + return date( $format, $i ); +} + +/** + * Retrieve the current time based on specified type. + * + * The 'mysql' type will return the time in the format for MySQL DATETIME field. + * The 'timestamp' type will return the current timestamp. + * + * If $gmt is set to either '1' or 'true', then both types will use GMT time. + * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option. + * + * @since 1.0.0 + * + * @param string $type Either 'mysql' or 'timestamp'. + * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false. + * @return int|string String if $type is 'gmt', int if $type is 'timestamp'. + */ +function current_time( $type, $gmt = 0 ) { + switch ( $type ) { + case 'mysql': + return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) ); + break; + case 'timestamp': + return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ); + break; + } +} + +/** + * Retrieve the date in localized format, based on timestamp. + * + * If the locale specifies the locale month and weekday, then the locale will + * take over the format for the date. If it isn't, then the date format string + * will be used instead. + * + * @since 0.71 + * + * @param string $dateformatstring Format to display the date. + * @param int $unixtimestamp Optional. Unix timestamp. + * @param bool $gmt Optional, default is false. Whether to convert to GMT for time. + * @return string The date, translated if locale specifies it. + */ +function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) { + global $wp_locale; + $i = $unixtimestamp; + + if ( false === $i ) { + if ( ! $gmt ) + $i = current_time( 'timestamp' ); + else + $i = time(); + // we should not let date() interfere with our + // specially computed timestamp + $gmt = true; + } + + // store original value for language with untypical grammars + // see http://core.trac.wordpress.org/ticket/9396 + $req_format = $dateformatstring; + + $datefunc = $gmt? 'gmdate' : 'date'; + + if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) { + $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) ); + $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth ); + $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) ); + $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday ); + $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) ); + $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) ); + $dateformatstring = ' '.$dateformatstring; + $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring ); + $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring ); + $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring ); + $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring ); + $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring ); + $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring ); + + $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 ); + } + $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' ); + $timezone_formats_re = implode( '|', $timezone_formats ); + if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) { + $timezone_string = get_option( 'timezone_string' ); + if ( $timezone_string ) { + $timezone_object = timezone_open( $timezone_string ); + $date_object = date_create( null, $timezone_object ); + foreach( $timezone_formats as $timezone_format ) { + if ( false !== strpos( $dateformatstring, $timezone_format ) ) { + $formatted = date_format( $date_object, $timezone_format ); + $dateformatstring = ' '.$dateformatstring; + $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring ); + $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 ); + } + } + } + } + $j = @$datefunc( $dateformatstring, $i ); + // allow plugins to redo this entirely for languages with untypical grammars + $j = apply_filters('date_i18n', $j, $req_format, $i, $gmt); + return $j; +} + +/** + * Convert integer number to format based on the locale. + * + * @since 2.3.0 + * + * @param int $number The number to convert based on locale. + * @param int $decimals Precision of the number of decimal places. + * @return string Converted number in string format. + */ +function number_format_i18n( $number, $decimals = 0 ) { + global $wp_locale; + $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] ); + return apply_filters( 'number_format_i18n', $formatted ); +} + +/** + * Convert number of bytes largest unit bytes will fit into. + * + * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts + * number of bytes to human readable number by taking the number of that unit + * that the bytes will go into it. Supports TB value. + * + * Please note that integers in PHP are limited to 32 bits, unless they are on + * 64 bit architecture, then they have 64 bit size. If you need to place the + * larger size then what PHP integer type will hold, then use a string. It will + * be converted to a double, which should always have 64 bit length. + * + * Technically the correct unit names for powers of 1024 are KiB, MiB etc. + * @link http://en.wikipedia.org/wiki/Byte + * + * @since 2.3.0 + * + * @param int|string $bytes Number of bytes. Note max integer size for integers. + * @param int $decimals Precision of number of decimal places. Deprecated. + * @return bool|string False on failure. Number string on success. + */ +function size_format( $bytes, $decimals = 0 ) { + $quant = array( + // ========================= Origin ==== + 'TB' => 1099511627776, // pow( 1024, 4) + 'GB' => 1073741824, // pow( 1024, 3) + 'MB' => 1048576, // pow( 1024, 2) + 'kB' => 1024, // pow( 1024, 1) + 'B ' => 1, // pow( 1024, 0) + ); + foreach ( $quant as $unit => $mag ) + if ( doubleval($bytes) >= $mag ) + return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit; + + return false; +} + +/** + * Get the week start and end from the datetime or date string from mysql. + * + * @since 0.71 + * + * @param string $mysqlstring Date or datetime field type from mysql. + * @param int $start_of_week Optional. Start of the week as an integer. + * @return array Keys are 'start' and 'end'. + */ +function get_weekstartend( $mysqlstring, $start_of_week = '' ) { + $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year + $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month + $md = substr( $mysqlstring, 5, 2 ); // Mysql string day + $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day. + $weekday = date( 'w', $day ); // The day of the week from the timestamp + if ( !is_numeric($start_of_week) ) + $start_of_week = get_option( 'start_of_week' ); + + if ( $weekday < $start_of_week ) + $weekday += 7; + + $start = $day - DAY_IN_SECONDS * ( $weekday - $start_of_week ); // The most recent week start day on or before $day + $end = $start + 7 * DAY_IN_SECONDS - 1; // $start + 7 days - 1 second + return compact( 'start', 'end' ); +} + +/** + * Unserialize value only if it was serialized. + * + * @since 2.0.0 + * + * @param string $original Maybe unserialized original, if is needed. + * @return mixed Unserialized data can be any type. + */ +function maybe_unserialize( $original ) { + if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in + return @unserialize( $original ); + return $original; +} + +/** + * Check value to find if it was serialized. + * + * If $data is not an string, then returned value will always be false. + * Serialized data is always a string. + * + * @since 2.0.5 + * + * @param mixed $data Value to check to see if was serialized. + * @param bool $strict Optional. Whether to be strict about the end of the string. Defaults true. + * @return bool False if not serialized and true if it was. + */ +function is_serialized( $data, $strict = true ) { + // if it isn't a string, it isn't serialized + if ( ! is_string( $data ) ) + return false; + $data = trim( $data ); + if ( 'N;' == $data ) + return true; + $length = strlen( $data ); + if ( $length < 4 ) + return false; + if ( ':' !== $data[1] ) + return false; + if ( $strict ) { + $lastc = $data[ $length - 1 ]; + if ( ';' !== $lastc && '}' !== $lastc ) + return false; + } else { + $semicolon = strpos( $data, ';' ); + $brace = strpos( $data, '}' ); + // Either ; or } must exist. + if ( false === $semicolon && false === $brace ) + return false; + // But neither must be in the first X characters. + if ( false !== $semicolon && $semicolon < 3 ) + return false; + if ( false !== $brace && $brace < 4 ) + return false; + } + $token = $data[0]; + switch ( $token ) { + case 's' : + if ( $strict ) { + if ( '"' !== $data[ $length - 2 ] ) + return false; + } elseif ( false === strpos( $data, '"' ) ) { + return false; + } + // or else fall through + case 'a' : + case 'O' : + return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data ); + case 'b' : + case 'i' : + case 'd' : + $end = $strict ? '$' : ''; + return (bool) preg_match( "/^{$token}:[0-9.E-]+;$end/", $data ); + } + return false; +} + +/** + * Check whether serialized data is of string type. + * + * @since 2.0.5 + * + * @param mixed $data Serialized data + * @return bool False if not a serialized string, true if it is. + */ +function is_serialized_string( $data ) { + // if it isn't a string, it isn't a serialized string + if ( !is_string( $data ) ) + return false; + $data = trim( $data ); + $length = strlen( $data ); + if ( $length < 4 ) + return false; + elseif ( ':' !== $data[1] ) + return false; + elseif ( ';' !== $data[$length-1] ) + return false; + elseif ( $data[0] !== 's' ) + return false; + elseif ( '"' !== $data[$length-2] ) + return false; + else + return true; +} + +/** + * Serialize data, if needed. + * + * @since 2.0.5 + * + * @param mixed $data Data that might be serialized. + * @return mixed A scalar data + */ +function maybe_serialize( $data ) { + if ( is_array( $data ) || is_object( $data ) ) + return serialize( $data ); + + // Double serialization is required for backward compatibility. + // See http://core.trac.wordpress.org/ticket/12930 + if ( is_serialized( $data, false ) ) + return serialize( $data ); + + return $data; +} + +/** + * Retrieve post title from XMLRPC XML. + * + * If the title element is not part of the XML, then the default post title from + * the $post_default_title will be used instead. + * + * @package WordPress + * @subpackage XMLRPC + * @since 0.71 + * + * @global string $post_default_title Default XMLRPC post title. + * + * @param string $content XMLRPC XML Request content + * @return string Post title + */ +function xmlrpc_getposttitle( $content ) { + global $post_default_title; + if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) { + $post_title = $matchtitle[1]; + } else { + $post_title = $post_default_title; + } + return $post_title; +} + +/** + * Retrieve the post category or categories from XMLRPC XML. + * + * If the category element is not found, then the default post category will be + * used. The return type then would be what $post_default_category. If the + * category is found, then it will always be an array. + * + * @package WordPress + * @subpackage XMLRPC + * @since 0.71 + * + * @global string $post_default_category Default XMLRPC post category. + * + * @param string $content XMLRPC XML Request content + * @return string|array List of categories or category name. + */ +function xmlrpc_getpostcategory( $content ) { + global $post_default_category; + if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) { + $post_category = trim( $matchcat[1], ',' ); + $post_category = explode( ',', $post_category ); + } else { + $post_category = $post_default_category; + } + return $post_category; +} + +/** + * XMLRPC XML content without title and category elements. + * + * @package WordPress + * @subpackage XMLRPC + * @since 0.71 + * + * @param string $content XMLRPC XML Request content + * @return string XMLRPC XML Request content without title and category elements. + */ +function xmlrpc_removepostdata( $content ) { + $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content ); + $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content ); + $content = trim( $content ); + return $content; +} + +/** + * Use RegEx to extract URLs from arbitrary content + * + * @since 3.7.0 + * + * @param string $content + * @return array URLs found in passed string + */ +function wp_extract_urls( $content ) { + preg_match_all( + "#((?:[\w-]+://?|[\w\d]+[.])[^\s()<>]+[.](?:\([\w\d]+\)|(?:[^`!()\[\]{};:'\".,<>?«»“â€â€˜â€™\s]|(?:[:]\d+)?/?)+))#", + $content, + $post_links + ); + + $post_links = array_unique( array_map( 'html_entity_decode', $post_links[0] ) ); + + return array_values( $post_links ); +} + +/** + * Check content for video and audio links to add as enclosures. + * + * Will not add enclosures that have already been added and will + * remove enclosures that are no longer in the post. This is called as + * pingbacks and trackbacks. + * + * @package WordPress + * @since 1.5.0 + * + * @uses $wpdb + * + * @param string $content Post Content + * @param int $post_ID Post ID + */ +function do_enclose( $content, $post_ID ) { + global $wpdb; + + //TODO: Tidy this ghetto code up and make the debug code optional + include_once( ABSPATH . WPINC . '/class-IXR.php' ); + + $post_links = array(); + + $pung = get_enclosed( $post_ID ); + + $post_links_temp = wp_extract_urls( $content ); + + foreach ( $pung as $link_test ) { + if ( ! in_array( $link_test, $post_links_temp ) ) { // link no longer in post + $mids = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $link_test ) . '%') ); + foreach ( $mids as $mid ) + delete_metadata_by_mid( 'post', $mid ); + } + } + + foreach ( (array) $post_links_temp as $link_test ) { + if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already + $test = @parse_url( $link_test ); + if ( false === $test ) + continue; + if ( isset( $test['query'] ) ) + $post_links[] = $link_test; + elseif ( isset($test['path']) && ( $test['path'] != '/' ) && ($test['path'] != '' ) ) + $post_links[] = $link_test; + } + } + + foreach ( (array) $post_links as $url ) { + if ( $url != '' && !$wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $url ) . '%' ) ) ) { + + if ( $headers = wp_get_http_headers( $url) ) { + $len = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0; + $type = isset( $headers['content-type'] ) ? $headers['content-type'] : ''; + $allowed_types = array( 'video', 'audio' ); + + // Check to see if we can figure out the mime type from + // the extension + $url_parts = @parse_url( $url ); + if ( false !== $url_parts ) { + $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION ); + if ( !empty( $extension ) ) { + foreach ( wp_get_mime_types() as $exts => $mime ) { + if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) { + $type = $mime; + break; + } + } + } + } + + if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) { + add_post_meta( $post_ID, 'enclosure', "$url\n$len\n$mime\n" ); + } + } + } + } +} + +/** + * Perform a HTTP HEAD or GET request. + * + * If $file_path is a writable filename, this will do a GET request and write + * the file to that path. + * + * @since 2.5.0 + * + * @param string $url URL to fetch. + * @param string|bool $file_path Optional. File path to write request to. + * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false. + * @return bool|string False on failure and string of headers if HEAD request. + */ +function wp_get_http( $url, $file_path = false, $red = 1 ) { + @set_time_limit( 60 ); + + if ( $red > 5 ) + return false; + + $options = array(); + $options['redirection'] = 5; + + if ( false == $file_path ) + $options['method'] = 'HEAD'; + else + $options['method'] = 'GET'; + + $response = wp_safe_remote_request( $url, $options ); + + if ( is_wp_error( $response ) ) + return false; + + $headers = wp_remote_retrieve_headers( $response ); + $headers['response'] = wp_remote_retrieve_response_code( $response ); + + // WP_HTTP no longer follows redirects for HEAD requests. + if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) { + return wp_get_http( $headers['location'], $file_path, ++$red ); + } + + if ( false == $file_path ) + return $headers; + + // GET request - write it to the supplied filename + $out_fp = fopen($file_path, 'w'); + if ( !$out_fp ) + return $headers; + + fwrite( $out_fp, wp_remote_retrieve_body( $response ) ); + fclose($out_fp); + clearstatcache(); + + return $headers; +} + +/** + * Retrieve HTTP Headers from URL. + * + * @since 1.5.1 + * + * @param string $url + * @param bool $deprecated Not Used. + * @return bool|string False on failure, headers on success. + */ +function wp_get_http_headers( $url, $deprecated = false ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.7' ); + + $response = wp_safe_remote_head( $url ); + + if ( is_wp_error( $response ) ) + return false; + + return wp_remote_retrieve_headers( $response ); +} + +/** + * Whether today is a new day. + * + * @since 0.71 + * @uses $day Today + * @uses $previousday Previous day + * + * @return int 1 when new day, 0 if not a new day. + */ +function is_new_day() { + global $currentday, $previousday; + if ( $currentday != $previousday ) + return 1; + else + return 0; +} + +/** + * Build URL query based on an associative and, or indexed array. + * + * This is a convenient function for easily building url queries. It sets the + * separator to '&' and uses _http_build_query() function. + * + * @see _http_build_query() Used to build the query + * @link http://us2.php.net/manual/en/function.http-build-query.php more on what + * http_build_query() does. + * + * @since 2.3.0 + * + * @param array $data URL-encode key/value pairs. + * @return string URL encoded string + */ +function build_query( $data ) { + return _http_build_query( $data, null, '&', '', false ); +} + +// from php.net (modified by Mark Jaquith to behave like the native PHP5 function) +function _http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) { + $ret = array(); + + foreach ( (array) $data as $k => $v ) { + if ( $urlencode) + $k = urlencode($k); + if ( is_int($k) && $prefix != null ) + $k = $prefix.$k; + if ( !empty($key) ) + $k = $key . '%5B' . $k . '%5D'; + if ( $v === null ) + continue; + elseif ( $v === FALSE ) + $v = '0'; + + if ( is_array($v) || is_object($v) ) + array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode)); + elseif ( $urlencode ) + array_push($ret, $k.'='.urlencode($v)); + else + array_push($ret, $k.'='.$v); + } + + if ( null === $sep ) + $sep = ini_get('arg_separator.output'); + + return implode($sep, $ret); +} + +/** + * Retrieve a modified URL query string. + * + * You can rebuild the URL and append a new query variable to the URL query by + * using this function. You can also retrieve the full URL with query data. + * + * Adding a single key & value or an associative array. Setting a key value to + * an empty string removes the key. Omitting oldquery_or_uri uses the $_SERVER + * value. Additional values provided are expected to be encoded appropriately + * with urlencode() or rawurlencode(). + * + * @since 1.5.0 + * + * @param mixed $param1 Either newkey or an associative_array + * @param mixed $param2 Either newvalue or oldquery or uri + * @param mixed $param3 Optional. Old query or uri + * @return string New URL query string. + */ +function add_query_arg() { + $ret = ''; + $args = func_get_args(); + if ( is_array( $args[0] ) ) { + if ( count( $args ) < 2 || false === $args[1] ) + $uri = $_SERVER['REQUEST_URI']; + else + $uri = $args[1]; + } else { + if ( count( $args ) < 3 || false === $args[2] ) + $uri = $_SERVER['REQUEST_URI']; + else + $uri = $args[2]; + } + + if ( $frag = strstr( $uri, '#' ) ) + $uri = substr( $uri, 0, -strlen( $frag ) ); + else + $frag = ''; + + if ( 0 === stripos( $uri, 'http://' ) ) { + $protocol = 'http://'; + $uri = substr( $uri, 7 ); + } elseif ( 0 === stripos( $uri, 'https://' ) ) { + $protocol = 'https://'; + $uri = substr( $uri, 8 ); + } else { + $protocol = ''; + } + + if ( strpos( $uri, '?' ) !== false ) { + list( $base, $query ) = explode( '?', $uri, 2 ); + $base .= '?'; + } elseif ( $protocol || strpos( $uri, '=' ) === false ) { + $base = $uri . '?'; + $query = ''; + } else { + $base = ''; + $query = $uri; + } + + wp_parse_str( $query, $qs ); + $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string + if ( is_array( $args[0] ) ) { + $kayvees = $args[0]; + $qs = array_merge( $qs, $kayvees ); + } else { + $qs[ $args[0] ] = $args[1]; + } + + foreach ( $qs as $k => $v ) { + if ( $v === false ) + unset( $qs[$k] ); + } + + $ret = build_query( $qs ); + $ret = trim( $ret, '?' ); + $ret = preg_replace( '#=(&|$)#', '$1', $ret ); + $ret = $protocol . $base . $ret . $frag; + $ret = rtrim( $ret, '?' ); + return $ret; +} + +/** + * Removes an item or list from the query string. + * + * @since 1.5.0 + * + * @param string|array $key Query key or keys to remove. + * @param bool $query When false uses the $_SERVER value. + * @return string New URL query string. + */ +function remove_query_arg( $key, $query=false ) { + if ( is_array( $key ) ) { // removing multiple keys + foreach ( $key as $k ) + $query = add_query_arg( $k, false, $query ); + return $query; + } + return add_query_arg( $key, false, $query ); +} + +/** + * Walks the array while sanitizing the contents. + * + * @since 0.71 + * + * @param array $array Array to walk while sanitizing contents. + * @return array Sanitized $array. + */ +function add_magic_quotes( $array ) { + foreach ( (array) $array as $k => $v ) { + if ( is_array( $v ) ) { + $array[$k] = add_magic_quotes( $v ); + } else { + $array[$k] = addslashes( $v ); + } + } + return $array; +} + +/** + * HTTP request for URI to retrieve content. + * + * @since 1.5.1 + * @uses wp_remote_get() + * + * @param string $uri URI/URL of web page to retrieve. + * @return bool|string HTTP content. False on failure. + */ +function wp_remote_fopen( $uri ) { + $parsed_url = @parse_url( $uri ); + + if ( !$parsed_url || !is_array( $parsed_url ) ) + return false; + + $options = array(); + $options['timeout'] = 10; + + $response = wp_safe_remote_get( $uri, $options ); + + if ( is_wp_error( $response ) ) + return false; + + return wp_remote_retrieve_body( $response ); +} + +/** + * Set up the WordPress query. + * + * @since 2.0.0 + * + * @param string $query_vars Default WP_Query arguments. + */ +function wp( $query_vars = '' ) { + global $wp, $wp_query, $wp_the_query; + $wp->main( $query_vars ); + + if ( !isset($wp_the_query) ) + $wp_the_query = $wp_query; +} + +/** + * Retrieve the description for the HTTP status. + * + * @since 2.3.0 + * + * @param int $code HTTP status code. + * @return string Empty string if not found, or description if found. + */ +function get_status_header_desc( $code ) { + global $wp_header_to_desc; + + $code = absint( $code ); + + if ( !isset( $wp_header_to_desc ) ) { + $wp_header_to_desc = array( + 100 => 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', + + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-Status', + 226 => 'IM Used', + + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => 'Reserved', + 307 => 'Temporary Redirect', + + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 422 => 'Unprocessable Entity', + 423 => 'Locked', + 424 => 'Failed Dependency', + 426 => 'Upgrade Required', + + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 506 => 'Variant Also Negotiates', + 507 => 'Insufficient Storage', + 510 => 'Not Extended' + ); + } + + if ( isset( $wp_header_to_desc[$code] ) ) + return $wp_header_to_desc[$code]; + else + return ''; +} + +/** + * Set HTTP status header. + * + * @since 2.0.0 + * @uses apply_filters() Calls 'status_header' on status header string, HTTP + * HTTP code, HTTP code description, and protocol string as separate + * parameters. + * + * @param int $header HTTP status code + * @return unknown + */ +function status_header( $header ) { + $text = get_status_header_desc( $header ); + + if ( empty( $text ) ) + return false; + + $protocol = $_SERVER["SERVER_PROTOCOL"]; + if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol ) + $protocol = 'HTTP/1.0'; + $status_header = "$protocol $header $text"; + if ( function_exists( 'apply_filters' ) ) + $status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol ); + + return @header( $status_header, true, $header ); +} + +/** + * Gets the header information to prevent caching. + * + * The several different headers cover the different ways cache prevention is handled + * by different browsers + * + * @since 2.8.0 + * + * @uses apply_filters() + * @return array The associative array of header names and field values. + */ +function wp_get_nocache_headers() { + $headers = array( + 'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT', + 'Cache-Control' => 'no-cache, must-revalidate, max-age=0', + 'Pragma' => 'no-cache', + ); + + if ( function_exists('apply_filters') ) { + $headers = (array) apply_filters('nocache_headers', $headers); + } + $headers['Last-Modified'] = false; + return $headers; +} + +/** + * Sets the headers to prevent caching for the different browsers. + * + * Different browsers support different nocache headers, so several headers must + * be sent so that all of them get the point that no caching should occur. + * + * @since 2.0.0 + * @uses wp_get_nocache_headers() + */ +function nocache_headers() { + $headers = wp_get_nocache_headers(); + + unset( $headers['Last-Modified'] ); + + // In PHP 5.3+, make sure we are not sending a Last-Modified header. + if ( function_exists( 'header_remove' ) ) { + @header_remove( 'Last-Modified' ); + } else { + // In PHP 5.2, send an empty Last-Modified header, but only as a + // last resort to override a header already sent. #WP23021 + foreach ( headers_list() as $header ) { + if ( 0 === stripos( $header, 'Last-Modified' ) ) { + $headers['Last-Modified'] = ''; + break; + } + } + } + + foreach( $headers as $name => $field_value ) + @header("{$name}: {$field_value}"); +} + +/** + * Set the headers for caching for 10 days with JavaScript content type. + * + * @since 2.1.0 + */ +function cache_javascript_headers() { + $expiresOffset = 10 * DAY_IN_SECONDS; + header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) ); + header( "Vary: Accept-Encoding" ); // Handle proxies + header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" ); +} + +/** + * Retrieve the number of database queries during the WordPress execution. + * + * @since 2.0.0 + * + * @return int Number of database queries + */ +function get_num_queries() { + global $wpdb; + return $wpdb->num_queries; +} + +/** + * Whether input is yes or no. Must be 'y' to be true. + * + * @since 1.0.0 + * + * @param string $yn Character string containing either 'y' or 'n' + * @return bool True if yes, false on anything else + */ +function bool_from_yn( $yn ) { + return ( strtolower( $yn ) == 'y' ); +} + +/** + * Loads the feed template from the use of an action hook. + * + * If the feed action does not have a hook, then the function will die with a + * message telling the visitor that the feed is not valid. + * + * It is better to only have one hook for each feed. + * + * @since 2.1.0 + * @uses $wp_query Used to tell if the use a comment feed. + * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed. + */ +function do_feed() { + global $wp_query; + + $feed = get_query_var( 'feed' ); + + // Remove the pad, if present. + $feed = preg_replace( '/^_+/', '', $feed ); + + if ( $feed == '' || $feed == 'feed' ) + $feed = get_default_feed(); + + $hook = 'do_feed_' . $feed; + if ( ! has_action( $hook ) ) + wp_die( __( 'ERROR: This is not a valid feed template.' ), '', array( 'response' => 404 ) ); + + do_action( $hook, $wp_query->is_comment_feed ); +} + +/** + * Load the RDF RSS 0.91 Feed template. + * + * @since 2.1.0 + */ +function do_feed_rdf() { + load_template( ABSPATH . WPINC . '/feed-rdf.php' ); +} + +/** + * Load the RSS 1.0 Feed Template. + * + * @since 2.1.0 + */ +function do_feed_rss() { + load_template( ABSPATH . WPINC . '/feed-rss.php' ); +} + +/** + * Load either the RSS2 comment feed or the RSS2 posts feed. + * + * @since 2.1.0 + * + * @param bool $for_comments True for the comment feed, false for normal feed. + */ +function do_feed_rss2( $for_comments ) { + if ( $for_comments ) + load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' ); + else + load_template( ABSPATH . WPINC . '/feed-rss2.php' ); +} + +/** + * Load either Atom comment feed or Atom posts feed. + * + * @since 2.1.0 + * + * @param bool $for_comments True for the comment feed, false for normal feed. + */ +function do_feed_atom( $for_comments ) { + if ($for_comments) + load_template( ABSPATH . WPINC . '/feed-atom-comments.php'); + else + load_template( ABSPATH . WPINC . '/feed-atom.php' ); +} + +/** + * Display the robots.txt file content. + * + * The echo content should be with usage of the permalinks or for creating the + * robots.txt file. + * + * @since 2.1.0 + * @uses do_action() Calls 'do_robotstxt' hook for displaying robots.txt rules. + */ +function do_robots() { + header( 'Content-Type: text/plain; charset=utf-8' ); + + do_action( 'do_robotstxt' ); + + $output = "User-agent: *\n"; + $public = get_option( 'blog_public' ); + if ( '0' == $public ) { + $output .= "Disallow: /\n"; + } else { + $site_url = parse_url( site_url() ); + $path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : ''; + $output .= "Disallow: $path/wp-admin/\n"; + $output .= "Disallow: $path/wp-includes/\n"; + } + + echo apply_filters('robots_txt', $output, $public); +} + +/** + * Test whether blog is already installed. + * + * The cache will be checked first. If you have a cache plugin, which saves the + * cache values, then this will work. If you use the default WordPress cache, + * and the database goes away, then you might have problems. + * + * Checks for the option siteurl for whether WordPress is installed. + * + * @since 2.1.0 + * @uses $wpdb + * + * @return bool Whether blog is already installed. + */ +function is_blog_installed() { + global $wpdb; + + // Check cache first. If options table goes away and we have true cached, oh well. + if ( wp_cache_get( 'is_blog_installed' ) ) + return true; + + $suppress = $wpdb->suppress_errors(); + if ( ! defined( 'WP_INSTALLING' ) ) { + $alloptions = wp_load_alloptions(); + } + // If siteurl is not set to autoload, check it specifically + if ( !isset( $alloptions['siteurl'] ) ) + $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" ); + else + $installed = $alloptions['siteurl']; + $wpdb->suppress_errors( $suppress ); + + $installed = !empty( $installed ); + wp_cache_set( 'is_blog_installed', $installed ); + + if ( $installed ) + return true; + + // If visiting repair.php, return true and let it take over. + if ( defined( 'WP_REPAIRING' ) ) + return true; + + $suppress = $wpdb->suppress_errors(); + + // Loop over the WP tables. If none exist, then scratch install is allowed. + // If one or more exist, suggest table repair since we got here because the options + // table could not be accessed. + $wp_tables = $wpdb->tables(); + foreach ( $wp_tables as $table ) { + // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install. + if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table ) + continue; + if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table ) + continue; + + if ( ! $wpdb->get_results( "DESCRIBE $table;" ) ) + continue; + + // One or more tables exist. We are insane. + + wp_load_translations_early(); + + // Die with a DB error. + $wpdb->error = sprintf( __( 'One or more database tables are unavailable. The database may need to be <a href="%s">repaired</a>.' ), 'maint/repair.php?referrer=is_blog_installed' ); + dead_db(); + } + + $wpdb->suppress_errors( $suppress ); + + wp_cache_set( 'is_blog_installed', false ); + + return false; +} + +/** + * Retrieve URL with nonce added to URL query. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @param string $actionurl URL to add nonce action. + * @param string $action Optional. Nonce action name. + * @param string $name Optional. Nonce name. + * @return string URL with nonce action added. + */ +function wp_nonce_url( $actionurl, $action = -1, $name = '_wpnonce' ) { + $actionurl = str_replace( '&', '&', $actionurl ); + return esc_html( add_query_arg( $name, wp_create_nonce( $action ), $actionurl ) ); +} + +/** + * Retrieve or display nonce hidden field for forms. + * + * The nonce field is used to validate that the contents of the form came from + * the location on the current site and not somewhere else. The nonce does not + * offer absolute protection, but should protect against most cases. It is very + * important to use nonce field in forms. + * + * The $action and $name are optional, but if you want to have better security, + * it is strongly suggested to set those two parameters. It is easier to just + * call the function without any parameters, because validation of the nonce + * doesn't require any parameters, but since crackers know what the default is + * it won't be difficult for them to find a way around your nonce and cause + * damage. + * + * The input name will be whatever $name value you gave. The input value will be + * the nonce creation value. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @param string $action Optional. Action name. + * @param string $name Optional. Nonce name. + * @param bool $referer Optional, default true. Whether to set the referer field for validation. + * @param bool $echo Optional, default true. Whether to display or return hidden form field. + * @return string Nonce field. + */ +function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) { + $name = esc_attr( $name ); + $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />'; + + if ( $referer ) + $nonce_field .= wp_referer_field( false ); + + if ( $echo ) + echo $nonce_field; + + return $nonce_field; +} + +/** + * Retrieve or display referer hidden field for forms. + * + * The referer link is the current Request URI from the server super global. The + * input name is '_wp_http_referer', in case you wanted to check manually. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @param bool $echo Whether to echo or return the referer field. + * @return string Referer field. + */ +function wp_referer_field( $echo = true ) { + $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. esc_attr( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . '" />'; + + if ( $echo ) + echo $referer_field; + return $referer_field; +} + +/** + * Retrieve or display original referer hidden field for forms. + * + * The input name is '_wp_original_http_referer' and will be either the same + * value of {@link wp_referer_field()}, if that was posted already or it will + * be the current page, if it doesn't exist. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @param bool $echo Whether to echo the original http referer + * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to. + * @return string Original referer field. + */ +function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) { + if ( ! $ref = wp_get_original_referer() ) { + $ref = 'previous' == $jump_back_to ? wp_get_referer() : wp_unslash( $_SERVER['REQUEST_URI'] ); + } + $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( $ref ) . '" />'; + if ( $echo ) + echo $orig_referer_field; + return $orig_referer_field; +} + +/** + * Retrieve referer from '_wp_http_referer' or HTTP referer. If it's the same + * as the current request URL, will return false. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @return string|bool False on failure. Referer URL on success. + */ +function wp_get_referer() { + if ( ! function_exists( 'wp_validate_redirect' ) ) + return false; + $ref = false; + if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) + $ref = wp_unslash( $_REQUEST['_wp_http_referer'] ); + else if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) + $ref = wp_unslash( $_SERVER['HTTP_REFERER'] ); + + if ( $ref && $ref !== wp_unslash( $_SERVER['REQUEST_URI'] ) ) + return wp_validate_redirect( $ref, false ); + return false; +} + +/** + * Retrieve original referer that was posted, if it exists. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @return string|bool False if no original referer or original referer if set. + */ +function wp_get_original_referer() { + if ( ! empty( $_REQUEST['_wp_original_http_referer'] ) && function_exists( 'wp_validate_redirect' ) ) + return wp_validate_redirect( wp_unslash( $_REQUEST['_wp_original_http_referer'] ), false ); + return false; +} + +/** + * Recursive directory creation based on full path. + * + * Will attempt to set permissions on folders. + * + * @since 2.0.1 + * + * @param string $target Full path to attempt to create. + * @return bool Whether the path was created. True if path already exists. + */ +function wp_mkdir_p( $target ) { + $wrapper = null; + + // strip the protocol + if( wp_is_stream( $target ) ) { + list( $wrapper, $target ) = explode( '://', $target, 2 ); + } + + // from php.net/mkdir user contributed notes + $target = str_replace( '//', '/', $target ); + + // put the wrapper back on the target + if( $wrapper !== null ) { + $target = $wrapper . '://' . $target; + } + + // safe mode fails with a trailing slash under certain PHP versions. + $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency. + if ( empty($target) ) + $target = '/'; + + if ( file_exists( $target ) ) + return @is_dir( $target ); + + // We need to find the permissions of the parent folder that exists and inherit that. + $target_parent = dirname( $target ); + while ( '.' != $target_parent && ! is_dir( $target_parent ) ) { + $target_parent = dirname( $target_parent ); + } + + // Get the permission bits. + if ( $target_parent && '.' != $target_parent ) { + $stat = @stat( $target_parent ); + $dir_perms = $stat['mode'] & 0007777; + } else { + $dir_perms = 0777; + } + + if ( @mkdir( $target, $dir_perms, true ) ) { + return true; + } + + return false; +} + +/** + * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows'). + * + * @since 2.5.0 + * + * @param string $path File path + * @return bool True if path is absolute, false is not absolute. + */ +function path_is_absolute( $path ) { + // this is definitive if true but fails if $path does not exist or contains a symbolic link + if ( realpath($path) == $path ) + return true; + + if ( strlen($path) == 0 || $path[0] == '.' ) + return false; + + // windows allows absolute paths like this + if ( preg_match('#^[a-zA-Z]:\\\\#', $path) ) + return true; + + // a path starting with / or \ is absolute; anything else is relative + return ( $path[0] == '/' || $path[0] == '\\' ); +} + +/** + * Join two filesystem paths together (e.g. 'give me $path relative to $base'). + * + * If the $path is absolute, then it the full path is returned. + * + * @since 2.5.0 + * + * @param string $base + * @param string $path + * @return string The path with the base or absolute path. + */ +function path_join( $base, $path ) { + if ( path_is_absolute($path) ) + return $path; + + return rtrim($base, '/') . '/' . ltrim($path, '/'); +} + +/** + * Determines a writable directory for temporary files. + * Function's preference is the return value of <code>sys_get_temp_dir()</code>, + * followed by your PHP temporary upload directory, followed by WP_CONTENT_DIR, + * before finally defaulting to /tmp/ + * + * In the event that this function does not find a writable location, + * It may be overridden by the <code>WP_TEMP_DIR</code> constant in + * your <code>wp-config.php</code> file. + * + * @since 2.5.0 + * + * @return string Writable temporary directory + */ +function get_temp_dir() { + static $temp; + if ( defined('WP_TEMP_DIR') ) + return trailingslashit(WP_TEMP_DIR); + + if ( $temp ) + return trailingslashit( rtrim( $temp, '\\' ) ); + + if ( function_exists('sys_get_temp_dir') ) { + $temp = sys_get_temp_dir(); + if ( @is_dir( $temp ) && wp_is_writable( $temp ) ) + return trailingslashit( rtrim( $temp, '\\' ) ); + } + + $temp = ini_get('upload_tmp_dir'); + if ( @is_dir( $temp ) && wp_is_writable( $temp ) ) + return trailingslashit( rtrim( $temp, '\\' ) ); + + $temp = WP_CONTENT_DIR . '/'; + if ( is_dir( $temp ) && wp_is_writable( $temp ) ) + return $temp; + + $temp = '/tmp/'; + return $temp; +} + +/** + * Determine if a directory is writable. + * + * This function is used to work around certain ACL issues + * in PHP primarily affecting Windows Servers. + * + * @see win_is_writable() + * + * @since 3.6.0 + * + * @param string $path + * @return bool + */ +function wp_is_writable( $path ) { + if ( 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) ) + return win_is_writable( $path ); + else + return @is_writable( $path ); +} + +/** + * Workaround for Windows bug in is_writable() function + * + * PHP has issues with Windows ACL's for determine if a + * directory is writable or not, this works around them by + * checking the ability to open files rather than relying + * upon PHP to interprate the OS ACL. + * + * @link http://bugs.php.net/bug.php?id=27609 + * @link http://bugs.php.net/bug.php?id=30931 + * + * @since 2.8.0 + * + * @param string $path + * @return bool + */ +function win_is_writable( $path ) { + + if ( $path[strlen( $path ) - 1] == '/' ) // if it looks like a directory, check a random file within the directory + return win_is_writable( $path . uniqid( mt_rand() ) . '.tmp'); + else if ( is_dir( $path ) ) // If it's a directory (and not a file) check a random file within the directory + return win_is_writable( $path . '/' . uniqid( mt_rand() ) . '.tmp' ); + + // check tmp file for read/write capabilities + $should_delete_tmp_file = !file_exists( $path ); + $f = @fopen( $path, 'a' ); + if ( $f === false ) + return false; + fclose( $f ); + if ( $should_delete_tmp_file ) + unlink( $path ); + return true; +} + +/** + * Get an array containing the current upload directory's path and url. + * + * Checks the 'upload_path' option, which should be from the web root folder, + * and if it isn't empty it will be used. If it is empty, then the path will be + * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will + * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path. + * + * The upload URL path is set either by the 'upload_url_path' option or by using + * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path. + * + * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in + * the administration settings panel), then the time will be used. The format + * will be year first and then month. + * + * If the path couldn't be created, then an error will be returned with the key + * 'error' containing the error message. The error suggests that the parent + * directory is not writable by the server. + * + * On success, the returned array will have many indices: + * 'path' - base directory and sub directory or full path to upload directory. + * 'url' - base url and sub directory or absolute URL to upload directory. + * 'subdir' - sub directory if uploads use year/month folders option is on. + * 'basedir' - path without subdir. + * 'baseurl' - URL path without subdir. + * 'error' - set to false. + * + * @since 2.0.0 + * @uses apply_filters() Calls 'upload_dir' on returned array. + * + * @param string $time Optional. Time formatted in 'yyyy/mm'. + * @return array See above for description. + */ +function wp_upload_dir( $time = null ) { + $siteurl = get_option( 'siteurl' ); + $upload_path = trim( get_option( 'upload_path' ) ); + + if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) { + $dir = WP_CONTENT_DIR . '/uploads'; + } elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) { + // $dir is absolute, $upload_path is (maybe) relative to ABSPATH + $dir = path_join( ABSPATH, $upload_path ); + } else { + $dir = $upload_path; + } + + if ( !$url = get_option( 'upload_url_path' ) ) { + if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) ) + $url = WP_CONTENT_URL . '/uploads'; + else + $url = trailingslashit( $siteurl ) . $upload_path; + } + + // Obey the value of UPLOADS. This happens as long as ms-files rewriting is disabled. + // We also sometimes obey UPLOADS when rewriting is enabled -- see the next block. + if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) ) { + $dir = ABSPATH . UPLOADS; + $url = trailingslashit( $siteurl ) . UPLOADS; + } + + // If multisite (and if not the main site in a post-MU network) + if ( is_multisite() && ! ( is_main_network() && is_main_site() && defined( 'MULTISITE' ) ) ) { + + if ( ! get_site_option( 'ms_files_rewriting' ) ) { + // If ms-files rewriting is disabled (networks created post-3.5), it is fairly straightforward: + // Append sites/%d if we're not on the main site (for post-MU networks). (The extra directory + // prevents a four-digit ID from conflicting with a year-based directory for the main site. + // But if a MU-era network has disabled ms-files rewriting manually, they don't need the extra + // directory, as they never had wp-content/uploads for the main site.) + + if ( defined( 'MULTISITE' ) ) + $ms_dir = '/sites/' . get_current_blog_id(); + else + $ms_dir = '/' . get_current_blog_id(); + + $dir .= $ms_dir; + $url .= $ms_dir; + + } elseif ( defined( 'UPLOADS' ) && ! ms_is_switched() ) { + // Handle the old-form ms-files.php rewriting if the network still has that enabled. + // When ms-files rewriting is enabled, then we only listen to UPLOADS when: + // 1) we are not on the main site in a post-MU network, + // as wp-content/uploads is used there, and + // 2) we are not switched, as ms_upload_constants() hardcodes + // these constants to reflect the original blog ID. + // + // Rather than UPLOADS, we actually use BLOGUPLOADDIR if it is set, as it is absolute. + // (And it will be set, see ms_upload_constants().) Otherwise, UPLOADS can be used, as + // as it is relative to ABSPATH. For the final piece: when UPLOADS is used with ms-files + // rewriting in multisite, the resulting URL is /files. (#WP22702 for background.) + + if ( defined( 'BLOGUPLOADDIR' ) ) + $dir = untrailingslashit( BLOGUPLOADDIR ); + else + $dir = ABSPATH . UPLOADS; + $url = trailingslashit( $siteurl ) . 'files'; + } + } + + $basedir = $dir; + $baseurl = $url; + + $subdir = ''; + if ( get_option( 'uploads_use_yearmonth_folders' ) ) { + // Generate the yearly and monthly dirs + if ( !$time ) + $time = current_time( 'mysql' ); + $y = substr( $time, 0, 4 ); + $m = substr( $time, 5, 2 ); + $subdir = "/$y/$m"; + } + + $dir .= $subdir; + $url .= $subdir; + + $uploads = apply_filters( 'upload_dir', + array( + 'path' => $dir, + 'url' => $url, + 'subdir' => $subdir, + 'basedir' => $basedir, + 'baseurl' => $baseurl, + 'error' => false, + ) ); + + // Make sure we have an uploads dir + if ( ! wp_mkdir_p( $uploads['path'] ) ) { + if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) + $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; + else + $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; + + $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path ); + $uploads['error'] = $message; + } + + return $uploads; +} + +/** + * Get a filename that is sanitized and unique for the given directory. + * + * If the filename is not unique, then a number will be added to the filename + * before the extension, and will continue adding numbers until the filename is + * unique. + * + * The callback is passed three parameters, the first one is the directory, the + * second is the filename, and the third is the extension. + * + * @since 2.5.0 + * + * @param string $dir + * @param string $filename + * @param mixed $unique_filename_callback Callback. + * @return string New filename, if given wasn't unique. + */ +function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) { + // sanitize the file name before we begin processing + $filename = sanitize_file_name($filename); + + // separate the filename into a name and extension + $info = pathinfo($filename); + $ext = !empty($info['extension']) ? '.' . $info['extension'] : ''; + $name = basename($filename, $ext); + + // edge case: if file is named '.ext', treat as an empty name + if ( $name === $ext ) + $name = ''; + + // Increment the file number until we have a unique file to save in $dir. Use callback if supplied. + if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) { + $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext ); + } else { + $number = ''; + + // change '.ext' to lower case + if ( $ext && strtolower($ext) != $ext ) { + $ext2 = strtolower($ext); + $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename ); + + // check for both lower and upper case extension or image sub-sizes may be overwritten + while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) { + $new_number = $number + 1; + $filename = str_replace( "$number$ext", "$new_number$ext", $filename ); + $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 ); + $number = $new_number; + } + return $filename2; + } + + while ( file_exists( $dir . "/$filename" ) ) { + if ( '' == "$number$ext" ) + $filename = $filename . ++$number . $ext; + else + $filename = str_replace( "$number$ext", ++$number . $ext, $filename ); + } + } + + return $filename; +} + +/** + * Create a file in the upload folder with given content. + * + * If there is an error, then the key 'error' will exist with the error message. + * If success, then the key 'file' will have the unique file path, the 'url' key + * will have the link to the new file. and the 'error' key will be set to false. + * + * This function will not move an uploaded file to the upload folder. It will + * create a new file with the content in $bits parameter. If you move the upload + * file, read the content of the uploaded file, and then you can give the + * filename and content to this function, which will add it to the upload + * folder. + * + * The permissions will be set on the new file automatically by this function. + * + * @since 2.0.0 + * + * @param string $name + * @param null $deprecated Never used. Set to null. + * @param mixed $bits File content + * @param string $time Optional. Time formatted in 'yyyy/mm'. + * @return array + */ +function wp_upload_bits( $name, $deprecated, $bits, $time = null ) { + if ( !empty( $deprecated ) ) + _deprecated_argument( __FUNCTION__, '2.0' ); + + if ( empty( $name ) ) + return array( 'error' => __( 'Empty filename' ) ); + + $wp_filetype = wp_check_filetype( $name ); + if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) ) + return array( 'error' => __( 'Invalid file type' ) ); + + $upload = wp_upload_dir( $time ); + + if ( $upload['error'] !== false ) + return $upload; + + $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) ); + if ( !is_array( $upload_bits_error ) ) { + $upload[ 'error' ] = $upload_bits_error; + return $upload; + } + + $filename = wp_unique_filename( $upload['path'], $name ); + + $new_file = $upload['path'] . "/$filename"; + if ( ! wp_mkdir_p( dirname( $new_file ) ) ) { + if ( 0 === strpos( $upload['basedir'], ABSPATH ) ) + $error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir']; + else + $error_path = basename( $upload['basedir'] ) . $upload['subdir']; + + $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path ); + return array( 'error' => $message ); + } + + $ifp = @ fopen( $new_file, 'wb' ); + if ( ! $ifp ) + return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) ); + + @fwrite( $ifp, $bits ); + fclose( $ifp ); + clearstatcache(); + + // Set correct file permissions + $stat = @ stat( dirname( $new_file ) ); + $perms = $stat['mode'] & 0007777; + $perms = $perms & 0000666; + @ chmod( $new_file, $perms ); + clearstatcache(); + + // Compute the URL + $url = $upload['url'] . "/$filename"; + + return array( 'file' => $new_file, 'url' => $url, 'error' => false ); +} + +/** + * Retrieve the file type based on the extension name. + * + * @package WordPress + * @since 2.5.0 + * @uses apply_filters() Calls 'ext2type' hook on default supported types. + * + * @param string $ext The extension to search. + * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found. + */ +function wp_ext2type( $ext ) { + $ext = strtolower( $ext ); + $ext2type = apply_filters( 'ext2type', array( + 'image' => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico' ), + 'audio' => array( 'aac', 'ac3', 'aif', 'aiff', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ), + 'video' => array( 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ), + 'document' => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'rtf', 'wp', 'wpd' ), + 'spreadsheet' => array( 'numbers', 'ods', 'xls', 'xlsx', 'xlsm', 'xlsb' ), + 'interactive' => array( 'swf', 'key', 'ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ), + 'text' => array( 'asc', 'csv', 'tsv', 'txt' ), + 'archive' => array( 'bz2', 'cab', 'dmg', 'gz', 'rar', 'sea', 'sit', 'sqx', 'tar', 'tgz', 'zip', '7z' ), + 'code' => array( 'css', 'htm', 'html', 'php', 'js' ), + ) ); + + foreach ( $ext2type as $type => $exts ) + if ( in_array( $ext, $exts ) ) + return $type; + + return null; +} + +/** + * Retrieve the file type from the file name. + * + * You can optionally define the mime array, if needed. + * + * @since 2.0.4 + * + * @param string $filename File name or path. + * @param array $mimes Optional. Key is the file extension with value as the mime type. + * @return array Values with extension first and mime type. + */ +function wp_check_filetype( $filename, $mimes = null ) { + if ( empty($mimes) ) + $mimes = get_allowed_mime_types(); + $type = false; + $ext = false; + + foreach ( $mimes as $ext_preg => $mime_match ) { + $ext_preg = '!\.(' . $ext_preg . ')$!i'; + if ( preg_match( $ext_preg, $filename, $ext_matches ) ) { + $type = $mime_match; + $ext = $ext_matches[1]; + break; + } + } + + return compact( 'ext', 'type' ); +} + +/** + * Attempt to determine the real file type of a file. + * If unable to, the file name extension will be used to determine type. + * + * If it's determined that the extension does not match the file's real type, + * then the "proper_filename" value will be set with a proper filename and extension. + * + * Currently this function only supports validating images known to getimagesize(). + * + * @since 3.0.0 + * + * @param string $file Full path to the file. + * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory) + * @param array $mimes Optional. Key is the file extension with value as the mime type. + * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid + */ +function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) { + + $proper_filename = false; + + // Do basic extension validation and MIME mapping + $wp_filetype = wp_check_filetype( $filename, $mimes ); + extract( $wp_filetype ); + + // We can't do any further validation without a file to work with + if ( ! file_exists( $file ) ) + return compact( 'ext', 'type', 'proper_filename' ); + + // We're able to validate images using GD + if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) { + + // Attempt to figure out what type of image it actually is + $imgstats = @getimagesize( $file ); + + // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME + if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) { + // This is a simplified array of MIMEs that getimagesize() can detect and their extensions + // You shouldn't need to use this filter, but it's here just in case + $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array( + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + 'image/gif' => 'gif', + 'image/bmp' => 'bmp', + 'image/tiff' => 'tif', + ) ); + + // Replace whatever is after the last period in the filename with the correct extension + if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) { + $filename_parts = explode( '.', $filename ); + array_pop( $filename_parts ); + $filename_parts[] = $mime_to_ext[ $imgstats['mime'] ]; + $new_filename = implode( '.', $filename_parts ); + + if ( $new_filename != $filename ) + $proper_filename = $new_filename; // Mark that it changed + + // Redefine the extension / MIME + $wp_filetype = wp_check_filetype( $new_filename, $mimes ); + extract( $wp_filetype ); + } + } + } + + // Let plugins try and validate other types of files + // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename ) + return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes ); +} + +/** + * Retrieve list of mime types and file extensions. + * + * @since 3.5.0 + * + * @uses apply_filters() Calls 'mime_types' on returned array. This filter should + * be used to add types, not remove them. To remove types use the upload_mimes filter. + * + * @return array Array of mime types keyed by the file extension regex corresponding to those types. + */ +function wp_get_mime_types() { + // Accepted MIME types are set here as PCRE unless provided. + return apply_filters( 'mime_types', array( + // Image formats + 'jpg|jpeg|jpe' => 'image/jpeg', + 'gif' => 'image/gif', + 'png' => 'image/png', + 'bmp' => 'image/bmp', + 'tif|tiff' => 'image/tiff', + 'ico' => 'image/x-icon', + // Video formats + 'asf|asx' => 'video/x-ms-asf', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wm' => 'video/x-ms-wm', + 'avi' => 'video/avi', + 'divx' => 'video/divx', + 'flv' => 'video/x-flv', + 'mov|qt' => 'video/quicktime', + 'mpeg|mpg|mpe' => 'video/mpeg', + 'mp4|m4v' => 'video/mp4', + 'ogv' => 'video/ogg', + 'webm' => 'video/webm', + 'mkv' => 'video/x-matroska', + // Text formats + 'txt|asc|c|cc|h' => 'text/plain', + 'csv' => 'text/csv', + 'tsv' => 'text/tab-separated-values', + 'ics' => 'text/calendar', + 'rtx' => 'text/richtext', + 'css' => 'text/css', + 'htm|html' => 'text/html', + // Audio formats + 'mp3|m4a|m4b' => 'audio/mpeg', + 'ra|ram' => 'audio/x-realaudio', + 'wav' => 'audio/wav', + 'ogg|oga' => 'audio/ogg', + 'mid|midi' => 'audio/midi', + 'wma' => 'audio/x-ms-wma', + 'wax' => 'audio/x-ms-wax', + 'mka' => 'audio/x-matroska', + // Misc application formats + 'rtf' => 'application/rtf', + 'js' => 'application/javascript', + 'pdf' => 'application/pdf', + 'swf' => 'application/x-shockwave-flash', + 'class' => 'application/java', + 'tar' => 'application/x-tar', + 'zip' => 'application/zip', + 'gz|gzip' => 'application/x-gzip', + 'rar' => 'application/rar', + '7z' => 'application/x-7z-compressed', + 'exe' => 'application/x-msdownload', + // MS Office formats + 'doc' => 'application/msword', + 'pot|pps|ppt' => 'application/vnd.ms-powerpoint', + 'wri' => 'application/vnd.ms-write', + 'xla|xls|xlt|xlw' => 'application/vnd.ms-excel', + 'mdb' => 'application/vnd.ms-access', + 'mpp' => 'application/vnd.ms-project', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'docm' => 'application/vnd.ms-word.document.macroEnabled.12', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12', + 'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote', + // OpenOffice formats + 'odt' => 'application/vnd.oasis.opendocument.text', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'odf' => 'application/vnd.oasis.opendocument.formula', + // WordPerfect formats + 'wp|wpd' => 'application/wordperfect', + // iWork formats + 'key' => 'application/vnd.apple.keynote', + 'numbers' => 'application/vnd.apple.numbers', + 'pages' => 'application/vnd.apple.pages', + ) ); +} +/** + * Retrieve list of allowed mime types and file extensions. + * + * @since 2.8.6 + * + * @uses apply_filters() Calls 'upload_mimes' on returned array + * @uses wp_get_upload_mime_types() to fetch the list of mime types + * + * @param int|WP_User $user Optional. User to check. Defaults to current user. + * @return array Array of mime types keyed by the file extension regex corresponding to those types. + */ +function get_allowed_mime_types( $user = null ) { + $t = wp_get_mime_types(); + + unset( $t['swf'], $t['exe'] ); + if ( function_exists( 'current_user_can' ) ) + $unfiltered = $user ? user_can( $user, 'unfiltered_html' ) : current_user_can( 'unfiltered_html' ); + + if ( empty( $unfiltered ) ) + unset( $t['htm|html'] ); + + return apply_filters( 'upload_mimes', $t, $user ); +} + +/** + * Display "Are You Sure" message to confirm the action being taken. + * + * If the action has the nonce explain message, then it will be displayed along + * with the "Are you sure?" message. + * + * @package WordPress + * @subpackage Security + * @since 2.0.4 + * + * @param string $action The nonce action. + */ +function wp_nonce_ays( $action ) { + $title = __( 'WordPress Failure Notice' ); + if ( 'log-out' == $action ) { + $html = sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'name' ) ) . '</p><p>'; + $html .= sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url() ); + } else { + $html = __( 'Are you sure you want to do this?' ); + if ( wp_get_referer() ) + $html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>"; + } + + wp_die( $html, $title, array('response' => 403) ); +} + +/** + * Kill WordPress execution and display HTML message with error message. + * + * This function complements the die() PHP function. The difference is that + * HTML will be displayed to the user. It is recommended to use this function + * only, when the execution should not continue any further. It is not + * recommended to call this function very often and try to handle as many errors + * as possible silently. + * + * @since 2.0.4 + * + * @param string $message Error message. + * @param string $title Error title. + * @param string|array $args Optional arguments to control behavior. + */ +function wp_die( $message = '', $title = '', $args = array() ) { + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' ); + elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) + $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' ); + else + $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' ); + + call_user_func( $function, $message, $title, $args ); +} + +/** + * Kill WordPress execution and display HTML message with error message. + * + * This is the default handler for wp_die if you want a custom one for your + * site then you can overload using the wp_die_handler filter in wp_die + * + * @since 3.0.0 + * @access private + * + * @param string $message Error message. + * @param string $title Error title. + * @param string|array $args Optional arguments to control behavior. + */ +function _default_wp_die_handler( $message, $title = '', $args = array() ) { + $defaults = array( 'response' => 500 ); + $r = wp_parse_args($args, $defaults); + + $have_gettext = function_exists('__'); + + if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) { + if ( empty( $title ) ) { + $error_data = $message->get_error_data(); + if ( is_array( $error_data ) && isset( $error_data['title'] ) ) + $title = $error_data['title']; + } + $errors = $message->get_error_messages(); + switch ( count( $errors ) ) : + case 0 : + $message = ''; + break; + case 1 : + $message = "<p>{$errors[0]}</p>"; + break; + default : + $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>"; + break; + endswitch; + } elseif ( is_string( $message ) ) { + $message = "<p>$message</p>"; + } + + if ( isset( $r['back_link'] ) && $r['back_link'] ) { + $back_text = $have_gettext? __('« Back') : '« Back'; + $message .= "\n<p><a href='javascript:history.back()'>$back_text</a></p>"; + } + + if ( ! did_action( 'admin_head' ) ) : + if ( !headers_sent() ) { + status_header( $r['response'] ); + nocache_headers(); + header( 'Content-Type: text/html; charset=utf-8' ); + } + + if ( empty($title) ) + $title = $have_gettext ? __('WordPress › Error') : 'WordPress › Error'; + + $text_direction = 'ltr'; + if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] ) + $text_direction = 'rtl'; + elseif ( function_exists( 'is_rtl' ) && is_rtl() ) + $text_direction = 'rtl'; +?> +<!DOCTYPE html> +<!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono +--> +<html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) ) language_attributes(); else echo "dir='$text_direction'"; ?>> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title><?php echo $title ?> + + + + + + + + 500 ); + + $r = wp_parse_args($args, $defaults); + + if ( $wp_xmlrpc_server ) { + $error = new IXR_Error( $r['response'] , $message); + $wp_xmlrpc_server->output( $error->getXml() ); + } + die(); +} + +/** + * Kill WordPress ajax execution. + * + * This is the handler for wp_die when processing Ajax requests. + * + * @since 3.4.0 + * @access private + * + * @param string $message Optional. Response to print. + */ +function _ajax_wp_die_handler( $message = '' ) { + if ( is_scalar( $message ) ) + die( (string) $message ); + die( '0' ); +} + +/** + * Kill WordPress execution. + * + * This is the handler for wp_die when processing APP requests. + * + * @since 3.4.0 + * @access private + * + * @param string $message Optional. Response to print. + */ +function _scalar_wp_die_handler( $message = '' ) { + if ( is_scalar( $message ) ) + die( (string) $message ); + die(); +} + +/** + * Send a JSON response back to an Ajax request. + * + * @since 3.5.0 + * + * @param mixed $response Variable (usually an array or object) to encode as JSON, then print and die. + */ +function wp_send_json( $response ) { + @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) ); + echo json_encode( $response ); + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) + wp_die(); + else + die; +} + +/** + * Send a JSON response back to an Ajax request, indicating success. + * + * @since 3.5.0 + * + * @param mixed $data Data to encode as JSON, then print and die. + */ +function wp_send_json_success( $data = null ) { + $response = array( 'success' => true ); + + if ( isset( $data ) ) + $response['data'] = $data; + + wp_send_json( $response ); +} + +/** + * Send a JSON response back to an Ajax request, indicating failure. + * + * @since 3.5.0 + * + * @param mixed $data Data to encode as JSON, then print and die. + */ +function wp_send_json_error( $data = null ) { + $response = array( 'success' => false ); + + if ( isset( $data ) ) + $response['data'] = $data; + + wp_send_json( $response ); +} + +/** + * Retrieve the WordPress home page URL. + * + * If the constant named 'WP_HOME' exists, then it will be used and returned by + * the function. This can be used to counter the redirection on your local + * development environment. + * + * @access private + * @package WordPress + * @since 2.2.0 + * + * @param string $url URL for the home location + * @return string Homepage location. + */ +function _config_wp_home( $url = '' ) { + if ( defined( 'WP_HOME' ) ) + return untrailingslashit( WP_HOME ); + return $url; +} + +/** + * Retrieve the WordPress site URL. + * + * If the constant named 'WP_SITEURL' is defined, then the value in that + * constant will always be returned. This can be used for debugging a site on + * your localhost while not having to change the database to your URL. + * + * @access private + * @package WordPress + * @since 2.2.0 + * + * @param string $url URL to set the WordPress site location. + * @return string The WordPress Site URL + */ +function _config_wp_siteurl( $url = '' ) { + if ( defined( 'WP_SITEURL' ) ) + return untrailingslashit( WP_SITEURL ); + return $url; +} + +/** + * Set the localized direction for MCE plugin. + * + * Will only set the direction to 'rtl', if the WordPress locale has the text + * direction set to 'rtl'. + * + * Fills in the 'directionality', 'plugins', and 'theme_advanced_button1' array + * keys. These keys are then returned in the $input array. + * + * @access private + * @package WordPress + * @subpackage MCE + * @since 2.1.0 + * + * @param array $input MCE plugin array. + * @return array Direction set for 'rtl', if needed by locale. + */ +function _mce_set_direction( $input ) { + if ( is_rtl() ) { + $input['directionality'] = 'rtl'; + $input['plugins'] .= ',directionality'; + $input['theme_advanced_buttons1'] .= ',ltr'; + } + + return $input; +} + +/** + * Convert smiley code to the icon graphic file equivalent. + * + * You can turn off smilies, by going to the write setting screen and unchecking + * the box, or by setting 'use_smilies' option to false or removing the option. + * + * Plugins may override the default smiley list by setting the $wpsmiliestrans + * to an array, with the key the code the blogger types in and the value the + * image file. + * + * The $wp_smiliessearch global is for the regular expression and is set each + * time the function is called. + * + * The full list of smilies can be found in the function and won't be listed in + * the description. Probably should create a Codex page for it, so that it is + * available. + * + * @global array $wpsmiliestrans + * @global array $wp_smiliessearch + * @since 2.2.0 + */ +function smilies_init() { + global $wpsmiliestrans, $wp_smiliessearch; + + // don't bother setting up smilies if they are disabled + if ( !get_option( 'use_smilies' ) ) + return; + + if ( !isset( $wpsmiliestrans ) ) { + $wpsmiliestrans = array( + ':mrgreen:' => 'icon_mrgreen.gif', + ':neutral:' => 'icon_neutral.gif', + ':twisted:' => 'icon_twisted.gif', + ':arrow:' => 'icon_arrow.gif', + ':shock:' => 'icon_eek.gif', + ':smile:' => 'icon_smile.gif', + ':???:' => 'icon_confused.gif', + ':cool:' => 'icon_cool.gif', + ':evil:' => 'icon_evil.gif', + ':grin:' => 'icon_biggrin.gif', + ':idea:' => 'icon_idea.gif', + ':oops:' => 'icon_redface.gif', + ':razz:' => 'icon_razz.gif', + ':roll:' => 'icon_rolleyes.gif', + ':wink:' => 'icon_wink.gif', + ':cry:' => 'icon_cry.gif', + ':eek:' => 'icon_surprised.gif', + ':lol:' => 'icon_lol.gif', + ':mad:' => 'icon_mad.gif', + ':sad:' => 'icon_sad.gif', + '8-)' => 'icon_cool.gif', + '8-O' => 'icon_eek.gif', + ':-(' => 'icon_sad.gif', + ':-)' => 'icon_smile.gif', + ':-?' => 'icon_confused.gif', + ':-D' => 'icon_biggrin.gif', + ':-P' => 'icon_razz.gif', + ':-o' => 'icon_surprised.gif', + ':-x' => 'icon_mad.gif', + ':-|' => 'icon_neutral.gif', + ';-)' => 'icon_wink.gif', + // This one transformation breaks regular text with frequency. + // '8)' => 'icon_cool.gif', + '8O' => 'icon_eek.gif', + ':(' => 'icon_sad.gif', + ':)' => 'icon_smile.gif', + ':?' => 'icon_confused.gif', + ':D' => 'icon_biggrin.gif', + ':P' => 'icon_razz.gif', + ':o' => 'icon_surprised.gif', + ':x' => 'icon_mad.gif', + ':|' => 'icon_neutral.gif', + ';)' => 'icon_wink.gif', + ':!:' => 'icon_exclaim.gif', + ':?:' => 'icon_question.gif', + ); + } + + if (count($wpsmiliestrans) == 0) { + return; + } + + /* + * NOTE: we sort the smilies in reverse key order. This is to make sure + * we match the longest possible smilie (:???: vs :?) as the regular + * expression used below is first-match + */ + krsort($wpsmiliestrans); + + $wp_smiliessearch = '/(?:\s|^)'; + + $subchar = ''; + foreach ( (array) $wpsmiliestrans as $smiley => $img ) { + $firstchar = substr($smiley, 0, 1); + $rest = substr($smiley, 1); + + // new subpattern? + if ($firstchar != $subchar) { + if ($subchar != '') { + $wp_smiliessearch .= ')|(?:\s|^)'; + } + $subchar = $firstchar; + $wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:'; + } else { + $wp_smiliessearch .= '|'; + } + $wp_smiliessearch .= preg_quote($rest, '/'); + } + + $wp_smiliessearch .= ')(?:\s|$)/m'; +} + +/** + * Merge user defined arguments into defaults array. + * + * This function is used throughout WordPress to allow for both string or array + * to be merged into another array. + * + * @since 2.2.0 + * + * @param string|array $args Value to merge with $defaults + * @param array $defaults Array that serves as the defaults. + * @return array Merged user defined values with defaults. + */ +function wp_parse_args( $args, $defaults = '' ) { + if ( is_object( $args ) ) + $r = get_object_vars( $args ); + elseif ( is_array( $args ) ) + $r =& $args; + else + wp_parse_str( $args, $r ); + + if ( is_array( $defaults ) ) + return array_merge( $defaults, $r ); + return $r; +} + +/** + * Clean up an array, comma- or space-separated list of IDs. + * + * @since 3.0.0 + * + * @param array|string $list + * @return array Sanitized array of IDs + */ +function wp_parse_id_list( $list ) { + if ( !is_array($list) ) + $list = preg_split('/[\s,]+/', $list); + + return array_unique(array_map('absint', $list)); +} + +/** + * Extract a slice of an array, given a list of keys. + * + * @since 3.1.0 + * + * @param array $array The original array + * @param array $keys The list of keys + * @return array The array slice + */ +function wp_array_slice_assoc( $array, $keys ) { + $slice = array(); + foreach ( $keys as $key ) + if ( isset( $array[ $key ] ) ) + $slice[ $key ] = $array[ $key ]; + + return $slice; +} + +/** + * Filters a list of objects, based on a set of key => value arguments. + * + * @since 3.0.0 + * + * @param array $list An array of objects to filter + * @param array $args An array of key => value arguments to match against each object + * @param string $operator The logical operation to perform. 'or' means only one element + * from the array needs to match; 'and' means all elements must match. The default is 'and'. + * @param bool|string $field A field from the object to place instead of the entire object + * @return array A list of objects or object fields + */ +function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) { + if ( ! is_array( $list ) ) + return array(); + + $list = wp_list_filter( $list, $args, $operator ); + + if ( $field ) + $list = wp_list_pluck( $list, $field ); + + return $list; +} + +/** + * Filters a list of objects, based on a set of key => value arguments. + * + * @since 3.1.0 + * + * @param array $list An array of objects to filter + * @param array $args An array of key => value arguments to match against each object + * @param string $operator The logical operation to perform: + * 'AND' means all elements from the array must match; + * 'OR' means only one element needs to match; + * 'NOT' means no elements may match. + * The default is 'AND'. + * @return array + */ +function wp_list_filter( $list, $args = array(), $operator = 'AND' ) { + if ( ! is_array( $list ) ) + return array(); + + if ( empty( $args ) ) + return $list; + + $operator = strtoupper( $operator ); + $count = count( $args ); + $filtered = array(); + + foreach ( $list as $key => $obj ) { + $to_match = (array) $obj; + + $matched = 0; + foreach ( $args as $m_key => $m_value ) { + if ( array_key_exists( $m_key, $to_match ) && $m_value == $to_match[ $m_key ] ) + $matched++; + } + + if ( ( 'AND' == $operator && $matched == $count ) + || ( 'OR' == $operator && $matched > 0 ) + || ( 'NOT' == $operator && 0 == $matched ) ) { + $filtered[$key] = $obj; + } + } + + return $filtered; +} + +/** + * Pluck a certain field out of each object in a list. + * + * @since 3.1.0 + * + * @param array $list A list of objects or arrays + * @param int|string $field A field from the object to place instead of the entire object + * @return array + */ +function wp_list_pluck( $list, $field ) { + foreach ( $list as $key => $value ) { + if ( is_object( $value ) ) + $list[ $key ] = $value->$field; + else + $list[ $key ] = $value[ $field ]; + } + + return $list; +} + +/** + * Determines if Widgets library should be loaded. + * + * Checks to make sure that the widgets library hasn't already been loaded. If + * it hasn't, then it will load the widgets library and run an action hook. + * + * @since 2.2.0 + * @uses add_action() Calls '_admin_menu' hook with 'wp_widgets_add_menu' value. + */ +function wp_maybe_load_widgets() { + if ( ! apply_filters('load_default_widgets', true) ) + return; + require_once( ABSPATH . WPINC . '/default-widgets.php' ); + add_action( '_admin_menu', 'wp_widgets_add_menu' ); +} + +/** + * Append the Widgets menu to the themes main menu. + * + * @since 2.2.0 + * @uses $submenu The administration submenu list. + */ +function wp_widgets_add_menu() { + global $submenu; + + if ( ! current_theme_supports( 'widgets' ) ) + return; + + $submenu['themes.php'][7] = array( __( 'Widgets' ), 'edit_theme_options', 'widgets.php' ); + ksort( $submenu['themes.php'], SORT_NUMERIC ); +} + +/** + * Flush all output buffers for PHP 5.2. + * + * Make sure all output buffers are flushed before our singletons our destroyed. + * + * @since 2.2.0 + */ +function wp_ob_end_flush_all() { + $levels = ob_get_level(); + for ($i=0; $i<$levels; $i++) + ob_end_flush(); +} + +/** + * Load custom DB error or display WordPress DB error. + * + * If a file exists in the wp-content directory named db-error.php, then it will + * be loaded instead of displaying the WordPress DB error. If it is not found, + * then the WordPress DB error will be displayed instead. + * + * The WordPress DB error sets the HTTP status header to 500 to try to prevent + * search engines from caching the message. Custom DB messages should do the + * same. + * + * This function was backported to WordPress 2.3.2, but originally was added + * in WordPress 2.5.0. + * + * @since 2.3.2 + * @uses $wpdb + */ +function dead_db() { + global $wpdb; + + // Load custom DB error template, if present. + if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) { + require_once( WP_CONTENT_DIR . '/db-error.php' ); + die(); + } + + // If installing or in the admin, provide the verbose message. + if ( defined('WP_INSTALLING') || defined('WP_ADMIN') ) + wp_die($wpdb->error); + + // Otherwise, be terse. + status_header( 500 ); + nocache_headers(); + header( 'Content-Type: text/html; charset=utf-8' ); + + wp_load_translations_early(); +?> + +> + + + <?php _e( 'Database Error' ); ?> + + + +

    + + +deprecated since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) ); + else + trigger_error( sprintf( __('%1$s is deprecated since version %2$s with no alternative available.'), $function, $version ) ); + } else { + if ( ! is_null( $replacement ) ) + trigger_error( sprintf( '%1$s is deprecated since version %2$s! Use %3$s instead.', $function, $version, $replacement ) ); + else + trigger_error( sprintf( '%1$s is deprecated since version %2$s with no alternative available.', $function, $version ) ); + } + } +} + +/** + * Marks a file as deprecated and informs when it has been used. + * + * There is a hook deprecated_file_included that will be called that can be used + * to get the backtrace up to what file and function included the deprecated + * file. + * + * The current behavior is to trigger a user error if WP_DEBUG is true. + * + * This function is to be used in every file that is deprecated. + * + * @package WordPress + * @subpackage Debug + * @since 2.5.0 + * @access private + * + * @uses do_action() Calls 'deprecated_file_included' and passes the file name, what to use instead, + * the version in which the file was deprecated, and any message regarding the change. + * @uses apply_filters() Calls 'deprecated_file_trigger_error' and expects boolean value of true to do + * trigger or false to not trigger error. + * + * @param string $file The file that was included + * @param string $version The version of WordPress that deprecated the file + * @param string $replacement Optional. The file that should have been included based on ABSPATH + * @param string $message Optional. A message regarding the change + */ +function _deprecated_file( $file, $version, $replacement = null, $message = '' ) { + + do_action( 'deprecated_file_included', $file, $replacement, $version, $message ); + + // Allow plugin to filter the output error trigger + if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) { + $message = empty( $message ) ? '' : ' ' . $message; + if ( function_exists( '__' ) ) { + if ( ! is_null( $replacement ) ) + trigger_error( sprintf( __('%1$s is deprecated since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message ); + else + trigger_error( sprintf( __('%1$s is deprecated since version %2$s with no alternative available.'), $file, $version ) . $message ); + } else { + if ( ! is_null( $replacement ) ) + trigger_error( sprintf( '%1$s is deprecated since version %2$s! Use %3$s instead.', $file, $version, $replacement ) . $message ); + else + trigger_error( sprintf( '%1$s is deprecated since version %2$s with no alternative available.', $file, $version ) . $message ); + } + } +} +/** + * Marks a function argument as deprecated and informs when it has been used. + * + * This function is to be used whenever a deprecated function argument is used. + * Before this function is called, the argument must be checked for whether it was + * used by comparing it to its default value or evaluating whether it is empty. + * For example: + * + * if ( !empty($deprecated) ) + * _deprecated_argument( __FUNCTION__, '3.0' ); + * + * + * There is a hook deprecated_argument_run that will be called that can be used + * to get the backtrace up to what file and function used the deprecated + * argument. + * + * The current behavior is to trigger a user error if WP_DEBUG is true. + * + * @package WordPress + * @subpackage Debug + * @since 3.0.0 + * @access private + * + * @uses do_action() Calls 'deprecated_argument_run' and passes the function name, a message on the change, + * and the version in which the argument was deprecated. + * @uses apply_filters() Calls 'deprecated_argument_trigger_error' and expects boolean value of true to do + * trigger or false to not trigger error. + * + * @param string $function The function that was called + * @param string $version The version of WordPress that deprecated the argument used + * @param string $message Optional. A message regarding the change. + */ +function _deprecated_argument( $function, $version, $message = null ) { + + do_action( 'deprecated_argument_run', $function, $message, $version ); + + // Allow plugin to filter the output error trigger + if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) { + if ( function_exists( '__' ) ) { + if ( ! is_null( $message ) ) + trigger_error( sprintf( __('%1$s was called with an argument that is deprecated since version %2$s! %3$s'), $function, $version, $message ) ); + else + trigger_error( sprintf( __('%1$s was called with an argument that is deprecated since version %2$s with no alternative available.'), $function, $version ) ); + } else { + if ( ! is_null( $message ) ) + trigger_error( sprintf( '%1$s was called with an argument that is deprecated since version %2$s! %3$s', $function, $version, $message ) ); + else + trigger_error( sprintf( '%1$s was called with an argument that is deprecated since version %2$s with no alternative available.', $function, $version ) ); + } + } +} + +/** + * Marks something as being incorrectly called. + * + * There is a hook doing_it_wrong_run that will be called that can be used + * to get the backtrace up to what file and function called the deprecated + * function. + * + * The current behavior is to trigger a user error if WP_DEBUG is true. + * + * @package WordPress + * @subpackage Debug + * @since 3.1.0 + * @access private + * + * @uses do_action() Calls 'doing_it_wrong_run' and passes the function arguments. + * @uses apply_filters() Calls 'doing_it_wrong_trigger_error' and expects boolean value of true to do + * trigger or false to not trigger error. + * + * @param string $function The function that was called. + * @param string $message A message explaining what has been done incorrectly. + * @param string $version The version of WordPress where the message was added. + */ +function _doing_it_wrong( $function, $message, $version ) { + + do_action( 'doing_it_wrong_run', $function, $message, $version ); + + // Allow plugin to filter the output error trigger + if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) { + if ( function_exists( '__' ) ) { + $version = is_null( $version ) ? '' : sprintf( __( '(This message was added in version %s.)' ), $version ); + $message .= ' ' . __( 'Please see Debugging in WordPress for more information.' ); + trigger_error( sprintf( __( '%1$s was called incorrectly. %2$s %3$s' ), $function, $message, $version ) ); + } else { + $version = is_null( $version ) ? '' : sprintf( '(This message was added in version %s.)', $version ); + $message .= ' Please see Debugging in WordPress for more information.'; + trigger_error( sprintf( '%1$s was called incorrectly. %2$s %3$s', $function, $message, $version ) ); + } + } +} + +/** + * Is the server running earlier than 1.5.0 version of lighttpd? + * + * @since 2.5.0 + * + * @return bool Whether the server is running lighttpd < 1.5.0 + */ +function is_lighttpd_before_150() { + $server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' ); + $server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : ''; + return 'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' ); +} + +/** + * Does the specified module exist in the Apache config? + * + * @since 2.5.0 + * + * @param string $mod e.g. mod_rewrite + * @param bool $default The default return value if the module is not found + * @return bool + */ +function apache_mod_loaded($mod, $default = false) { + global $is_apache; + + if ( !$is_apache ) + return false; + + if ( function_exists('apache_get_modules') ) { + $mods = apache_get_modules(); + if ( in_array($mod, $mods) ) + return true; + } elseif ( function_exists('phpinfo') ) { + ob_start(); + phpinfo(8); + $phpinfo = ob_get_clean(); + if ( false !== strpos($phpinfo, $mod) ) + return true; + } + return $default; +} + +/** + * Check if IIS 7+ supports pretty permalinks. + * + * @since 2.8.0 + * + * @return bool + */ +function iis7_supports_permalinks() { + global $is_iis7; + + $supports_permalinks = false; + if ( $is_iis7 ) { + /* First we check if the DOMDocument class exists. If it does not exist, then we cannot + * easily update the xml configuration file, hence we just bail out and tell user that + * pretty permalinks cannot be used. + * + * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When + * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'. + * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs + * via ISAPI then pretty permalinks will not work. + */ + $supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( php_sapi_name() == 'cgi-fcgi' ); + } + + return apply_filters('iis7_supports_permalinks', $supports_permalinks); +} + +/** + * File validates against allowed set of defined rules. + * + * A return value of '1' means that the $file contains either '..' or './'. A + * return value of '2' means that the $file contains ':' after the first + * character. A return value of '3' means that the file is not in the allowed + * files list. + * + * @since 1.2.0 + * + * @param string $file File path. + * @param array $allowed_files List of allowed files. + * @return int 0 means nothing is wrong, greater than 0 means something was wrong. + */ +function validate_file( $file, $allowed_files = '' ) { + if ( false !== strpos( $file, '..' ) ) + return 1; + + if ( false !== strpos( $file, './' ) ) + return 1; + + if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) ) + return 3; + + if (':' == substr( $file, 1, 1 ) ) + return 2; + + return 0; +} + +/** + * Determine if SSL is used. + * + * @since 2.6.0 + * + * @return bool True if SSL, false if not used. + */ +function is_ssl() { + if ( isset($_SERVER['HTTPS']) ) { + if ( 'on' == strtolower($_SERVER['HTTPS']) ) + return true; + if ( '1' == $_SERVER['HTTPS'] ) + return true; + } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) { + return true; + } + return false; +} + +/** + * Whether SSL login should be forced. + * + * @since 2.6.0 + * + * @param string|bool $force Optional. + * @return bool True if forced, false if not forced. + */ +function force_ssl_login( $force = null ) { + static $forced = false; + + if ( !is_null( $force ) ) { + $old_forced = $forced; + $forced = $force; + return $old_forced; + } + + return $forced; +} + +/** + * Whether to force SSL used for the Administration Screens. + * + * @since 2.6.0 + * + * @param string|bool $force + * @return bool True if forced, false if not forced. + */ +function force_ssl_admin( $force = null ) { + static $forced = false; + + if ( !is_null( $force ) ) { + $old_forced = $forced; + $forced = $force; + return $old_forced; + } + + return $forced; +} + +/** + * Guess the URL for the site. + * + * Will remove wp-admin links to retrieve only return URLs not in the wp-admin + * directory. + * + * @since 2.6.0 + * + * @return string + */ +function wp_guess_url() { + if ( defined('WP_SITEURL') && '' != WP_SITEURL ) { + $url = WP_SITEURL; + } else { + $abspath_fix = str_replace( '\\', '/', ABSPATH ); + $script_filename_dir = dirname( $_SERVER['SCRIPT_FILENAME'] ); + + // The request is for the admin + if ( strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) !== false || strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false ) { + $path = preg_replace( '#/(wp-admin/.*|wp-login.php)#i', '', $_SERVER['REQUEST_URI'] ); + + // The request is for a file in ABSPATH + } elseif ( $script_filename_dir . '/' == $abspath_fix ) { + // Strip off any file/query params in the path + $path = preg_replace( '#/[^/]*$#i', '', $_SERVER['PHP_SELF'] ); + + } else { + if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) { + // Request is hitting a file inside ABSPATH + $directory = str_replace( ABSPATH, '', $script_filename_dir ); + // Strip off the sub directory, and any file/query paramss + $path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ); + } elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) { + // Request is hitting a file above ABSPATH + $subdirectory = str_replace( $script_filename_dir, '', $abspath_fix ); + // Strip off any file/query params from the path, appending the sub directory to the install + $path = preg_replace( '#/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ) . $subdirectory; + } else { + $path = $_SERVER['REQUEST_URI']; + } + } + + $schema = is_ssl() ? 'https://' : 'http://'; // set_url_scheme() is not defined yet + $url = $schema . $_SERVER['HTTP_HOST'] . $path; + } + + return rtrim($url, '/'); +} + +/** + * Temporarily suspend cache additions. + * + * Stops more data being added to the cache, but still allows cache retrieval. + * This is useful for actions, such as imports, when a lot of data would otherwise + * be almost uselessly added to the cache. + * + * Suspension lasts for a single page load at most. Remember to call this + * function again if you wish to re-enable cache adds earlier. + * + * @since 3.3.0 + * + * @param bool $suspend Optional. Suspends additions if true, re-enables them if false. + * @return bool The current suspend setting + */ +function wp_suspend_cache_addition( $suspend = null ) { + static $_suspend = false; + + if ( is_bool( $suspend ) ) + $_suspend = $suspend; + + return $_suspend; +} + +/** + * Suspend cache invalidation. + * + * Turns cache invalidation on and off. Useful during imports where you don't wont to do invalidations + * every time a post is inserted. Callers must be sure that what they are doing won't lead to an inconsistent + * cache when invalidation is suspended. + * + * @since 2.7.0 + * + * @param bool $suspend Whether to suspend or enable cache invalidation + * @return bool The current suspend setting + */ +function wp_suspend_cache_invalidation($suspend = true) { + global $_wp_suspend_cache_invalidation; + + $current_suspend = $_wp_suspend_cache_invalidation; + $_wp_suspend_cache_invalidation = $suspend; + return $current_suspend; +} + +/** + * Whether a site is the main site of the current network. + * + * @since 3.0.0 + * + * @param int $site_id Optional. Site ID to test. Defaults to current site. + * @return bool True if $site_id is the main site of the network, or if not running multisite. + */ +function is_main_site( $site_id = null ) { + // This is the current network's information; 'site' is old terminology. + global $current_site; + + if ( ! is_multisite() ) + return true; + + if ( ! $site_id ) + $site_id = get_current_blog_id(); + + return (int) $site_id === (int) $current_site->blog_id; +} + +/** + * Whether a network is the main network of the multisite install. + * + * @since 3.7.0 + * + * @param int $network_id Optional. Network ID to test. Defaults to current network. + * @return bool True if $network_id is the main network, or if not running multisite. + */ +function is_main_network( $network_id = null ) { + global $current_site, $wpdb; + + if ( ! is_multisite() ) + return true; + + $current_network_id = (int) $current_site->id; + + if ( ! $network_id ) + $network_id = $current_network_id; + $network_id = (int) $network_id; + + if ( defined( 'PRIMARY_NETWORK_ID' ) ) + return $network_id === (int) PRIMARY_NETWORK_ID; + + if ( 1 === $current_network_id ) + return $network_id === $current_network_id; + + $primary_network_id = (int) wp_cache_get( 'primary_network_id', 'site-options' ); + + if ( $primary_network_id ) + return $network_id === $primary_network_id; + + $primary_network_id = (int) $wpdb->get_var( "SELECT id FROM $wpdb->site ORDER BY id LIMIT 1" ); + wp_cache_add( 'primary_network_id', $primary_network_id, 'site-options' ); + + return $network_id === $primary_network_id; +} + +/** + * Whether global terms are enabled. + * + * + * @since 3.0.0 + * @package WordPress + * + * @return bool True if multisite and global terms enabled + */ +function global_terms_enabled() { + if ( ! is_multisite() ) + return false; + + static $global_terms = null; + if ( is_null( $global_terms ) ) { + $filter = apply_filters( 'global_terms_enabled', null ); + if ( ! is_null( $filter ) ) + $global_terms = (bool) $filter; + else + $global_terms = (bool) get_site_option( 'global_terms_enabled', false ); + } + return $global_terms; +} + +/** + * gmt_offset modification for smart timezone handling. + * + * Overrides the gmt_offset option if we have a timezone_string available. + * + * @since 2.8.0 + * + * @return float|bool + */ +function wp_timezone_override_offset() { + if ( !$timezone_string = get_option( 'timezone_string' ) ) { + return false; + } + + $timezone_object = timezone_open( $timezone_string ); + $datetime_object = date_create(); + if ( false === $timezone_object || false === $datetime_object ) { + return false; + } + return round( timezone_offset_get( $timezone_object, $datetime_object ) / HOUR_IN_SECONDS, 2 ); +} + +/** + * Sort-helper for timezones. + * + * @since 2.9.0 + * + * @param array $a + * @param array $b + * @return int + */ +function _wp_timezone_choice_usort_callback( $a, $b ) { + // Don't use translated versions of Etc + if ( 'Etc' === $a['continent'] && 'Etc' === $b['continent'] ) { + // Make the order of these more like the old dropdown + if ( 'GMT+' === substr( $a['city'], 0, 4 ) && 'GMT+' === substr( $b['city'], 0, 4 ) ) { + return -1 * ( strnatcasecmp( $a['city'], $b['city'] ) ); + } + if ( 'UTC' === $a['city'] ) { + if ( 'GMT+' === substr( $b['city'], 0, 4 ) ) { + return 1; + } + return -1; + } + if ( 'UTC' === $b['city'] ) { + if ( 'GMT+' === substr( $a['city'], 0, 4 ) ) { + return -1; + } + return 1; + } + return strnatcasecmp( $a['city'], $b['city'] ); + } + if ( $a['t_continent'] == $b['t_continent'] ) { + if ( $a['t_city'] == $b['t_city'] ) { + return strnatcasecmp( $a['t_subcity'], $b['t_subcity'] ); + } + return strnatcasecmp( $a['t_city'], $b['t_city'] ); + } else { + // Force Etc to the bottom of the list + if ( 'Etc' === $a['continent'] ) { + return 1; + } + if ( 'Etc' === $b['continent'] ) { + return -1; + } + return strnatcasecmp( $a['t_continent'], $b['t_continent'] ); + } +} + +/** + * Gives a nicely formatted list of timezone strings. + * + * @since 2.9.0 + * + * @param string $selected_zone Selected Zone + * @return string + */ +function wp_timezone_choice( $selected_zone ) { + static $mo_loaded = false; + + $continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific'); + + // Load translations for continents and cities + if ( !$mo_loaded ) { + $locale = get_locale(); + $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo'; + load_textdomain( 'continents-cities', $mofile ); + $mo_loaded = true; + } + + $zonen = array(); + foreach ( timezone_identifiers_list() as $zone ) { + $zone = explode( '/', $zone ); + if ( !in_array( $zone[0], $continents ) ) { + continue; + } + + // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later + $exists = array( + 0 => ( isset( $zone[0] ) && $zone[0] ), + 1 => ( isset( $zone[1] ) && $zone[1] ), + 2 => ( isset( $zone[2] ) && $zone[2] ), + ); + $exists[3] = ( $exists[0] && 'Etc' !== $zone[0] ); + $exists[4] = ( $exists[1] && $exists[3] ); + $exists[5] = ( $exists[2] && $exists[3] ); + + $zonen[] = array( + 'continent' => ( $exists[0] ? $zone[0] : '' ), + 'city' => ( $exists[1] ? $zone[1] : '' ), + 'subcity' => ( $exists[2] ? $zone[2] : '' ), + 't_continent' => ( $exists[3] ? translate( str_replace( '_', ' ', $zone[0] ), 'continents-cities' ) : '' ), + 't_city' => ( $exists[4] ? translate( str_replace( '_', ' ', $zone[1] ), 'continents-cities' ) : '' ), + 't_subcity' => ( $exists[5] ? translate( str_replace( '_', ' ', $zone[2] ), 'continents-cities' ) : '' ) + ); + } + usort( $zonen, '_wp_timezone_choice_usort_callback' ); + + $structure = array(); + + if ( empty( $selected_zone ) ) { + $structure[] = ''; + } + + foreach ( $zonen as $key => $zone ) { + // Build value in an array to join later + $value = array( $zone['continent'] ); + + if ( empty( $zone['city'] ) ) { + // It's at the continent level (generally won't happen) + $display = $zone['t_continent']; + } else { + // It's inside a continent group + + // Continent optgroup + if ( !isset( $zonen[$key - 1] ) || $zonen[$key - 1]['continent'] !== $zone['continent'] ) { + $label = $zone['t_continent']; + $structure[] = ''; + } + + // Add the city to the value + $value[] = $zone['city']; + + $display = $zone['t_city']; + if ( !empty( $zone['subcity'] ) ) { + // Add the subcity to the value + $value[] = $zone['subcity']; + $display .= ' - ' . $zone['t_subcity']; + } + } + + // Build the value + $value = join( '/', $value ); + $selected = ''; + if ( $value === $selected_zone ) { + $selected = 'selected="selected" '; + } + $structure[] = '"; + + // Close continent optgroup + if ( !empty( $zone['city'] ) && ( !isset($zonen[$key + 1]) || (isset( $zonen[$key + 1] ) && $zonen[$key + 1]['continent'] !== $zone['continent']) ) ) { + $structure[] = ''; + } + } + + // Do UTC + $structure[] = ''; + $selected = ''; + if ( 'UTC' === $selected_zone ) + $selected = 'selected="selected" '; + $structure[] = ''; + $structure[] = ''; + + // Do manual UTC offsets + $structure[] = ''; + $offset_range = array (-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, + 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14); + foreach ( $offset_range as $offset ) { + if ( 0 <= $offset ) + $offset_name = '+' . $offset; + else + $offset_name = (string) $offset; + + $offset_value = $offset_name; + $offset_name = str_replace(array('.25','.5','.75'), array(':15',':30',':45'), $offset_name); + $offset_name = 'UTC' . $offset_name; + $offset_value = 'UTC' . $offset_value; + $selected = ''; + if ( $offset_value === $selected_zone ) + $selected = 'selected="selected" '; + $structure[] = '"; + + } + $structure[] = ''; + + return join( "\n", $structure ); +} + +/** + * Strip close comment and close php tags from file headers used by WP. + * See http://core.trac.wordpress.org/ticket/8497 + * + * @since 2.8.0 + * + * @param string $str + * @return string + */ +function _cleanup_header_comment($str) { + return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $str)); +} + +/** + * Permanently deletes posts, pages, attachments, and comments which have been in the trash for EMPTY_TRASH_DAYS. + * + * @since 2.9.0 + */ +function wp_scheduled_delete() { + global $wpdb; + + $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS ); + + $posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A); + + foreach ( (array) $posts_to_delete as $post ) { + $post_id = (int) $post['post_id']; + if ( !$post_id ) + continue; + + $del_post = get_post($post_id); + + if ( !$del_post || 'trash' != $del_post->post_status ) { + delete_post_meta($post_id, '_wp_trash_meta_status'); + delete_post_meta($post_id, '_wp_trash_meta_time'); + } else { + wp_delete_post($post_id); + } + } + + $comments_to_delete = $wpdb->get_results($wpdb->prepare("SELECT comment_id FROM $wpdb->commentmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A); + + foreach ( (array) $comments_to_delete as $comment ) { + $comment_id = (int) $comment['comment_id']; + if ( !$comment_id ) + continue; + + $del_comment = get_comment($comment_id); + + if ( !$del_comment || 'trash' != $del_comment->comment_approved ) { + delete_comment_meta($comment_id, '_wp_trash_meta_time'); + delete_comment_meta($comment_id, '_wp_trash_meta_status'); + } else { + wp_delete_comment($comment_id); + } + } +} + +/** + * Retrieve metadata from a file. + * + * Searches for metadata in the first 8kiB of a file, such as a plugin or theme. + * Each piece of metadata must be on its own line. Fields can not span multiple + * lines, the value will get cut at the end of the first line. + * + * If the file data is not within that first 8kiB, then the author should correct + * their plugin file and move the data headers to the top. + * + * @see http://codex.wordpress.org/File_Header + * + * @since 2.9.0 + * @param string $file Path to the file + * @param array $default_headers List of headers, in the format array('HeaderKey' => 'Header Name') + * @param string $context If specified adds filter hook "extra_{$context}_headers" + */ +function get_file_data( $file, $default_headers, $context = '' ) { + // We don't need to write to the file, so just open for reading. + $fp = fopen( $file, 'r' ); + + // Pull only the first 8kiB of the file in. + $file_data = fread( $fp, 8192 ); + + // PHP will close file handle, but we are good citizens. + fclose( $fp ); + + // Make sure we catch CR-only line endings. + $file_data = str_replace( "\r", "\n", $file_data ); + + if ( $context && $extra_headers = apply_filters( "extra_{$context}_headers", array() ) ) { + $extra_headers = array_combine( $extra_headers, $extra_headers ); // keys equal values + $all_headers = array_merge( $extra_headers, (array) $default_headers ); + } else { + $all_headers = $default_headers; + } + + foreach ( $all_headers as $field => $regex ) { + if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] ) + $all_headers[ $field ] = _cleanup_header_comment( $match[1] ); + else + $all_headers[ $field ] = ''; + } + + return $all_headers; +} + +/** + * Returns true. + * + * Useful for returning true to filters easily. + * + * @since 3.0.0 + * @see __return_false() + * @return bool true + */ +function __return_true() { + return true; +} + +/** + * Returns false. + * + * Useful for returning false to filters easily. + * + * @since 3.0.0 + * @see __return_true() + * @return bool false + */ +function __return_false() { + return false; +} + +/** + * Returns 0. + * + * Useful for returning 0 to filters easily. + * + * @since 3.0.0 + * @see __return_zero() + * @return int 0 + */ +function __return_zero() { + return 0; +} + +/** + * Returns an empty array. + * + * Useful for returning an empty array to filters easily. + * + * @since 3.0.0 + * @see __return_zero() + * @return array Empty array + */ +function __return_empty_array() { + return array(); +} + +/** + * Returns null. + * + * Useful for returning null to filters easily. + * + * @since 3.4.0 + * @return null + */ +function __return_null() { + return null; +} + +/** + * Returns an empty string. + * + * Useful for returning an empty string to filters easily. + * + * @since 3.7.0 + * @see __return_null() + * @return string Empty string + */ +function __return_empty_string() { + return ''; +} + +/** + * Send a HTTP header to disable content type sniffing in browsers which support it. + * + * @link http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx + * @link http://src.chromium.org/viewvc/chrome?view=rev&revision=6985 + * + * @since 3.0.0 + * @return none + */ +function send_nosniff_header() { + @header( 'X-Content-Type-Options: nosniff' ); +} + +/** + * Returns a MySQL expression for selecting the week number based on the start_of_week option. + * + * @internal + * @since 3.0.0 + * @param string $column + * @return string + */ +function _wp_mysql_week( $column ) { + switch ( $start_of_week = (int) get_option( 'start_of_week' ) ) { + default : + case 0 : + return "WEEK( $column, 0 )"; + case 1 : + return "WEEK( $column, 1 )"; + case 2 : + case 3 : + case 4 : + case 5 : + case 6 : + return "WEEK( DATE_SUB( $column, INTERVAL $start_of_week DAY ), 0 )"; + } +} + +/** + * Finds hierarchy loops using a callback function that maps object IDs to parent IDs. + * + * @since 3.1.0 + * @access private + * + * @param callback $callback function that accepts ( ID, $callback_args ) and outputs parent_ID + * @param int $start The ID to start the loop check at + * @param int $start_parent the parent_ID of $start to use instead of calling $callback( $start ). Use null to always use $callback + * @param array $callback_args optional additional arguments to send to $callback + * @return array IDs of all members of loop + */ +function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_args = array() ) { + $override = is_null( $start_parent ) ? array() : array( $start => $start_parent ); + + if ( !$arbitrary_loop_member = wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override, $callback_args ) ) + return array(); + + return wp_find_hierarchy_loop_tortoise_hare( $callback, $arbitrary_loop_member, $override, $callback_args, true ); +} + +/** + * Uses the "The Tortoise and the Hare" algorithm to detect loops. + * + * For every step of the algorithm, the hare takes two steps and the tortoise one. + * If the hare ever laps the tortoise, there must be a loop. + * + * @since 3.1.0 + * @access private + * + * @param callback $callback function that accepts ( ID, callback_arg, ... ) and outputs parent_ID + * @param int $start The ID to start the loop check at + * @param array $override an array of ( ID => parent_ID, ... ) to use instead of $callback + * @param array $callback_args optional additional arguments to send to $callback + * @param bool $_return_loop Return loop members or just detect presence of loop? + * Only set to true if you already know the given $start is part of a loop + * (otherwise the returned array might include branches) + * @return mixed scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if $_return_loop + */ +function wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override = array(), $callback_args = array(), $_return_loop = false ) { + $tortoise = $hare = $evanescent_hare = $start; + $return = array(); + + // Set evanescent_hare to one past hare + // Increment hare two steps + while ( + $tortoise + && + ( $evanescent_hare = isset( $override[$hare] ) ? $override[$hare] : call_user_func_array( $callback, array_merge( array( $hare ), $callback_args ) ) ) + && + ( $hare = isset( $override[$evanescent_hare] ) ? $override[$evanescent_hare] : call_user_func_array( $callback, array_merge( array( $evanescent_hare ), $callback_args ) ) ) + ) { + if ( $_return_loop ) + $return[$tortoise] = $return[$evanescent_hare] = $return[$hare] = true; + + // tortoise got lapped - must be a loop + if ( $tortoise == $evanescent_hare || $tortoise == $hare ) + return $_return_loop ? $return : $tortoise; + + // Increment tortoise by one step + $tortoise = isset( $override[$tortoise] ) ? $override[$tortoise] : call_user_func_array( $callback, array_merge( array( $tortoise ), $callback_args ) ); + } + + return false; +} + +/** + * Send a HTTP header to limit rendering of pages to same origin iframes. + * + * @link https://developer.mozilla.org/en/the_x-frame-options_response_header + * + * @since 3.1.3 + * @return none + */ +function send_frame_options_header() { + @header( 'X-Frame-Options: SAMEORIGIN' ); +} + +/** + * Retrieve a list of protocols to allow in HTML attributes. + * + * @since 3.3.0 + * @see wp_kses() + * @see esc_url() + * + * @return array Array of allowed protocols + */ +function wp_allowed_protocols() { + static $protocols; + + if ( empty( $protocols ) ) { + $protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp' ); + $protocols = apply_filters( 'kses_allowed_protocols', $protocols ); + } + + return $protocols; +} + +/** + * Return a comma separated string of functions that have been called to get to the current point in code. + * + * @link http://core.trac.wordpress.org/ticket/19589 + * @since 3.4 + * + * @param string $ignore_class A class to ignore all function calls within - useful when you want to just give info about the callee + * @param int $skip_frames A number of stack frames to skip - useful for unwinding back to the source of the issue + * @param bool $pretty Whether or not you want a comma separated string or raw array returned + * @return string|array Either a string containing a reversed comma separated trace or an array of individual calls. + */ +function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) { + if ( version_compare( PHP_VERSION, '5.2.5', '>=' ) ) + $trace = debug_backtrace( false ); + else + $trace = debug_backtrace(); + + $caller = array(); + $check_class = ! is_null( $ignore_class ); + $skip_frames++; // skip this function + + foreach ( $trace as $call ) { + if ( $skip_frames > 0 ) { + $skip_frames--; + } elseif ( isset( $call['class'] ) ) { + if ( $check_class && $ignore_class == $call['class'] ) + continue; // Filter out calls + + $caller[] = "{$call['class']}{$call['type']}{$call['function']}"; + } else { + if ( in_array( $call['function'], array( 'do_action', 'apply_filters' ) ) ) { + $caller[] = "{$call['function']}('{$call['args'][0]}')"; + } elseif ( in_array( $call['function'], array( 'include', 'include_once', 'require', 'require_once' ) ) ) { + $caller[] = $call['function'] . "('" . str_replace( array( WP_CONTENT_DIR, ABSPATH ) , '', $call['args'][0] ) . "')"; + } else { + $caller[] = $call['function']; + } + } + } + if ( $pretty ) + return join( ', ', array_reverse( $caller ) ); + else + return $caller; +} + +/** + * Retrieve ids that are not already present in the cache + * + * @since 3.4.0 + * + * @param array $object_ids ID list + * @param string $cache_key The cache bucket to check against + * + * @return array + */ +function _get_non_cached_ids( $object_ids, $cache_key ) { + $clean = array(); + foreach ( $object_ids as $id ) { + $id = (int) $id; + if ( !wp_cache_get( $id, $cache_key ) ) { + $clean[] = $id; + } + } + + return $clean; +} + +/** + * Test if the current device has the capability to upload files. + * + * @since 3.4.0 + * @access private + * + * @return bool true|false + */ +function _device_can_upload() { + if ( ! wp_is_mobile() ) + return true; + + $ua = $_SERVER['HTTP_USER_AGENT']; + + if ( strpos($ua, 'iPhone') !== false + || strpos($ua, 'iPad') !== false + || strpos($ua, 'iPod') !== false ) { + return preg_match( '#OS ([\d_]+) like Mac OS X#', $ua, $version ) && version_compare( $version[1], '6', '>=' ); + } + + return true; +} + +/** + * Test if a given path is a stream URL + * + * @param string $path The resource path or URL + * @return bool True if the path is a stream URL + */ +function wp_is_stream( $path ) { + $wrappers = stream_get_wrappers(); + $wrappers_re = '(' . join('|', $wrappers) . ')'; + + return preg_match( "!^$wrappers_re://!", $path ) === 1; +} + +/** + * Test if the supplied date is valid for the Gregorian calendar + * + * @since 3.5.0 + * + * @return bool true|false + */ +function wp_checkdate( $month, $day, $year, $source_date ) { + return apply_filters( 'wp_checkdate', checkdate( $month, $day, $year ), $source_date ); +} + +/** + * Load the auth check for monitoring whether the user is still logged in. + * + * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' ); + * + * This is disabled for certain screens where a login screen could cause an + * inconvenient interruption. A filter called wp_auth_check_load can be used + * for fine-grained control. + * + * @since 3.6.0 + */ +function wp_auth_check_load() { + if ( ! is_admin() && ! is_user_logged_in() ) + return; + + if ( defined( 'IFRAME_REQUEST' ) ) + return; + + $screen = get_current_screen(); + $hidden = array( 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' ); + $show = ! in_array( $screen->id, $hidden ); + + if ( apply_filters( 'wp_auth_check_load', $show, $screen ) ) { + wp_enqueue_style( 'wp-auth-check' ); + wp_enqueue_script( 'wp-auth-check' ); + + add_action( 'admin_print_footer_scripts', 'wp_auth_check_html', 5 ); + add_action( 'wp_print_footer_scripts', 'wp_auth_check_html', 5 ); + } +} + +/** + * Output the HTML that shows the wp-login dialog when the user is no longer logged in. + * + * @since 3.6.0 + */ +function wp_auth_check_html() { + $login_url = wp_login_url(); + $current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST']; + $same_domain = ( strpos( $login_url, $current_domain ) === 0 ); + + if ( $same_domain && force_ssl_login() && ! force_ssl_admin() ) + $same_domain = false; + + // Let plugins change this if they know better. + $same_domain = apply_filters( 'wp_auth_check_same_domain', $same_domain ); + $wrap_class = $same_domain ? 'hidden' : 'hidden fallback'; + + ?> +
    +
    +
    +
    + +
    + +
    +

    +

    +

    +
    +
    +
    + [\s\S]*<\/%1$s>|\s*\/>)', tag_escape( $tag ) ); +} + +/** + * Return a canonical form of the provided charset appropriate for passing to PHP + * functions such as htmlspecialchars() and charset html attributes. + * + * @link http://core.trac.wordpress.org/ticket/23688 + * @since 3.6.0 + * + * @param string A charset name + * @return string The canonical form of the charset + */ +function _canonical_charset( $charset ) { + if ( 'UTF-8' === $charset || 'utf-8' === $charset || 'utf8' === $charset || + 'UTF8' === $charset ) + return 'UTF-8'; + + if ( 'ISO-8859-1' === $charset || 'iso-8859-1' === $charset || + 'iso8859-1' === $charset || 'ISO8859-1' === $charset ) + return 'ISO-8859-1'; + + return $charset; +} + +/** + * Sets the mbstring internal encoding to a binary safe encoding whne func_overload is enabled. + * + * When mbstring.func_overload is in use for multi-byte encodings, the results from strlen() and + * similar functions respect the utf8 characters, causing binary data to return incorrect lengths. + * + * This function overrides the mbstring encoding to a binary-safe encoding, and resets it to the + * users expected encoding afterwards through the `reset_mbstring_encoding` function. + * + * It is safe to recursively call this function, however each `mbstring_binary_safe_encoding()` + * call must be followed up with an equal number of `reset_mbstring_encoding()` calls. + * + * @see reset_mbstring_encoding() + * + * @since 3.7.0 + * + * @param bool $reset Whether to reset the encoding back to a previously-set encoding. + */ +function mbstring_binary_safe_encoding( $reset = false ) { + static $encodings = array(); + static $overloaded = null; + + if ( is_null( $overloaded ) ) + $overloaded = function_exists( 'mb_internal_encoding' ) && ( ini_get( 'mbstring.func_overload' ) & 2 ); + + if ( false === $overloaded ) + return; + + if ( ! $reset ) { + $encoding = mb_internal_encoding(); + array_push( $encodings, $encoding ); + mb_internal_encoding( 'ISO-8859-1' ); + } + + if ( $reset && $encodings ) { + $encoding = array_pop( $encodings ); + mb_internal_encoding( $encoding ); + } +} + +/** + * Resets the mbstring internal encoding to a users previously set encoding. + * + * @see mbstring_binary_safe_encoding() + * + * @since 3.7.0 + */ +function reset_mbstring_encoding() { + mbstring_binary_safe_encoding( true ); +} diff --git a/sources/wp-includes/functions.wp-scripts.php b/sources/wp-includes/functions.wp-scripts.php new file mode 100644 index 0000000..e89553b --- /dev/null +++ b/sources/wp-includes/functions.wp-scripts.php @@ -0,0 +1,253 @@ +wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + + if ( !$handles ) + return array(); // No need to instantiate if nothing is there. + else + $wp_scripts = new WP_Scripts(); + } + + return $wp_scripts->do_items( $handles ); +} + +/** + * Register a new script. + * + * Registers a script to be linked later using the wp_enqueue_script() function. + * + * @see WP_Dependencies::add(), WP_Dependencies::add_data() + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.6.0 + * + * @param string $handle Name of the script. Should be unique. + * @param string $src Path to the script from the WordPress root directory. Example: '/js/myscript.js'. + * @param array $deps Optional. An array of registered script handles this script depends on. Set to false if there + * are no dependencies. Default empty array. + * @param string|bool $ver Optional. String specifying script version number, if it has one, which is concatenated + * to end of path as a query string. If no version is specified or set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. Default 'false'. Accepts 'false', 'null', or 'string'. + * @param bool $in_footer Optional. Whether to enqueue the script before or before . + * Default 'false'. Accepts 'false' or 'true'. + */ +function wp_register_script( $handle, $src, $deps = array(), $ver = false, $in_footer = false ) { + global $wp_scripts; + if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_scripts = new WP_Scripts(); + } + + $wp_scripts->add( $handle, $src, $deps, $ver ); + if ( $in_footer ) + $wp_scripts->add_data( $handle, 'group', 1 ); +} + +/** + * Localize a script. + * + * Works only if the script has already been added. + * + * Accepts an associative array $l10n and creates a JavaScript object: + * + * "$object_name" = { + * key: value, + * key: value, + * ... + * } + * + * + * @see WP_Dependencies::localize() + * @link http://core.trac.wordpress.org/ticket/11520 + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.6.0 + * + * @param string $handle Script handle the data will be attached to. + * @param string $object_name Name for the JavaScript object. Passed directly, so it should be qualified JS variable. + * Example: '/[a-zA-Z0-9_]+/'. + * @param array $l10n The data itself. The data can be either a single or multi-dimensional array. + * @return bool True if the script was successfully localized, false otherwise. + */ +function wp_localize_script( $handle, $object_name, $l10n ) { + global $wp_scripts; + if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + + return false; + } + + return $wp_scripts->localize( $handle, $object_name, $l10n ); +} + +/** + * Remove a registered script. + * + * Note: there are intentional safeguards in place to prevent critical admin scripts, + * such as jQuery core, from being unregistered. + * + * @see WP_Dependencies::remove() + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.6.0 + * + * @param string $handle Name of the script to be removed. + */ +function wp_deregister_script( $handle ) { + global $wp_scripts; + if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_scripts = new WP_Scripts(); + } + + /** + * Do not allow accidental or negligent de-registering of critical scripts in the admin. + * Show minimal remorse if the correct hook is used. + */ + $current_filter = current_filter(); + if ( ( is_admin() && 'admin_enqueue_scripts' !== $current_filter ) || + ( 'wp-login.php' === $GLOBALS['pagenow'] && 'login_enqueue_scripts' !== $current_filter ) + ) { + $no = array( + 'jquery', 'jquery-core', 'jquery-migrate', 'jquery-ui-core', 'jquery-ui-accordion', + 'jquery-ui-autocomplete', 'jquery-ui-button', 'jquery-ui-datepicker', 'jquery-ui-dialog', + 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-menu', 'jquery-ui-mouse', + 'jquery-ui-position', 'jquery-ui-progressbar', 'jquery-ui-resizable', 'jquery-ui-selectable', + 'jquery-ui-slider', 'jquery-ui-sortable', 'jquery-ui-spinner', 'jquery-ui-tabs', + 'jquery-ui-tooltip', 'jquery-ui-widget', 'underscore', 'backbone', + ); + + if ( in_array( $handle, $no ) ) { + $message = sprintf( __( 'Do not deregister the %1$s script in the administration area. To target the frontend theme, use the %2$s hook.' ), + "$handle", 'wp_enqueue_scripts' ); + _doing_it_wrong( __FUNCTION__, $message, '3.6' ); + return; + } + } + + $wp_scripts->remove( $handle ); +} + +/** + * Enqueue a script. + * + * Registers the script if $src provided (does NOT overwrite), and enqueues it. + * + * @see WP_Dependencies::add(), WP_Dependencies::add_data(), WP_Dependencies::enqueue() + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.6.0 + + * @param string $handle Name of the script. + * @param string|bool $src Path to the script from the root directory of WordPress. Example: '/js/myscript.js'. + * @param array $deps An array of registered handles this script depends on. Default empty array. + * @param string|bool $ver Optional. String specifying the script version number, if it has one. This parameter + * is used to ensure that the correct version is sent to the client regardless of caching, + * and so should be included if a version number is available and makes sense for the script. + * @param bool $in_footer Optional. Whether to enqueue the script before or before . + * Default 'false'. Accepts 'false' or 'true'. + */ +function wp_enqueue_script( $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) { + global $wp_scripts; + if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_scripts = new WP_Scripts(); + } + + if ( $src ) { + $_handle = explode('?', $handle); + $wp_scripts->add( $_handle[0], $src, $deps, $ver ); + if ( $in_footer ) + $wp_scripts->add_data( $_handle[0], 'group', 1 ); + } + $wp_scripts->enqueue( $handle ); +} + +/** + * Remove a previously enqueued script. + * + * @see WP_Dependencies::dequeue() + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 3.1.0 + * + * @param string $handle Name of the script to be removed. + */ +function wp_dequeue_script( $handle ) { + global $wp_scripts; + if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_scripts = new WP_Scripts(); + } + + $wp_scripts->dequeue( $handle ); +} + +/** + * Check whether a script has been added to the queue. + * + * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts. + * + * @since 2.8.0 + * @since 3.5.0 'enqueued' added as an alias of the 'queue' list. + * + * @param string $handle Name of the script. + * @param string $list Optional. Status of the script to check. Default 'enqueued'. + * Accepts 'enqueued', 'registered', 'queue', 'to_do', and 'done'. + * @return bool Whether the script script is queued. + */ +function wp_script_is( $handle, $list = 'enqueued' ) { + global $wp_scripts; + if ( ! is_a( $wp_scripts, 'WP_Scripts' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_scripts = new WP_Scripts(); + } + + return (bool) $wp_scripts->query( $handle, $list ); +} diff --git a/sources/wp-includes/functions.wp-styles.php b/sources/wp-includes/functions.wp-styles.php new file mode 100644 index 0000000..df45bf5 --- /dev/null +++ b/sources/wp-includes/functions.wp-styles.php @@ -0,0 +1,242 @@ +wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + + if ( !$handles ) + return array(); // No need to instantiate if nothing is there. + else + $wp_styles = new WP_Styles(); + } + + return $wp_styles->do_items( $handles ); +} + +/** + * Add extra CSS styles to a registered stylesheet. + * + * Styles will only be added if the stylesheet in already in the queue. + * Accepts a string $data containing the CSS. If two or more CSS code blocks + * are added to the same stylesheet $handle, they will be printed in the order + * they were added, i.e. the latter added styles can redeclare the previous. + * + * @see WP_Styles::add_inline_style() + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 3.3.0 + * + * @param string $handle Name of the stylesheet to add the extra styles to. Must be lowercase. + * @param string $data String containing the CSS styles to be added. + * @return bool True on success, false on failure. + */ +function wp_add_inline_style( $handle, $data ) { + global $wp_styles; + if ( ! is_a( $wp_styles, 'WP_Styles' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_styles = new WP_Styles(); + } + + if ( false !== stripos( $data, '' ) ) { + _doing_it_wrong( __FUNCTION__, 'Do not pass style tags to wp_add_inline_style().', '3.7' ); + $data = trim( preg_replace( '#]*>(.*)#is', '$1', $data ) ); + } + + return $wp_styles->add_inline_style( $handle, $data ); +} + +/** + * Register a CSS stylesheet. + * + * @see WP_Dependencies::add() + * @link http://www.w3.org/TR/CSS2/media.html#media-types List of CSS media types. + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 2.6.0 + * + * @param string $handle Name of the stylesheet. + * @param string|bool $src Path to the stylesheet from the WordPress root directory. Example: '/css/mystyle.css'. + * @param array $deps An array of registered style handles this stylesheet depends on. Default empty array. + * @param string|bool $ver String specifying the stylesheet version number. Used to ensure that the correct version + * is sent to the client regardless of caching. Default 'false'. Accepts 'false', 'null', or 'string'. + * @param string $media Optional. The media for which this stylesheet has been defined. + * Default 'all'. Accepts 'all', 'aural', 'braille', 'handheld', 'projection', 'print', + * 'screen', 'tty', or 'tv'. + */ +function wp_register_style( $handle, $src, $deps = array(), $ver = false, $media = 'all' ) { + global $wp_styles; + if ( ! is_a( $wp_styles, 'WP_Styles' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_styles = new WP_Styles(); + } + + $wp_styles->add( $handle, $src, $deps, $ver, $media ); +} + +/** + * Remove a registered stylesheet. + * + * @see WP_Dependencies::remove() + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 2.1.0 + * + * @param string $handle Name of the stylesheet to be removed. + */ +function wp_deregister_style( $handle ) { + global $wp_styles; + if ( ! is_a( $wp_styles, 'WP_Styles' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_styles = new WP_Styles(); + } + + $wp_styles->remove( $handle ); +} + +/** + * Enqueue a CSS stylesheet. + * + * Registers the style if source provided (does NOT overwrite) and enqueues. + * + * @see WP_Dependencies::add(), WP_Dependencies::enqueue() + * @link http://www.w3.org/TR/CSS2/media.html#media-types List of CSS media types. + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 2.6.0 + * + * @param string $handle Name of the stylesheet. + * @param string|bool $src Path to the stylesheet from the root directory of WordPress. Example: '/css/mystyle.css'. + * @param array $deps An array of registered style handles this stylesheet depends on. Default empty array. + * @param string|bool $ver String specifying the stylesheet version number, if it has one. This parameter is used + * to ensure that the correct version is sent to the client regardless of caching, and so + * should be included if a version number is available and makes sense for the stylesheet. + * @param string $media Optional. The media for which this stylesheet has been defined. + * Default 'all'. Accepts 'all', 'aural', 'braille', 'handheld', 'projection', 'print', + * 'screen', 'tty', or 'tv'. + */ +function wp_enqueue_style( $handle, $src = false, $deps = array(), $ver = false, $media = 'all' ) { + global $wp_styles; + if ( ! is_a( $wp_styles, 'WP_Styles' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_styles = new WP_Styles(); + } + + if ( $src ) { + $_handle = explode('?', $handle); + $wp_styles->add( $_handle[0], $src, $deps, $ver, $media ); + } + $wp_styles->enqueue( $handle ); +} + +/** + * Remove a previously enqueued CSS stylesheet. + * + * @see WP_Dependencies::dequeue() + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 3.1.0 + * + * @param string $handle Name of the stylesheet to be removed. + */ +function wp_dequeue_style( $handle ) { + global $wp_styles; + if ( ! is_a( $wp_styles, 'WP_Styles' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_styles = new WP_Styles(); + } + + $wp_styles->dequeue( $handle ); +} + +/** + * Check whether a CSS stylesheet has been added to the queue. + * + * @global WP_Styles $wp_styles The WP_Styles object for printing styles. + * + * @since 2.8.0 + * + * @param string $handle Name of the stylesheet. + * @param string $list Optional. Status of the stylesheet to check. Default 'enqueued'. + * Accepts 'enqueued', 'registered', 'queue', 'to_do', and 'done'. + * @return bool Whether style is queued. + */ +function wp_style_is( $handle, $list = 'enqueued' ) { + global $wp_styles; + if ( ! is_a( $wp_styles, 'WP_Styles' ) ) { + if ( ! did_action( 'init' ) ) + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Scripts and styles should not be registered or enqueued until the %1$s, %2$s, or %3$s hooks.' ), + 'wp_enqueue_scripts', 'admin_enqueue_scripts', 'login_enqueue_scripts' ), '3.3' ); + $wp_styles = new WP_Styles(); + } + + return (bool) $wp_styles->query( $handle, $list ); +} + +/** + * Add metadata to a CSS stylesheet. + * + * Works only if the stylesheet has already been added. + * + * Possible values for $key and $value: + * 'conditional' string Comments for IE 6, lte IE 7 etc. + * 'rtl' bool|string To declare an RTL stylesheet. + * 'suffix' string Optional suffix, used in combination with RTL. + * 'alt' bool For rel="alternate stylesheet". + * 'title' string For preferred/alternate stylesheets. + * + * @see WP_Dependency::add_data() + * + * @since 3.6.0 + * + * @param string $handle Name of the stylesheet. + * @param string $key Name of data point for which we're storing a value. + * Accepts 'conditional', 'rtl' and 'suffix', 'alt' and 'title'. + * @param mixed $data String containing the CSS data to be added. + * @return bool True on success, false on failure. + */ +function wp_style_add_data( $handle, $key, $value ) { + global $wp_styles; + return $wp_styles->add_data( $handle, $key, $value ); +} diff --git a/sources/wp-includes/general-template.php b/sources/wp-includes/general-template.php new file mode 100644 index 0000000..90e19d4 --- /dev/null +++ b/sources/wp-includes/general-template.php @@ -0,0 +1,2372 @@ + + + + '; + } else { + $form = ''; + } + } + + $result = apply_filters( 'get_search_form', $form ); + if ( null === $result ) + $result = $form; + + if ( $echo ) + echo $result; + else + return $result; +} + +/** + * Display the Log In/Out link. + * + * Displays a link, which allows users to navigate to the Log In page to log in + * or log out depending on whether they are currently logged in. + * + * @since 1.5.0 + * @uses apply_filters() Calls 'loginout' hook on HTML link content. + * + * @param string $redirect Optional path to redirect to on login/logout. + * @param boolean $echo Default to echo and not return the link. + * @return string|null String when retrieving, null when displaying. + */ +function wp_loginout($redirect = '', $echo = true) { + if ( ! is_user_logged_in() ) + $link = '' . __('Log in') . ''; + else + $link = '' . __('Log out') . ''; + + if ( $echo ) + echo apply_filters('loginout', $link); + else + return apply_filters('loginout', $link); +} + +/** + * Returns the Log Out URL. + * + * Returns the URL that allows the user to log out of the site. + * + * @since 2.7.0 + * @uses wp_nonce_url() To protect against CSRF. + * @uses site_url() To generate the log out URL. + * @uses apply_filters() calls 'logout_url' hook on final logout URL. + * + * @param string $redirect Path to redirect to on logout. + * @return string A log out URL. + */ +function wp_logout_url($redirect = '') { + $args = array( 'action' => 'logout' ); + if ( !empty($redirect) ) { + $args['redirect_to'] = urlencode( $redirect ); + } + + $logout_url = add_query_arg($args, site_url('wp-login.php', 'login')); + $logout_url = wp_nonce_url( $logout_url, 'log-out' ); + + return apply_filters('logout_url', $logout_url, $redirect); +} + +/** + * Returns the Log In URL. + * + * Returns the URL that allows the user to log in to the site. + * + * @since 2.7.0 + * @uses site_url() To generate the log in URL. + * @uses apply_filters() calls 'login_url' hook on final login URL. + * + * @param string $redirect Path to redirect to on login. + * @param bool $force_reauth Whether to force reauthorization, even if a cookie is present. Default is false. + * @return string A log in URL. + */ +function wp_login_url($redirect = '', $force_reauth = false) { + $login_url = site_url('wp-login.php', 'login'); + + if ( !empty($redirect) ) + $login_url = add_query_arg('redirect_to', urlencode($redirect), $login_url); + + if ( $force_reauth ) + $login_url = add_query_arg('reauth', '1', $login_url); + + return apply_filters('login_url', $login_url, $redirect); +} + +/** + * Returns the user registration URL. + * + * Returns the URL that allows the user to register on the site. + * + * @since 3.6.0 + * @uses site_url() To generate the registration URL. + * @uses apply_filters() calls 'register_url' hook on final URL. + * + * @return string + */ +function wp_registration_url() { + return apply_filters( 'register_url', site_url( 'wp-login.php?action=register', 'login' ) ); +} + +/** + * Provides a simple login form for use anywhere within WordPress. By default, it echoes + * the HTML immediately. Pass array('echo'=>false) to return the string instead. + * + * @since 3.0.0 + * @param array $args Configuration options to modify the form output. + * @return string|null String when retrieving, null when displaying. + */ +function wp_login_form( $args = array() ) { + $defaults = array( + 'echo' => true, + 'redirect' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], // Default redirect is back to the current page + 'form_id' => 'loginform', + 'label_username' => __( 'Username' ), + 'label_password' => __( 'Password' ), + 'label_remember' => __( 'Remember Me' ), + 'label_log_in' => __( 'Log In' ), + 'id_username' => 'user_login', + 'id_password' => 'user_pass', + 'id_remember' => 'rememberme', + 'id_submit' => 'wp-submit', + 'remember' => true, + 'value_username' => '', + 'value_remember' => false, // Set this to true to default the "Remember me" checkbox to checked + ); + $args = wp_parse_args( $args, apply_filters( 'login_form_defaults', $defaults ) ); + + $form = ' +
    + ' . apply_filters( 'login_form_top', '', $args ) . ' + + + ' . apply_filters( 'login_form_middle', '', $args ) . ' + ' . ( $args['remember'] ? '' : '' ) . ' + + ' . apply_filters( 'login_form_bottom', '', $args ) . ' +
    '; + + if ( $args['echo'] ) + echo $form; + else + return $form; +} + +/** + * Returns the Lost Password URL. + * + * Returns the URL that allows the user to retrieve the lost password + * + * @since 2.8.0 + * @uses site_url() To generate the lost password URL + * @uses apply_filters() calls 'lostpassword_url' hook on the lostpassword url + * + * @param string $redirect Path to redirect to on login. + * @return string Lost password URL. + */ +function wp_lostpassword_url( $redirect = '' ) { + $args = array( 'action' => 'lostpassword' ); + if ( !empty($redirect) ) { + $args['redirect_to'] = $redirect; + } + + $lostpassword_url = add_query_arg( $args, network_site_url('wp-login.php', 'login') ); + return apply_filters( 'lostpassword_url', $lostpassword_url, $redirect ); +} + +/** + * Display the Registration or Admin link. + * + * Display a link which allows the user to navigate to the registration page if + * not logged in and registration is enabled or to the dashboard if logged in. + * + * @since 1.5.0 + * @uses apply_filters() Calls 'register' hook on register / admin link content. + * + * @param string $before Text to output before the link (defaults to
  • ). + * @param string $after Text to output after the link (defaults to
  • ). + * @param boolean $echo Default to echo and not return the link. + * @return string|null String when retrieving, null when displaying. + */ +function wp_register( $before = '
  • ', $after = '
  • ', $echo = true ) { + + if ( ! is_user_logged_in() ) { + if ( get_option('users_can_register') ) + $link = $before . '' . __('Register') . '' . $after; + else + $link = ''; + } else { + $link = $before . '' . __('Site Admin') . '' . $after; + } + + if ( $echo ) + echo apply_filters('register', $link); + else + return apply_filters('register', $link); +} + +/** + * Theme container function for the 'wp_meta' action. + * + * The 'wp_meta' action can have several purposes, depending on how you use it, + * but one purpose might have been to allow for theme switching. + * + * @since 1.5.0 + * @link http://trac.wordpress.org/ticket/1458 Explanation of 'wp_meta' action. + * @uses do_action() Calls 'wp_meta' hook. + */ +function wp_meta() { + do_action('wp_meta'); +} + +/** + * Display information about the blog. + * + * @see get_bloginfo() For possible values for the parameter. + * @since 0.71 + * + * @param string $show What to display. + */ +function bloginfo( $show='' ) { + echo get_bloginfo( $show, 'display' ); +} + +/** + * Retrieve information about the blog. + * + * Some show parameter values are deprecated and will be removed in future + * versions. These options will trigger the _deprecated_argument() function. + * The deprecated blog info options are listed in the function contents. + * + * The possible values for the 'show' parameter are listed below. + *
      + *
    1. url - Blog URI to homepage.
    2. + *
    3. wpurl - Blog URI path to WordPress.
    4. + *
    5. description - Secondary title
    6. + *
    + * + * The feed URL options can be retrieved from 'rdf_url' (RSS 0.91), + * 'rss_url' (RSS 1.0), 'rss2_url' (RSS 2.0), or 'atom_url' (Atom feed). The + * comment feeds can be retrieved from the 'comments_atom_url' (Atom comment + * feed) or 'comments_rss2_url' (RSS 2.0 comment feed). + * + * @since 0.71 + * + * @param string $show Blog info to retrieve. + * @param string $filter How to filter what is retrieved. + * @return string Mostly string values, might be empty. + */ +function get_bloginfo( $show = '', $filter = 'raw' ) { + + switch( $show ) { + case 'home' : // DEPRECATED + case 'siteurl' : // DEPRECATED + _deprecated_argument( __FUNCTION__, '2.2', sprintf( __('The %s option is deprecated for the family of bloginfo() functions.' ), $show ) . ' ' . sprintf( __( 'Use the %s option instead.' ), 'url' ) ); + case 'url' : + $output = home_url(); + break; + case 'wpurl' : + $output = site_url(); + break; + case 'description': + $output = get_option('blogdescription'); + break; + case 'rdf_url': + $output = get_feed_link('rdf'); + break; + case 'rss_url': + $output = get_feed_link('rss'); + break; + case 'rss2_url': + $output = get_feed_link('rss2'); + break; + case 'atom_url': + $output = get_feed_link('atom'); + break; + case 'comments_atom_url': + $output = get_feed_link('comments_atom'); + break; + case 'comments_rss2_url': + $output = get_feed_link('comments_rss2'); + break; + case 'pingback_url': + $output = site_url( 'xmlrpc.php' ); + break; + case 'stylesheet_url': + $output = get_stylesheet_uri(); + break; + case 'stylesheet_directory': + $output = get_stylesheet_directory_uri(); + break; + case 'template_directory': + case 'template_url': + $output = get_template_directory_uri(); + break; + case 'admin_email': + $output = get_option('admin_email'); + break; + case 'charset': + $output = get_option('blog_charset'); + if ('' == $output) $output = 'UTF-8'; + break; + case 'html_type' : + $output = get_option('html_type'); + break; + case 'version': + global $wp_version; + $output = $wp_version; + break; + case 'language': + $output = get_locale(); + $output = str_replace('_', '-', $output); + break; + case 'text_direction': + //_deprecated_argument( __FUNCTION__, '2.2', sprintf( __('The %s option is deprecated for the family of bloginfo() functions.' ), $show ) . ' ' . sprintf( __( 'Use the %s function instead.' ), 'is_rtl()' ) ); + if ( function_exists( 'is_rtl' ) ) { + $output = is_rtl() ? 'rtl' : 'ltr'; + } else { + $output = 'ltr'; + } + break; + case 'name': + default: + $output = get_option('blogname'); + break; + } + + $url = true; + if (strpos($show, 'url') === false && + strpos($show, 'directory') === false && + strpos($show, 'home') === false) + $url = false; + + if ( 'display' == $filter ) { + if ( $url ) + $output = apply_filters('bloginfo_url', $output, $show); + else + $output = apply_filters('bloginfo', $output, $show); + } + + return $output; +} + +/** + * Display or retrieve page title for all areas of blog. + * + * By default, the page title will display the separator before the page title, + * so that the blog title will be before the page title. This is not good for + * title display, since the blog title shows up on most tabs and not what is + * important, which is the page that the user is looking at. + * + * There are also SEO benefits to having the blog title after or to the 'right' + * or the page title. However, it is mostly common sense to have the blog title + * to the right with most browsers supporting tabs. You can achieve this by + * using the seplocation parameter and setting the value to 'right'. This change + * was introduced around 2.5.0, in case backwards compatibility of themes is + * important. + * + * @since 1.0.0 + * + * @param string $sep Optional, default is '»'. How to separate the various items within the page title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @param string $seplocation Optional. Direction to display title, 'right'. + * @return string|null String on retrieve, null when displaying. + */ +function wp_title($sep = '»', $display = true, $seplocation = '') { + global $wpdb, $wp_locale; + + $m = get_query_var('m'); + $year = get_query_var('year'); + $monthnum = get_query_var('monthnum'); + $day = get_query_var('day'); + $search = get_query_var('s'); + $title = ''; + + $t_sep = '%WP_TITILE_SEP%'; // Temporary separator, for accurate flipping, if necessary + + // If there is a post + if ( is_single() || ( is_home() && !is_front_page() ) || ( is_page() && !is_front_page() ) ) { + $title = single_post_title( '', false ); + } + + // If there's a post type archive + if ( is_post_type_archive() ) { + $post_type = get_query_var( 'post_type' ); + if ( is_array( $post_type ) ) + $post_type = reset( $post_type ); + $post_type_object = get_post_type_object( $post_type ); + if ( ! $post_type_object->has_archive ) + $title = post_type_archive_title( '', false ); + } + + // If there's a category or tag + if ( is_category() || is_tag() ) { + $title = single_term_title( '', false ); + } + + // If there's a taxonomy + if ( is_tax() ) { + $term = get_queried_object(); + if ( $term ) { + $tax = get_taxonomy( $term->taxonomy ); + $title = single_term_title( $tax->labels->name . $t_sep, false ); + } + } + + // If there's an author + if ( is_author() ) { + $author = get_queried_object(); + if ( $author ) + $title = $author->display_name; + } + + // Post type archives with has_archive should override terms. + if ( is_post_type_archive() && $post_type_object->has_archive ) + $title = post_type_archive_title( '', false ); + + // If there's a month + if ( is_archive() && !empty($m) ) { + $my_year = substr($m, 0, 4); + $my_month = $wp_locale->get_month(substr($m, 4, 2)); + $my_day = intval(substr($m, 6, 2)); + $title = $my_year . ( $my_month ? $t_sep . $my_month : '' ) . ( $my_day ? $t_sep . $my_day : '' ); + } + + // If there's a year + if ( is_archive() && !empty($year) ) { + $title = $year; + if ( !empty($monthnum) ) + $title .= $t_sep . $wp_locale->get_month($monthnum); + if ( !empty($day) ) + $title .= $t_sep . zeroise($day, 2); + } + + // If it's a search + if ( is_search() ) { + /* translators: 1: separator, 2: search phrase */ + $title = sprintf(__('Search Results %1$s %2$s'), $t_sep, strip_tags($search)); + } + + // If it's a 404 page + if ( is_404() ) { + $title = __('Page not found'); + } + + $prefix = ''; + if ( !empty($title) ) + $prefix = " $sep "; + + // Determines position of the separator and direction of the breadcrumb + if ( 'right' == $seplocation ) { // sep on right, so reverse the order + $title_array = explode( $t_sep, $title ); + $title_array = array_reverse( $title_array ); + $title = implode( " $sep ", $title_array ) . $prefix; + } else { + $title_array = explode( $t_sep, $title ); + $title = $prefix . implode( " $sep ", $title_array ); + } + + $title = apply_filters('wp_title', $title, $sep, $seplocation); + + // Send it out + if ( $display ) + echo $title; + else + return $title; + +} + +/** + * Display or retrieve page title for post. + * + * This is optimized for single.php template file for displaying the post title. + * + * It does not support placing the separator after the title, but by leaving the + * prefix parameter empty, you can set the title separator manually. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 0.71 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @return string|null Title when retrieving, null when displaying or failure. + */ +function single_post_title($prefix = '', $display = true) { + $_post = get_queried_object(); + + if ( !isset($_post->post_title) ) + return; + + $title = apply_filters('single_post_title', $_post->post_title, $_post); + if ( $display ) + echo $prefix . $title; + else + return $prefix . $title; +} + +/** + * Display or retrieve title for a post type archive. + * + * This is optimized for archive.php and archive-{$post_type}.php template files + * for displaying the title of the post type. + * + * @since 3.1.0 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @return string|null Title when retrieving, null when displaying or failure. + */ +function post_type_archive_title( $prefix = '', $display = true ) { + if ( ! is_post_type_archive() ) + return; + + $post_type = get_query_var( 'post_type' ); + if ( is_array( $post_type ) ) + $post_type = reset( $post_type ); + + $post_type_obj = get_post_type_object( $post_type ); + $title = apply_filters('post_type_archive_title', $post_type_obj->labels->name ); + + if ( $display ) + echo $prefix . $title; + else + return $prefix . $title; +} + +/** + * Display or retrieve page title for category archive. + * + * This is useful for category template file or files, because it is optimized + * for category page title and with less overhead than {@link wp_title()}. + * + * It does not support placing the separator after the title, but by leaving the + * prefix parameter empty, you can set the title separator manually. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 0.71 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @return string|null Title when retrieving, null when displaying or failure. + */ +function single_cat_title( $prefix = '', $display = true ) { + return single_term_title( $prefix, $display ); +} + +/** + * Display or retrieve page title for tag post archive. + * + * Useful for tag template files for displaying the tag page title. It has less + * overhead than {@link wp_title()}, because of its limited implementation. + * + * It does not support placing the separator after the title, but by leaving the + * prefix parameter empty, you can set the title separator manually. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 2.3.0 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @return string|null Title when retrieving, null when displaying or failure. + */ +function single_tag_title( $prefix = '', $display = true ) { + return single_term_title( $prefix, $display ); +} + +/** + * Display or retrieve page title for taxonomy term archive. + * + * Useful for taxonomy term template files for displaying the taxonomy term page title. + * It has less overhead than {@link wp_title()}, because of its limited implementation. + * + * It does not support placing the separator after the title, but by leaving the + * prefix parameter empty, you can set the title separator manually. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 3.1.0 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @return string|null Title when retrieving, null when displaying or failure. + */ +function single_term_title( $prefix = '', $display = true ) { + $term = get_queried_object(); + + if ( !$term ) + return; + + if ( is_category() ) + $term_name = apply_filters( 'single_cat_title', $term->name ); + elseif ( is_tag() ) + $term_name = apply_filters( 'single_tag_title', $term->name ); + elseif ( is_tax() ) + $term_name = apply_filters( 'single_term_title', $term->name ); + else + return; + + if ( empty( $term_name ) ) + return; + + if ( $display ) + echo $prefix . $term_name; + else + return $prefix . $term_name; +} + +/** + * Display or retrieve page title for post archive based on date. + * + * Useful for when the template only needs to display the month and year, if + * either are available. Optimized for just this purpose, so if it is all that + * is needed, should be better than {@link wp_title()}. + * + * It does not support placing the separator after the title, but by leaving the + * prefix parameter empty, you can set the title separator manually. The prefix + * does not automatically place a space between the prefix, so if there should + * be a space, the parameter value will need to have it at the end. + * + * @since 0.71 + * + * @param string $prefix Optional. What to display before the title. + * @param bool $display Optional, default is true. Whether to display or retrieve title. + * @return string|null Title when retrieving, null when displaying or failure. + */ +function single_month_title($prefix = '', $display = true ) { + global $wp_locale; + + $m = get_query_var('m'); + $year = get_query_var('year'); + $monthnum = get_query_var('monthnum'); + + if ( !empty($monthnum) && !empty($year) ) { + $my_year = $year; + $my_month = $wp_locale->get_month($monthnum); + } elseif ( !empty($m) ) { + $my_year = substr($m, 0, 4); + $my_month = $wp_locale->get_month(substr($m, 4, 2)); + } + + if ( empty($my_month) ) + return false; + + $result = $prefix . $my_month . $prefix . $my_year; + + if ( !$display ) + return $result; + echo $result; +} + +/** + * Retrieve archive link content based on predefined or custom code. + * + * The format can be one of four styles. The 'link' for head element, 'option' + * for use in the select element, 'html' for use in list (either ol or ul HTML + * elements). Custom content is also supported using the before and after + * parameters. + * + * The 'link' format uses the link HTML element with the archives + * relationship. The before and after parameters are not used. The text + * parameter is used to describe the link. + * + * The 'option' format uses the option HTML element for use in select element. + * The value is the url parameter and the before and after parameters are used + * between the text description. + * + * The 'html' format, which is the default, uses the li HTML element for use in + * the list HTML elements. The before parameter is before the link and the after + * parameter is after the closing link. + * + * The custom format uses the before parameter before the link ('a' HTML + * element) and the after parameter after the closing link tag. If the above + * three values for the format are not used, then custom format is assumed. + * + * @since 1.0.0 + * + * @param string $url URL to archive. + * @param string $text Archive text description. + * @param string $format Optional, default is 'html'. Can be 'link', 'option', 'html', or custom. + * @param string $before Optional. + * @param string $after Optional. + * @return string HTML link content for archive. + */ +function get_archives_link($url, $text, $format = 'html', $before = '', $after = '') { + $text = wptexturize($text); + $url = esc_url($url); + + if ('link' == $format) + $link_html = "\t\n"; + elseif ('option' == $format) + $link_html = "\t\n"; + elseif ('html' == $format) + $link_html = "\t
  • $before$text$after
  • \n"; + else // custom + $link_html = "\t$before$text$after\n"; + + $link_html = apply_filters( 'get_archives_link', $link_html ); + + return $link_html; +} + +/** + * Display archive links based on type and format. + * + * The 'type' argument offers a few choices and by default will display monthly + * archive links. The other options for values are 'daily', 'weekly', 'monthly', + * 'yearly', 'postbypost' or 'alpha'. Both 'postbypost' and 'alpha' display the + * same archive link list, the difference between the two is that 'alpha' + * will order by post title and 'postbypost' will order by post date. + * + * The date archives will logically display dates with links to the archive post + * page. The 'postbypost' and 'alpha' values for 'type' argument will display + * the post titles. + * + * The 'limit' argument will only display a limited amount of links, specified + * by the 'limit' integer value. By default, there is no limit. The + * 'show_post_count' argument will show how many posts are within the archive. + * By default, the 'show_post_count' argument is set to false. + * + * For the 'format', 'before', and 'after' arguments, see {@link + * get_archives_link()}. The values of these arguments have to do with that + * function. + * + * @since 1.2.0 + * + * @param string|array $args Optional. Override defaults. + * @return string|null String when retrieving, null when displaying. + */ +function wp_get_archives($args = '') { + global $wpdb, $wp_locale; + + $defaults = array( + 'type' => 'monthly', 'limit' => '', + 'format' => 'html', 'before' => '', + 'after' => '', 'show_post_count' => false, + 'echo' => 1, 'order' => 'DESC', + ); + + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + if ( '' == $type ) + $type = 'monthly'; + + if ( '' != $limit ) { + $limit = absint($limit); + $limit = ' LIMIT '.$limit; + } + + $order = strtoupper( $order ); + if ( $order !== 'ASC' ) + $order = 'DESC'; + + // this is what will separate dates on weekly archive links + $archive_week_separator = '–'; + + // over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride + $archive_date_format_over_ride = 0; + + // options for daily archive (only if you over-ride the general date format) + $archive_day_date_format = 'Y/m/d'; + + // options for weekly archive (only if you over-ride the general date format) + $archive_week_start_date_format = 'Y/m/d'; + $archive_week_end_date_format = 'Y/m/d'; + + if ( !$archive_date_format_over_ride ) { + $archive_day_date_format = get_option('date_format'); + $archive_week_start_date_format = get_option('date_format'); + $archive_week_end_date_format = get_option('date_format'); + } + + $where = apply_filters( 'getarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r ); + $join = apply_filters( 'getarchives_join', '', $r ); + + $output = ''; + + $last_changed = wp_cache_get( 'last_changed', 'posts' ); + if ( ! $last_changed ) { + $last_changed = microtime(); + wp_cache_set( 'last_changed', $last_changed, 'posts' ); + } + + if ( 'monthly' == $type ) { + $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date $order $limit"; + $key = md5( $query ); + $key = "wp_get_archives:$key:$last_changed"; + if ( ! $results = wp_cache_get( $key, 'posts' ) ) { + $results = $wpdb->get_results( $query ); + wp_cache_set( $key, $results, 'posts' ); + } + if ( $results ) { + $afterafter = $after; + foreach ( (array) $results as $result ) { + $url = get_month_link( $result->year, $result->month ); + /* translators: 1: month name, 2: 4-digit year */ + $text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($result->month), $result->year); + if ( $show_post_count ) + $after = ' ('.$result->posts.')' . $afterafter; + $output .= get_archives_link($url, $text, $format, $before, $after); + } + } + } elseif ('yearly' == $type) { + $query = "SELECT YEAR(post_date) AS `year`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date) ORDER BY post_date $order $limit"; + $key = md5( $query ); + $key = "wp_get_archives:$key:$last_changed"; + if ( ! $results = wp_cache_get( $key, 'posts' ) ) { + $results = $wpdb->get_results( $query ); + wp_cache_set( $key, $results, 'posts' ); + } + if ( $results ) { + $afterafter = $after; + foreach ( (array) $results as $result) { + $url = get_year_link($result->year); + $text = sprintf('%d', $result->year); + if ($show_post_count) + $after = ' ('.$result->posts.')' . $afterafter; + $output .= get_archives_link($url, $text, $format, $before, $after); + } + } + } elseif ( 'daily' == $type ) { + $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date), DAYOFMONTH(post_date) ORDER BY post_date $order $limit"; + $key = md5( $query ); + $key = "wp_get_archives:$key:$last_changed"; + if ( ! $results = wp_cache_get( $key, 'posts' ) ) { + $results = $wpdb->get_results( $query ); + $cache[ $key ] = $results; + wp_cache_set( $key, $results, 'posts' ); + } + if ( $results ) { + $afterafter = $after; + foreach ( (array) $results as $result ) { + $url = get_day_link($result->year, $result->month, $result->dayofmonth); + $date = sprintf('%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth); + $text = mysql2date($archive_day_date_format, $date); + if ($show_post_count) + $after = ' ('.$result->posts.')'.$afterafter; + $output .= get_archives_link($url, $text, $format, $before, $after); + } + } + } elseif ( 'weekly' == $type ) { + $week = _wp_mysql_week( '`post_date`' ); + $query = "SELECT DISTINCT $week AS `week`, YEAR( `post_date` ) AS `yr`, DATE_FORMAT( `post_date`, '%Y-%m-%d' ) AS `yyyymmdd`, count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit"; + $key = md5( $query ); + $key = "wp_get_archives:$key:$last_changed"; + if ( ! $results = wp_cache_get( $key, 'posts' ) ) { + $results = $wpdb->get_results( $query ); + wp_cache_set( $key, $results, 'posts' ); + } + $arc_w_last = ''; + $afterafter = $after; + if ( $results ) { + foreach ( (array) $results as $result ) { + if ( $result->week != $arc_w_last ) { + $arc_year = $result->yr; + $arc_w_last = $result->week; + $arc_week = get_weekstartend($result->yyyymmdd, get_option('start_of_week')); + $arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']); + $arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']); + $url = sprintf('%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&', '=', $result->week); + $text = $arc_week_start . $archive_week_separator . $arc_week_end; + if ($show_post_count) + $after = ' ('.$result->posts.')'.$afterafter; + $output .= get_archives_link($url, $text, $format, $before, $after); + } + } + } + } elseif ( ( 'postbypost' == $type ) || ('alpha' == $type) ) { + $orderby = ('alpha' == $type) ? 'post_title ASC ' : 'post_date DESC '; + $query = "SELECT * FROM $wpdb->posts $join $where ORDER BY $orderby $limit"; + $key = md5( $query ); + $key = "wp_get_archives:$key:$last_changed"; + if ( ! $results = wp_cache_get( $key, 'posts' ) ) { + $results = $wpdb->get_results( $query ); + wp_cache_set( $key, $results, 'posts' ); + } + if ( $results ) { + foreach ( (array) $results as $result ) { + if ( $result->post_date != '0000-00-00 00:00:00' ) { + $url = get_permalink( $result ); + if ( $result->post_title ) { + /** This filter is documented in wp-includes/post-template.php */ + $text = strip_tags( apply_filters( 'the_title', $result->post_title, $result->ID ) ); + } else { + $text = $result->ID; + } + $output .= get_archives_link($url, $text, $format, $before, $after); + } + } + } + } + if ( $echo ) + echo $output; + else + return $output; +} + +/** + * Get number of days since the start of the week. + * + * @since 1.5.0 + * + * @param int $num Number of day. + * @return int Days since the start of the week. + */ +function calendar_week_mod($num) { + $base = 7; + return ($num - $base*floor($num/$base)); +} + +/** + * Display calendar with days that have posts as links. + * + * The calendar is cached, which will be retrieved, if it exists. If there are + * no posts for the month, then it will not be displayed. + * + * @since 1.0.0 + * @uses calendar_week_mod() + * + * @param bool $initial Optional, default is true. Use initial calendar names. + * @param bool $echo Optional, default is true. Set to false for return. + * @return string|null String when retrieving, null when displaying. + */ +function get_calendar($initial = true, $echo = true) { + global $wpdb, $m, $monthnum, $year, $wp_locale, $posts; + + $cache = array(); + $key = md5( $m . $monthnum . $year ); + if ( $cache = wp_cache_get( 'get_calendar', 'calendar' ) ) { + if ( is_array($cache) && isset( $cache[ $key ] ) ) { + if ( $echo ) { + echo apply_filters( 'get_calendar', $cache[$key] ); + return; + } else { + return apply_filters( 'get_calendar', $cache[$key] ); + } + } + } + + if ( !is_array($cache) ) + $cache = array(); + + // Quick check. If we have no posts at all, abort! + if ( !$posts ) { + $gotsome = $wpdb->get_var("SELECT 1 as test FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1"); + if ( !$gotsome ) { + $cache[ $key ] = ''; + wp_cache_set( 'get_calendar', $cache, 'calendar' ); + return; + } + } + + if ( isset($_GET['w']) ) + $w = ''.intval($_GET['w']); + + // week_begins = 0 stands for Sunday + $week_begins = intval(get_option('start_of_week')); + + // Let's figure out when we are + if ( !empty($monthnum) && !empty($year) ) { + $thismonth = ''.zeroise(intval($monthnum), 2); + $thisyear = ''.intval($year); + } elseif ( !empty($w) ) { + // We need to get the month from MySQL + $thisyear = ''.intval(substr($m, 0, 4)); + $d = (($w - 1) * 7) + 6; //it seems MySQL's weeks disagree with PHP's + $thismonth = $wpdb->get_var("SELECT DATE_FORMAT((DATE_ADD('{$thisyear}0101', INTERVAL $d DAY) ), '%m')"); + } elseif ( !empty($m) ) { + $thisyear = ''.intval(substr($m, 0, 4)); + if ( strlen($m) < 6 ) + $thismonth = '01'; + else + $thismonth = ''.zeroise(intval(substr($m, 4, 2)), 2); + } else { + $thisyear = gmdate('Y', current_time('timestamp')); + $thismonth = gmdate('m', current_time('timestamp')); + } + + $unixmonth = mktime(0, 0 , 0, $thismonth, 1, $thisyear); + $last_day = date('t', $unixmonth); + + // Get the next and previous month and year with at least one post + $previous = $wpdb->get_row("SELECT MONTH(post_date) AS month, YEAR(post_date) AS year + FROM $wpdb->posts + WHERE post_date < '$thisyear-$thismonth-01' + AND post_type = 'post' AND post_status = 'publish' + ORDER BY post_date DESC + LIMIT 1"); + $next = $wpdb->get_row("SELECT MONTH(post_date) AS month, YEAR(post_date) AS year + FROM $wpdb->posts + WHERE post_date > '$thisyear-$thismonth-{$last_day} 23:59:59' + AND post_type = 'post' AND post_status = 'publish' + ORDER BY post_date ASC + LIMIT 1"); + + /* translators: Calendar caption: 1: month name, 2: 4-digit year */ + $calendar_caption = _x('%1$s %2$s', 'calendar caption'); + $calendar_output = ' + + + '; + + $myweek = array(); + + for ( $wdcount=0; $wdcount<=6; $wdcount++ ) { + $myweek[] = $wp_locale->get_weekday(($wdcount+$week_begins)%7); + } + + foreach ( $myweek as $wd ) { + $day_name = (true == $initial) ? $wp_locale->get_weekday_initial($wd) : $wp_locale->get_weekday_abbrev($wd); + $wd = esc_attr($wd); + $calendar_output .= "\n\t\t"; + } + + $calendar_output .= ' + + + + + '; + + if ( $previous ) { + $calendar_output .= "\n\t\t".''; + } else { + $calendar_output .= "\n\t\t".''; + } + + $calendar_output .= "\n\t\t".''; + + if ( $next ) { + $calendar_output .= "\n\t\t".''; + } else { + $calendar_output .= "\n\t\t".''; + } + + $calendar_output .= ' + + + + + '; + + // Get days with posts + $dayswithposts = $wpdb->get_results("SELECT DISTINCT DAYOFMONTH(post_date) + FROM $wpdb->posts WHERE post_date >= '{$thisyear}-{$thismonth}-01 00:00:00' + AND post_type = 'post' AND post_status = 'publish' + AND post_date <= '{$thisyear}-{$thismonth}-{$last_day} 23:59:59'", ARRAY_N); + if ( $dayswithposts ) { + foreach ( (array) $dayswithposts as $daywith ) { + $daywithpost[] = $daywith[0]; + } + } else { + $daywithpost = array(); + } + + if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false || stripos($_SERVER['HTTP_USER_AGENT'], 'camino') !== false || stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) + $ak_title_separator = "\n"; + else + $ak_title_separator = ', '; + + $ak_titles_for_day = array(); + $ak_post_titles = $wpdb->get_results("SELECT ID, post_title, DAYOFMONTH(post_date) as dom " + ."FROM $wpdb->posts " + ."WHERE post_date >= '{$thisyear}-{$thismonth}-01 00:00:00' " + ."AND post_date <= '{$thisyear}-{$thismonth}-{$last_day} 23:59:59' " + ."AND post_type = 'post' AND post_status = 'publish'" + ); + if ( $ak_post_titles ) { + foreach ( (array) $ak_post_titles as $ak_post_title ) { + + /** This filter is documented in wp-includes/post-template.php */ + $post_title = esc_attr( apply_filters( 'the_title', $ak_post_title->post_title, $ak_post_title->ID ) ); + + if ( empty($ak_titles_for_day['day_'.$ak_post_title->dom]) ) + $ak_titles_for_day['day_'.$ak_post_title->dom] = ''; + if ( empty($ak_titles_for_day["$ak_post_title->dom"]) ) // first one + $ak_titles_for_day["$ak_post_title->dom"] = $post_title; + else + $ak_titles_for_day["$ak_post_title->dom"] .= $ak_title_separator . $post_title; + } + } + + // See how much we should pad in the beginning + $pad = calendar_week_mod(date('w', $unixmonth)-$week_begins); + if ( 0 != $pad ) + $calendar_output .= "\n\t\t".''; + + $daysinmonth = intval(date('t', $unixmonth)); + for ( $day = 1; $day <= $daysinmonth; ++$day ) { + if ( isset($newrow) && $newrow ) + $calendar_output .= "\n\t\n\t\n\t\t"; + $newrow = false; + + if ( $day == gmdate('j', current_time('timestamp')) && $thismonth == gmdate('m', current_time('timestamp')) && $thisyear == gmdate('Y', current_time('timestamp')) ) + $calendar_output .= ''; + + if ( 6 == calendar_week_mod(date('w', mktime(0, 0 , 0, $thismonth, $day, $thisyear))-$week_begins) ) + $newrow = true; + } + + $pad = 7 - calendar_week_mod(date('w', mktime(0, 0 , 0, $thismonth, $day, $thisyear))-$week_begins); + if ( $pad != 0 && $pad != 7 ) + $calendar_output .= "\n\t\t".''; + + $calendar_output .= "\n\t\n\t\n\t
    ' . sprintf($calendar_caption, $wp_locale->get_month($thismonth), date('Y', $unixmonth)) . '
    $day_name
    « ' . $wp_locale->get_month_abbrev($wp_locale->get_month($previous->month)) . '  ' . $wp_locale->get_month_abbrev($wp_locale->get_month($next->month)) . ' » 
     
    '; + else + $calendar_output .= ''; + + if ( in_array($day, $daywithpost) ) // any posts today? + $calendar_output .= '$day"; + else + $calendar_output .= $day; + $calendar_output .= ' 
    "; + + $cache[ $key ] = $calendar_output; + wp_cache_set( 'get_calendar', $cache, 'calendar' ); + + if ( $echo ) + echo apply_filters( 'get_calendar', $calendar_output ); + else + return apply_filters( 'get_calendar', $calendar_output ); + +} + +/** + * Purge the cached results of get_calendar. + * + * @see get_calendar + * @since 2.1.0 + */ +function delete_get_calendar_cache() { + wp_cache_delete( 'get_calendar', 'calendar' ); +} +add_action( 'save_post', 'delete_get_calendar_cache' ); +add_action( 'delete_post', 'delete_get_calendar_cache' ); +add_action( 'update_option_start_of_week', 'delete_get_calendar_cache' ); +add_action( 'update_option_gmt_offset', 'delete_get_calendar_cache' ); + +/** + * Display all of the allowed tags in HTML format with attributes. + * + * This is useful for displaying in the comment area, which elements and + * attributes are supported. As well as any plugins which want to display it. + * + * @since 1.0.1 + * @uses $allowedtags + * + * @return string HTML allowed tags entity encoded. + */ +function allowed_tags() { + global $allowedtags; + $allowed = ''; + foreach ( (array) $allowedtags as $tag => $attributes ) { + $allowed .= '<'.$tag; + if ( 0 < count($attributes) ) { + foreach ( $attributes as $attribute => $limits ) { + $allowed .= ' '.$attribute.'=""'; + } + } + $allowed .= '> '; + } + return htmlentities($allowed); +} + +/***** Date/Time tags *****/ + +/** + * Outputs the date in iso8601 format for xml files. + * + * @since 1.0.0 + */ +function the_date_xml() { + echo mysql2date( 'Y-m-d', get_post()->post_date, false ); +} + +/** + * Display or Retrieve the date the current $post was written (once per date) + * + * Will only output the date if the current post's date is different from the + * previous one output. + * + * i.e. Only one date listing will show per day worth of posts shown in the loop, even if the + * function is called several times for each post. + * + * HTML output can be filtered with 'the_date'. + * Date string output can be filtered with 'get_the_date'. + * + * @since 0.71 + * @uses get_the_date() + * @param string $d Optional. PHP date format defaults to the date_format option if not specified. + * @param string $before Optional. Output before the date. + * @param string $after Optional. Output after the date. + * @param bool $echo Optional, default is display. Whether to echo the date or return it. + * @return string|null Null if displaying, string if retrieving. + */ +function the_date( $d = '', $before = '', $after = '', $echo = true ) { + global $currentday, $previousday; + $the_date = ''; + if ( $currentday != $previousday ) { + $the_date .= $before; + $the_date .= get_the_date( $d ); + $the_date .= $after; + $previousday = $currentday; + + $the_date = apply_filters('the_date', $the_date, $d, $before, $after); + + if ( $echo ) + echo $the_date; + else + return $the_date; + } + + return null; +} + +/** + * Retrieve the date the current $post was written. + * + * Unlike the_date() this function will always return the date. + * Modify output with 'get_the_date' filter. + * + * @since 3.0.0 + * + * @param string $d Optional. PHP date format defaults to the date_format option if not specified. + * @return string|null Null if displaying, string if retrieving. + */ +function get_the_date( $d = '' ) { + $post = get_post(); + $the_date = ''; + + if ( '' == $d ) + $the_date .= mysql2date(get_option('date_format'), $post->post_date); + else + $the_date .= mysql2date($d, $post->post_date); + + return apply_filters('get_the_date', $the_date, $d); +} + +/** + * Display the date on which the post was last modified. + * + * @since 2.1.0 + * + * @param string $d Optional. PHP date format defaults to the date_format option if not specified. + * @param string $before Optional. Output before the date. + * @param string $after Optional. Output after the date. + * @param bool $echo Optional, default is display. Whether to echo the date or return it. + * @return string|null Null if displaying, string if retrieving. + */ +function the_modified_date($d = '', $before='', $after='', $echo = true) { + + $the_modified_date = $before . get_the_modified_date($d) . $after; + $the_modified_date = apply_filters('the_modified_date', $the_modified_date, $d, $before, $after); + + if ( $echo ) + echo $the_modified_date; + else + return $the_modified_date; + +} + +/** + * Retrieve the date on which the post was last modified. + * + * @since 2.1.0 + * + * @param string $d Optional. PHP date format. Defaults to the "date_format" option + * @return string + */ +function get_the_modified_date($d = '') { + if ( '' == $d ) + $the_time = get_post_modified_time(get_option('date_format'), null, null, true); + else + $the_time = get_post_modified_time($d, null, null, true); + return apply_filters('get_the_modified_date', $the_time, $d); +} + +/** + * Display the time at which the post was written. + * + * @since 0.71 + * + * @param string $d Either 'G', 'U', or php date format. + */ +function the_time( $d = '' ) { + echo apply_filters('the_time', get_the_time( $d ), $d); +} + +/** + * Retrieve the time at which the post was written. + * + * @since 1.5.0 + * + * @param string $d Optional Either 'G', 'U', or php date format defaults to the value specified in the time_format option. + * @param int|object $post Optional post ID or object. Default is global $post object. + * @return string + */ +function get_the_time( $d = '', $post = null ) { + $post = get_post($post); + + if ( '' == $d ) + $the_time = get_post_time(get_option('time_format'), false, $post, true); + else + $the_time = get_post_time($d, false, $post, true); + return apply_filters('get_the_time', $the_time, $d, $post); +} + +/** + * Retrieve the time at which the post was written. + * + * @since 2.0.0 + * + * @param string $d Optional Either 'G', 'U', or php date format. + * @param bool $gmt Optional, default is false. Whether to return the gmt time. + * @param int|object $post Optional post ID or object. Default is global $post object. + * @param bool $translate Whether to translate the time string + * @return string + */ +function get_post_time( $d = 'U', $gmt = false, $post = null, $translate = false ) { // returns timestamp + $post = get_post($post); + + if ( $gmt ) + $time = $post->post_date_gmt; + else + $time = $post->post_date; + + $time = mysql2date($d, $time, $translate); + return apply_filters('get_post_time', $time, $d, $gmt); +} + +/** + * Display the time at which the post was last modified. + * + * @since 2.0.0 + * + * @param string $d Optional Either 'G', 'U', or php date format defaults to the value specified in the time_format option. + */ +function the_modified_time($d = '') { + echo apply_filters('the_modified_time', get_the_modified_time($d), $d); +} + +/** + * Retrieve the time at which the post was last modified. + * + * @since 2.0.0 + * + * @param string $d Optional Either 'G', 'U', or php date format defaults to the value specified in the time_format option. + * @return string + */ +function get_the_modified_time($d = '') { + if ( '' == $d ) + $the_time = get_post_modified_time(get_option('time_format'), null, null, true); + else + $the_time = get_post_modified_time($d, null, null, true); + return apply_filters('get_the_modified_time', $the_time, $d); +} + +/** + * Retrieve the time at which the post was last modified. + * + * @since 2.0.0 + * + * @param string $d Optional, default is 'U'. Either 'G', 'U', or php date format. + * @param bool $gmt Optional, default is false. Whether to return the gmt time. + * @param int|object $post Optional, default is global post object. A post_id or post object + * @param bool $translate Optional, default is false. Whether to translate the result + * @return string Returns timestamp + */ +function get_post_modified_time( $d = 'U', $gmt = false, $post = null, $translate = false ) { + $post = get_post($post); + + if ( $gmt ) + $time = $post->post_modified_gmt; + else + $time = $post->post_modified; + $time = mysql2date($d, $time, $translate); + + return apply_filters('get_post_modified_time', $time, $d, $gmt); +} + +/** + * Display the weekday on which the post was written. + * + * @since 0.71 + * @uses $wp_locale + * @uses $post + */ +function the_weekday() { + global $wp_locale; + $the_weekday = $wp_locale->get_weekday( mysql2date( 'w', get_post()->post_date, false ) ); + $the_weekday = apply_filters('the_weekday', $the_weekday); + echo $the_weekday; +} + +/** + * Display the weekday on which the post was written. + * + * Will only output the weekday if the current post's weekday is different from + * the previous one output. + * + * @since 0.71 + * + * @param string $before Optional Output before the date. + * @param string $after Optional Output after the date. + */ +function the_weekday_date($before='',$after='') { + global $wp_locale, $currentday, $previousweekday; + $the_weekday_date = ''; + if ( $currentday != $previousweekday ) { + $the_weekday_date .= $before; + $the_weekday_date .= $wp_locale->get_weekday( mysql2date( 'w', get_post()->post_date, false ) ); + $the_weekday_date .= $after; + $previousweekday = $currentday; + } + $the_weekday_date = apply_filters('the_weekday_date', $the_weekday_date, $before, $after); + echo $the_weekday_date; +} + +/** + * Fire the wp_head action + * + * @since 1.2.0 + * @uses do_action() Calls 'wp_head' hook. + */ +function wp_head() { + do_action('wp_head'); +} + +/** + * Fire the wp_footer action + * + * @since 1.5.1 + * @uses do_action() Calls 'wp_footer' hook. + */ +function wp_footer() { + do_action('wp_footer'); +} + +/** + * Display the links to the general feeds. + * + * @since 2.8.0 + * + * @param array $args Optional arguments. + */ +function feed_links( $args = array() ) { + if ( !current_theme_supports('automatic-feed-links') ) + return; + + $defaults = array( + /* translators: Separator between blog name and feed type in feed links */ + 'separator' => _x('»', 'feed link'), + /* translators: 1: blog title, 2: separator (raquo) */ + 'feedtitle' => __('%1$s %2$s Feed'), + /* translators: 1: blog title, 2: separator (raquo) */ + 'comstitle' => __('%1$s %2$s Comments Feed'), + ); + + $args = wp_parse_args( $args, $defaults ); + + echo '\n"; + echo '\n"; +} + +/** + * Display the links to the extra feeds such as category feeds. + * + * @since 2.8.0 + * + * @param array $args Optional arguments. + */ +function feed_links_extra( $args = array() ) { + $defaults = array( + /* translators: Separator between blog name and feed type in feed links */ + 'separator' => _x('»', 'feed link'), + /* translators: 1: blog name, 2: separator(raquo), 3: post title */ + 'singletitle' => __('%1$s %2$s %3$s Comments Feed'), + /* translators: 1: blog name, 2: separator(raquo), 3: category name */ + 'cattitle' => __('%1$s %2$s %3$s Category Feed'), + /* translators: 1: blog name, 2: separator(raquo), 3: tag name */ + 'tagtitle' => __('%1$s %2$s %3$s Tag Feed'), + /* translators: 1: blog name, 2: separator(raquo), 3: author name */ + 'authortitle' => __('%1$s %2$s Posts by %3$s Feed'), + /* translators: 1: blog name, 2: separator(raquo), 3: search phrase */ + 'searchtitle' => __('%1$s %2$s Search Results for “%3$s” Feed'), + /* translators: 1: blog name, 2: separator(raquo), 3: post type name */ + 'posttypetitle' => __('%1$s %2$s %3$s Feed'), + ); + + $args = wp_parse_args( $args, $defaults ); + + if ( is_singular() ) { + $id = 0; + $post = get_post( $id ); + + if ( comments_open() || pings_open() || $post->comment_count > 0 ) { + $title = sprintf( $args['singletitle'], get_bloginfo('name'), $args['separator'], esc_html( get_the_title() ) ); + $href = get_post_comments_feed_link( $post->ID ); + } + } elseif ( is_post_type_archive() ) { + $post_type = get_query_var( 'post_type' ); + if ( is_array( $post_type ) ) + $post_type = reset( $post_type ); + + $post_type_obj = get_post_type_object( $post_type ); + $title = sprintf( $args['posttypetitle'], get_bloginfo( 'name' ), $args['separator'], $post_type_obj->labels->name ); + $href = get_post_type_archive_feed_link( $post_type_obj->name ); + } elseif ( is_category() ) { + $term = get_queried_object(); + + if ( $term ) { + $title = sprintf( $args['cattitle'], get_bloginfo('name'), $args['separator'], $term->name ); + $href = get_category_feed_link( $term->term_id ); + } + } elseif ( is_tag() ) { + $term = get_queried_object(); + + if ( $term ) { + $title = sprintf( $args['tagtitle'], get_bloginfo('name'), $args['separator'], $term->name ); + $href = get_tag_feed_link( $term->term_id ); + } + } elseif ( is_author() ) { + $author_id = intval( get_query_var('author') ); + + $title = sprintf( $args['authortitle'], get_bloginfo('name'), $args['separator'], get_the_author_meta( 'display_name', $author_id ) ); + $href = get_author_feed_link( $author_id ); + } elseif ( is_search() ) { + $title = sprintf( $args['searchtitle'], get_bloginfo('name'), $args['separator'], get_search_query( false ) ); + $href = get_search_feed_link(); + } elseif ( is_post_type_archive() ) { + $title = sprintf( $args['posttypetitle'], get_bloginfo('name'), $args['separator'], post_type_archive_title( '', false ) ); + $post_type_obj = get_queried_object(); + if ( $post_type_obj ) + $href = get_post_type_archive_feed_link( $post_type_obj->name ); + } + + if ( isset($title) && isset($href) ) + echo '' . "\n"; +} + +/** + * Display the link to the Really Simple Discovery service endpoint. + * + * @link http://archipelago.phrasewise.com/rsd + * @since 2.0.0 + */ +function rsd_link() { + echo '\n"; +} + +/** + * Display the link to the Windows Live Writer manifest file. + * + * @link http://msdn.microsoft.com/en-us/library/bb463265.aspx + * @since 2.3.1 + */ +function wlwmanifest_link() { + echo ' ' . "\n"; +} + +/** + * Display a noindex meta tag if required by the blog configuration. + * + * If a blog is marked as not being public then the noindex meta tag will be + * output to tell web robots not to index the page content. Add this to the wp_head action. + * Typical usage is as a wp_head callback. add_action( 'wp_head', 'noindex' ); + * + * @see wp_no_robots + * + * @since 2.1.0 + */ +function noindex() { + // If the blog is not public, tell robots to go away. + if ( '0' == get_option('blog_public') ) + wp_no_robots(); +} + +/** + * Display a noindex meta tag. + * + * Outputs a noindex meta tag that tells web robots not to index the page content. + * Typical usage is as a wp_head callback. add_action( 'wp_head', 'wp_no_robots' ); + * + * @since 3.3.0 + */ +function wp_no_robots() { + echo "\n"; +} + +/** + * Determine if TinyMCE is available. + * + * Checks to see if the user has deleted the tinymce files to slim down there WordPress install. + * + * @since 2.1.0 + * + * @return bool Whether TinyMCE exists. + */ +function rich_edit_exists() { + global $wp_rich_edit_exists; + if ( !isset($wp_rich_edit_exists) ) + $wp_rich_edit_exists = file_exists(ABSPATH . WPINC . '/js/tinymce/tiny_mce.js'); + return $wp_rich_edit_exists; +} + +/** + * Whether the user should have a WYSIWIG editor. + * + * Checks that the user requires a WYSIWIG editor and that the editor is + * supported in the users browser. + * + * @since 2.0.0 + * + * @return bool + */ +function user_can_richedit() { + global $wp_rich_edit, $is_gecko, $is_opera, $is_safari, $is_chrome, $is_IE; + + if ( !isset($wp_rich_edit) ) { + $wp_rich_edit = false; + + if ( get_user_option( 'rich_editing' ) == 'true' || ! is_user_logged_in() ) { // default to 'true' for logged out users + if ( $is_safari ) { + $wp_rich_edit = ! wp_is_mobile() || ( preg_match( '!AppleWebKit/(\d+)!', $_SERVER['HTTP_USER_AGENT'], $match ) && intval( $match[1] ) >= 534 ); + } elseif ( $is_gecko || $is_chrome || $is_IE || ( $is_opera && !wp_is_mobile() ) ) { + $wp_rich_edit = true; + } + } + } + + return apply_filters('user_can_richedit', $wp_rich_edit); +} + +/** + * Find out which editor should be displayed by default. + * + * Works out which of the two editors to display as the current editor for a + * user. The 'html' setting is for the "Text" editor tab. + * + * @since 2.5.0 + * + * @return string Either 'tinymce', or 'html', or 'test' + */ +function wp_default_editor() { + $r = user_can_richedit() ? 'tinymce' : 'html'; // defaults + if ( $user = wp_get_current_user() ) { // look for cookie + $ed = get_user_setting('editor', 'tinymce'); + $r = ( in_array($ed, array('tinymce', 'html', 'test') ) ) ? $ed : $r; + } + return apply_filters( 'wp_default_editor', $r ); // filter +} + +/** + * Renders an editor. + * + * Using this function is the proper way to output all needed components for both TinyMCE and Quicktags. + * _WP_Editors should not be used directly. See http://core.trac.wordpress.org/ticket/17144. + * + * NOTE: Once initialized the TinyMCE editor cannot be safely moved in the DOM. For that reason + * running wp_editor() inside of a metabox is not a good idea unless only Quicktags is used. + * On the post edit screen several actions can be used to include additional editors + * containing TinyMCE: 'edit_page_form', 'edit_form_advanced' and 'dbx_post_sidebar'. + * See http://core.trac.wordpress.org/ticket/19173 for more information. + * + * @see wp-includes/class-wp-editor.php + * @since 3.3.0 + * + * @param string $content Initial content for the editor. + * @param string $editor_id HTML ID attribute value for the textarea and TinyMCE. Can only be /[a-z]+/. + * @param array $settings See _WP_Editors::editor(). + */ +function wp_editor( $content, $editor_id, $settings = array() ) { + if ( ! class_exists( '_WP_Editors' ) ) + require( ABSPATH . WPINC . '/class-wp-editor.php' ); + + _WP_Editors::editor($content, $editor_id, $settings); +} + +/** + * Retrieve the contents of the search WordPress query variable. + * + * The search query string is passed through {@link esc_attr()} + * to ensure that it is safe for placing in an html attribute. + * + * @since 2.3.0 + * @uses esc_attr() + * + * @param bool $escaped Whether the result is escaped. Default true. + * Only use when you are later escaping it. Do not use unescaped. + * @return string + */ +function get_search_query( $escaped = true ) { + $query = apply_filters( 'get_search_query', get_query_var( 's' ) ); + if ( $escaped ) + $query = esc_attr( $query ); + return $query; +} + +/** + * Display the contents of the search query variable. + * + * The search query string is passed through {@link esc_attr()} + * to ensure that it is safe for placing in an html attribute. + * + * @uses esc_attr() + * @since 2.1.0 + */ +function the_search_query() { + echo esc_attr( apply_filters( 'the_search_query', get_search_query( false ) ) ); +} + +/** + * Display the language attributes for the html tag. + * + * Builds up a set of html attributes containing the text direction and language + * information for the page. + * + * @since 2.1.0 + * + * @param string $doctype The type of html document (xhtml|html). + */ +function language_attributes($doctype = 'html') { + $attributes = array(); + $output = ''; + + if ( function_exists( 'is_rtl' ) && is_rtl() ) + $attributes[] = 'dir="rtl"'; + + if ( $lang = get_bloginfo('language') ) { + if ( get_option('html_type') == 'text/html' || $doctype == 'html' ) + $attributes[] = "lang=\"$lang\""; + + if ( get_option('html_type') != 'text/html' || $doctype == 'xhtml' ) + $attributes[] = "xml:lang=\"$lang\""; + } + + $output = implode(' ', $attributes); + $output = apply_filters('language_attributes', $output); + echo $output; +} + +/** + * Retrieve paginated link for archive post pages. + * + * Technically, the function can be used to create paginated link list for any + * area. The 'base' argument is used to reference the url, which will be used to + * create the paginated links. The 'format' argument is then used for replacing + * the page number. It is however, most likely and by default, to be used on the + * archive post pages. + * + * The 'type' argument controls format of the returned value. The default is + * 'plain', which is just a string with the links separated by a newline + * character. The other possible values are either 'array' or 'list'. The + * 'array' value will return an array of the paginated link list to offer full + * control of display. The 'list' value will place all of the paginated links in + * an unordered HTML list. + * + * The 'total' argument is the total amount of pages and is an integer. The + * 'current' argument is the current page number and is also an integer. + * + * An example of the 'base' argument is "http://example.com/all_posts.php%_%" + * and the '%_%' is required. The '%_%' will be replaced by the contents of in + * the 'format' argument. An example for the 'format' argument is "?page=%#%" + * and the '%#%' is also required. The '%#%' will be replaced with the page + * number. + * + * You can include the previous and next links in the list by setting the + * 'prev_next' argument to true, which it is by default. You can set the + * previous text, by using the 'prev_text' argument. You can set the next text + * by setting the 'next_text' argument. + * + * If the 'show_all' argument is set to true, then it will show all of the pages + * instead of a short list of the pages near the current page. By default, the + * 'show_all' is set to false and controlled by the 'end_size' and 'mid_size' + * arguments. The 'end_size' argument is how many numbers on either the start + * and the end list edges, by default is 1. The 'mid_size' argument is how many + * numbers to either side of current page, but not including current page. + * + * It is possible to add query vars to the link by using the 'add_args' argument + * and see {@link add_query_arg()} for more information. + * + * @since 2.1.0 + * + * @param string|array $args Optional. Override defaults. + * @return array|string String of page links or array of page links. + */ +function paginate_links( $args = '' ) { + $defaults = array( + 'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below) + 'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number + 'total' => 1, + 'current' => 0, + 'show_all' => false, + 'prev_next' => true, + 'prev_text' => __('« Previous'), + 'next_text' => __('Next »'), + 'end_size' => 1, + 'mid_size' => 2, + 'type' => 'plain', + 'add_args' => false, // array of query args to add + 'add_fragment' => '' + ); + + $args = wp_parse_args( $args, $defaults ); + extract($args, EXTR_SKIP); + + // Who knows what else people pass in $args + $total = (int) $total; + if ( $total < 2 ) + return; + $current = (int) $current; + $end_size = 0 < (int) $end_size ? (int) $end_size : 1; // Out of bounds? Make it the default. + $mid_size = 0 <= (int) $mid_size ? (int) $mid_size : 2; + $add_args = is_array($add_args) ? $add_args : false; + $r = ''; + $page_links = array(); + $n = 0; + $dots = false; + + if ( $prev_next && $current && 1 < $current ) : + $link = str_replace('%_%', 2 == $current ? '' : $format, $base); + $link = str_replace('%#%', $current - 1, $link); + if ( $add_args ) + $link = add_query_arg( $add_args, $link ); + $link .= $add_fragment; + $page_links[] = ''; + endif; + for ( $n = 1; $n <= $total; $n++ ) : + $n_display = number_format_i18n($n); + if ( $n == $current ) : + $page_links[] = "$n_display"; + $dots = true; + else : + if ( $show_all || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) : + $link = str_replace('%_%', 1 == $n ? '' : $format, $base); + $link = str_replace('%#%', $n, $link); + if ( $add_args ) + $link = add_query_arg( $add_args, $link ); + $link .= $add_fragment; + $page_links[] = "$n_display"; + $dots = true; + elseif ( $dots && !$show_all ) : + $page_links[] = '' . __( '…' ) . ''; + $dots = false; + endif; + endif; + endfor; + if ( $prev_next && $current && ( $current < $total || -1 == $total ) ) : + $link = str_replace('%_%', $format, $base); + $link = str_replace('%#%', $current + 1, $link); + if ( $add_args ) + $link = add_query_arg( $add_args, $link ); + $link .= $add_fragment; + $page_links[] = ''; + endif; + switch ( $type ) : + case 'array' : + return $page_links; + break; + case 'list' : + $r .= "
      \n\t
    • "; + $r .= join("
    • \n\t
    • ", $page_links); + $r .= "
    • \n
    \n"; + break; + default : + $r = join("\n", $page_links); + break; + endswitch; + return $r; +} + +/** + * Registers an admin colour scheme css file. + * + * Allows a plugin to register a new admin colour scheme. For example: + * + * wp_admin_css_color('classic', __('Classic'), admin_url("css/colors-classic.css"), + * array('#07273E', '#14568A', '#D54E21', '#2683AE')); + * + * + * @since 2.5.0 + * + * @param string $key The unique key for this theme. + * @param string $name The name of the theme. + * @param string $url The url of the css file containing the colour scheme. + * @param array $colors Optional An array of CSS color definitions which are used to give the user a feel for the theme. + */ +function wp_admin_css_color($key, $name, $url, $colors = array()) { + global $_wp_admin_css_colors; + + if ( !isset($_wp_admin_css_colors) ) + $_wp_admin_css_colors = array(); + + $_wp_admin_css_colors[$key] = (object) array('name' => $name, 'url' => $url, 'colors' => $colors); +} + +/** + * Registers the default Admin color schemes + * + * @since 3.0.0 + */ +function register_admin_color_schemes() { + wp_admin_css_color( 'classic', _x( 'Blue', 'admin color scheme' ), admin_url( 'css/colors-classic.min.css' ), + array( '#5589aa', '#cfdfe9', '#d1e5ee', '#eff8ff' ) ); + wp_admin_css_color( 'fresh', _x( 'Gray', 'admin color scheme' ), admin_url( 'css/colors-fresh.min.css' ), + array( '#555', '#a0a0a0', '#ccc', '#f1f1f1' ) ); +} + +/** + * Display the URL of a WordPress admin CSS file. + * + * @see WP_Styles::_css_href and its style_loader_src filter. + * + * @since 2.3.0 + * + * @param string $file file relative to wp-admin/ without its ".css" extension. + */ +function wp_admin_css_uri( $file = 'wp-admin' ) { + if ( defined('WP_INSTALLING') ) { + $_file = "./$file.css"; + } else { + $_file = admin_url("$file.css"); + } + $_file = add_query_arg( 'version', get_bloginfo( 'version' ), $_file ); + + return apply_filters( 'wp_admin_css_uri', $_file, $file ); +} + +/** + * Enqueues or directly prints a stylesheet link to the specified CSS file. + * + * "Intelligently" decides to enqueue or to print the CSS file. If the + * 'wp_print_styles' action has *not* yet been called, the CSS file will be + * enqueued. If the wp_print_styles action *has* been called, the CSS link will + * be printed. Printing may be forced by passing true as the $force_echo + * (second) parameter. + * + * For backward compatibility with WordPress 2.3 calling method: If the $file + * (first) parameter does not correspond to a registered CSS file, we assume + * $file is a file relative to wp-admin/ without its ".css" extension. A + * stylesheet link to that generated URL is printed. + * + * @package WordPress + * @since 2.3.0 + * @uses $wp_styles WordPress Styles Object + * + * @param string $file Optional. Style handle name or file name (without ".css" extension) relative + * to wp-admin/. Defaults to 'wp-admin'. + * @param bool $force_echo Optional. Force the stylesheet link to be printed rather than enqueued. + */ +function wp_admin_css( $file = 'wp-admin', $force_echo = false ) { + global $wp_styles; + if ( !is_a($wp_styles, 'WP_Styles') ) + $wp_styles = new WP_Styles(); + + // For backward compatibility + $handle = 0 === strpos( $file, 'css/' ) ? substr( $file, 4 ) : $file; + + if ( $wp_styles->query( $handle ) ) { + if ( $force_echo || did_action( 'wp_print_styles' ) ) // we already printed the style queue. Print this one immediately + wp_print_styles( $handle ); + else // Add to style queue + wp_enqueue_style( $handle ); + return; + } + + echo apply_filters( 'wp_admin_css', "\n", $file ); + if ( function_exists( 'is_rtl' ) && is_rtl() ) + echo apply_filters( 'wp_admin_css', "\n", "$file-rtl" ); +} + +/** + * Enqueues the default ThickBox js and css. + * + * If any of the settings need to be changed, this can be done with another js + * file similar to media-upload.js. That file should + * require array('thickbox') to ensure it is loaded after. + * + * @since 2.5.0 + */ +function add_thickbox() { + wp_enqueue_script( 'thickbox' ); + wp_enqueue_style( 'thickbox' ); + + if ( is_network_admin() ) + add_action( 'admin_head', '_thickbox_path_admin_subfolder' ); +} + +/** + * Display the XHTML generator that is generated on the wp_head hook. + * + * @since 2.5.0 + */ +function wp_generator() { + the_generator( apply_filters( 'wp_generator_type', 'xhtml' ) ); +} + +/** + * Display the generator XML or Comment for RSS, ATOM, etc. + * + * Returns the correct generator type for the requested output format. Allows + * for a plugin to filter generators overall the the_generator filter. + * + * @since 2.5.0 + * @uses apply_filters() Calls 'the_generator' hook. + * + * @param string $type The type of generator to output - (html|xhtml|atom|rss2|rdf|comment|export). + */ +function the_generator( $type ) { + echo apply_filters('the_generator', get_the_generator($type), $type) . "\n"; +} + +/** + * Creates the generator XML or Comment for RSS, ATOM, etc. + * + * Returns the correct generator type for the requested output format. Allows + * for a plugin to filter generators on an individual basis using the + * 'get_the_generator_{$type}' filter. + * + * @since 2.5.0 + * @uses apply_filters() Calls 'get_the_generator_$type' hook. + * + * @param string $type The type of generator to return - (html|xhtml|atom|rss2|rdf|comment|export). + * @return string The HTML content for the generator. + */ +function get_the_generator( $type = '' ) { + if ( empty( $type ) ) { + + $current_filter = current_filter(); + if ( empty( $current_filter ) ) + return; + + switch ( $current_filter ) { + case 'rss2_head' : + case 'commentsrss2_head' : + $type = 'rss2'; + break; + case 'rss_head' : + case 'opml_head' : + $type = 'comment'; + break; + case 'rdf_header' : + $type = 'rdf'; + break; + case 'atom_head' : + case 'comments_atom_head' : + case 'app_head' : + $type = 'atom'; + break; + } + } + + switch ( $type ) { + case 'html': + $gen = ''; + break; + case 'xhtml': + $gen = ''; + break; + case 'atom': + $gen = 'WordPress'; + break; + case 'rss2': + $gen = 'http://wordpress.org/?v=' . get_bloginfo_rss( 'version' ) . ''; + break; + case 'rdf': + $gen = ''; + break; + case 'comment': + $gen = ''; + break; + case 'export': + $gen = ''; + break; + } + return apply_filters( "get_the_generator_{$type}", $gen, $type ); +} + +/** + * Outputs the html checked attribute. + * + * Compares the first two arguments and if identical marks as checked + * + * @since 1.0.0 + * + * @param mixed $checked One of the values to compare + * @param mixed $current (true) The other value to compare if not just true + * @param bool $echo Whether to echo or just return the string + * @return string html attribute or empty string + */ +function checked( $checked, $current = true, $echo = true ) { + return __checked_selected_helper( $checked, $current, $echo, 'checked' ); +} + +/** + * Outputs the html selected attribute. + * + * Compares the first two arguments and if identical marks as selected + * + * @since 1.0.0 + * + * @param mixed $selected One of the values to compare + * @param mixed $current (true) The other value to compare if not just true + * @param bool $echo Whether to echo or just return the string + * @return string html attribute or empty string + */ +function selected( $selected, $current = true, $echo = true ) { + return __checked_selected_helper( $selected, $current, $echo, 'selected' ); +} + +/** + * Outputs the html disabled attribute. + * + * Compares the first two arguments and if identical marks as disabled + * + * @since 3.0.0 + * + * @param mixed $disabled One of the values to compare + * @param mixed $current (true) The other value to compare if not just true + * @param bool $echo Whether to echo or just return the string + * @return string html attribute or empty string + */ +function disabled( $disabled, $current = true, $echo = true ) { + return __checked_selected_helper( $disabled, $current, $echo, 'disabled' ); +} + +/** + * Private helper function for checked, selected, and disabled. + * + * Compares the first two arguments and if identical marks as $type + * + * @since 2.8.0 + * @access private + * + * @param mixed $helper One of the values to compare + * @param mixed $current (true) The other value to compare if not just true + * @param bool $echo Whether to echo or just return the string + * @param string $type The type of checked|selected|disabled we are doing + * @return string html attribute or empty string + */ +function __checked_selected_helper( $helper, $current, $echo, $type ) { + if ( (string) $helper === (string) $current ) + $result = " $type='$type'"; + else + $result = ''; + + if ( $echo ) + echo $result; + + return $result; +} + +/** + * Default settings for heartbeat + * + * Outputs the nonce used in the heartbeat XHR + * + * @since 3.6.0 + * + * @param array $settings + * @return array $settings + */ +function wp_heartbeat_settings( $settings ) { + if ( ! is_admin() ) + $settings['ajaxurl'] = admin_url( 'admin-ajax.php', 'relative' ); + + if ( is_user_logged_in() ) + $settings['nonce'] = wp_create_nonce( 'heartbeat-nonce' ); + + return $settings; +} diff --git a/sources/wp-includes/http.php b/sources/wp-includes/http.php new file mode 100644 index 0000000..e30fa41 --- /dev/null +++ b/sources/wp-includes/http.php @@ -0,0 +1,558 @@ +request( $url, $args ); +} + +/** + * Retrieve the raw response from a safe HTTP request using the GET method. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @see wp_remote_request() For more information on the response array format + * and default arguments. + * + * @since 3.6.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_safe_remote_get( $url, $args = array() ) { + $args['reject_unsafe_urls'] = true; + $http = _wp_http_get_object(); + return $http->get( $url, $args ); +} + +/** + * Retrieve the raw response from a safe HTTP request using the POST method. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @see wp_remote_request() For more information on the response array format + * and default arguments. + * + * @since 3.6.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_safe_remote_post( $url, $args = array() ) { + $args['reject_unsafe_urls'] = true; + $http = _wp_http_get_object(); + return $http->post( $url, $args ); +} + +/** + * Retrieve the raw response from a safe HTTP request using the HEAD method. + * + * This function is ideal when the HTTP request is being made to an arbitrary + * URL. The URL is validated to avoid redirection and request forgery attacks. + * + * @see wp_remote_request() For more information on the response array format + * and default arguments. + * + * @since 3.6.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_safe_remote_head( $url, $args = array() ) { + $args['reject_unsafe_urls'] = true; + $http = _wp_http_get_object(); + return $http->head( $url, $args ); +} + +/** + * Retrieve the raw response from the HTTP request. + * + * The array structure is a little complex. + * + * + * $res = array( 'headers' => array(), 'response' => array('code' => int, 'message' => string) ); + * + * + * All of the headers in $res['headers'] are with the name as the key and the + * value as the value. So to get the User-Agent, you would do the following. + * + * + * $user_agent = $res['headers']['user-agent']; + * + * + * The body is the raw response content and can be retrieved from $res['body']. + * + * This function is called first to make the request and there are other API + * functions to abstract out the above convoluted setup. + * + * List of default arguments: + * 'method' => 'GET' + * - Default 'GET' for wp_remote_get() + * - Default 'POST' for wp_remote_post() + * - Default 'HEAD' for wp_remote_head() + * 'timeout' => 5 + * 'redirection' => 5 + * 'httpversion' => '1.0' + * 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) + * 'blocking' => true + * 'headers' => array() + * 'cookies' => array() + * 'body' => null + * 'compress' => false, + * 'decompress' => true, + * 'sslverify' => true, + * 'stream' => false, + * 'filename' => null + * + * @since 2.7.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_remote_request($url, $args = array()) { + $objFetchSite = _wp_http_get_object(); + return $objFetchSite->request($url, $args); +} + +/** + * Retrieve the raw response from the HTTP request using the GET method. + * + * @see wp_remote_request() For more information on the response array format and default arguments. + * + * @since 2.7.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_remote_get($url, $args = array()) { + $objFetchSite = _wp_http_get_object(); + return $objFetchSite->get($url, $args); +} + +/** + * Retrieve the raw response from the HTTP request using the POST method. + * + * @see wp_remote_request() For more information on the response array format and default arguments. + * + * @since 2.7.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_remote_post($url, $args = array()) { + $objFetchSite = _wp_http_get_object(); + return $objFetchSite->post($url, $args); +} + +/** + * Retrieve the raw response from the HTTP request using the HEAD method. + * + * @see wp_remote_request() For more information on the response array format and default arguments. + * + * @since 2.7.0 + * + * @param string $url Site URL to retrieve. + * @param array $args Optional. Override the defaults. + * @return WP_Error|array The response or WP_Error on failure. + */ +function wp_remote_head($url, $args = array()) { + $objFetchSite = _wp_http_get_object(); + return $objFetchSite->head($url, $args); +} + +/** + * Retrieve only the headers from the raw response. + * + * @since 2.7.0 + * + * @param array $response HTTP response. + * @return array The headers of the response. Empty array if incorrect parameter given. + */ +function wp_remote_retrieve_headers(&$response) { + if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers'])) + return array(); + + return $response['headers']; +} + +/** + * Retrieve a single header by name from the raw response. + * + * @since 2.7.0 + * + * @param array $response + * @param string $header Header name to retrieve value from. + * @return string The header value. Empty string on if incorrect parameter given, or if the header doesn't exist. + */ +function wp_remote_retrieve_header(&$response, $header) { + if ( is_wp_error($response) || ! isset($response['headers']) || ! is_array($response['headers'])) + return ''; + + if ( array_key_exists($header, $response['headers']) ) + return $response['headers'][$header]; + + return ''; +} + +/** + * Retrieve only the response code from the raw response. + * + * Will return an empty array if incorrect parameter value is given. + * + * @since 2.7.0 + * + * @param array $response HTTP response. + * @return string the response code. Empty string on incorrect parameter given. + */ +function wp_remote_retrieve_response_code(&$response) { + if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response'])) + return ''; + + return $response['response']['code']; +} + +/** + * Retrieve only the response message from the raw response. + * + * Will return an empty array if incorrect parameter value is given. + * + * @since 2.7.0 + * + * @param array $response HTTP response. + * @return string The response message. Empty string on incorrect parameter given. + */ +function wp_remote_retrieve_response_message(&$response) { + if ( is_wp_error($response) || ! isset($response['response']) || ! is_array($response['response'])) + return ''; + + return $response['response']['message']; +} + +/** + * Retrieve only the body from the raw response. + * + * @since 2.7.0 + * + * @param array $response HTTP response. + * @return string The body of the response. Empty string if no body or incorrect parameter given. + */ +function wp_remote_retrieve_body(&$response) { + if ( is_wp_error($response) || ! isset($response['body']) ) + return ''; + + return $response['body']; +} + +/** + * Determines if there is an HTTP Transport that can process this request. + * + * @since 3.2.0 + * + * @param array $capabilities Array of capabilities to test or a wp_remote_request() $args array. + * @param string $url Optional. If given, will check if the URL requires SSL and adds that requirement to the capabilities array. + * + * @return bool + */ +function wp_http_supports( $capabilities = array(), $url = null ) { + $objFetchSite = _wp_http_get_object(); + + $capabilities = wp_parse_args( $capabilities ); + + $count = count( $capabilities ); + + // If we have a numeric $capabilities array, spoof a wp_remote_request() associative $args array + if ( $count && count( array_filter( array_keys( $capabilities ), 'is_numeric' ) ) == $count ) { + $capabilities = array_combine( array_values( $capabilities ), array_fill( 0, $count, true ) ); + } + + if ( $url && !isset( $capabilities['ssl'] ) ) { + $scheme = parse_url( $url, PHP_URL_SCHEME ); + if ( 'https' == $scheme || 'ssl' == $scheme ) { + $capabilities['ssl'] = true; + } + } + + return (bool) $objFetchSite->_get_first_available_transport( $capabilities ); +} + +/** + * Get the HTTP Origin of the current request. + * + * @since 3.4.0 + * + * @return string URL of the origin. Empty string if no origin. + */ +function get_http_origin() { + $origin = ''; + if ( ! empty ( $_SERVER[ 'HTTP_ORIGIN' ] ) ) + $origin = $_SERVER[ 'HTTP_ORIGIN' ]; + + /** + * Change the origin of an HTTP request. + * + * @since 3.4.0 + * + * @param string $origin The original origin for the request. + */ + return apply_filters( 'http_origin', $origin ); +} + +/** + * Retrieve list of allowed HTTP origins. + * + * @since 3.4.0 + * + * @return array Array of origin URLs. + */ +function get_allowed_http_origins() { + $admin_origin = parse_url( admin_url() ); + $home_origin = parse_url( home_url() ); + + // @todo preserve port? + $allowed_origins = array_unique( array( + 'http://' . $admin_origin[ 'host' ], + 'https://' . $admin_origin[ 'host' ], + 'http://' . $home_origin[ 'host' ], + 'https://' . $home_origin[ 'host' ], + ) ); + + /** + * Change the origin types allowed for HTTP requests. + * + * @since 3.4.0 + * + * @param array $allowed_origins { + * Default allowed HTTP origins. + * @type string Non-secure URL for admin origin. + * @type string Secure URL for admin origin. + * @type string Non-secure URL for home origin. + * @type string Secure URL for home origin. + * } + */ + return apply_filters( 'allowed_http_origins' , $allowed_origins ); +} + +/** + * Determines if the HTTP origin is an authorized one. + * + * @since 3.4.0 + * + * @param string Origin URL. If not provided, the value of get_http_origin() is used. + * @return bool True if the origin is allowed. False otherwise. + */ +function is_allowed_http_origin( $origin = null ) { + $origin_arg = $origin; + + if ( null === $origin ) + $origin = get_http_origin(); + + if ( $origin && ! in_array( $origin, get_allowed_http_origins() ) ) + $origin = ''; + + /** + * Change the allowed HTTP origin result. + * + * @since 3.4.0 + * + * @param string $origin Result of check for allowed origin. + * @param string $origin_arg original origin string passed into is_allowed_http_origin function. + */ + return apply_filters( 'allowed_http_origin', $origin, $origin_arg ); +} + +/** + * Send Access-Control-Allow-Origin and related headers if the current request + * is from an allowed origin. + * + * If the request is an OPTIONS request, the script exits with either access + * control headers sent, or a 403 response if the origin is not allowed. For + * other request methods, you will receive a return value. + * + * @since 3.4.0 + * + * @return bool|string Returns the origin URL if headers are sent. Returns false + * if headers are not sent. + */ +function send_origin_headers() { + $origin = get_http_origin(); + + if ( is_allowed_http_origin( $origin ) ) { + @header( 'Access-Control-Allow-Origin: ' . $origin ); + @header( 'Access-Control-Allow-Credentials: true' ); + if ( 'OPTIONS' === $_SERVER['REQUEST_METHOD'] ) + exit; + return $origin; + } + + if ( 'OPTIONS' === $_SERVER['REQUEST_METHOD'] ) { + status_header( 403 ); + exit; + } + + return false; +} + +/** + * Validate a URL for safe use in the HTTP API. + * + * @since 3.5.2 + * + * @return mixed URL or false on failure. + */ +function wp_http_validate_url( $url ) { + $url = wp_kses_bad_protocol( $url, array( 'http', 'https' ) ); + if ( ! $url ) + return false; + + $parsed_url = @parse_url( $url ); + if ( ! $parsed_url || empty( $parsed_url['host'] ) ) + return false; + + if ( isset( $parsed_url['user'] ) || isset( $parsed_url['pass'] ) ) + return false; + + if ( false !== strpos( $parsed_url['host'], ':' ) ) + return false; + + $parsed_home = @parse_url( get_option( 'home' ) ); + + $same_host = strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] ); + + if ( ! $same_host ) { + $host = trim( $parsed_url['host'], '.' ); + if ( preg_match( '#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $host ) ) { + $ip = $host; + } else { + $ip = gethostbyname( $host ); + if ( $ip === $host ) // Error condition for gethostbyname() + $ip = false; + } + if ( $ip ) { + $parts = array_map( 'intval', explode( '.', $ip ) ); + if ( '127.0.0.1' === $ip + || ( 10 === $parts[0] ) + || ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] ) + || ( 192 === $parts[0] && 168 === $parts[1] ) + ) { + // If host appears local, reject unless specifically allowed. + /** + * Check if HTTP request is external or not. + * + * Allows to change and allow external requests for the HTTP request. + * + * @since 3.6.0 + * + * @param bool false Whether HTTP request is external or not. + * @param string $host IP of the requested host. + * @param string $url URL of the requested host. + */ + if ( ! apply_filters( 'http_request_host_is_external', false, $host, $url ) ) + return false; + } + } + } + + if ( empty( $parsed_url['port'] ) ) + return $url; + + $port = $parsed_url['port']; + if ( 80 === $port || 443 === $port || 8080 === $port ) + return $url; + + if ( $parsed_home && $same_host && $parsed_home['port'] === $port ) + return $url; + + return false; +} + +/** + * Whitelists allowed redirect hosts for safe HTTP requests as well. + * + * Attached to the http_request_host_is_external filter. + * + * @since 3.6.0 + * + * @param bool $is_external + * @param string $host + * @return bool + */ +function allowed_http_request_hosts( $is_external, $host ) { + if ( ! $is_external && wp_validate_redirect( 'http://' . $host ) ) + $is_external = true; + return $is_external; +} + +/** + * Whitelists any domain in a multisite installation for safe HTTP requests. + * + * Attached to the http_request_host_is_external filter. + * + * @since 3.6.0 + * + * @param bool $is_external + * @param string $host + * @return bool + */ +function ms_allowed_http_request_hosts( $is_external, $host ) { + global $wpdb, $current_site; + static $queried = array(); + if ( $is_external ) + return $is_external; + if ( $host === $current_site->domain ) + return true; + if ( isset( $queried[ $host ] ) ) + return $queried[ $host ]; + $queried[ $host ] = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM $wpdb->blogs WHERE domain = %s LIMIT 1", $host ) ); + return $queried[ $host ]; +} diff --git a/sources/wp-includes/images/admin-bar-sprite-2x.png b/sources/wp-includes/images/admin-bar-sprite-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9accbee7d315d1325e9157190e370c58f7700a72 GIT binary patch literal 4122 zcmb_f_d6R5+f5`fV#TUZHEOSzwM9^BloFeyMx|9k&7wxF@Sv#C)@(f*wL*g;YOj{o z9z{{Bl&aB3HFmy!&-;G=!S~C#&vpNFuKPOIxv!IKWqFMi$`1tq0Ia4aSJ8i_6aWCE zFoOTEqIF*m0Dyhj^s2sX*yn95v%l>W9};Y0Lgxu&Vi&=n%B3=3#oncLbm`6P@_CHE&FhPm{2q@=JcB~|%r2gTYF zg(#j}7XX0Gk!2{Y@e+V%!^@an%}9NVAoF>)QSoP(z=1zdXUHtM?HAF#CARbip1xe| zQ}#dr^k`MXueX8s1yvJ#s2(ZMv;;;byd;4F5ry|TX`n+f%N2=1ED5^K5(aHr-anK( zhYR&x^9MzD?37(kkNM`WeGYDKTFLmU@X8%tMNPVB=zO{YOp`05qaWLS!>B)qH$&Uq z(6l?~hmU2L6M31CDx}Sm)cS1hQ~SE(tLs{y>~}+`s{a-EugbuR6KSjVdR+KgcQjj< zk%1B>$pI_?j2w?Bt_BWsa2~2RgDem5SQmD;Q_XJcQ_q^1krTEzS60}8KUA-OE8ClB z23Q_koqb?c4~aqhC;GG9-oFzFJQbc|{05O+id+>a6zWt=qdmV^JU!75t!v0WI*qJ} z(K(w6t*OT9==p>>-`pgx9zi#GI4GKVNwl*$OcNBa!QAf2;txDr#5Y1n+%>M;i zLGJ@cy^HPzPS*oeNQbk7dTZ`&_#6OnX#{pLVXMK=B$5400rJG5lSL(5G&ECMXTKSvOTdNZk z22?NP@i3y$Rr0Zi>E2Cea-0P&Hbl^*UP)ZGm)iA@T=%2HVKEwifQ2(VA25s3>+ySU zlh^`(Y9mJsd+hxFcye{Z_OTi7?&F5UPw49REJ1^!e|>yw<;61HmbkWPvDi4uB<|!^OZmUZPpcN2d%WJHza*U#v`uTZDgB4E4g2laQ`U! zQ8K#aocSc{njO@pLVEG;r<9EXaS*|-;_jFnUqg@>@e^t=>Ql7CclJOtco1DMAgLX{S;r0`89~1YdmuomD*?Am+HJ-8*~a zb35)Z@_Rv~tk@@+{p5@Vm-M|9{iXNZ4#NSYoMMBVjDP0G{x>6z)6tz=dkmLj*8#66 zeDMsRZ$h9I}bYt#t3bn7gMGYb)Plrf!E--LRJ{31k@J7=QzXbjI-I zTA2uWEZzPsX10$WMAlNPBj9A`;iQnWY7ZpK6f@ zhpIfp@jh+O>c1Oox0HGW_8Ci*!87K#DjA*YpQ3W`fO z0)Z8%1gb0_x5@vvor5lV>zW9}Hps|Yax7NbAQ%Jr2gw z+^>3!q4*B{N^x<*0D_2RmxZPlFf-xB4}Mi#$l+0QrhXU+?$0`@7>Y&bTT8$1w|_aU zE#+feKBPa}E>%E~TFaVjtRe;J{M9;aHTTRro^=x~FC|O5Nd>9=@+oJvx1-DYZX2Hj zFG-PrbXf^nFB5CPUMaRoT99O!{B0DX)y>oz8*wRbImM{EbHyBF3Ryqk<2VoZx56giHbDPd(;>vtk7Kq zJ!zb4_VdzcDHXr}_HNm*ub)u6m($w1xV(97x4E;7x`OllmI%Mq|BG1G@39XIjJ7~) zZ)Orwm%NelQ$1`LL7A`+4_~|0pQ1B`7c-{q+q5`7;Gc)c@3cG&IZdtU6ia_t`|wII zTif8;kJtwa3fhyN4A)l-Ek1sV=|PQe|c2J?CMbk-_n7g^U?8cvL`b|GVa(1H+Ze|psWr;(t|`fweyqN`7`AOM!dkn zUisH0BvJG*TiZv*-@qFDu(!N0+w`L03yAy9uaz}$CyjVu)4d68NcVbI_$(b#svHY| z?>}|;yTia>vxi%k#Rr^X65FswU1u;9eHXmIj*q81vi}?oQHK&YpO{xDpn80e!EEWC z_YF@tT31m!{sct~m5>~*)46?3&zP$-TimT7`V#~2c1)?_?+jy`N~*9zerz-#^PLbq z3&E*f*hP9DHLxXe;eGtu_~hQU?UM->MBF1su+L9mB=vv>Gs9yD!2m+kHqTg?TvetGTv4B2(fnEanqocxp%8$MppM8 z;4a_2K@7a(_4v=!3$i>O}?*vbx+rFT2LjiuqZPZ zY1P4LYEk1s+f~VXS#7(;?)MJe#<$8YMG*V9KrohkI*WN*uP6q1ZkuGkYT(A;@klry zyX)~<6P>mkMsZr_0(Kk%n`7D$}eA)hqEb0rK|~2TMd7UcMY{V7t6} zzFbz8o#Fb(;MsHu;8^MQWYNJ3@dS#hfFA+qfE1hQ(9#$m9Swi|R1L3``}92=SZTcX zYJV5WBI_(2(d}dIdVJKCu?rNdqv3MIvSl)fx>X!s_Z)xlSMOkE};M-xC(&AH%l54RXOXZ?r zs|6E6=~!W>y*?LNw;_1V-jXXPFZ&KoD5{38Q^#%kxp9ET>0W7y_L%SM>ePpZYU2vD zNIlZ}=A`_uML5ljtlpINwRSmrf&oj7&Rrx*3`g#w;_yTZ-Y?jIMPV8Ka0T8rHM3B4lK;r@L_uW+8 z73|^prCpO{NVOHtm2`Tt#}*}lGMBVnAA&KMzts7ARtwR^B; z)1XY5P{y;+oe0}&?02g9qjl|PGBL;mp8H@j#~*2KT=p8god$t^8t{cMxGan4>Jna0 zoChh2b89b1i`=-=i9EckTo|&xCw*5?N&{^Cen9b|WxS%`4T-OXGWDy3FaNpEP608R zz;oX-3k}p#GS!XyFCEj2qynGaB3#NN+Q!UYM+fIR)>fOQH0JTlK000SXNklS-^lG%9xA^jWZ5JM;wzz2cpsO2j=#?w+p+#gJqijOlJ0cvvBUc z-@EsobMJZQ-S+_g2cn75_&THbYL08}YZ#(Kvv5pWbyW3@YBq%a>dY~S+GZ`&Hfdu~ zo1!g5y{m`~*R|+B+Z_+y_I};Lw``B$>VagK`sSkCohJ)R zPv`Dj`y5Q$zrt{}Y!CQasqWxYq0nCDmf6fJRrebJs6F zehDU>*vSv4y%RnexRP96FFFQ31&ema746jMz}USxq3Heczk}cEXKM%We86%jcyCGI zwdz|CeB_0atj!6gn_#{-JEByn?@I^=|B5EQxwHs4@UQALu-XBbQoL7LJUhbt1c@&_ zd#cpPa@K=y&Uzy=vcqrUjJfb*YINpU9)Zue`GI+@W<9r*KR7sLk7ctJE3? z)+d%^>GV*Xf#;xb_2o0H@ICO&`(57V@-v2eQ$s;o@Z!8k;{)}1m{!|foPiEE-#D21 z?h@no+D-@nFL|u#(HWMr7No!x{K@!z=5G$BntRaU;B_*?d~<2cp|mrP-dhOXd6{_R zVU-r#3f?+P?wX}B=9?!o&^&(cXo^jrzW%f9gtAodtNw&1);)TA);mFeTa-M<)S)RJ z+CQ@cRY%Wu9ZSZg^e@a%7MxZWWiOur0XfUhcBzie4s_g+-g^`3J~y=~cm4HMmC`3Y%h>~=WenbaqNkr^GN}@?SF%wGS_-6b|vD8kYN76FM6_Q9J z>0a7FZ_{q7p;=T$60z3t-2&N9nv+72#D?KM-INqcn#uk_+DdW_X}S?K9*1Z!2`1Ob zN}eVqJveA0RUmHD3OXoPkti606SzjCK;*3ghndpt%AOXq!T5Ot0anEp-EV=(l)br)Pw0mL6=bp?I2O48%Q6K(tlD7 zHhR;$LZe_MI!L&P&ZWp8k9lGM5*|`Kkf1qyqg)^+*?Rm7y^F;A{LnG>!c7?1z) z5{m0VrFi)b9Jq&G!J)5OjrnkB;@4;`T}qD%x&rH$V#{%>F}!n|3};~n@A8IHt@Rp@TVv% z%>%QY5BOu+SO*B3svOA~ctbFPuBaaUtAvPKLh_)ZN8t9$d(pq`W5Ox0Ou!t>WBU zuXDkihX`%X^!){=pQ@M@RZR8tz=^5TInR+qucNzFta9L(YMneJW}Q5zs%k*ZacNr2v3@pZ1-|^Ne1mSFhH>`yA>2%!re(*J+$_%ah80cn;ij!kK7El3u@l28 zZyhYuG410FigtS;$%_l!wrbZKXkZ{`e>ux>OQv%X1^CTKH}G-Q##HW^j8%DR{Xi|t z-{;^(f$GLdVXB*e@oovV@h`&CjRSLdqQ_fAsyr0c2q79xsMAUKAAmRiTCFLfi_~`=)~bT zHx4G-i1-3RY_8V11!A+z8hQBMkWWgZ=8AK}FQOtCIakbD{QHT~Ko59~=T z<|us29CMBiR$KG_SXMju@e{^lY(Eao^*rM--pb&MAiy!}IWk1M$T zW5M+n<1vBYvJssJmyPH=xYjZr;{?~+ObjBymCnQ<5?mXZ7{&>%O^n9`f-95pm_Ts7 k%Xmy6xc9l1yydw#|uc+nCt4)v;~c?9Ke2r)u9t?T6iWxAs(> zbNAhK<2vjQzjJk%oQx;}EDr3qZ{HBa#eOS%l{{ao8#LJ0HtkHG>#G2B6cks2hK63- zk=_2P!q|zaJAV5Hhx%^?nceVt|N0WoNm$KE(bmMtRo}t*n}Ct6fiaPYxr4E*t%Ic_ zk&q&*ed8Y6w{M`nb`C14ZkZRFk}3fV=tb9p=IvmjHoaLb5Ky}flJ;XJcpUdeNOU~{ zA%FogCS*at* zk3Z^u24rX+hP<8_Y>|?AyuTVqvO>K;6)c<0AzZO1R$DNKz<$0de?QjJ8xzcU*8apC z!Zpbf_?7XndYh!aWayXcKC=%B=DoGrVtdsp*kjoapTAYRKH#%LD=i#}$$+<3jAI$$ zv(WWi?w|OYs%hzbuIkdhaYO}IhSX#xf@k0HT?agNxseYuWV7aqU@RBLh0rA9J&XO^ zhhG$IGRyU*x%R5rv6h>zMY_L%(b|6g{*qxDA*AX|kGvu&0?ZPrL%%bzeJ_RsY8jn! z%@b;74@5pbOATrotVVWpSxWJZOex_ueb4TNCtXYC0Imp%QuWW}s41w~#r$3DM4gMY36 zj~1#z=Dcs;IA5$Sl@z}&Z|^nNHIaBeHnib5FWEyQf=A(_^H0E)IZsRcc7a%UJgS5N z^jPxUE|?CoclAU0VM%#mp=U*QvVA3@i#ey@z>XZ>)Ir}>h*(kIAg)N z`$|hj-}erSZfAzSd+B0xGM)E%jtg&nBGEP}k4Zs?T6$2~Cb5j^R(5Ji?@eg=6R|0$ z=h4!*0*_LA`AsJ6`QvdAncl-qW{EG53m0w8wn;Y6-{%hgC;uP+^jW9qW1^A(Ycnp2 z`^pvLL0P2+zzak)*L^2{t|7Pd>*9%`J%Ejim&0YB9m?v+PuqLDCL^=+JglygHaAu&_vG=IiKH0<;%iHg#hW8ghlYqI zaOjt`?@~#+AatrPxgGL+_P?GCBwo0^e5yNg;EIPlD^2!`y`@o#l8H* zJZvtr%hy_KS*)`3&CT}umM5>K9~c7w1dRLS)J&A~?)^nN@#nV!Dj2yrc{wsSrQpAc z2fxh*``ftVktFG}q%XiBYZ?G3+T!yH_NB)5ed<(;B@LA4kI$m(+)2yy=>D;!{Ct58;3R$yT%b~lu$t+8aM@0fkMV^k_=9WtZtG5PWT!`+?C@* z7v3XjI3(!mKi|sGg=UksJqm4C&}8BF=2y;_#xOA;V8~};3~$6qb-Jhp=3a<-wU_5^ zbpp>7tj~AeAZ}v;|6TS8b^0P`dI$P8Y-pCLOMRA=6f@80oK#kH(b}dcRxuupRwyM; z+0bkOOM`VW2^(ZLB#*+$7|-yP0>Z9?P=mVacFi9vY*NmO0e$p$L|!RfMES3Er0q!17s9>nQwF^9o&`^oY&b-g-TMuy&Fn&L#TI>8uxo8(k)??`sL|bCLzn+{jh462awl@*Y2h z%cTEw5~pt8wLett7TQ9WfZXpENN%yZ&UV$ zN;9a#lSlOKGo@-lCQvtia39;uI*os870H)c((}QmG<~1@-3l-a|IUcdVi|8*Cy>PT z64ai#Znu3{F_~MJb~AN|QwK(RSIeFEZ4Q^f%tOd3X#lZO1XeR2>i4V?S}@IBhC*;f z19LpxVN__l%wWOVTExNKu@KSzI}~T#tYy630{1^$e3z5>APx z5boWcXsa3BVWf|3q5Ob)?VS*!p7}G!oQ5qV!Au!0EebSYcp&7$SImP`a92LiSG0pl4A=+cF&}7B7Eq%Y z>D;4#Yzf|mQL#uzD@K|TjmL}wG?^p*;C?G{*N+VRHjl|X_;icKBs)AZ-2D*$o?)4~ zo5wr#-2t2<^N>NHyExJZj6*oPriIYdUKDZ6Xci(u@BuqlCP$GO82!sKJ24&%sRT-{ zD?rxVc_GoaZqXwE6>yuwH_GR_XRp!4l&X@By6VK;EzAZRE@5fO$f%L6F2OGTVIPSVpAb?|e#XtmxHX}KJs%&}1g`(bXeLh{9M-?JCxObs4kKISatxf$kAxiUx zs=MAc01Jy>BKmz`Yw#e~8+D)K=W#qUtG`8pS4D_Du{0QLDaCR65fhY7 zJE1iz&ocv(eK8pBl_NE73VV8xwe}yfz>Dw1SDkdgH|p&syd}%|!ey98OrcX$dB-SX zCYf6lEV<;mc;eLT$&!ES>doBukNP)&Bs7ER_B?9By3uO*w1p#D9U%3=hKjh8amKHr?qW^iC{ zSxP(ak8=dVc%#AUE9HIWRs!`Mq~DPw+2PswDeCTF)LfHO7~YV8LFk#ViC$ep@(R1m zDvVa(_8ykMuLAOsAIbM1#=;)GKZ8}o(T4`AZTIirUdK2giD3mJPvZlfByRH%dPDSH zi-x1btw=IrqtsJ&Cw54v-g}C!{Y^SV5iw|N{ zP{B49wHC%gSX^Vp^$MNIp{Cf~3=B6DV9JoBiqD2iC#{U8F*Q7W$TWMipAF=&Y{#kL z!H!59iWd@u?PVUa_)rLFn_TYf9y9#nip1rD4*{T<+m~z=3%zFs~Q5WC*W;aFMT%RSL%W?v!q?cePzk+q-i^dmHuMq% zQ#&G?oWURQU4^8J4~nr;{)YEpz?9(zJLy>>^okKvm+%{oKmlX;Z8_1va9*j=u+||* zai*R&xmq)-6-@7C$OkF~^mI=cH@A+}EzzQO{NV=4t$&a2N9^_~Pv@0S@AXb7? ziG+@6d#Oc~s&hX_lVh!nd|DF?&?<%RpJ{&8d@vb$a+aw}S*ZMI_z}2B>gb5>xtln= zN7VZ`9(i#PsA4Kut}3W0Xoe4Jg4c%%O|j~eR@<35ZAH$~j;aBZ$Ga=Yy*riv@~aTD zS(m_`aWuL`%k4L399yawZjzW}=sh2%dBUNAZ6CGSRV{iS}E_+D%>Es(A30bF83KdDCx(g|K_Tu^E^6q|)L%fYEE9}h}(yVE~ zFUx4kdNHGJO$;=Hp!G093{qQ97F8D6tsZd<5^O=fkpx=QS-9&|2G{4+YELd7%=0 z33WiG;{JnrD%gSf@JpLjgakYe*0Ntj8`q?)hK-T;IXSQI(x}iv{by!Z4f!IaD$@GN zsjWIYs3d*E6-kEeP0J6&!@98p?B-i7Q_)vsQ*wY>^~kPa*)&|sPb~i;7ADi>4oMVsySX_Lu-gJv=80yed1#R#kWbEaVk-W=U>nq4pnQM0{UIqBI0Q)JZ(?9lS>xs&L<=HLM zr>#h>9__4R0%ztBpB6=4euxVD;UR!t+~~F%>#e_^5dmJd#KL5 zHWgCpd=gf!sB2h8_Q1!EP^-%m&^= zX1jX3bD*ye2}_I_VLg{j5^i=q?}03}O|wpqysl#eIM3N~D-!Ba_DsTzOcERa5s-?x zNXFAL9FqTUJ~c3KigejO$8If^K-RFoiR)bcWH_Jn>{>N|_jyuw-I?B^gh`H%Soea>|Sxjg$90d zQCH}ny9t@S5X>LaMx`VqqFaQK<_tvh6im!$enuWqMK$!Qr`us@)+SA#g(5twKP3S{ z-+8MzM=^Mdhe6(Z_kJ#;4VB$JZF{jk8d7Ha9l*SV+*NN6`V3I>(En+IEk)!Uz*%m*~4u}n7 zS<5$kr(52KXUk;_(~uoedN){4QlY_>@21rm^$+3o)PO3Ec0c70xQ9;NZGvu<|LV6|iq&Rt z9G>UMaPO0z*V|Rb(YAZ+?AV}g?=(2`UG!-C_)UVrGZZe18m`UY=%Kz|xz=$I@SPh| z&(uqahUh;vOHYpxE%P*29reWm1wP~&zgVWqS)5?e1gVQtca5B&W@tiT3a; z*FRb1|4M2Xx;}ue$k$we_8!2$Iltl)JzozlkOLat!sj54EOUB<44)0iXBb;zK3C?Y zUNZ-utx)Tqy=c&!=2B1STu=aX5>4^>lX=~l4KNkAgP&{Fxm0uJ;#ov-{QMeGHsJ10 zi1Mg~o#|`fpG$8CPc)=Q__eaCR)U-nDp5Y@E39K$n+AvRXHY+q&u|Za_q5!stmOyi zGOje0a+m^_8h;PEC?%U2hha4TX3euzO*UiW=Z}0w$KncpM1|i7;g*7#naao$)~x?` zD!$I50Ytg+u_#K;&%IW>4>ICGFbhmisO7ca6FtNyQs%nvkw?!7yXS))+~BfOL7fP@ zQ!qDG;@&^DweP32o^Sjt!DR7cns(Zuq}YS^J`nU;OD}G4-YFUyVVJiIRi_`xw!F(D9X;Hi^sc<3bF)JBcLNBg4<8O z8Wa^388n()Wxh`x_<>}%bT-Yr?NRkEc}`t)fet1o;uJEkxB@-QK-Ig)ZBPnEezwXVe24GQ^setrOgD@+p`(ed(%;Mv{J+v}Lmw)B81iKQb z472%>d4Oh0Oq5MkzGVml8*%ykJN$QcJFi%7TvrU%OdKhb(()VnK_i-dq(v%^tV*{i zD$C*4MJ;;7pzEqE5%H$b8jOoiapv@z77&7sOvIQEb$rL$E>L~)nHO=`*86DaiswRh z>>dF>$8=y&C!@j~ezo5nV8X4dwIUGC#DImL#(sr=|Nh^31z1o6foe{Wda-P{V zx|%Uhhr65@Zxz_6Ig5cTGI_DXC`D7A=mU_>BHtnV$SE8DF^oIS- zxY7DCqp*xrg1q@7jgqa12*klrDp46DA-S!_V-=ZJfm;V=gIAvPj(nOJ{ar}TFTWgT z)aqsP=!zUs9u4j;%%EZtR?}l&cw2t*rI@28ID}Ndu+fj#F^@$K5F8Yi62T1Mi)zOl ziWaETC5ad$4!ejNxJR(h?9CqYAKXlD!>B{83vvWf`}VjOqsC8*LvlUfrSOcSB$7|+ z4O^2$n0VYCAXkc_Mrd}!lzHI;ESS=Gimf0ryG3HIiI&@c2dV^kLrxl{lObhQ#oRJb zx!9sq=Y1N|*Xij7c(FHV@SfrpM2#5wj4zQzEGu^xctAcO4GmhBg#f=3CGPiLF;9K6 zCsy6E^%m+9!_iI$b|U`)i$8B9BV<5g&VT2v6P;iXBz)d$-!B+hZI2>&R^kly@Gd+C zB$`;M&cN+u=i_*U4*|sW?a%g{pSjiJZwmI(3GYK=cC6l9r}K|kWK4ncO#|(e%|tjY z9RswnsnVnx2*_n|!n-%_RtX-tq8;TZ-5QA?!L7~53Cm7_?Zj*LU%^hbPlak1a9Cx! z4oX!A_q6#=@vw7)S)p9!{m2Y|ANEu^8P;7i7~|OY@n;<$x251i?=K;hmj27 zdgN|;wEI`P8Jb4y#_5A)k0M9#M*DH;o0Nyi3JUvc*EvV|#We?RqXQa`XO3xwwxY~S zyWNGMgQb0kXdua}TdMgG4_^}<@x{$Tb9nRe;ziykL#s1YJ8J#C(`%z!wn{*1Rrc%? zQMaw;vuU%3XS^HegO});>~eMhgJkWwSi(M`W5|oC{Mr)#rk8Aigi^o~I!tHY00^K9o$XPjHtH_#5sPX_{g?odpKN@WXjM^Ti@cEY=fNo=6@ZN-i)o|| z+kOiYsL?<|HS#I!X(FhCGK9-E2dvk~Y7o%kI%Qp_;P{!-(3O(?5|^_3>MuR@u%)`( z)^8N-c76T_?eF;8lvkEMldH#r?2o@i0QHVpIW&M;!z}W}QhwUS?z=+cV(etPvLyn4 zPGfLWuJ@X@z>V|JUl>j}sHtxLlCwRm?h|alR7_Yz^@|QaTFDZ=ik6oB&C&4Si)y{K zfwVCOrY{&}_m6TPcwUx~<{`G)a_t0+JQhS$(PYhWw!DWX)@v7$fhvxAoP(I@(9T_7AUM3$t6nQU~U@d`*@cjXR&ognyqZJD;i1|2~*gb7YF^I$hh@r zaV;ZX_R^(x!VH@Jr`s><0dAXWBz0U*g0c4|TS1jA#i3OteMelx28S{JypQN6Z7q#0 z5%mzuWLf+|g_4STF5{e?Eu0lWjHu9zSlPD5jMx#dJ|DrAdb2-JFD<=4KL}RNo9D~7 zD9=~2k5@M2eIuGFt$p_+pp4c&Ba9-LMbK`|cy2H3b!-Jq!RwqyJ<1ei6<-vwoNUfm z^pH%rtW2VOQSkO2UeYTzIL7Kp#qPAg1(+10qyGb3t0djTPff>;v3ry&)VI) z34P)-!Q`KgU>wFZcN~c~!Wt+;o@Ggonh#mPNeFs(YM;uYr*=9$*4vls*cHD{_TQaY znF*dqnGOv+W?amjNZneZjIXBAKpoI9E2I0_2aOX6nm%g=BfVRD>KKYjWk zp0cRVltdj_70hJ-a9F!J&1M%t+FyJ0**OiD3<8l&f#gIhQ8%o~m}(3;a6=JueV+g?%B4zdY<#vjL}@ z%lBd`0p$P-x_v_Jhf9;JdXUBHg$u)(GgP8ZA%(z8PPV#`_G^+(5TMT=WW2|=3OhNQ zkPzBem*wKVKjTu{BW&4rk(kOKgr5AerWnbHZyvqj1lhjpoP)cfP%-v-JO;W@Zmon_ z)cQ==FciQaRgA6I$4%n2Wsj4AP-?Gq|WvnDOcPe)m(_9O= zuk?0dKXZZHl=8ND35Xzgo8~{zOvii=*lHsQ{it^=-CS|cs5*Iyo*LCYrJ_S1hx+wW zVoFxCX`b@k?bvsY!4c;Fi>*#@r{gwy>TqfN_s0>HU->lXDd3)!XPs7d={ySD%FMBW}i!zt~Nit1N+ zM1yl+iq%KpT1=Z8{g$sithG-s;_b)$hmsF}}Hf}DNb@@r>;ko)fyZ!~? zkj0off0bwptBumU*ZBT0gw8u^9eNRJMgJb)S(DTtgsk8FF2mJXSQx$jsX|? zQYhVpRR%TQ?N5phzB-SVChN))f?#=QWJe~(McB|}xR^HX**>_VrP{YRIz`h2vlJD% zoR2-9Hyal(`yg75E;r#Iu&qd(#A>zCAy?&xZNkhM$hET;=_ei=Ao`l~I-kI$b$1W0 zHV2EA4#xniPxXfX+M~Ij&kTjb>AhxcK9D(*u-G`Yu`Taqv}lfAc5Sl)vLkZ7@Z|3n zze9(*_R|~SM^yVTZ3U!qeh5MgHu07NX`%QKI2MQg>M%p*d3W*eP`Xy=guvQ7*rwo7 ztEf>tO(9x6%TgvyutbXL$~fgs2Izd0zEZu4;;>>3--1pRkGh~J!E^K*6D38FmVe1t2qF3z7?s+-GglOZ`PejQQW8r;t-JP-$7n z3gaX#Zyep4FIFQ!s0>LIA{TE3UShS2jp0FrkAcvUK@%NLf9g_zA4S#G2e#ldPND8) z`N^?&-mQ8ea=oFtthi(CuVY(f5ffP$60-QzsNRT7AMnmq0|kXOtR&ztNYqJJSM=3x>YHwPyo(?H<>itT_46>k;4uorsG z`G?hie`q3p8;oT9JbqiKn_=K70U(UxWrT&BU|@0DNM5NVt2 zG&v$niTyS*7w4RzNwuH2|9gDe_&>-QtPJOyFU&M!K>2q(-;4=8EnHl`K`Xd`4@y+>K;I8C28@LxUhBp}>(0UiBh^Y0{_EgH zP#ySX+psD4P|rpr`hKcRAmCq{POtlzOBT>uvnd|S7ckCPS}P5<9Gfp zXRl}J;0Q1Ou}e~6(n^Y&Riu)zhCQ#PiRdPgc@4J1k+T^N>86nx8na)8v-gm7f69P^ zpW3S(8lgEUydf4ao-T#QNfIbvGMmqw=1KmGoD)S=#V1~+%Fh4B6cb4k96N|ymz;l& zmR-cS<+-td4H=CZxeT5#s8@$2MHet?%+RW^)-9y2)SPG!qeUuTY{}4#=oWlun}`CowhgmZs64JO`4}XQ zWg(Dw{Jl7lnEE2JFv6X5_fn&F97%bav|!L}C7gU{OQenQSb;7>*{PzJ!VTb^iAVU9diq%uzvp)RL_FN}+SyJc%u{NaFxO-aHaKvrM zAFX#)*tMt$Yu@Dj1n^{i*%AQ~g6Vmb!s(Fq;Hl`HQ|SEk9dE=PRzdIF8e1v-pD^T& z0Y-3>S^GWgF&~C7k#R;U`hjc?OsH70S0dNzrN-!l_O#i&i=}Z3*+>?L zonRo*pffPsAu+c4<@g5q_oI}mK06h-bIe>lvsRTyV8exC^8rxI$%U}^+@*QMg) zcfeOfoWY!*owe{3(W^E<_0;lk{G(EIY7)eNz}0c(TdbC_Gq(Q(b&RLLj!{M`G4{1_ zj^^@J(iTLQk!)EXYw7W}lrfe?@+d>a4@M`rUup@bdGn?EirvN)>A&C-0?Qm(3%^|Y zVH4-7>qP(#Jz6?`!c`Ssz2y5W*+D@>`c@lxm$V@(3#M#(NLM(6c{I4BTP+ggThFJY_;rUp7 zuDSz6$pFzM9Gf@t4O4{k}6;(Gals-z)WI>c~GKIMoajgbOlP zSuXY}krxpw_XTHVp5GQ01bcnTiCyE5QpuShh3jXUrAKHo-f*xfs+#F-81y?-rZ(}x z@*X|yk9Fj+mu=ESrka;ahGwwKtj+##z=8@RuEI?FGdinbvc+LeVTa-$V+j2zE|3Wp zu7o}m3mO1{(H_i^9-)0Qdk1z*eS{TA3C;Ld5_OhpG=vSD(ElWbfStTH%u0~WL_3^0 zB%<&dECtlFYdN$|*Y^2MKA>bW2wX8!W?A8HM>wr*c@1ey6@@!0vk6!z+yPsv(WhV!m0&b1f~BE)`iEtvxSL(TJ-K5F6N zLyCpi3x(`VbCS?r-k%W5XZhq@aO)3#$MB)J9IS=C8Rp9!CRd{BI%0B^ZT)#tAt8qs z!s-F}fE{#)VptW`TuYUc5gQ@ObF@e6Ycex#_n7ba4(c~7DzP&tyK~3LhY8EqyqutO zokO@*1kwI{r)sxFy@t^}*@NuNCEnFBrPJarszI1#O49Q;hhpO$#}qegcZ90Z5M-gG!Z zngINb?&zGF;#UI9bOm_J?&IwgA6xKm#%2}wSr9@ddp z)~SccKTTi{Jn;WG_*r&y%$RIV3u#qSNzsKJW^1y$<_EK#>c5-RbU3@Hz;WT2X%J%@ z;Ef{4s@}*`t`_v)2w1B9dlJFT;idly{z86Tl&Km7pwsh zIOqRzrtB+vpC>zRoSxWGS2JAGK3={cw~&`zKfK=#NJd%RgXX-aRDJYMg!m}ZXUY9k zhc!KYPAIYyvNVHlgbylTm`%r{T6gp3SD=v_wPrQ-UHRvUxY=Z{xI-h^?|IJ3<`DJ6VMgSJ3cU5IrVIM)|d0+pTs^2Te_0b)WV~Stg<5pxdSF+uhWD%dc zui|Sq%r&<6mCMq)Z)kVks-xpUd)2D=dhZH3ThtjFRLn*t1zu2 zAglS9HH2w#ri&Lzu^JIR;4yW@VDgb5^DSC=CH>vZU-29q}`Sd=NpzDtM z#Oivs+0|)N+ATPaV~>~@?^fi6_Rj4FaVFr$+Pk?TT~Qf0$468lvBCGO?~4pB9mEY@ zNEUa=Lt~?$R6Jq$?jq_1&F?P&MI7URdX^oUCJpMmITW<(`b%n{uq}>hdP2vQp$B>o zAy2V?r(PzPFA_l2kUw}AMlCzmmIDZ@b1vG^2iDf7d8t2kO31CrF_*WHU}zC^KA|=V zaUT8LKJrU4_o#jT2&0j=5(V+(mXIhc@0PzJh2D$bE1}Ru@?)5IvVC$s(zMq=!)M>Q zcqrWTGRQRiLxabG_bS>K*>F7o>*zI1^^nfwh!+6pmfL!RxV*6(oc=CUos}2$UzW%P zC3IDStuaF#UB%&XfoH9Pr~QuwAq?=mHKOI!r@wPo=VVp>6S%77)?bkYNToX;HB&yCE=FY~i^8C-#=IK?tm{og?5 zXFRq>{;00eVU|km9b%1RlDlf{-4Or~=R(&H(AD_|i|zjnj9*jeAJa45RqY;YZy*2s zSB4iv3~+Qs{_m6!b?^EAmO&aEv*8835+;~FJN+7(p5f-vp@?3k(QNOrMHmdsVbq$^ zfzg~=GLVPT?rmF>&FrL{;_{*Kyfqo1EABzKF|2p0;w$-K9?kL%#FDfP^LS1`P&NEi zhk>+DG>Kkj$wKhn)Va+BbCI<{?}Y~XiVdFkV|q#x;%Q%IzI5W&%To!~-GJBW&c_je{{Gm91fCA;Nn zy%yN7@&hGfZgisj;$k;`tAm>$k8Fp{7ZfTV5N~Yb^IV;KeUQ;$-4OR!>gpkctVR~= z!NYo%pjowHYrMBFvDF`anHp%R#*ABG*mdq{B$9JW1tEu!_i|P2#w^$RyAo>=s_N^o z*Jkgc)Om>f)l3^Ms)B;~S8?%0t#3g7+16HG4kaHpw1 zG`-KLhDCUS2vtjf(~)r*i}lHSeijVxt0+hxi!Zf&6*ruR(r!ki$b1mBtVOS7K)j#B z_?{oMyd0`y)W|tX#9l*)6@1>l;0Hjr@;@TGdSB@l5P4l7di7)_IDjO zSy@+y4mBM+eNyx9%jf2cBZ)h*K|(bvydw38bod<%>#3X3;X)EEkC1RQdio^hKlI+t zn`}_~Eb|6KHsEP?hVuiq_WqxEG6eTnyBz4|Z|HhRvHJzZd50KXF?!a3sF}lzBR`Q2 z{fv4W*+2+)i8QyuBo#l~xikIB+p_P-NcDYIa8RgC3eFpHMAjN5|<}P-^;Z6owINDqq3@EBz|J6^B=#-6IZO1 z#JbMP_jao7!#SI08Z`+rZ3WPd)Vmfgltko_G6*8Ho}-Ph9z^mvO~;DUIAA3dA-(!Xh*-la9t+lttIP+1tGD#m zI}C>}aSh;C0TmrM)`TIeRaco!N9Mi?id%Lo^aMrICepghQ)#lJ^>lpce1XiHv$c8b z)W=~wpPjT9U#M(Rkf>WRr&eme@j@ZIH6$UuiwQLofAKsxntTcR=xGn^aFUf3A-`u} z(!bC$5?tK;`BPr_$KTT5-;dJko=5a zx0!tF0DzQII$b!lzFzoF?xjv`u^;e7h4^LXiriZ_D-Oxbisb%R^2MVL!EyAPwfRG7?A*$PEyHU#T%5}&g&t6xK*T~aM zKm&DnQ&+#)_-Z@Cdd|;bx$2nx6=`#qTcU~;3oCophQX+;gudOy;j?R3oa#MMsDek< z6=%B1TOW94>#hI{UW%&8&oXP_(-?6Z0Wv-JFij%H43SeDB839^!M)FFao*{I=Nb`p z2n=IPJr!yVA2$4*pBZ5gQ?@VZMsYRszA+p8Rs1J3{=s^tpS*YL=jWh|W0{MAd`p^< z!xi~gq+qy-;{8}^C1-1eFdS<}apZbPPhyxuMiHq4kOU8(Gr=tSI^#>#Fk3;9f1YG5 z{IPW3V38$G`<~KFfw&T??ir~W&#>+;f5>^hc+pPy{fc_pA5ynJ7+wy}u!1Y9zopAs z%*!uQz5u(B*#3{GqXd_*@yzX3Acj%1#|O?edbIu%-OmrxS>`*5Prj*yw&KiN*PYej z{l#4c!WpyZP4L4$rY-+UNwGJKhsx+T15I{D$Z>h!)b+N+hjMwgY|%JKj3661`iheC zDxxRH|D!6#w9&wkccM6kbjAr=>+)mz$VOr=Y_kdv+L%26f6|<}FQqV6{b0C6as+f| zHM@w1o@LHS(E>anK7g?zodIUD=H3~xhkBRn(KV#ub!A4D9|@1}?jpe;m2)Eore|n& z6O<`|J`Cmp~K?H#ESnq2{C= zoERRep)*n&Q&xktRvJT12z6U_L++K?2j+3GQc=6^hI7U#3O#rsHO>~%kGHwZdY`FPk7OlC|kb=J6cm=`)X>AJJash?vIQj)KF>kR=7gA#9_lM)<$>$CCRUqeS zpDTLj=fK+7qOF(z6nP4yNeQ7nepvORplx6!Kh0Ix8oF(o9Fpl`i}X!e3#(26CuV>F z!*hx^yLb*;5$@e;Ck!7QNda$NWR*JP!J-lK7yX4PmaMf~GP#os+(XW@b?iOv8(Ld^ z%>9?~&7B`7dOG}v_;!9ere|GH0EOh!aa57aNSt0Y!IIn)4?_DA#(Ea_%hm&D75q z{736u_okzlNu7~7PnN42oO1^Z{mfv#DSka92UZ6Iq$c2Kfpo}#u;TKVms-jp^pH=t zH)Cd*&)u~b7jC*7*IXK7?T5*m6W84P;R^QrH`wL#SLq|Oa42s4)uT+gne*A9!~Zc+ zEPzW|<=%XcbM5%PxL#z^7BRiSxu=THZdn?z{GevyXQ)~|9I&q3_TQp-j4V?Unb~mz}%yg z%F|G>D8cyl-}-d87g5#DcJ(7GzXwa_H?{jVaIq_7#1Q(US|o)XAsmLZlCr?=n;hYJVQaZq2Bo0 z2R=^e&y{l*JJ?x{73;NggVx$ds1a<`Z8EqK$&SG#_>Fj06EDF~sILdnI1S03> zdGLG#b2EhJciHDbak-{Sgf*^TQjpk^A=hwQ|3I<(4fgl?mnQOjY2xN#-BjVE;#~%; zryMVxiN0cjVfWe(CqSxBW@D*YPW-v1wowIXhuIm$y3c&jT4pwW2yPV}SA$c^_Xaan zLrE8eg%X>h)(TB*(#6Viqv~|CbP6d6ZO}=bK0P~d6C;KbtgXXlsE}zjUjg1{|J~r; zQ;;YAork!E{zhv{-Uo(ALBG_5uv(R04O(vV8*vyqSf8C75D>n-^Ltk!?fGd_*h(&s2%CF(xomQXG@Ep{Q7{n^>@X2) z1Ax9^`5YV@JhPWyS)^TGiKSmjpxQFyi2e-7=aXC4Xx{>QVY=n{Q-_?qZ0rVqbwX69KL*6e7h)u2WD;IVn*mEC77a_7*LB_m4dxTrqzIk2HH-) zT&MuMV}xR7_vV`-5K+5CTO(XZD?P$TBl;#|zEKxg&Slgo?Sv)3hyV_H-8=S1St{G) zee?DD%1X9q5?X(Nk|!?XqZrJae3;dM7zJ0j`Ak4`cKPODjNO7h7RB#0F04Wb-8KT< zVxih~;jgS%_pd!sdIfx?$og^&{y)l({qN3Ssj=x{)@KaJ5ZYom;>1*BQH8PS@gfSL z{A|yLJXT^WwMNhBQ1DK%yS3v&B#m3tMTrU$RR1;~OHWTvpJ!*55T4_ zipn_~HtYv?caFf<*H=fMapw{OT-96! zc=R6kq3bMpEldaun`#NAcgUQ0Dd-E;-Ay-@Oj6Zes?AQD6jmp=HMAPLqtPtRQOZ=u z6>C@O`kD^0DdPoradB}S9qR2?{4^{@>Mf8#)G@o8`6&9Ht%5(!-jNcg^W@E!U_P7O zR!4h;_k8@BV}1xc=l0H)l6bB;SGyn|RvMFgV*XItB(1*RD#bSiR$WUF5-z@2ArcW7 z?|)ES@rExx^9N0)+MXP}*!W%4>OY>HXWVysv13Jjf8k62;2(~?S5E#h&Ru?m8k1l7 z9z%a){n(f-<4b?MCm!9n@?>%+zZmfD;W=`{GiNk$!ggYmX7j>*T)jF5EUJ_50!y}j z^YnaTy&(JOc>_0}DRw(V2b%H>k=>F^>U90!J$HwRGpNNq?v7ILx#~PH2SMG3Dnt^BnnKK`8 zKv82pQSVRwK_Is8<7cePZe}NT^fNPXR1M9?qVqK~#S`?|L#gCmpjlRD>UOMVh7awj zp5HOcJ!Z_Ss_EKyOOz@{u9%0Oagou7DS0M)DL6-gz7LE2Ip!PgToOGN=}R2AhY)y zAt_5yU|#9ftC#+$gAwdAg27t+?)%KJ^43}!DA5rMAx;N;fdR+eG(ysE+1US33<=IF6ejMmKfKzx-|SE71JhPss^*w?hxR ztFEuElr_Nk2agSGc*vM3O|Y+6{NLzd{PirVAZ&87|1}T%+EL7iL3(B|V5ek7u1MmX zulTY1rfEHWhds}~VBJ4bz`v#gO!Tm({p+y)Ii9WezfkrTP*Fzf!Z4u%(jcLfiUCpr z(lLaD(jd~H($d`wNK1o&vt&!hd=Jc=I;+lt>7!urTfnE_lNo9X_}?+l{u!p zXpXcriFUlceP%B@KP}_wDGq6}hOerx-@tQRBt666%Vp_6NNhd^Unfczfd@h~4_$GJ zd;@o3U9<0Vd~@*cOfn+Qp!-KZU2&G!qu3lgD(%d|0kPtW^RUbzgLR3G>|0zbamh0X__P-~OI4+e|<}sQ2GX zOh4w|2lhW}+|c>?4g0VU_ab#j+-OPMXqen+{_#@N9!lQy>k-s^3SeiH zC!*FeEvW9JcjY)*rU5u7)`g3QTQnX7yq7r0-|^24LJux>wVKahM?E?b7I+BEFL((6 zIm8E9FZ;tGh~-8sY77bM!gf`o*dfSrq+HdU4?0I_E}sqJ@Lx?sA@BUpj{YwxS8{;6 z*A>k&?|w($IK6rJ-{|%4`Cn@MTgf-*U6j!@k-vBQ1MiauWuDx>_v#4VC$U+PEh>0_ zsJVp*VbCuAS>mlmuhUW!?y5XRAv73?jKjhk&KNAtf^CXCMm&UYSeTVu$$*!a%M8>Nm1LGh4H=ilhRRh={VlS`nHI>ZyIejtVdbmFSNf_z$C*bkae zfIJ-V-Wk=Z*cmDjN8N_kIVtyrPX(Qs;@S4_577XgXC~*JpLN00_>FUXar3G?a@;*vx-$_|wyBI%3Iyzk}uh_bk&#%>}r|BN^YEzL#JTMGr-{u6dupm)c{ z>&0d^C0Opbt|-$M)=^w%-uWNU^*k1lk@P#`|E#vPar2?-#+whN-uLf|Ijv=TI>h>K z4dXux;|zd=FSdI2x1>lH2neVk|2ded~aVC(q{Wc4h+T_R)79%+h$KgM>-jnmyyx);UzQ0ov?pB)&UsQ#la2?oDU4# zlth-nHa&_f2&}J=J$RkH>#sQBKs*k+GgG4V&upQ<>(d=5n7=a!eJO?bBW8W;9Ic`} zi>}X0%hS5(A`+d#Rb5(K=%BpQex*W=px3!(?@lYWZ<#&lFfSghvOQ`KkahhGEB8M* z@>Q)g~__yT$KrO;kW<8o>M?eh3(uQ6Av!Cnby@7UASQQT}iZu#*IdgQ{x+0*eIV< z1}TJYqtMA)Cd~#xCo_M=AmU6+J!F&~ zmwyrj!J)<&DlowJHuLyBU~YTp7;fLCRPVjdA*=uUpeg>%Fo8+g(%?|(_wL@UauR7jpDq3Zx`dzut98_-Hi(}IAxQEH(d;ltT@+Mid8r( z(9GmNZsO-TN^UW?23pO+Ixy-kJSL_Ce3vC`4sD2SN~=o)U=(5;#TB%QP23lSyRBlM zbaK`K{3k`z_Y`J+kJ~d1Aud6HQ+3SF{c*9XM_a;&S{6D%llg>R7l?hA`%u;__RKvK zluTYRwWmYzP%QdNqZ^+*h#tHAM7mmZnsa2|2KvsXa_%Xz()JN?CmU@N!KfKU3k{Y8fSdAIM0y}u`_cAGby z5Rb|S8_R89Oq88+=$raCVN9;;RpfW(W$4XIc-*~CFaZq*>hE{vFgP-peldU>|6aCo zI`u4af*Zwt8|Ir75tu`4v{x}5I>^vw%We-m-^wu^@UverxBRP*nmKjZn0X;XTS(qr z*L(KpYy{VT^o}vDZpNsXxB=j9b83sjkFaOaqYZL0JmyC_-m@+`U(a5=$bY}c0XMwn z+_@)%A5$J$!2-*O!R0By3?7q$2j%O^=fMMhw^hqc)iZ+s+29GS>8QduJL+?hyw!%T zg!_4y??_56yBPLe)*pQHsSeb$VX8u}^vvXc1M=k0?{U{PO-S8msy`f4Cfs4HtCy1W zr9>Yr41BdK2V+wFmmB)PJ;IXl=rpc!c}CweWMFs&BAlTNT^P1R2CzT$TBM zto(rkcuVFIHL@cdulpZHnxvSXzypyAEd81gyuHgG8>z|7Pyi; z!taiNg{@#x!{w5;3KB!Qx$#5ih(HyC;Is@l#OHpwQ2Bw>sg1w1JSZ_4`qlRE&|(h= zbELgSm5eg^O=1(k)405W&AL;W>fE|;{mi)wHa}sRyoW6KG?Q~tiz9T)5?W#T82gEaHUciNakCnB!% z2=8NLcf58C{3@*~Mk=bRr>*>1|Fw8t?5>ys48*%t3R6ZQ92|t;O(LTHCN)Oz7HKfJYG9 zQ-N*5!jGt((%ntP^d;h)_Muz>15>%KxtX2b)+;+iK9hSU=n9l?^#PSiDWYKv)s+A> z!$WHTwo(_oFlXp=2l0}Nk9ezDRoyfs4Ob0@egY!#L+~vC3Z(UZuU+Q4*?7_7Y+?}4 zhA!mn^0vkRHg>&RCNwP!2JyLd2@GWyUG8f}>LCY9E>a0J*MIUS1nX>TC0yT|r>Qgq z%VwHb+>~$D)N0a0vfa;T5dIe}YzKD3c9#%3%_&WtCR^-?PRK$xnYT4i%k-Xuxj4c6 zx5QFnZ)w5<<4^vr)wRncri2L__a0~+x)vu?-~Pnd>HH*^@i?fW^X9PRu78>^^U2hA zN+-1~^4;<+Z~eguoSAu>eZ6KY_1aFe0h|0~8)rSzH{sx0`5sa7-_Oty&;E-;R&qD; z_&Q0F!Y;6q%p|4%)A`9eW$mwEMJ^@-b(j1!%VU!dCA>6Q0Dxiuzc*%bTTedufME5e3+5Qj`c z_DO)jelu!Sa2k!il`AE)+O%`(%er)9JVHyk$jPFzzYTrgyYtR;HUZ1Su2_?LN9F}0 zbGSV4dzZ@bTQ;p`#gQFi1GDRN2Hylh{<=&=!w+f+3#I(Yn%|q09oY9+HxQ2S0ywh8 z?LEx}E8Y4rk{kp+>@rc=xpi{Q=2M!J4+pgpu`Qo(1@LW#xtw>fuIRB@LDDQn^AHn| zuo2vq(9SHIl>NJB`93e86F#V@rp#2yJF|CMOF$r7NM&QH9!{%Zi^OB>aP4#A>V7NY zsd2nXu*GP#)!uwnQ_)E+Pj1fq$$86|kJ%z#>^}$js_n-Cvl)2Bfqn7lO`KO!Cy#ZB zx>-3LVq*Rag3v|YJQ4N>E+wO)TTlncA=vXitgd04my$*@p8I`idg#KK_(T&f$O5a6 zmXU-OYs24fF%af?JH+zmubMg5D1(| zFi$cY)oIb3%oTJ?P-!8JFZPk`YYEs%+aQ-#F1t88i=XIukIQ$j73y$aTyu26FT^jD zfC6ir8eOs*iJot|eLAc>`Z*Ij3U|-_U=2Lnx3;OlGbHYc-hD|@>gb=6?;*ctQQKb5 z{0B}w?JHI@f7n#`0^XIW3y-pIu0TU;F9bc+jabFGJ;h5WyGT9I$F7*%Dv<<)(C?0DJt>3c*b%%#oCR2I3jFP?Qd~iRWVI*P?s``VJokem<9V#az7GJX zCN=FVdFsn@+b{#Sm3;{T{XMw>ii_(q?(HiODUeC+M;JjEgIf zu%?~5RrSH~X6QmDnZ!LIl5@vIg&Awn_d(W|$d>55%JNfPELYRQUf<}(8rgds)OzI7 z_#JD(LHMgxGza1%(CTNUwGhc#3YN$D#OMg2xyh;xPgy4zWa8%H5 zd(zo`h$~>F$uqDF255s%FbRyrBdITt9)JAd+A!|>D!V(oi#=sQ0mhJs3E}d(OlPry z&p0Mmw82@|gpbXR=Ov<9smlj^4K)FEK%~Nu5jFS^j(~sdn*Snl|Bxq+ksGuDQ;X>H zv?-gjH@7z zPJSO&cUks!a$YX($u{wVKf4@Pp85n_%tfNuX`<#?R%@fw(YLN;%AE{$_fLm}yex_? z<16su3)Sg6d-Jkj%=S_fZ{kR{aS2y*$bY zxoA?7tT@zKF3^&a##i7yaxs1x+3`sT6pkP!Syk;)2K_ev+@m&1A;yWf> zRY8RdPpOGP9_q{3Wn9Nqq<-f1Zv;Xo^8)Ms{1Vv#H-!N!pTkl-bKV&>gMH4wj`{Py zJ}Z_fT`>rp84h-nu_)*y@GI-oXj?gfEiMv{gOKUf+n_`T9HD0k;**|?&|h?5@pKK? zuU>P>B1o$mZVkEq_BXj>Iq`BGd+e#co}(w4@Ag3ve>C=))dpKHoX$DAxANyk2$&Nj z$L}4f9#!MakXfm)80>}V<0FI7u{E=uvx*TMMoX$w=($|y;g(#mrwYpiMzXaWQw9sz zS@jAX!R?C?Itj)y>}KkiLA4EXIo`uqgwT3b2|NB~;9~#$X%CKEZ1V6jM0j$*%p1m- z3@=+*_4S#~J71Mt%8*_1`+76#1t-+ePd@(yc#dpe$nU;9|{K>h&8h?%$e- zcTK{K0h`cTYSxUV6W>5Dd;8xdqSQLZI%aFTt@%$c1NMn$zT)*73?{tHs^6DiOr95N zya;&jlGj`M-CzmqB4pb2d^;=nEifYYk z{dswL>&uuVcS)9H1-i~zE4STS_hQQfi)M**u^v5SuL4zC`t zk=SX!u{JWu{CjB55%W44yN>D>^s5R^0$T|cd}k@8kVqT&%cF81M%gK_(5&r*m3yBu zT-4OjvHGSNmE{Rfw9>K1Te;Xxc^Fy$iq>c#~VA0RGD4wJC!cf7R5=Xhprqyz1k zcCq;m)rgei5HFHFR^Pf(c#(EmHn*SO?GRv=FEiysa`gTB+V2zK(U&tt6S2uU8A}gh z6Tr9n_>*kQ_P zM}GXT;QOW%h{r7>K#3f9wzlW`2>}@!i`T~+eJ)-9Py>}AmpW~+1`=fyedy43@aE-l zIA@m6Vdxsmk zmkGf+GMzh2JOwn-FA?pqTpn&)2%TP4?{0$yw-ta56v-Y93`nDGkjT1hr(~oo!HA`d z;Njvhz5=Ip?Sr7$_1iWFmh(M?EH(0C#|(#|{sg<|v^=lANe_){PDqNr*@3L81@e2h z-<44c$h-B?a?C~Cj)hadJq2FZYZK>D&tW!hnB&AzVquHsHZoe{rbapaHG}x^X4FIq=N?3!2u=28@Anus0hMYBRK!Zg&JOJE5F%!Hk4_O>L4`Dgy z=FLZ^Lw8_0*}CwoPnH6i9`6ormKoC?` z4um$$@1B5uKYh-JA=sW7#&dNTBm=;gsO;LB_So}*WhNMEZST%`%raT)Kr6F1Ztzny3LxVJQY>>3dkmZhAcv_cWP;`5V z*UpLWUv>YrU+nDqxW1PZ{|MTaCWqM=Y1uAYQ<=+<`<7iCjX@`M8lAD^9Sp!eOrNc- z?aV%AeV%NW3KR}o=|1OEFh4kRu&@P;o&Km+2ILghl|RI%twOwC1_mx9OtLHhWk4mW zUD|{2Wm}lXVbhiX$c|$n`Q!~H$P>E~%mfKYK82y2%}atp8xh8Tuc%x7UgsTToPiIU z&O~;j_wX>oVPG-d!29^TxI~MMh5P6+y2kS51na1`(R%8_067I7W_*eW3|?=scq#zC z%{y@pbTthb9d7ZP_;ZsZFgd&@CEy#$G`}(7ae=YeyVE2Az_XQWkF8XTthSjRnRIOV z1+Fa;G55hP`s2lOXThsi`L+bx=&sR`8ufr}z(4Wwk^;tTvF;$;*$s=7txwsyBFbl3 zUKwP%^51??K72)F5tfSqFAC{fznmn_)meMi31}rvCi&)O=@TUhBVKENY;-) zI)Gz8(p+&X4NB|nP+76i!CAF_gA8kQ5}X@fFDxx=4k1})X>93rIIggAytV}PJZt)_ z#*>}1;{tqaeTtIi-x|sLklnLy&L!+Wb_%}S^}3ti^UHCWN3;zE^{$6!OJ_zxX!@$7 zC_5d*%^3rc20(O_J1F-fb8JHNv+*q)a^T6;L=5sXAn7rgY27vDTf&M;5zCOl>CSDsa zryldU38Vv{btf`i`_i{Nmp>*~XbgWe0rR@?$sLmH!_?_sTAv zT^BNm!G8B&yjRii$`a>sBNHjsqY{_Dl7!qqIqGJ<50DbR1+iERSHJ{I4YWF2Z~CZY z71btJ-P^DOy~tPFMo4h%!ZGtdx`vxmfwI(+`OZDUdknC<7AAO$7r+B2&p(zJoh*Y{30Hc$3{+T#c?feMeD=UM9txBJ^i-Les*IS_Sa}Nx17q{|X zS_yosmxLP zj!~!WKhmftL0t3@o9i09WH3kmuhE&sLUTgLANJG(&M=V&64iCTneq%k;NT`xse8)+ zZ=7>N#!=fPEJf6M%)J;oh3z`i|D+e}eO-bpG;cxbQ)r24aqR_4@m%YH_f*a?uL1!J zHb)%w_(^2r3joMHAp>a;3>E^r3~1ug7xPDMb^|?}1RfG>mGH3~_8oQ#pO0D@hC1C- zjTOB-bm}(5o8VX9;v%p~!4n?*TXajremPV4B&V=fi;Y?-i*tTORHj^24oOA@u)i$^Yk`_#Zpt%Xa>LZN`jX>RTMR7xNQ>aw?{q`CZ#9 zY9q&MG*EXnL;Uv!44$NL)Lwc3XXi-1P|bF{oAs6EhOO+BKnPWPGFLsHQ%4l`{>4x zGZus|Jge0RSTo3A$0nlR8nsj#BP&Pt8-9Lx+7w55G+pEfV2TME3Ys_Sws|Isw zf%W})c6;>k04X?@{@Nn}wqlhP%h+J{t5Z zcn`lC7|~SA)0ey!p^1|K7Ot;$2c-ol4CZlq-l^XE4)KL2ZOv7BBpMEPIaJ5#RdBpN z%Ek!H!P>mu%DC)Ps9?K}rDNyX)Su%EYtPgxP9>?gUz^p6u6(Yr$;~{qRsVi)%Rg73 znrETIBp@LZ%GTi`xU&gYtqIVkmwiNURZTH?)QMq^7fFwd{@cZdE0sN zn$!&32N7Og69SURsG#>B_V738`i54m$~ikcdmr`DR~S$5;|uCxC8V&IfZzqwe>1SN z$2V*$;r~0U`hPEZ!@vgdG#_%!U#6(?(#7;YPF8)wc>m_fnQZuk?tV;sTwGi{ZzfO& zodeIy+q<5{&qf=2?8)i}K*;{^Bii`i{e=aI<`FE_CG!nJls`lj_7S<74cvAhfJOxO zoqb|k54}r6*m##^GVe)`&uZ#oO?c1Ac%TR7MA3yHEqhg-XUF7V*T@Vxi3*rn$>&;P2)Nj)L46McT8pX=-YoS%+mVxU!$- zWATf0D{aLw3kk-dX<4m1FP}MT*YUu6H4opg}ISY zPu(Nqsm`d4P)!Y@KowN=SQj+00o@W?s)B>Rm~itKidcrli1N;(ng_ajzBp0kvE91) zZRrY8D&cB+HG`EFV4)TOv}2l@HTxy$@=`T=vv0d{H!?hAxa`m2W1V9ca_xRj9p$Cw z_JOFge%zvIed%vE$DBZOCR!BpicLD0AcDM}T}(`GpCuHup}9Jzpaa>MKRP=oDgEZ9 zv5pK#OhAhaJ>^&Ur8)eSoY_H=nam+uv%B3XRAPY|10#A-;uWet5GYg{x%gCS3PBs1 zUC!2Qro8bHlEMupFVj_es%l{QQp1*bP`2%gTfo!aF4gAy#T?mGvtgv{$OvmG-Kf&& z!08q@L;9>VHSeD2rN^s*jc(w)NVfm_r(;0T&$k@M>zAf1()YDkHJ)m5a*1t=u1l6M z%8=!j?PF(RNsQzRk-cH6l#S)2N$Nj5M6)M|HNp({hprVY4RfD?zQ66D_q=7@#y@gN zhbaY<3G*|5w&wZ<2FywWa`^=Jp19^}5y}u?fxh=1(8ZDCm#}0UX3}pxdkdQ0+h%8d z2zy%A^KMNBtymIIO4XCH+L3T48Y5}E$5SPH~x;Z#yaTND!tR#?GXoAz{T#c`qF0v zbsd9D$SU>HQ=c&7XnTLWrKonDcBmevA5MB@6DG^m3n(agwIz>d%h*7rHK0;=yylF z9l^AC&?Oeq#pIcW*O5}~4(BKENZkn{x#dyGtW2}Tro+Xq_NEe!{AIYB9X?okw?&YA z6ounaOGK6KS{cT1m`T0uFHAsKl1BSJ$t`(31!-ENrpfzBZ}`C;!v65E^k9lc&T%Xe z?e6@?=}BnmpgBZhA{^nbpaRbOp(DdE=xjr??GXNY|FXhb>aKJt_KNZ23`Ul>Ve@BR z_UA!_L)1%!e3P3?W;UO6u@SUJfqo<}UyiwAUr{)Z-XC@Q@Xc^A^_mRj4Q{yHWnSd> zy-;7>d4zYy}0 zi4B78G(g+1hx;%O%6{3Tt)IeIjfk}sQIlU&wrQmq6uRp13-M*8*R+)YrY0_m_-8(= z{9=ln!3qJSU(Bj!?m{**^k)r-YAM7rrv-tZ9fH4Df3s9+>vCrt1zmGYZoOXMXQ7ih zA62Vgfgg|#$gLWzf@(DAh|w>1LXwEL&_}!5?Jp-x?<}4A0+Y_FyuofzP2->BvYfXD zDZ|3!))ka8$TEw$)4sGm^IMP)^4tL^p!dm*4xPAq4c@qJgbvr7hMbT$2X+W$@a$sO zO@*2+A0Dl7CpoT&H_dxGGT&zHku&C3=m;r9FyBhEK8c8p54$=1cOE(z<|J$N{Y~f| z&JlNh`dpLpW29C8PZi;or}2^PoaNkr-FEPk+k_q*tWYvy3lSOm+9M-Ykb*8JpTlD} z6>YvrYdYLxm`!C5Y466<`QLotRAF|p{mJdIA@NxaiOl<<;IH?;^0HLyZd<%?mQwxF zgBny~R2Zy@WSh5i>JKVluqB&ELb;G)9)mvuIPPHe>Gcyz$os`RR8x9NBzEkMrwLi@Wc&7ecC zPn-j!qqBgVvzgk#kjcg`nQmSQgv=U}|2?kIE79wvLGx#M?UlAni^Z)O$CRW&TZ6=^ zg{W1{w0m=$=@!nJQ7VWcS7KLkUgHRMI=sGDw&+kQvhV$`?3q8!J1>>glEq#GHes2~ zssnN{Vj{|>d$WygD1V&=h9CZqHokyJ$h;U-LuBFjvtM4WS+z@-7w;Ae+gyaTxudV@ zP1eolM7QRb&bB^0U&YhR0U2m8*}71EHk)jobZ zq4q+{sX|2_yGqk^J{=_4_~Jq5D7_a&zs>ChNjABWa$VI-e&W+b#MeKfy(jH8eWD4U zlXeJ8EdQ!#xoYuI(x56u*;JXPv8a_1pjz(m+rP{D-4ln5lC5t+VV${OvBTcdw*CoQ zal5xp9-iPy1(jd8Ic4%mrBc2*jlV}AMhPHZW8c&|LI!uVL0*N4WWu`Nm`BZF0h({66Z zhYMn^ETMqru%Wm$wTe4Q$bqL+LnTi_rKmUC0qj_v3U}ss(K=UcVzCeHA2TDH_snI& zNy4$iy0AtIrpSxTI&P=JaFA^GYhh0I-a?9Yi|3TEH@IH5;Yu&+@mR&45kB2`XBz9R z>hQW+@EM1PM_M;r9XuvIR4G8;u+E~(9jNYUA=tKe+9U0C5u|kY^^m_~@5z&Usx!1y zJP1uvHVX!!!!8dJOTy)9zEgMA=8NG1lu6Pz+IH(7 zG(<2dx4+8E-0yx!w!6+qde#7K=~H?Y7kcMWdYv19#&P>QNz#RU)df{_KBLi%Ccs0| zNteBhON9jg#~A9jq~aFNO^p-!-=4NOtWpzK&XnHHyK6?9Gn06IGv>Ofk zf!8xJuJGHe*ZNWlLOz0UYGflvPsw=$wQVTgU(Elwboi3|JX^E% z{L|Psfr2MWnrSU%cU6hyA@*x%9dem3UVIz^@BZq@zm`ZXES5P>vRqt{D$;7(5Q@n~NzCPS9!Q2zD z#ZqS}b-UByx`VYNnSVJeKuvyBncA8#1Qe7`5{V=Zmsjy6T&JnNJ>?kmtO58FO~@j25-zH6SPA zp}2cbajwQG=Y&ICl{sw7+U5k&GU!Q>G9j(~));@D@JB8z5s`E~w1VGdD`;bUm8%w5 zmB{&liYbWcW4;5euI48G$McNfH~Noy9Zn4hLqgT#vW+1ZufN~YR7>kAzKt9!(BHa4 zQJ4enM`Bl{>a%Re=n(3`AGyqSs@EPVeD>bunzA_sU2qh3wVazaohj_x4oZ>tQbp<( z6#byRGeJZ!XM2GB4u7D*0Vgk&7K@_Lifxh{IvO!SI*EE6d0!^1f~15K{x--AVcQIk+7>8ZbIW{QDbpfX?egIKY=HC)#C!OU zynk9ue~HWiIjINd4W)gvIi z^dfI(Ji>jxte8`jz0OD4l~R9+Kacaj{L; z9s)>({S<`ylL7)e@wY|lN}8jBMrC~i+_*k=)hD&*mK9zQJ_NOeig}>c znxz|!9Oys($^2vv}V4v47>N@uzV}Lbq>> zsjjDY7U8tH@!O--kEUFNBkV)Qnc7O}i3fQ2L&2|EYlXK9>=M?IxrcstULy4flGGm! z`B9DQ5NlJ9<dMX3JbP9BF<*j)=(*4^VP1didgB|03MG)Z;qcWP_qqPNuS)6D zU-;!=KXHJ8v7_xX4+J=4D1HB|POV4{3hCb9vn-bIV)Op|hL#xk=%*bbb?&=Cn%x90|e%HA0W>V-=>1X#n1B3x_ zg`^dMns>Ne#b`fe&JqFPTYG@nk45&|ujv~M97%yGjD!Up$I*rv`9$5uOR`d4SGn9p z4lcypoCX_1<9b=nRhGIPzUSWpOu9V`y#DYhh= zNAS+IKqM-*d9l98@quu$9_H~v?!G#_Bib-&KLVCpZn7cbbXjmkMbX-&Lm>0mE9f$L z&=vgsg>U?)%ek0V_*TXir@aPG-L+hs@uMU%Tobq|`1AU-(YMtK2Ik~~`spX^0Fke0 zKb-D(?t4X>J&byqAeVq#jgX{zWhcHI*8IJo&C~0UNw`}Ib$23Jt4L5@z&*C>R%hnz zyDWpWVBHrY-8Up{^w56g*=NpMM(je8txt?exjt4}{gs2tKKH+yckfO(M4hIhx~^iG zi0L4z@pp%)ane+`c;E+?LDAL6L_2YYgo03u5NiM1&uJ*(%6z|(ZBvP8z#o*MIngP( zyd*%7^e2hb!kC?a8uQI16wfb6C@|hy&U762!MBw4PQSDdQ(W8`EZYBr7+cc`ka4gR z%j{;-*s1RJG1R$s#h7{{##1M>1n`ag1D8uDEqBl3HHDkTRn>HlhaJDFr9aMgW1~L( z#vWsCuyX6h2Y9=nkLNY})(>(!ITE6hiYeh^YdQ{5oMvEp3R7dx@7Om|e(=OI00*(S zr^%f#lf6gDVO7#7g(>~hB#>TLEa5Jx^X4y zs}diNH`paoQ`}ryAx_iEE9d#A;c}>N?u+_zfGcVJ{WJ_mjKIQ+QT501_pB`ZC^!(n zdMB-0r~B?!BN$A3K%XRliw0Zi8 zXMZBHOTvmPS)5UOHNtGEF{=>bV?y_n(8rN^4=mLXXO%YVoB@eEcbQNt-;KArrcizG zYb~7XHL5zI`le6Lm^Wh&H4s}E3oe4|&~~c(#}9H+nBm7F+@f@<0+$zKM&p7}%@1pI zbpOUVaPT^h&Z7-gJ1Xyt#2iy4hmDK^?#berv#e}VZxO*4OJRy&ZODDq%#_w2HUfKtm?Cg9Mje ziav(aKblWG%Ri9Vw{nzxo=$-lRDIkdt*Y5b^vsOBUj%%aDB36idc^qVNKoo=(lGlK z+{jlR3{m6D@Vfvy1=;~QvM8)rDStjTI|f7W%Lgr_`Yrq)9m;J#eew}{RT2LS`#r4t zGhfR?9jdaiUIHzvbiVmp^F5N9U+9}&8X z?q&N-sS2OfFt;(Hr(GYPutAn%nJ5Tb3ceI_+KRsLEtcRot_nvu1gIueNgE`UUXmWI zC@|_kS9&J3@$!kF$D}&kH367d)R5S3< zXxs>snIMY&%#z_wEI1{|;PC1SW&hl8_&&xa%v5s4x@xT*`EVt;MOz|kXIk(G8lPBq z_mU&>nOK6jPQgc4>kH5cB69aKTI8XGi^ngGCBF=^3$m{;rTHSow;n zM!nDMoL_kM%YwSJI`@&{X`v$_v#mPSL;TBEF*U#@KRqN-aZn)6ZLx06Ve}Zi@A`#n$G+(@B!qK}fmGc#}{{3^#YTa2DMa4mYr6n(Y>h0-SUmgxxthqXG-3vW2h4nT!2gzLY$si5OiA>+3Ub_423yXSpe~h`;EG z-?a--@r~p7V}!fuos$Srm`3nXfF6f!w}kUUKXqRytNDY0p^YsoY-92WeDTU8o!yJx_apkR%z&sS`(qb6k`RpNxS~Q zbl=)0)iXIt(Pblldjk%~a33A|9tv94ji4`nZq!U3>y?Lfk3N*waRmEu{^ZkQUL~JP zF1u_hc=OXR4VmOLKT3NK*p4GPDIN0zpM*|bTTYEJ=lY;cO*`Ut zRNfor-B@XD(?qxj_J%*t(vp`^2tl*Qg{^*Z-9{*;zU92zUP?nTpO=?df_F>%D^f$L zJJkngY7IFE^?Cp7D1w_}_IKE#vz)67A|6(2wmKFdT;bg)Nsgjo2B8`v*ZPc-cgJmB zd^A8zTSPs3e)p}zOXuR4pVhCMeRmVlK=N;<0;;JiW5cg0HoS-@+^CJyO_$MYs{h!l{UF$@Jy3uBbwSH_M=b_zIy;t9wQtyBQ z+F9=r)?~4>OG(WKEC0AugA0pII%M5TAM=tXb-iq`8cEpMjpk7-1>Vmpy1AD;UU!2! z8L8plGMIRCAee>QnP57E^!MLem$MHYm58ZS*jW6=9Xp~V>Bf@rZ{pXEQd~G{6b_~3 zO%vj>Ohpr|j(4%jzt-J2*1-kC5jrs@n+<}}4yEu_%|6*Re1_iBz=JOnlW7PK!gpSS zj@CUFDW9_BgXEhJ{vI*rjo0G@x3DZPyX6BohSjc9N4~S%n`v$L{5(Z+3YxTHRDUDm zo<~MY{Zm`l_6!X=vrzxktXo&OM>&vpK;sA~-%R?J$NlKfyh(YCa_?VKmw6bukNq8bmT zWJ|7y*NK?75)v~VTPU~6(Mx6-mN9KpCMvOc(f)ETnT>e4kYI&MOPe?e1rp(M4>yKp z();Qp(-WzGNm?Gmu>U`m8HC;szp{8Lj7BQ5Ul(@oDB)WR6Gdp1<#u+&ROUs^ z$qEA&gJn{3bW-Up`6!b}&SXb=%Gg_~pkndYE20i!* zQOVI&73XF`u-6g)#cRWu2Vuh^hR*j`vw8|HiL#~Ef*NPbpBicbI)a6sU9T>%!kbBy z-9LZ+Nz43`EkZmxo7_)+WN@45MU4Rs8EruweN4#jX__}l)3o1_w^AhpT1vdWeB!~>D$?Ek_99F6#=}5;XijL-al!#}qF>T)faJ;0nIU??@@%jVsHKk} zSJ#7S@IAPqPTi{FNrAt^0d^^N5hr7hf7xF3J)o8GA^m^TWaSnZ)F+oar z^r?ZZh5J^AbQq*_eB~s{+TvKSk%0}9y-!~}V=cH-BNxW@y4~iiZ@NW3YBAHs;~PcCC~s-lnrs(N*a*xzo5n;c z1(W2oQ&O*h@%N`Ix{sP9J@kk3zZ&=xETKqXgZ!+NT&xQ@#;6%Ne4hnFvCifmw+#AS=D_dGQzx>6i)rQh`hoXeF5Z*mzOv36GjD(ta#O2I292 z=WR1CWY+dq^bp1EV5q%`uK)8$=JqU-K^2BP&T8-EjG!giVt_%gD@U~l_y-^l?@+fU zkA$f8xeqk-4@@}7rN222lr{G~_GkuRP3Mk3@V;i*-M$!0A^aWp=f-YdO|qA3K+Kf5 zjQRiCJM(C$zyFUbLX?V!%#1BtmPob=Nwy@VjSyum zOGK6yp|Wpdr_f-G`QA)lpU>}eKIi*8^E>Bz&hL-8f82T9*ZX;2_uj|*HD@^UzIPg| zv-n0AN#5L-v_I`B(&xC+&%bEyXrqJ>^%r8{Q?i*%j&$ceJqHiJJUAU@w))x?+Z%c- z{;H$8TspP9Or_#SQ}DKUo2<43F9;=WKSjS!^+LLedvkkG!2zBD!5EwNrGA1-XRL>} z)j^$ztN=mU-CbqAkGFPoP$cXG#6FKcGl*zeMYiEeezwoINlS1okIa@EP!Jc6O9(g?=o#Vi3{6baYFqAGI4$+&++nH@ts^$>PDRJXB6USx z={hrWovy4(a29#=zKR!lQL-0#qJpnplI9G0#-F>r3ayl5lr^rKe;0EgMY``N-zk{m@&h-oBm{E%MYh)6(3)mu+!LW31Uip-iGPjzsaHav!!3jmR(RBza%@ z@Vfu1o*lcBiJi>SD&ioy?kM_o`3R@m1#)464Y}i5;_T!1>^()4( zatw{NCeC(IIpL|4HHTG3TunxDoz_&7xLWe0>`bV5;wGwm-GtRWc8|1(uv+)~E@E8x zJmsQt9qqSIjs&V~864#+%}7$##db}``^enLUXoNNu;0X^bfLapriH=oC{?3v+crKX zf$#llLsNG{nlv&j5A9wqiRYrJ$B5K&OuB9UHYNSl!6ByNdAxlf?uN&3@zXqE7UBAW z)7E-N)GBdB6K}6e<<^#SUT-T#>iL%KQG9OvTvC5y1y?`#$edU5%|aKq>`3l?;K3K> z-zCD?BM)7Yd4HWd!nFu1l0-F){Lsi#Hc53@X}Q;OHoWDn-ERGBJ45d^-`YfW(P%;| zvR7Ih;2N@0X;&&61^9e>N z=e=uLnva}_N>W~w_sNd!GIODR-71nG>}DW-@$`+_uL*nuo2yQ3#|#uy^_U!wmf)z~ zP_S;KN`zbY~JjCvSfKAF6qCwR{zciU`>A%@cR6y*X zff-cYfy7u+?k&tcHp(W}Q+RHn{I}FO=QK5|MVd(6Hp77(jy}Rah}L+%&b_U(2nZ z-*Kk!vWnC(tcPfB)o4UQKKSeAlM(xFPjwEdn{g_6qbSXZ^7hiErftVXbOl2(V!q~& zwTEe*5yobvL&^15wU0#Kl7V-8DB2Tww&)59WA>!)bZlXPM@$9jaqHU~t=z25{Dg!9 z>Os}TiN}U9&?Aqg9+4grEZa?f49xrWY#4v+D2pLS;x>L*ZQXCZ-CM8^YdEnl;Gu+Dov)eBDKE~r>M-*JUb&m0{s>Bpra0T3(cEgKE6&I`N!90^ zh31>(1znLaAJ_4@SntG}!{q&Lg;tXgu04I?#@{}bOZa_GXUT)TPZ&7Ml1V8OMT{vL zE8xsEpDNRmF+TQGnEtnw9@g6G{$OMp_r1^0+^Lm~BS_NKYn(zY);`Oc{O{t(yL-N# z@_GE=)3Mp}*M78|NUm%(X^WAFw>0^5b zqKR!G#bI8o+Ch~op*$B`#0$POY4X&TTE575vQl32`N?JSmkEV;-!3F8{IUA7@%~q% zUK>2sEzQ;6RHHR-J7Ndd-I90y_X~tWUaFSzRw*Uhz`HPGgr1nCI<1Td+N&W5x7zqw z&B(wJiQk^Hl`}Uq>?<4ogVC$mg zpO1+4ANc2oJ{j|ZM?||-!C7=W>%Q;g)VQpz8|joYmUH;<_Oe@&EK#-`$5`cgC0IUu z*tm78Nqnuxp?I;zA&s6A!BetMI|o#~{L}cp(F~U*`$pr%DhX2)Mn}34N@{AW)0Dsl zfl$^2yXh0;;gi_~d*kZI33hqZ-ka0vzUhklwy^8?=}cD8w&AI zN`pkZX>JNBjztz9Xu*V3%rL%$fXCY@+*K1ZnxQ?kq*%YF+U4J&MY|_Ne59J>2FPZ# zDwaK}t-+I4V)4|VtULFqUlvlt zXp9zPNv3+0VJE22aYD5-4R((*JvR0boO4&)0|Nu5E(9GUFClx$FP_d-|7y?E^aAHp z(@Dw0c;^W}*>M8YgXW!0IZ)6dd(+d}yp5!NcQurXQ15(KVVAa>e?d8)K%@P{Q>c|s z(dXMpwJp?FiSnx%1`p5^$C3Pi_(~{7r&w)J zC&0k+3r&A)HR{P6KdE)HG>0c%+J)$mbWv3sR1iiSxB+b1GK@JpehfVnQKye zkVt#bn;Kfs)fgI$e;-BtP2DOk|8f{fovWHRopzMvl+S7*3v_6IYY@pSY<5*Q_V|{W zpkb5f*;NeB8(@-}c=}f&1i!#jX*c*b^QO{>{2o?005iFD38&l#Nu}LF@c{R7%$!YO z!x<%-a+YBDT(9g~kMucegsX>OCG7_M$goInP-A#PHMv&?`ev3|zeP{^|8yXo;O$o{ zHzW_~=EE#lSY(8qP0Wer`hTdPaabvoJfDQ{UR93BIM zD=RDi3L_&U2^5k9UpFGkN79WTLJ#uqINA;bG~U^r=!|oN{ECaR!+8>sQ0T9L*30j8 zVcpjUawGg^2PndPQ0_3elr(HTGU$i^OjNY+4k#iHZ-T?Qs?k@j)q z5IE>11(#BU=%diiZbTfx2?6_izdtAPXGjNa6wyHqfC7l%l5k}cxU!0jvI-n-@t6K| z(cil3>Jfe`2&pt2pBDSQJss8H>U=z}($12-u&_|2RMTtU;!LB!#VK>A$DG zes}*X#-H5(E8*!unS(F{mx+ssiy;CGiJ95O#KjN+hQ!S5V&Yx_OfFUt6yO_8bBEXQCnO#g=3=v>R%*-w(E`|s&BxYt86Bk1S z7!otHi;0UN0t|_n*~P@g5CMk7%WQwduI}#co}QlGwGvx137VkL4dACYf$_IXbpJm(*Spg-e`~Hs zUJp(e06%>ieSLkv05#o1chYO%S)V7}Sg(PeUVsJ|{cDAO6*SkK^h~x+td+sR zLGTJ{x&dtZB_IZI=r!;Fdt_vUUJtJo`Y6Bzejorfhzy$av4BA$k$?@t0%L4!3}}Eo zIywq$;0MO|`1sJ!(8R<97gp;;hCrteO&~4q6O9av z!LK>|DjQkZHnFpFaBk+}-nM-QFW*jqJ^LWSBBF9u6yE?p|!28 zt(~2l2cAIm42p=nb~EW#^6j+rj60b*j~+jHnwR&ow6wgUs-~gwT~l*&%ZHC`ZS5VM zUqIS{TQx8U$dO2EtC<9=o0S5s7U*eEw@ zu%Q0?YNTY@B-XK|Y0uagWg@+GZj#XAkLl4!VGD8kuBX3nZ0}%-_=%FruaiA?4XFba z7L&n8okdMK7O~nX_WI}9@?!SfY?l$NIj$&Xc)~0BWKWZuxBUr&hObpFRBq9voy&z^ zsN{oxOiy9*GZ%Oj7Ba_w+UIHO&76?mr!Krhc1PYvw#dB}hBs4=Z7UJGdFZ{?c!LYy zXcf7(o$aDKG9R}QDTVZK*@!eidSEvqenLQc!9#tv$E% z*~j#e=3u_P8(anMz=QYeb~MJC=f*g`L9rfkueIIFiLMbAmFUjiv z_P4(1EEjM9U6l#n@DFi5{>FEZ?Ph z-75ZB5zvBwe>XSAhFBSQ8LZq!y^v*%o$A5Qw<|r~5A*n9%A+P|SE!XJoXZ{XEe3XK zocK`u!1?&@-90&##1iG2Z8kFGLfq~#uYA$SHrpW~GCtOkw0FxD!53(H7s@s0}>B4s>6+It7ie2OUCgmbqIs_1V z;P|LOlJq7+#pA-UlYX{}!EvT+&|J3O6>I>u(e}EKhhs5ancj>GJa!s?I2?U2Omkj3qk#OamB?3l;vo5$&(%IcxX=&H`> ztj_1L(CE0)<-F44!PMl(*5b?9;?3FN)7#+9?7?d|UF?(y;Q^Yioc^z`@l_xSku`T6<#`}_R- z{Qdp?{{H^||NlQ$javW!02FjmPE!B@0s|H-IYe4wYW13;PedR5)%>eXV&0-V~ z0VXjH?CtY`S-n8SLC=af&_ZX8BF1&65SHihZY?p5aoGw354t}`8OFJ<1Iaa}D91Q$ z2iJWbJ<;%|Tp^7-D!la6#D#)raPz{l41mzmy9~u&;A7sIx z@9@>rUCHUH%U2I?sJ)QUMY|X+HnTZP(^=Epj)~z@^S! zT)|Lg_jZ9>_w4jJusXkiU3SD{5uKXWCh+rC`qXR+yH%25$~#=*X|t$92^)Q$HT$+ksvJF!a`Q$NKyWSC|~?{#vldDij+uEqS%S$53va` z=3(=?^WEM)X8Tc{uI`!Xg@M&6F{Rm_>YkpiUp>2b7jE3Rv9YnCloBr>01*ExIp-4J zQr885$Ve$iqY+%ce*L45K0-ty0)VAZnD0MbBD>$VOd=v04u_w8_F3jRaWH~FJsjy# zA4HTCyUU4)vdBp(qnOzCjp5<<5iFk{M-Z_C)PZ}(Fo?()KK}UQbLY-=!eZMub)4`b z!KvFrzr@Dfw5qCZ-MWQ~^7>52FTwE)?%w=3EfFFnCbV%TLs^1m+0*`DU+L8L(IiSx zmM+cA|A&TYIU1fFp}b@?OiR%CHbHsGXqc9xNl;kKOGLx898H4qQqe3g-@RCQ`Dm78 zQxD2di3XTGFq&s$Wr@54R6mv?0Ge`5#yNkvG`O_hbWpN*>lez7=?w}%^mh?uIC9Ps zSs^TgAmc|^07}3@W(8m-AOpnS4wc#jWl`8NG(sQ%ks{^gS?7G~fC-)NS`(%?02Ba% z3|U1cIzoCuAPbba=ecd|5nxb)5^(j=2<98?f`u71R|+LcR*?XZNSS(M>K&O6v*F1s z9|A(OlOV%rEfK>d;k1CdT^v{`nPXPSyadb>lm#@v0O9~Es)P1ch*o==JM(xt`k@|u z4|Y^fcSuhK7@1cx8)CMWRa@EM6)XwSUJ2KuBCsg)Yd8Lug@iU7N+=m7WcvOeK|jGPFVT9%ttKG` z^T}?#`=hS4HlXU7$QD^9jK*T@r^u=rD?#$`1al>1>0hXzEDEjXD5U|^Moh;K9zD7} zpL!RI^Y8v{?c_z$GY7zEz%>rCsup?SdjJ{cCF!Z&dw`G&nfq>09vRn;vJ>UHaFa*0 zf9L4oK{*)YmDjZpfJ7vmTjR*q$2?;?A*V3a_h97)m}W!6*wa~*ggJQt1-xd z1na`P0<$)Q0GuD75cwb-Ib#J%;fxkq>3XuieSco>XXT;QV_O?;wB_Gdqiq@w-1-yjHuDJuZ@hRs@g~MRo*f=V=~VVh@Ezsx8>Sac7W#jvRLwJ&+?$5hp`M*0P+7Fvvs@lwvw4Pt4sFO#*F zp|yUC48~rneNI?U)La6^Xm9V+-+!v}p&1xZ#_+2#E~8el z1JE>(GIc($IimoA;tnu8OBqDmh)B@|*mRB3Yinybo_zDyKW}ZG(%SOOM2>-z1Ed&s zVdo+s#}HaH4){())(J~s2v}rifDTGT*Jhg_qm7w6NYZ9T=S8-D^spnNn-x;55Gq3~ zAsRRc3Bi+&i+~8tSNLXcq8JSzqJJobZL}UR!k~z2uz>?G2lJzW!r-}Q00zuk14&G+Yf~Rddy#{ry zwvNas&2ikLtj*=-84+prf+0e200Ll-7~7aIRN`ob#@&m@!jM5ulVe0-UZRvit>=iG zwd7(IT2ATAtPPQ4NRB@t@R(1PHV{GxiV!nIq7Q{R`REyV&M z7N7)+325UVTpPKpEA>?hu|iI!z0Xzg6YgCwIQ6_imxtEeily5@Zwtp>Gu~qalNO z1c)fWntG}{*{oVSd*b5d*WUi{)$6>iMr9K74rpyRU!v z_Vd}!O*D_n+~s-cVOhd}n*tKHGMDED3j`A2jGoWt^<25CI{LFy7v8_{iz{1aUq62Q z@MJs{q+${!-O|x1?U7)tHZvn7o;iK|+}Ts}tG{~kc<0`on|E)1{^a3TZgziI*rF^j z8<4|zV6vgYF$7!JJ|gGF;E_Wcm(E=N;PtoOJ$>fv;k6YB))+M%?LtVRC@hjCN_!Af zcO+)(IAg3Q5OY9$<;3ddt5@E?a&>!WboaY&Z{Pf4=iWcm&bNbnHmr&)9~d>R=iUfT z6erg=-+%j!D;M5;XY=&t>agG~$|zOuYu$WjmWVEeRN|6@7Hs9Z9V~u7Qc8ip5RV-x zP9DGX?tAa-?al7o{q8?s|MTJPzt=mrC;H_2nah_iUA=Je=bM|aW@xQZ)~eZL7UMlE zM-T~thQ8O}q$?~O6-$D+2_PI(1BH8wC-tGv=SOi&UH|tL0j30C@CfyseQr8VC|AI4w6c#NQ7C@ zL841(1YW$za{$23unB(@*5i}86W@mzS4-X4ftIDTKytn|CdEo$-NZMPJd*f6T+sna zn3H(+QPVbulO(GD&j+)K=j)k4v4l@fj<*hQa(9~6WU`cyGHCH1PvW-{&)s0Pq$0VF z=;==46Uv0gQHtYkO0-#|3=vmXhgqIGqOOoZ$1PUO7yS4A3=0TKn^-?ybliI8J{**Y v2w#5r<-L3NJh%Mc%f$bblq&Mp*4BRkpt%Q?+8@H2Z97DAQf>42~_bB z1c(YDQ4S%sN!1iekSHHowaR_8X|_$;ESqE<+w0q7&++)Z8GGW`Gd{9GOq%KV&GCNk zfBfG6h!4Y z5#aLCD76|^385&8qNy6hVATJ@VhwvDNDG#4O(%II&Q{PPM1!@f9486_?9oyS0S2C! z&ceP76oeQi5_62>1U6$sK|pN#=Q7doyugHCM?p9?F*A|IM3|T(f@u4;VLCIe#b*D0 zBxvw)LU@Lt&OmH>Q#91V)$&Bi!Ml*TWew&RZLT9cPi&I3SI#CP zP6}G4-4H<_1|>ZHFF-u(0w>;DJZa2jubu&wz_!iKY@=DGrUE|Mx{$q|4y?oI4(w`} z*5aX*wkc@&Xp;9*8zM1uc z=FNY6@dhvbHU@KNDYp=bL&lifta;aQY070$sKqW~q5rI%ur?pxY5UNU* z=o(lb)OY2*Yq#cacY@Lvno3!Df9}T1Ctshtem&s#V{XYKdj0aqNNgxP><{=c0P=v$ zw3=2{l-$x%DwV7#3QX85%U%~7a&_hoXgppqS196#g+r7CQI=z)@sUV0914emexDB} zE5UQ{jH>EYO{mrL#y{&@hXWrTApR8}!AZqw&P(ibOmXjShxF z0l(}42#)I5;5b^X*6=5vD`JVNQu*M<&2q7*nLGBwE2xG2u@B;kSCmY3* z3Z)QQE|&uV|5!8vc$TNw$I?>vtH+;*6ZfQ`cA{$^#7I7q_paui{mPg6V?V;{x@zx7 zT@>V~l$JrzQn^%`n20-mu}~~k5hqAeFgVb13lTJUxH;hMqM)v5V0KL1261FR7K%nniz0D(#a_7s-*A+4l}alybVI{}`9^BfcGp~ehq#z@lS+SRaOPd^*0%(QNR)8( zw6(i}ELXJO?BdLnI$BuWR-Cw)-4*&F{^oT!vn}S)4L5-q)HU;Eo4W4Gf8BFtr}?N| zs&c%`)r$kI?C1CUkQ~(1nlqFRChaOo(Nj?sO5MUdf~X!brI`h)=gwb2dJ-8P+`erl z6dbsFFF7Xu#Wnx7_DVI{oBnG{rCm{PZqlBu=+I4H6JoXea;2qnx zII`{M5AOMB(|Wj@QmIUg#W!qNRjaD|cJI8K%v?Tu=BGdYj$7{M>dZ&>Zr?aH_2Jx{ zTCGJ!1}DbjW16}W$?cU zboJQLL+MmHG7@Q?%NC4l6nFH{QI zwK@f6S(Ft>?erKGgHP|=dg;=8m(IMKnH(REM2h)BK;#eZ-!m~e4vn{nq*X!f>%;kT zPaOLDKmK*?>Xmit)-H}kk(^$+dTlW18ypPZx-~yK7DKJc+@uKr0hLD*hK2@FKS``e z1jAvk$AeOeEX%-KDwR-~ip8Qnvr^aWaSl>xM-v;3J@NR#WIBVY$w*|lP$&$CLfAp# zqp^|b2#PkMwb8K65oKV#T2mL3DNG-L>ji_MV8H$$iH&rq3b67ZYW(fpBO5Qal9ekb z@E?AnmPV<6-KSOyqA0WVda&UkI%Kgu+l$dtVF8TJoLS?MVo;;UToa9kOeWK7@&Wl* z6$JoH=j6@$7OTUenL+MnA*@6WIzhUI?nZ~8r)91}p(wHP9qFDO;((5zX`@<$AfSJY zps`_v16GKn>rCY=Y2+wFN&3jcD@rwBQk2--$#X=rl*>z^U=`}IZb+!csdj*9wVJHH zjy1wMJEGto`92VfS*3PsM6}*6`GSoQ#B>T0tZU3Ch-fu2cco@l&ebK)EX?XWnH4b%V|`vx zu#8V12n_U?`GNz@zM1JkZnjcap}tkN3?w8 zKG!vk+khZRKrq|hU@cj0f5uj{1;L8qJGg`bCUo7002ovPDHLk FV1iPHBCY@c literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/crystal/code.png b/sources/wp-includes/images/crystal/code.png new file mode 100644 index 0000000000000000000000000000000000000000..2fa960856a0d8a1c5ea2f5f0d264a709f89142b1 GIT binary patch literal 1604 zcmV-K2D|x*P)gwvYwzjvoxAgS%U2=prNIurr_Y<%F4>4qob>%hRku&}VQva_zPuGZGq-rnE6y}qrjuEWE_$jHgb$;qm!sc|K!ne1$*x1?0$;zgtroq9%#Kgtb)zzx1tHs5})6>)F=;^MmucxP{;o;)e*4D4D zvESd}&CSlBprGjJ>aVY`p`oFqq@?ih@uZ}s?(Xl^)z<6l?7O?Y($dr1+}*yuzs$_d zySu#1%+BE8;q2_~tgNl5sHnum#Hp#P!^6bn0)P8SmO5Lw@4m^jpw#pD%W+faeisCzh|D`*0A>AA2)@ zwiL{-{XDrpmcg)|>y5_#XBs%<-IsG_r9l#fU%$2N3%KvwM~e8FK}?&B)r{FGO*`bV z6@z24EMX1X6gZ{&{bV;%m~;i>u6-?F>o&)^oMhvTc{V)&>$x|?7?q$;^=W~~;21X3 zpJE3{ib9-Z@rRXyQ%`EXlA%H1m8$)T(~oJJgy3-)mWBPax|iVcl;>OB3qw5Q#R=K< zVw{e8k2{`qeErk%-c{(c<*hC?;t^+juWWTax-rQR>Cx|E2c_u#i2L5&dz(}@YDE8? z0m6JiMm*xa|FNsc@uy_Me((Xsyo~mPc;M?d-bl;^$M5 z{ypyb7WeWv4Dzk+<#G}730rZ!YOBc8$bV7e9Z$sNFdu)v{6-r3+~!BiQ^9=t^vBDK zjHbme?!EKO=i<`nT*tLOhSAHtkM8$MzMp>lboQGbpyd<&(|xOm3!-@c(pA=4Q<&oO z9I3u2u%3VNr3qF$06F|sitem))Zz48(gM;f!^DSYG`e3RJ)b)eDdP+Pr7Ij&G!Yjh zQR>NVFWiOoEOb{Zt0d`pGMmfHFg!56{~?_Q9+yPXv{biF-BN<*69&gwr%zU8oIVkU z5n<$3_d;BO+^{6qE2iXn$w)POfHwm9;1;2oZX{MqQp z#<_h_)VD7F(l@3s>zkAJRxYrSeXt~!bLsS^$e_M`evqDg#G+AX#HIvBi`Yf3X`$p zZk>hgn$xFT$oTySKHv(B6wUGb!`G0+Qvqv1@ zc;{|!sckKopB}x`=(^$0_wRMcOLrFVfrjq$?Bz~%`-#%LKbo%Nu@#e$vbg_yJ0F-p z&dN-)M_f0@bLXqYpdV@crBSq-`awLw>$+}rK3os?Y1HfKBl^S=kQ+J-j^nNSNBo2y zal(lBqyJwnPtwL~y&UpRGju%U@ne0!k@vY8;hsl4>S3ZDO=siC>tQcJjxbur(Jmhm zf(d9v?}6fBK=4N3C;=P6mJ<1V5+woC_L}szE&UI@DagStz&)qiD56H#@uvw%PS$HyL28ZzT^@`evz6pRNK!l!tF2Cc#`*)fkc~bw zS0{dDuAcO~3)yyKzpy8xRegf;81Yeg4EV4-dOj|Xb^wnEc_b51eoE`EIw6nOVd7Vl z`@()S7<0`}d*i2>=&+xz(}b8?ro{hC#yk g^=;?ivnIa%0}+&kK=WXcK>z>%07*qoM6N<$f+iy8c>n+a literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/crystal/document.png b/sources/wp-includes/images/crystal/document.png new file mode 100644 index 0000000000000000000000000000000000000000..a6342cfb3701cdfe6a05fb86159682c88b836d7f GIT binary patch literal 2230 zcmV;n2ub&eP)q61bLp*H zw~EE0ZQIb}LI}Z8FDa#e>|LFo-jk)2gpfv~L0#9qaNz>{AFmE3A%v8YbFL`L&6_u= z5CQ-?R_WNlZ;a@ZeoOex5O}?R;F(7VLA%Wr7#wP{gDi9<0AP&0kM9gRf1&=bIVm*W z(<7om2nC^>IGS!db;f>JQc8?*5Xy;r%9{zbS@%!cZ9pmI`ue(I7z0B(%48s(=jZ1U zLLJw1JQdCr0GODV2z_*S)I^V|j)S}xd22ieg>%JQ-E1~p*X{q&{n7MNlzcwli&!BJ z0)TeAZJK82qX)jYKbk_J;OCZqeRwdBjEo$|Dg8a=ImJ)yAQV5E0Bw6c`UtjJSXk(# zH{rp2`t<2g4ebT1Bk)md6B^zI6d^<@ z&1SRxcb`7$7XrmkX^*xMKlGSdJitMR(tbZnj)NxLK_~LQ=ov-7VD{8DRG^j*q%9mI zIF^(n2XT-Tkfb2FK!6B#B_J+1m*7fCg)50|2`srwsc1MT1;~X&G96doaw*X-g1mvJ zw%sJn=kra|5Do$&g>)oHA|()zEfZ4=hzp1ja9kHl>l?7-I|=TtP7&$_~X;S*x~9OF+y- zATc7CBTf*)APvNcP&hO>5I}%qShxb*@CXW^Id$rkf1RIww!3sJ<cJ0ai$8TS6fwc2URyV|}e?MQiJbPy0 zQhnb93j%T#?x3x$tpIJkyR);iZ>#n4)*ERYOcZjGqqTh_=TZ(%JmwUOMXPo|aExgh zv}=F<({(ML%8V4_Oa(BC8m`xk=l7PD9=!x1=iV8=GVwvr26QJZwK8RlQsVM>b-kWeP^mbaj#CU&U^7Nz6cE#LEC%4ZT2d*M@{zdG zY&JRP-SVty8cU@qL&oN6t7Y!ijJc^1*>;{ieQ70%#iU}`f|+eXFu|&gY!g9D;n)Qs zq$OPdhjXS9mM^6Bb~}VC{wmjdv1ytCwe`liTn;%c^(}ia%ySMK@`{=_fL9TRXpv7Xb zm)efDcOIWcS9W1Dd#)0o12>*+Ro0-`aSsR_4`Amsa&C0uIj6m`b2?c z-Rf7%E5rFAg`$Tmi=RxfhmZH1${1kz@wF>Wl>YpSEs%~%+2pA9_2SkauivIgb-Y;Y z8O;70rBbQaUjOi)UqNi~%>21ivkO<}b05yCzx(VZiY4-yMD@Vfdu{#U?<*f%8hf(5 zTB-8~FW!!qGHp7Vota3c5`X>My$8>i)p!n+_{GclT>^%ObL5*>%{x!F$#`L}V*lmlt3)-3M>hmflj+wrFw)3qDTX zB%u^3%??d@zC~sTh#^QMz=fxG*Ped)Iysip$5EwW$a<4kn~)d+VH>rUqQ&>QnvvPH z|7^K?U*JMf&6I>Feg8Bgj&<+pZqEoBh{hYAe>c6hZ2+Uvb(Czf(X#b=`&Cmf=IP9| zN>w$Nk^<}(>!?=IE4v33xejR+vZKNR(JW_qD}HM7=H2RrcjCeAFtjY#-rf#P5@u#* zrsLJ=?0lp8KbLo1t>s*vq%0e}D# zVU!=-+tU(!?!x5&E5dbUY;3Go!SdOS+sEuJ^s0%%xuWZOXl|=%+VQjNUMctBB*DL0 z*Y$`kgzM-AO`3O8RTQD23bru3(G@BIxge=+qvNBt%!d<5$|@U8jM}ihiKb=j(fw&EZ_x z+1csP_E7z;fs4GD(GTcF?X?hK? zL%lUhdpDQM4en6-XY={|K+!y!7WWB=aN+l88=bI>u`_4R9Jy`wzkDTdIN?tcqT8ld zFh^9|Z}XMIC6p(veglGeptzl&`VHvuN7+k{Z!rJCP>{A!q`G_TXWMbYieijaRdpQa zP}^_dG_udkz;WlGfR;+78#iurlAVEv`QOE1ym!{}Uq8wVdzqQ0y8r+H07*qoM6N<$ Efi_@% literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/crystal/interactive.png b/sources/wp-includes/images/crystal/interactive.png new file mode 100644 index 0000000000000000000000000000000000000000..687248b042b69e68a42126b410920bb067387c85 GIT binary patch literal 2680 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 literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/crystal/video.png b/sources/wp-includes/images/crystal/video.png new file mode 100644 index 0000000000000000000000000000000000000000..bd58b9b043ae4d48c7a49afed6f88b2b7d708dd5 GIT binary patch literal 1339 zcmV-B1;qM^P)D+RQ|vHd4Q{|N1{SZuew%nPi%#(Xdxag<`SP z_by`f_36}<-()Z|Q0l~&&4@-K3abb1-n!GnK5KV! zzTO@+A=rQO>};5^SOm{raQgZ) zS-CqOq!eMsMX_zmmJ8DmPu3-|Y)Cq=|H_};E1}}C7#feuV0I{Hm(~MHF~)U>*tRWq zUPUxfS5L2WchUZtxp4a6+B}1YL!Yd$zzFf4l^FmCfA)cLb7|cUWsu4~y~BV=sdwpw z6}BQNtPdu6ldz;u@`Yhb&P_o%miCL|I3j!N5RE57wCfZO z-0Iz(Mm!d0Y?4y0P_*P=1C&z0$1+OWA}ufysk9n@Tsm=RXg#S>8tEUUkjocEHdC2y z_{pR1y@hBZRfp-9#p%Eg?;#wEMKSrD4Ce9$$u0w2)u;X;N+(mPt>Q+fVNP`byLQ&z0ud38UU!daCue@=DyTC1 zjHv<|nUvaT0nx{4%clefGGwD1p@;||Qh*mq2?S(20AL)ZE!)c5fCC8JyU_XsAq!SM5;Sggj>l-7X2T*iq}*<-G0nl_;^X;i2xo)o-tEE(p!Z`Zv% zu`y11jqX=U^Q!i#hPiF;Pk*c-q7YQpt*cZwLy+{_ZEs8-S7!#CV0al?Ndg2DS8bd- zsVQmrn`ewARG9)1JilS}OA{Mwn5z9^Ftn8w9wL!BZOf-MKN8V*q|!V5c2+{9;hnYx zlgHPY?Dq={9&1E=JOq>0Y?%E-QzBe_1krp|h|migSH0Mrj*@QGWgo&rB>r04qUKsP z=9hN~*wc~-fft%qEM|kW{`!z42=IiSDWqW(jzhcDgA zlte3_U4@^|7hrX@etqu7z2S;Ctfz{qg(RoYb);q6>Fd3&c)AN;#UO2zGkm7?cz4gB z4R4hKA42vIlN7T9_ePc0OL~fR&pzHRm4twY@WJ8p^s0aXozB})W=0FIX+ x0{;@kd)(yEv0q&b5ORU?j{qK46#}R^{{adG{j4HkOS1p~002ovPDHLkV1h#DaE$-} literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/down_arrow-2x.gif b/sources/wp-includes/images/down_arrow-2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..2408bd5fe2f820f96ba296c331e4062415425b74 GIT binary patch literal 83 zcmZ?wbhEHb6k*U{XkY+=|Ns9h{$ycfXJBN|0r5dH3`|-*{VPwu0r5dH3{1j3{VPwu<>#LvvLH)1)$$jA Jn-3#{H2|P`4%+|# literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/icon-pointer-flag-2x.png b/sources/wp-includes/images/icon-pointer-flag-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..99a2c2ab0047e8c2be9369cdae3b335cbc2fb88a GIT binary patch literal 1369 zcmV-f1*ZCmP)3Y=Y&J9R`#k^5 zyq~inW)5|Nlrua${KnwmU~6Ar->*GAJwshxT}i03voqJx(ZLX2+wbET9E)>sF8Pg- zk&#RN{rx}m_V&gjk;ubXEXK35v%I>x%BfU}4Z|>1C=}QRukH77435P)I2UE0ER>0| zNk@i;h8ji9-QC^O(P)$x78cAz^Z7j23d%rPC=+F)4%CG@bui|6xfOntppEJ2Y2Mn} zVz)sZs0($XZp7e4W1hk#FG23&FPqEdST(2@+IczZW6AfJaVhKw;CTG&lZbC_8Z6vxgp0hk8?x|Xx#h? zazl=18YfA&_+Wc`oBa-QM6T6NAKqPGU+18JT#@ssC!TU|COKdrXXJjG@y_>{#{>=J zjNB`(=giN~XE>lBcX)7;L3bTo%Xv#gkoj5zkUKm$wp(9ZT>OWfgGyBH{d1x#q8p<7 zqQAM$zyo+u&Y-Uj4h~p_K^4>_igBHQ2QtFGO{F9fi8zD$8)WNKQJU3*x!P#y*389p zI$iLXLC_1LZdMGuu(y=#IoEfXztq+v>10}6SwMo=ag*oq;=Q>N4WEJf%#Regf6+Rsq(F4(S(S>8W z_dB9LUE0e}(ca$Pj1q&Kp&*(P%_&+un!nKhVubFi`v{G^jlA22+h&p+V(= zH?+LG{Ca3md6t%zu9^#G=q*Bno*-jyMWd_l2n~8-6Y&qSKttUe8uWiQH#b|zM((wj zFvbWCdQ1VH(0`Gwj%aAmBj5#>oXuzxX-Bh>(UwYSZk2mg^nZsY{Ay8od$ne`6^ z;bU?VJU!tPlM2X%+<=)s(EN7GAqR31`w_S->qpjXb5yXuzkf-yA;1)3CY4}+U6a9N z8)Bt;!OU-p=Gc48AvW>=_G4}>q72ucj1@}*c@1W6w1P{sdeTH3v6+w1QQjntKfG|8I%;NeYDNS^-leubz=KQMzK za0*z#C^*|VKLIRYKj@*9lI`e`o`%F}kH>Q{9*;lCWHO;*vA9~PRK8P05QGhOzP`S` zoKB}-g+ig*X0w@z9s>h<3LUUots}8m>~XnV{z?@_lH@q2!EiVn zo~c%=X{s^VY^-hSdQbkOYlapild_GKd%;x51iM>kP|8Pe#KA-QB_bVT z3|^P!tLF4ZqtRJvK-dVj+wDjH6LP!V!bbW7Q$#c9suKD8Z4_7 zLNR{1T&{nkZV#salq#WCZh{RpQdo}e5SFE-r3)0%Nr*89I-c1Jg~BIs&BQ`Dud@)t z0#-Vm#T^dEK7!SGQD-3u6LD#VxuJk>wTz(SBtg%~!ls*?!csJw|FYK0hm;1>9y zLFTnIv>AFt`UaZ52dV N002ovPDHLkV1o30WUT-I literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/rss-2x.png b/sources/wp-includes/images/rss-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7b525cf131cecb5c976061a81c532dff678adb85 GIT binary patch literal 1306 zcmV+#1?BpQP)p!7K&>iCU@o)Q>Hw|DX|N3j}O7V`DZ03B;i&rAkv!qckd28${aB zCWOUc$HvB7gN=8LS>DbW+a*_qk|^RzujbCY=bUHG*mH$-g^I8=_E;R@`HRw6iFg^1xgjwf&6%^BZ z-TMlgPj&EF7SDx70xp>Ee+~CwDI)jEsaArBvHC9X@U8-pF$Kb-Wi)c_kCY)WT#CJc zVmLHKFlnpccy7S)VK@PLauk7Ox(=@XV#=j@5+wr1%Kldowvmv&6uW(Lm~@}Pz53gk zQ1f^#yn_rnD#1` z6K&%02KU&8*hMEOi;s&K#1fX{Kz%VpbpZlfEAe~C-`y*7u>RBrOK&+`S{e3-jSe7Zt}2j$owEW&noK3nfg zh_}vkz@?ESf zoaM0!uAV%K;S6F4uVTRczI^yKdD!X7f!LYNozz`*#p+IjgoUGWIstkVHvh;VFRYO!|^EjV6 z7i-Frgf7>$H{tEczmGHArNd-^*Cz1V1% z!QT^&vE50BdwEWJtUs!-(~-#;#1dZ0qrf0b@-l#}H67;B8d$z>qLI(N1ny?X+@67r z2j55vzMZ~}9c3oZcPcYro^Fx&JBzc}VjCd_v4p>3KtI7+(jYGUAW0Dad_?Qya~T^_ zao`dE^Ic2NU}t`?I}3ZP6Qk}6>7BH%z}lS38N?D^#DK2$G}ciq&U$E_{6J?0Y|Say zUYL$s9Byv7$~~_t9jmQ{((4iQz{GrFyx_p1DA3uG3hU#pGl82kJ=_nlf({0>%=AjW zpBvvManG+zhp|2_;rqH?m&6&w5*A{>-PRPC^fhM!H->A-X9d}j-)0>?9XS00g@dp* zB$LNwX-WiI>XSKxSi*c^6zFYZ9o8qo`Eo{*Kyz9r-`}1J&z%%Fnv!9vy8`2_Pq^n| zn<0<1+j12a)-ib`dMBS4#1fvzfWEdAxLYas3hT5M=BY*+X-@0pf0T$pEa8tBkdDL0 z3VYZNcbk(THYU+Xb6Wo>QEg%ni-247@1ljv6fuZJN2>T;CWuV9WQoN37gqT}ntO!% QFaQ7m07*qoM6N<$g4A(rUjP6A literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/rss.png b/sources/wp-includes/images/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..9707305e354c8ab98211af984d806ec41041fc99 GIT binary patch literal 608 zcmV-m0-ybfP)?ffA=MReIkM!5S zx4H0}&g^^g6K4#5n%8Xq2a?y0IhP;qZ}O#+De6-`&#I6Mvc4|LRQ}7pCp6{V0F>b)!d4Dc2WuzdbK|;uXa(fLJ%w z%~0LHDJ^^2Sz)BRZ1c0TVC3|xR1CWRf@bVEh*iVReos2}w)VLjvZ;6EBMIA^wwFGY zJv=4k_bGOFK$VVxST#a{(c{m7bYf0yf;0rhtu>J3hp2#L`~*moAdcpVy_GK=eEbE) zl@FakghY;NW0000tSLu;wYQ>TAs=jBP*FkflM?zCbCrVb+sjSbO~t9>%IUtM${ Pu}&Z@V%kj=CI)K&O7cC% literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_biggrin.gif b/sources/wp-includes/images/smilies/icon_biggrin.gif new file mode 100644 index 0000000000000000000000000000000000000000..d3527723c6d8a0ddfa7ca0bfe1ab8fce0055918c GIT binary patch literal 172 zcmZ?wbhEHbgxLc6$23b2ZD19|4%af-@@>3F2nzSlmGt}{{R2@|NpQ5 zKLsg(0L7myj0_CC3_2h#$P5OS$PJ#HS#x(>T`Hg?&Q{P6{IT@*|fe Qt&nb$oR(_V$-rO@0AZ~_>i_@% literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_confused.gif b/sources/wp-includes/images/smilies/icon_confused.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c49e06983f1fff4bc0834b4d86ce39b8a36a914 GIT binary patch literal 171 zcmZ?wbhEHbZXiyV-#U P9L#x)b-Z(h7#XYqI2k)k literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_cool.gif b/sources/wp-includes/images/smilies/icon_cool.gif new file mode 100644 index 0000000000000000000000000000000000000000..cead0306c0e38e57bdb0cc85a407b995dcbdc656 GIT binary patch literal 172 zcmZ?wbhEHb+|z`)C(1LA_rU|@;d;3=6kcSq>7bCTj>1sqIsoCSRx)8`fJ$~w+{ zJX`yX^?~=R4m2(o_)+HS{ItMiUIk0)fwE>-?dDgxjscmQ{AM&TEaGA7z8`VSO88#> SHjRW8(oK@nQq4LU7_0%kd_$xF literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_cry.gif b/sources/wp-includes/images/smilies/icon_cry.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d54b1f994bb20c2a17c6e9e53edb39e0444b380 GIT binary patch literal 498 zcmZ?wbhEHbivPL&TtkAL9RpmA^bD98ftnS6varfA2r%e?3<5cWfi*@! zrOPq0Pa{O{R3VSL)CLZwJI;bVj@ow|9P^f2{b_KV;g#sD#JTIhK{X4eRSZoFOA4&E zE?xGWjgRM;Ia^8kzR>%TOS23r6eRl<`~6;g|7yg@*31^DX`|+%tO&MH1Y{u#11keN z5Hhd|DyTR-@tBu#X^wBxK7*WjP8?uWTo6?pKs7*@va%&Sa#%9C1z8HDof#;_rJ&H~ zFsWx*ry9h3B%L5>ZUqL1B|!6=oIFuX25Dyj%JU{%Vn~@hA!8Mj(`_aU6Ueh0) literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_eek.gif b/sources/wp-includes/images/smilies/icon_eek.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d3978106a2da37441ed17c9d05383b367570d46 GIT binary patch literal 170 zcmZ?wbhEHbd`4m;$l6XN^_D8SRJJ2FugV_ z;@-1W`~Ak%x7W!T7_8VEVD?C1V$(vmHm-x7t|ENQXTMbHG-$9e9m-TqP;V|s+-sI@ SDB66dp*Gz_Y_|#%gEasOPe3vN literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_evil.gif b/sources/wp-includes/images/smilies/icon_evil.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab1aa8e123fe263608d06126ce08c560ad419f97 GIT binary patch literal 236 zcmZ?wbhEHbgxLc6$23bKgaO@B*VYC4FCTM|KGy!A1Lx~^8f$G|7kJ& z%VnN6ZQB2*4FCVX1}P;4DE?$&WMB|r&;e-z*~!3~slec{BxBNqoiq9;sWfXDwJwx! zTfpypu*1~B&zIRcFi`x-!pOiN%b)||f$U^p%}h}5a*XWD2sb-X$e}K^frar-lVFcywmLVPpS#r! z1_#Bw>()y8Q=}6Xa7!$m)>9ItA-k>bRM`by3r4gxLc6$23b2ZD19|4%af-@@?!ukgRQ4FCU4{{R2@|EEBy z*B}*Op!k!8k%57iK?lSGnZdvkyTOw)YwnKFWkE{fYz4;!=ddvOIHYqKtO`15eTQk+ zwr{=ctfC9V1Rm6}I;$2M@y*$pa`Z}#oqrI+!z(?kVh8VTo6X#$!E$I32lMi<45x(( UGxi&cHs4b?vq7goSdhUQ00}uk)&Kwi literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_lol.gif b/sources/wp-includes/images/smilies/icon_lol.gif new file mode 100644 index 0000000000000000000000000000000000000000..374ba150fb238d6a33605bb26e86d4449625a46c GIT binary patch literal 336 zcmZ?wbhEHbgxLc6$23b2ZD19|4%af-@@>3F2n!7!vFtG{{R2@|NpQ5 zKLsg(0LA~@ey$E)D;vwK1$ZJE z)->GK{b0hvv^Z;7;HB1zIS=v}c`BF7qB`mkh55UYFL448CX~YJS?+%vC0^DXyTAT=mC2Y$ux)_YXI57TebiI literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_mad.gif b/sources/wp-includes/images/smilies/icon_mad.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f6c3c2fb401596ec44f4a1189bde2cbc45364aa GIT binary patch literal 174 zcmZ?wbhEHb3F2nzSlmGt}{tp7j|Nnpe z|0z%&3KV~`FfuUkGU$N#ATtF%wyNW~cLKD&UCI$nR5;ND%aoaG8jR+sH5 z;LGade6U~GQPko`gGJNAq7#;kr@G#2#;~znnVhs^*T0km#>C~4JR&=FdsEeR+|3R= Q;9xFbtmB<4#K>R`0GZ1@LjV8( literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_question.gif b/sources/wp-includes/images/smilies/icon_question.gif new file mode 100644 index 0000000000000000000000000000000000000000..9d072265bb9d7d5d4eeaaa9aadb44a49a60e5fe3 GIT binary patch literal 248 zcmZ?wbhEHbgxLc6~q5?4F69u{F}@0e+$F^zrz3jO@4oyp}v#>2=1R{ z`2YX-`F#xhd<^^7GyH$bps&p^e-cpewY&^Nd^p4X4Gi!1Fzlbske>!pj|LQfvM@3* zNHOSu#6fm4u$C@R>vD+fTM_1WrjSFOYeSph9VW&ehisimT`Ynp-iELv_k~jmS4OEzz h1Q^5k8{BNVn8hT-nI{@Cu+CwP)wEG_S5{=O1_1NkQKJ9= literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_razz.gif b/sources/wp-includes/images/smilies/icon_razz.gif new file mode 100644 index 0000000000000000000000000000000000000000..29da2a2fccc79981bc54db7513ca6d2374592f9d GIT binary patch literal 176 zcmZ?wbhEHb^3h|5y0`zsdjqAOHXV zwXw1B|EEADAfWh@g^_`Qk3k2-0hz(T5_`c@GHdRQt4o8V#Kj6YnC2W7^l?<@Q2(%O z^|TpzE=L6K%vq%4Qv0AgI88 ZPHWn(3w4)`M4Rs!oY|mbDlEug4FCb$KH>lX literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_redface.gif b/sources/wp-includes/images/smilies/icon_redface.gif new file mode 100644 index 0000000000000000000000000000000000000000..ad7628320c3d15756c84794c8c0523f1072da640 GIT binary patch literal 650 zcmZ?wbhEHb&Qw$Gs7{2#K|NnmWcSgp)ZKdDmF#NyN{%1+%|LxoV z&6x4L*vr+`_5YJ6|9^e`f9A~pR}4QI8vg%z`Rh8vzsC$emo5AMNBH0A=KudDKaP*T z>0!pe!0`X+%wGqqfegj}+zPv3R$%UgcxPlMx(u7qxxxfZd?$&YQ;PGndxWo3ZY ziH`8-T?`B&DNk$k=JGRs=w-6FQO@h2ko&aap$ji#VOF!1O><{wyHRCMkfx2Ai?Slv zYA%q~j0}tnyg^Qv|J?fJ`y}Jo`B}5IcZU0i%+^)m>vp{!Bqu6#)+xQyYu&8=mRY(7 z)}5aCNL5gG*%{+AHF>K87ridk_T^KXg3qiu^$yZP~SpxtUz5smy literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_rolleyes.gif b/sources/wp-includes/images/smilies/icon_rolleyes.gif new file mode 100644 index 0000000000000000000000000000000000000000..d7f5f2f4b18f8a141c7a5dd1e09ff106a2f9fa1e GIT binary patch literal 485 zcmZ?wbhEHbgxLc6$23bKgaO@B*Xvz|NqTp_`ikW|G&xq{~!PVSNQ)^ zpx|qe3NTRo&+X?L671|4;A*62z|05~RQ$=p%EiFTpaW6>GM0fQZi6Rh*4!PT(*&f% z*$TRZ<}@?I^CYG*?eW$Pd$isBan+(fO1gn0b6dW=x%w~q}~tKE&`I~ zWZ+_80zw8BmJOU2m9Ux1yJ3o3D&v+$ZG#t4ZLVMy3?Qu_ZQMY+8CYaDcq&S-H42Fh z{c)CE%Sn@EnS+n-#i)qLlhWcv5Vs)dU<2w9+u*4hy}}}Vq4ah~j;>ScENX^v3nduQ d4TmZP8gAjeGaoDCD!-THXQ zaD}Q`!Ef~@t%4VS^H`jpHe@qRnmW&T1rN_M_11z^Th4v=m-`t@{9)jl*%hj`3F2nzSlmGt}{tp7jjg5`} z|9}1eDNqRrDE?$&WMJT9&;fBkW-zcsU+|R7ntLO3**QsZu>uaJIn9DTj_MrhAC|2y zn^DM@#l<(@zDcWq`B+oyDaGR~0+SdoFXD`_(PqAxy<2o0Q>0^(jhH~$tb+>(~Mkip?iSJVUgxLc6$23bKgaNIF2n!7!vD80{0DM@;NRr`CxMLP|FjsU zO`B$HZ2T{m`TzgdAk{j*8D$QDUE*nK$ z7w|KG>@aokb7%R&!0WI`LE+V`jZbtHGVEq^HDzd8gshBhJhWk{9N&@6Gj#R{?N7d_ u@Ss3Q_U6Qmr`{j;vSH$AZf0`Va5JoNi_%bKV4KJmrQFw{HdRBB!5RP#AxjVd literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/smilies/icon_wink.gif b/sources/wp-includes/images/smilies/icon_wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..d1482880421dde677d3302940aa875ff22a11b06 GIT binary patch literal 170 zcmZ?wbhEHba9D@n#Zhbsv zutHU>;J1F0R>6zE2`tV}8xE^#?@bGklrZsUYAp!;dbG*vY{CM88Jk-qvwbqQUtQFY Pm?x1IA$CiJiNP8Goi0B( literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/toggle-arrow-2x.png b/sources/wp-includes/images/toggle-arrow-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a282075b0603250f7c2fd2c91bcaf82ee6f06eb0 GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^YCzn@!VDx$&Z=?%DXjpX5ZC|z|L-9VH0Riz2I}H1 z3GxeOU=Vv5vijAkP|=lPuWhFpTm(wo@^orJ+z#@`}h+6$H@Gm6A{xj4=Gv$x?`Z@ac)po8gln@igJ|D9f2B;}Q}ZRuWp zm(5{YlHE7k`)_W|xYkwnCS&=$ZBNQnZ>(>hTXk?+(^?j78{a0|MKOMl7{$#(`p=k7 z{P*`ni0ki*H`)s4&d7dbVi;ODD@t(r%AEx><7Tcp{pA+d>cn@44}a0T5zMbQoxjiQ z?&VYYH_jzYW|%F<6DF0DzQJ?BUQ?5^nU~tszPnz|UXbZG+010;*S-IZ%Gp9X+M*dn S8bg=d#Wzp$P!N&7%td literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/toggle-arrow.png b/sources/wp-includes/images/toggle-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..bfb6494262ae0f3eb0d654e37e43aa5fe1631a26 GIT binary patch literal 333 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 literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/wlw/wp-comments.png b/sources/wp-includes/images/wlw/wp-comments.png new file mode 100644 index 0000000000000000000000000000000000000000..6bc3d523f420e9cd3bf7daabb492a919dff33a69 GIT binary patch literal 1373 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

    4GIdTC30Oa>UpK;BU&;O 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 QD*ylh07*qoM6N<$f`Is7vj6}9 literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/wpicons-2x.png b/sources/wp-includes/images/wpicons-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..07390dcb1ec4b877be64fc4eff4f514ed514eb55 GIT binary patch literal 125467 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

    *thw`|7gRwBj!mbb*e8`+V>9 z#y5!&xbC65+xI$RVek9u_ah{P4=Pk|tI>33<*UoA{rt=ntZ*b?7Rai~r7B7r+da{V z$=ZyH3J-${pKEZZtM*Tq5FIXTDu^TqMzP#7UPDyA9s)(9eFLNn3WxilXq(9nAm;Y_ zJwmm7{ZxN;=)}^y+JNh>va}xlS+Me5F(8_ssi9IE3@60k(lg(v=ez$+ZiQW_0xf<;iLZ!r^M1{x&NGoBIjsetCrtQOL9!tgi$#1zO>sjX-cFx>>)RHX zl|{MsFC?>nsde76Xo^mTEZA}uHnn!;XO*ormC}yQyZnV)c?w_nK(xKR-FO-i#Kw8&N3xpqI_w|Nu*7ls>ogN2&?TX>tOyFda6t1|>@ zZ9Zv+y!mK^_YHLu?{TS-)y*Yx_SF^MU^_X~!s6QN4pBsB6aA?N1+Y!kXu0ISJpFYR zP#cQuGbhOPo!gjMgk8|Yul1;<%4#nG#2ACJn_;5*%(g|Q(z$_mZIL$yap!&%?|%}Y zqNx>79yXfgfXW30q_1JbrXFqU`}tekea$<`^RdFz!Y^=W8NMahpIm%L4gZ>x6-vQk zQGBMg`BcSj)$4dQwx~*LqphSx5kQj&`jj@djUx^-K3hj-n{41AyDYUC)-JC64*LVK zu@X=CLF8*?S!IC*2?6e*@M@VS+CI{>HN`>~G_^(%W_oxZ%4Ryj;6`ZRIM~d_hFU~(a0^v|O3(8!Q?hzo{7=syEUEalNGi}9Ql z0i~1Q^%1)Ap=E^vRl4$diqv=KNOIFTV5YSzaF&m=d!%)sGBL0CF!kXGz*fedrINul zYq6iZr8RE0B<3NHla)X7?3{8l%ycO@4u2`F_^+&rEPhgBu5tBC*>;Zy5mK4 zCrgrJ=_y8lt=PwR`9H)H`|l^ibdpk3@-u!BgU%v6!lRzx($Ej96En!#^vBhty?793 zSq!;8z@* zTo&#fl_wX*lWCEurf6b4V%BkIeqW~xJZ4Hzo;+Wv&cULmQlf1)e`voA_P@?7tSOLu zNj_0gqcT=O9U|6)HnJ&$WPAD0ZB(*%;e#9Cr>;7P2l1Ax^$$e1!_}D_UyLKt2iMu< z*2iV}K7Yl>@zdMxz;n9Ji`BLJou$cagLMuX1DnPkC_4X zMPc;o(VPTVWIhkG7we?7Eb#EhPxDw{FscAJp%MSCswC4Kuh@4cv93Fku1<4R(aH7v~k%ZhEU;dXeBqECdX374-k{i>Q`?4 z_A^e1mV%knG|)c2$EuE;zptd>_hei}>eSPyVq+&h?bVe4p6kxZ=#3psAKS$Kte)-xN-2O(^c2s!oPlLVAq-bXNsbdT0qX_ zM|MswXxNGQc?87HIg6lPWAYY$LU6-ZVLd}_8ui^rvFvm*;@3e$FzF(TttCU4-51(! zBXh1|qd9OOQ_VjPEGzW0EpPe=SQ8WYwVNGrH6;9q^p4uEP@9HBIuKR=$WcpdC2g>) zh=LnSuGi@Jyv9%}(Ee9|J{CM1YYQ?+^tBj{5*|W@m3D5ZeC}XEL4EO0AtSKx;`PbI z*@02^rSPu3^w{#YQj+y^NBd+yx_i07lG0f3Z1ArI4bFQaMDN|dwR-U$-2^FmDhe1} zTt;k@UA_efM3RfNLvQ32D0{+t419b z)hLfI^y|}VN=&oj!XfwWMy}i+_sUqv<9mYE5o8gmm}BnYQtYBg$j7Wbbw|5l4uPzbI+5Vk?Ve=_yh@?n!ncBd2LDjEEOt`pLcv$0n6l8qf+wq2{X3K zFgtuumsI!HADvF@I8K5}@2eSHKx({Pd4XF6wJEx>EPb0#xykZ&fe1xKo*m-CE~l|F zj=&6*2G)4pRd7vATX`@*SmmZ#iuv^apYbN@YZuPRk}_a9&rAZYTNoBCRT$bt+XqH& z|FCG^{lulH9 z3?!(0ffzUSlTnw?TAfyLt6iwc%NZMA>-*Ljcyaspyu$_?H;WM5 zS~d0iQ&2Q0;pYSB{5*GGU%qaCE?$+Vjm^ocf$iPxEpjM9h#gdYW=@(gISc?Hz{2$I z>%&(wBJ}<60B<;qhy)t@9+e30$0_p|vEDDz(~*rwk8^tx^@?mT?;)u=>fS!4c4IVe z<_1gQTk2X4SRL9ds;bPG>a@P`x$`|fFunx`y&NR#!K3caa6%5k9$NWkmotsLwdNDZ*}h~ ziVM%PWS*DXX$=3g;kys_f!Po(8!@>+<5F2o$#-9Ywy6={*8H1kI(~dxPQCz4<&sFb zs+5IK7RdB}hEBMb%5az51)+g#a65-A!PG>SzlN~QN(vn4pAi~nv3LaCWQ;1*Wd^NK zL{R@kmMK@%2KX&)RceO#de7c94iOoTnfXr9#&GJV2`M|axi)gANbvq&`ffhO7P=( z#0Od##9Z};L8J7e$pb6i?y+^iRI0eN!+ibfxX|R}?!k0A*P4KT?g%^p-D*oK=r?!g z3GCB^O_kJBibhUTx*lDBUv6~3km?X%v0rI=b(^G(jm^MaYwLZn8gFKZ#li>dNS9D? z%8Xw}HT6~IM@Z}}=B_VLFeF8c#FsDdtrfLa@i_gr6?Awx^LpRUEe7itMSp+n0|weN zMZoPAT~kxPdRr6rWJ_~tQVj}6tD8p~SVdg6}w0jAK z3Kn@Vdg}RoZalu^KPA#^@hhViGh`!gZ2sd{H~-^T z0o9TZL1BR;aoh0<=)#qk%iU z_f`-J6O>1Bc^fo5C;iR+J3VyLM{Jma<497zsl1Cug*|%&M>vR*m09e*fyLF_s~fwE zts3!YaY^ZhZnKt=EBjf)eu1Qb0s|7k-8=G6CRy>!L*muGUi$G`8p*^ba?>o#L%(J~ z$F(`mtJ~7|BxSPC`dLRR!bsq+v)Qe4fcdryT3S4RrT$n|{0o7CFbrjKQf~wdBLL>^ zL&v-VX=@8^Lnx3BfX~D6Llv1|e+^aQgCBq2*a;>!ay_W$q&Zjz)G4!B66xoIl^%cODxSH-0HG264EpE874z4bJI;#?d-FbQorcI;( zl6Gv>ZhCP$5P>&E?0k+7pTJP&Afc3xr(WO%I-a{GAd7==#l_ybN9Gu>$!fJleqF!(68sFTG2p3MC#R-AJQZE z_8in3{(*v#5gh@Y2mqRzn}x|Rg{W2eU(3tN4DIYd*E%ZDITTL^eyt+USL1>()=;%C zmCyEOeii0PM>))&)?G^w(MFYRJx%F>4Qq9V3ez=?(5gn`?U>}%+qbs&BqU?l$luq; zoYH&Pr`Q5z8DYW~pWKA#-)*}M+QlIak-ZP^G-d8GuIV&o$?l(li5>i#UnbL}^^I+C zV#3khKb{G4w9$N0Zvb_W^*{lMV-_Ap+sM*DG?4$evhZNYre&xs+e(sLdP>#`I9jY- zPZkFaL=79EZ8P$s=5#11L9-vIQ!pzE#$3x35D#UzLjw@WC#iV;^u>`AKabinpvefXv)*txScGc= zvnAM6w7-_L2$57*F~CHG!Ykt`lGES$todqQhWIh7>>%9C_Itth$^JffoGPcl-HT4G zca4Z`HTy1m@sY+w#2*lvi}H<@jonfYrlKtjSWw7 zfh#Jq4$%DA-=<%f{Ih$Yv^XE<0CVM5|I_O$B1&i3hYs$>^|_%?zZ<7a9fQ{t?#<4@ zG!~%BGyd+TKk-jxHZ^SsW{uy}rEd$AVO+V>^a_Lp2khmTKE{tvAc9F?cRVTzi_S=O za|Yj{&~W3wy^%5s_? znCu>ZCkrpPKWqOR)d+tb^6l7xC0X$<`*zH;q}B`t#7x3za{EW|4n=+ju0RknSzmFW zx;^|5iNM^oiWk664xf`Z=xJM}5&tqgw|Y1rg3v4lnd5_330^mgA^ntnJd;3Xk^@XwH-$?Zx^PTGE!I#HZgVzyM)f|{ z)x2w~y54;E7pE^aqdm2{6+$t;ui7!+zlTQOui)wf@fqFODMZBWn59RKg^e8y$~ie% zSpZY}z45Y*u$0sQWKiuRcD5LG_a@5jsaf#5E3 zdaOtG22J`5Yb#qTmIyY~{P=v35vXFX4{rX+bFJyMdL(0}Ji|4co0kK-+wB~x(`(40 z#XP|U#CE~0CiHO#pvV%-%?a!t*s$qdo8T2z1{%bGy` z{0ZA|AWkUSlPNmZPYLHl(0acHvp)nqeGse2r{}X*SyJ9*jB>ywaE*-;TjcDBZ*N4+%4MW6#a=$P&sI0V!u+5D9>!tv^?K7+CFC; zt6^-(>ca+%$M(ndnQcxC6lv$;iYx5090f~+LV_`TBcO7XpSxx`$BB34#gWtjiO_I1G1K&Y#;s^^1 zXD9~GeE^z}Hf{~S2JmaL65j+4{3@ri%T{|>Sfiw8HG_j_gxs{y)Up z3t;x*oRO(!sIl93hDAwTkwBS{NAS@g?G|@l@f=jYebp~XA2mYFTzD;Lcw;rg!?|#* zijc@1@l6m@8S#IC&LLgW*_-z}i9bR7_8i)9SQeNe-X8i;ms+E`8nPzCXjh!MqFEv( zbACQ6HNeUQot=EW5(_TuCNG2v@@-;>&C*KPtLpNIMlk z)nB$^t2x)4iU_f2<`+TaLCPWu`*sF%G=)P*7~UI>)7K92@rbCXVlFOs0#Yt6Y(zvv zn0Q44(BS$;OhQ6FLtN%tbt0eoK{PZ52aAaXFYdNMdZP#FotjtcrsOsbrGdFUC_I>tc|a~ z@bG%_5A8g|8_W6+>rEgH;4mdnQ?0!ib0*r5D_zJ^K;_mh_@qLCP8VNrXf9_QMT;{K z51Mq3;W*6Fv6<0E%OwC+zs)#Cf#N0we0!R(638vv5dIujJ%QT`y*!@X93Zs1P;S-i ze)QayR<^Ng`?K`0&40(#S%_YZAG+kolAT>9YohJiPkm#z43Q(jyAU0i@+z%-9*f-V zU)N&q9W6L2bcb<=kwVzGo(XYM_-uwuA5NFjOvQ*@;px$rR0?E`@UEKQq+&oe&n(qG zWU5-j06gDabsa2@|D<*EssIDDMX5E0xGRX{H;MB{o6`)|Q z4WXu+#j-;OGB_6HH8qzOzCuxyt@1cfo} zl@i{9p)M0ZkwxZ8QgD1;zi=?PiwH<8I;J+XAG}pBG6(g5 z%KPy1>qbYIRk56~^NBHsyg@nCvQRbIKPQ$SsiNZ*;`ZngMRsvpvc?Q4Vyr|zD+8tI z`*RM%P+>w|akdOeahUCJnPJpG7`rN^>=iobb6gxC@G(}Nc$^xZlp}%e_)1cpty>QA z9ZqaQVi*9u<29YcX~VRE4Jgw&af27?14s$bKFe-Z>@bWnRjduXaZTqIwMNMVh{)-o z@I9voDLi^cqSrCAZ84!cKj8?`q>h>wnkT~LnI{UQyB7`>mNX= zq*9XrP>~zCjKiGlPQWtTi~1kDzy4{VZ~m>dd}dvDZ2C^bV&PWn0UE#-ce>VkG$gD7 zGvx_dJ8@S#4r)baLUVYEsCSz5-+yb+#)~LY2&w7ed{RcbzPau)uFe{tLI5Liv2Iwf z4$=Vq;PcJhy8rq@hr6i25&q9#zc-mb6IF#$ASM|GpdrhKA|XI0bA;`18mhpWN8nms zP?*1+Q0=>ON3t+@`PI)CvdisPEuQ$d`@78bkNe`jxk*xv^zK|P3ad!+f(%x6$v#r* zC?{iu1?AZwFHE&o6|X*HmlKPYcU~mw)$|$ECg@?JQyqv7{oB z5BmGvOz;-DWlnNGDJm2t6I*5V(`mG;D+!{v$UwK+Iq0`4k*riRQ#6|60X8CtqI%&e z+0f*{P@TM|>h)jedH6b)Z$CqnIa+u#la%n==}q|qUnDp8Mcce(26R+KGC6$zh|R`66dcWQL0!bg5}8JD8vd&*SPwO4c&ykVE|B;lDMU0#;KVh z0g~f5^8O%>U4gzjPu02!R$RzKW0_5Bq($_cM=Nllv|AKVhvCNa=P|R|i15UmCl#fm?6b_|I9&`5Y+c~?4Qe0} zxy*;UPwLJmT&O6@)!!*cgj~cXZyv-ug<-V}Xp**IZ zMq_S_b7x;BqY$+z!ublo13V%=qb#encUf=K0&)|w!%in6INJHJ{^?jEv=pblck$$w zP%yx5I1F*4`dr<@%X#z+J~5L|%UfUG3rn)#lh=Z}BihX;IfnObbt|;tzlZvafGVr+ z^WW=H^aOuAqA10q=0AJ@_U}9Jhqth7D4PPe4FJ^!t41nA7(zLOLGdw8@yt#=4yy|owge-(F zT{wCgLvT7QaA_k--O}kr{+X7#-Q|_>g%uZNi-+}m7;^H{5$fnOWyZsK-waFSi*D+S zkB1HOz8E%;0Lq%s8uXL|nRG%y35OTKZK<<>V8z4ET|E-d%#Z$)z-yXlPLca*JAB>$ z?d8S~X%?o$xIXDPQJAq@qPXcj+GTN-`9n`q*Y`Mp)i{8cM>t~uKr2EBSw!BbY6$#? zZWBL{9+g3Nt@oar(>JdCVjTPxBo_(JS6?4xFZMe=wZ;F^Hi82R8F3>Qs{Xp(QWM(a z{%PWBNdHS3F{-nCOUbfTl{a2-Eu~r8d5A`hjiL->7@W$lc`?XsyeD91BuR(Szmrl( z_)JW%v83x!XZ15j-awo9TpyQXXuc%DO#TCG_#U^|+ok&+syM9`TywAM=Lbr(SCi8a zN<%|51QOVuOBsS^`@|WHV{Qwbq?$u<7owcWAe=>8$T`*is13sZTh0m!+1OAA40cTWk*69Ne`08S0&$16 zI?2wfTZ(hR|Ns6$kxZ1nc2C0mrJMxZD7Q(YWKX@PVojealTBFzBT!|mYkvNeQ^Nz9Z zvLpNW5e@uYpYKAXBLcb}U!f3h3H-U#`+mYg$?Lt#fcoE^SGc&ix3_CB&z%Y8OMfjc zQLD_H(|A)M(-z|!f!hl2F_w`Y03p>Q1tqj!AV6>LM}U zV{Cw}QaRquL{N};{M6Si&yMrHCA24;qtxRPa=L#OX#h4HGd?!J&0cj{1+7;LOAS_pIX|802_#&@~o1}FS41xYDa)qX7k*FxZg~9c!W<$P z=)toDoF)Pz0HcTv*DQi=)q+h1Kn3VBB7n?v6%QGi;c+c^zT_4(!+Y*}QkT*Dc!T!; zOtgWlkO`GbU2iwSlw$3b7+ulQ9Hd-o@1(=zK*iHv5TTE3!Y)^0*qo*Ix=(fS!Hu3d zwc@M!C)Q6){-gShEPj1@=pioeg+}kI&G|a?Nd4{%)(iZr?>r`()MIr0$E%meJF1t? zlcYZVnS03S+;ki{Q$?hJ+m|MWLjElASQGumw9_aVM9e9oMHvCtd2TDwyZj`NEyvEn z`bz-!$OrBy(eZqGI{20h|FGzZcXrJE>-sqpL!|St!m~i*w!m$LwUsw0%(q2lneQ@8Nw-pdB4Z`$}g19m> z0;$${ZzsMydU^fJFobJ#!lkCS6Z4YiSlaP@vs(AjewcgyMn(#>k1uwVRG$Ahh;=1j z2e^^V0&U;Ld0Li!@!;@4fe2=|Ivfhq_(^AB^YbWLQ?gQvVyJzsvCg_yrb8e@`B(FD zw0zgCT(LJFtT9vPsXkM;6xF~=Yw%n&{DoS;j`qM><<7u6v$BScJ}gJGO^nQyN4lTk z(E?{i%gw>T#_CfF+v*|rOs4E(&`spl<3>issilQB8E&}i@9^)q2Id)j?)KZ@RGepI z6qL=qy&rHWxVjiPh}1w|zEG8LNVMeUqWR#+%&U zSAv<*NNF9r^D;4Q_2Ef-+V5CKZ$1EM#?_h?R++C0oVq3tA*Fh&_ztseP5z!+QCO@nXWWrMZh;nf4pRMt4h8ZVg&*A1M7-A< z>#bZENf}E=OEB<2YhN;XhiWJY%?47M@44kll4FT74?~ng`K|CL0y+WX25B?>mcCcp z(SmD!;3S?}hlKUClg$k%5zxhojSQz*XVa!jjzBFW95!^Br^#4r>N(%PygsC%(z(dLgOE|vxoJBrr{0}lJY5Os z^s>J2OsCUkt#r=bigs`c@XX-bR8`I!NM}S}yi#+NS})%O{z3o#?fmD*!YZ;54N;gr z+pIQI*OU(F`H9Tli~Wia^-rH;&v)V^=u@ZoRe%{&sW0Q5a>ddV^Fqz*wsdXyj`1NGkjdl z^Z%o=I_xA@^f@>U>0eD7(FU9fHHD8Dkm9Aocik*quujGX%mD>;b@jC^4nG>|2CuVa zM^sVGp6l=-8yybv-i1^caZP5iQ9x4x3S5l(6+INJ#cG+$v7a5E4HgUFf*xWbkNECr z17*kU_GD3R{YpWO;PhQ2q?5+7Y~ZhZ2gwyU9>V|}XCe?FEIl)WK%3b1ANb@hq7N6U zuS04?rhbW1{iWR#*n4sZZ4P|TJ&Q{2v;=&{wvjyWHQzT$xaI{oUKqYT^4}C$4t%tGfMQGpq*uiOSN32djG$-mDHba`n?|LB{x zxhkCf9s3V&=C%{w$ zY~XP$Fm}BIWnyc)VzT^t>A3u7Yu7gHS=sDkb`=ki2A>9XC^Ty_Dsm2_J;P5D9WRGW5mQ{U zX0>}rglLfe0uN>Y%m~l&|Bp?1m{nI`(y!2>hoRHN`kQ=OO&lQ>b4<;=gE7 z$uumfqOs*%Ac?0uA3~JIKO~}zGMcL`>W`FoL3N^FaOO|Y{yuhirF`0ryqKOo7}cNw zmPZKdOZ{Zqd7!csRhT%D{m(k-sa+~>060O6RA@`w*98r=>?m3h0(H_OG}lrJEA7*w z@#EqrUXFkVyA2&S83-K09MXX7N_yoY^brApa=vMC$L&iRn<8 z97srsHb8U2gAtpCIbb$q7OPtTN&6M@sPojMwRy@ReV&-NUJGUDGWMzlgN!zZTbD5b z&58NEV*YhoB~s+@{-sd5&sE`Dj_r18yQ$>PwU0 zo5PyD`gWl2$t|V`GOxy$3Fuev+mmEfn;PiZZXs=zROAGF1O$xN0}>pZT?B2&;Ly;N zeX^dQV1453{H?s%a;izEG^8Wgg!utQiT*4g3*VU6U)a*)0qu=59sr}pHU^6uO zWMKdHA=Cm#kHySXv&ty>Z|Y&)_t1H(zlNY}iG^>)otjq&0)!NqFcE(@>Dn_xG=bP= zUHb?jvI+KSzyGLUG=C^~k0vnE<;OD=ocp;JOU8E%C>k_?0K1bFe2P>YqvBmeJ3gtt zTplFAgpS18KjYDxrraMEYBhkoQuWWe{ayM$5R$bPP?!0WqO3k|Mo%x$~flrMX_ z6D)ei|9Zb|-FRAw5W(9}jCj#-GH}N_q)DnIJaq1EQJvqaUWRl20S9b|;BNG~IePHd ze{p$3jmF;#z=DSI<#mULqsATz`G^}1Cm@Z1Elys@j$m;)hR8!SmIFd2&vFzGt(q%G zNC}?V5FaWITUneKTa{4rm#{SudJ{3xXCI_mfxt7lMkEq~83*eXX-`e#z;fJz;K*NZ zd(s};%hWISXXR6{D)c{@dzxb!SFA{AAo#Pq8?g>eqv5NU;LD)+Ft6Xi*b z*-vu))3DW=x_o|R_;1tmB4z7qaktiL=>v#>^-*t{Yo@*j0j`g~r z6V`KiE4K^6`&aH5ZL-UjGXC98{-q>vT_T%rrm$EdGwt&Bh5f1i-h7{HRkOt&yfPD+=Lr_$B*iV7xOGPjD+;gUoVl-U}xH& zMJ;@2z#L(jtWmQmsDE2veE%vM9DTzDtn+U<;MW`ep%mM?jfyIMFa{Qe_OD#EUSyYV zi$x+5CObM%I|)0#0m*fUu_Xb%l$`_rAWD;oh|^fMz6o2T;|N5ED0ojuknXPQ-}f)y z(5R6;_;m%|nL9|!Ns3e2O|D~tY5XCvRYVmLb5HzbptTIb-Q>|v!qr|}QPJI%#b#_* zH#g1;sCX6}>-Ju9jQgXAX-YLJGZM6a zc@fcb%cV2dQ|w562Qw;qTonB8_}u>6K9MmoN;A=duiTdUD+0UL_%^7DibBzp2vBgH zu&_i`Swbz@P=6(EFo!=WLZA^9Cx^LT@_f`GFNbYZ;Th_UJ=HTU*(@=P=zw;VZc__$ zOVw+@3~C$8>Uf2DTAS66sHxA_DWc-jD>S^u11Grx|AzlNxgYICJzkbm8QangW(=W# zQHIkKGy{X53$FKWojH#CX<90MMEG2Nbr8%cXfx^*k~nhesbe@-xx#5W>p20A2lQ|M zi?O#3i?aXTMW3Oi1w=|vNl{utI;BKFK)OT$>68woL|RFamQ+gVRz#$c25F>Ay5X$( z?(@BV`h)i{(cNYmQM5uUW6I+SvjR)xZDixz_{b z&GM?Wo;txz$@XgugRAPHFO7=gBhnfK)-@JO%^NY;Hj7PSzxu`fve@eRoo3%tWocz& zLd*AuD0H>?-|vb~hjULI6Ds;%U~de*b|_x(eV>&2qm4O+^RSfw#ocRRIu$DI-5{2Q zBk2N>p_!$)ASdsulHGYvP4oeBij|#QRP!s{rTKX!={H!?f={I@QHE0tpDX$rOC3zC>ZeLo==L4ljSdQmNz++BY#wr(3-duUK3 zMo3Tc;;{{!)gbxP&f3?si_T-w8aKtTulq8M%4>^lPdimBV`F@y7rwR0%l0mK6jNcw zsoGl0!*n2>ib@xQFg*z`D_8#3q^Eg%=)D^c84$MKK{49{+(|v^#VrT@@)jCb>gV*_ z-r~lr-*KZ_`xSbr6n8ec7mlWiJZ(apd{^GpdmX$u@@aW<#eF8|s+xwgacpN-7kqj9 z-*0(_8!!j-<-Xq6!i1W%$!>FQzQ^53>QaVbODa1RvcCEMP^S0w*G5X`7FGs7$#7mV zAcNZMqE|8FdZ0_b-TN1OL>A87N-%3SVb^P?6Em2g6xoS(<|w91Unm&GzlrBN&0Vl!ufE7xww z-_N`frBZj?c{8d9`3TN^?4|Fd(|$4guI}m1DUoq5v-WTposstw-bue(cm&@+Y|V3x z{$f`vCXP(2X&Gy^t^2F;DV4@ zS2_Mp8`sft-qq4{$<8xL{%0=>#Djwfu2QCJoF_oDto^SSS*Ku?Npc7IDP-to)kQ-CSJ0nA-e`v|o$E#`IXc6l6Jq6c+Egq!RN^%;?P&6#Z5WB5}9 zVc&mVU`mS1sjrg|-sNt0c6PqTqS9xS_fq)p!U6_OAoi!gn7R+2&T1yFrtO}pd7bYD zFb9->D>AHg;pJ?eeit3>fYp@PFxJxAN{+bChO*KNRl-b3qmz60?k#s#bpm^PU+7_9z3o-_`~8lQfemO0^%+U^EmVMtlhlohVF(E{z|#}68cfMFEMZ9Zi@RH zyGSW3cf9U&%TQr^^Y*fIpDGi_w6ur)+NwD#wgax@W&a`mFtN(dx@#U7?FMl^zX{Wk zruvs7ozV4uBQu!PX)Q^PUXVV@C1ro{sBd1|=~M30se;NX?LX#(2)n7wotRY*)soLC zv(MjAo-G|p+)pYg#vol0K2>-IU7UwoW79tt9zXZoUVh7*BxohGZ6`RAx2DPS^JkUq zw(O^$>55r=49WZ(f_&rw%7{{V(pyHzi3uSm#`WpyQKGC+3NY5&2)k~tzjnxm!F)xU zPW85o-s3BQw(C{8nc**XsO(XEW|)D8qc_-pT%K!XKNHs*8!O$bTpe+|e!&|%8pY^5)Fj!{yps~< zUW~C%2zzhg63T3b59pl7JUt*CJ06QEqY*^ZZ!Ze_x2%j3Vxx$St$t*m4)GzB|Bk#3 zAG`Kv`*2TK{#bPEcTaJ1{gPkei#Epv?5vRAYF+_UIZy+7nCDOn=fxHQpP6{T+)B9sIY&ZH*oeT45uRFIb?dF1;=-9y4#yDN;RR z&7i#L?6d%TL&nMiLQ0%?m>=;Jlzm`AHdGe^{g2GgOCoBfjxziRY)%hU2AzT(B2 zs0*g?&R1DP0Q2xbfmmdPkg>^3PkclfD>8sLbV|3VTZba1Bv;w`legWsi;nQTY)%%%zYb@dz%51)RXkHQj8?7^oZ zkRZ`7(V-AEj3qV|d_$YAM*4K(^S7f$)C$Xjl5!!QnBd(MT1%`Rjyq80to|>4L zP-Q?aXOHxtUiIK3;ewLLjGH%Zywr{6&I_uL_%wF7CRhLNQ~zeqmMY6xb^}BGCDt)Ale^bKUcNM) zKD=|DM06d$NtBI1d}+p);wL}bJDgk$A&hBv_?QDKzU5mBTXTjZ%}wY>FJ>8@nf!&` zz39F@!v8)llDRPmG5^1hfXL;~)#0BXc>ecE|NWDZ^uE6-T;Kox=;itE&;QSh{O3RE zW>lzPVBG)rhg9qT>4i+OsBr#&k84>H130HwZUn+;Gwf*sle_*_$nbwgcGD>Rp`xO~ zA)$|2B$~d5Tt-fpn}?AP82`kelbx3R53>H}Dg%S+v0b(Z85tRy${4xyE<%Os#e~`C zO2W~r=-KDZGY$w9=5<65M|i>E$;bLe!i(A;t*xrK|8V?ucQba7^W^C0XknMfx2U@- zc(}Q_m)=%Y35g-SVw%D5IOPMBf7(cQGf;ArR+ zb=w&K37ua@S12jJcXbgFP~NGchf%_m{>~I~JgrBujK&x+4cQ-Mjrll1$JNx9Rxp`(q#r|z%3#MtSG4#1UGxqit9j$WA zBIejk5uEb=DuEF$^Z4=59EgOvLCbJ)86CZNJ?Y(WxG(!NBiONF7-BWnV*Y;+rCV>v zE=%vCMlk=uXus4C$;qoScFev;MAgMdNB8n-R@@U2kq|Wd8O~W@ zSm%BjZUr^(pI}C=x_{D9By4Ddw50DH5@N)bevR$Fh1~Ic-iMbScz)14maoj{PxdC0 z2G=s-{&3dCS;^MG7whZ2$($4jq-IZ^KE3-fnWCPDZY?}4>?`g+E~JB1<^9u*`FU(X zLBSH8JJ8^bfwZ@`r>n84>FB&ZJ@tlgEr2>CY6|}G<460q3f(_0Lk3hN37V9{|J4Fe ztWnOy>m#HJaWbC;G20tyeSO-M)m0Q?Zf=fu>C(5d z=lu?lbZT=MH>`b|+oH5&{|>nP9?}kp@a7w7#sIV_Qdg&eGGY)hC(91>n(H*u_FZoUu(b9NaJbONlRqCz*=*xcOA z1=szVF>oAXIzB1s2q&$_*how3nU$R#CuLa6aqWwBJt71$u~A+alunXCVdu##E-p^k zWP!Zm_m#q&c-qC(=g*(15feMR$=z;|O;HuRYDx9j2e`wlaWFE)1gV9# z76ZU-5}d(FfZ{Gt^1Ay*XA~IPS^G%>1m^wm%jO zMG{%f_>ikvJGjZj%zVZAL{CvsaiUo4OxS-LfT_CYNXa+?hsLtsLdIGsq6+@Jk8 zSE^$wZVS|}UEVqY9QqXxQ2q^L`2=E<sE61$o2K{?RV%gxKXQo3H{IENr}tx>IOqhD{3 zg?6f@2w(B~H~sC3qoZRo$~zW}J>fMIIJ@<^Mi^qR2xkObi=?hDHMrL4zkdS*a7k+9 z<>ZcDQkuZ}g0dQ_ot>S27e`m3cG~8Cv6O*$pR*F{k*_`{`xycm#^Fr0@^1^-Egk3n z?JoCQbft>X78Vvpw>{++6bvaXh2jz>aU_bkaU!yY4cs-%hgEF|)nF(oA>+1rejE#E_4M@DjnhlU=J zAtJYKEteBqCz<$l6c#W1TG8sNXwfmCTiU< zkyQ8DOYWYY=!p^~U%xsZtyfOrbP1@0Mno85nG9#jg@wboA1SNYku z4<0@0yKMNUH(9(-NBRMZWV=6?Z-3;j?radB}Y6BG46 z2M71O)zo@Tr4@){>Ei;HZ%C-AQmC}{?eDoPjP_mA>vgcQwkA+iR@V20Ijy%^T3Qy$ z%gYUAJ!xr^A78ziz(PV2)d}Hj3J+Ag8!xU3;oZnl!#^#gkbC}jYrmvntin0H*NCg_ zt3?lSs)V2Tg9owZ0|NuoFmC8qM@N7HlQgt#BH4)9)2CSW_V!q~xXnXDlm?tvVR~Fn z2noY^YbZHu=Ircj<^}#FH>3F#{#PX&TwEbpS&VRX!o+0KYDPxHY*!SKrk9ww!A*51 zOe`!$VPRpbuF`Z?Csb7T$y{_)zbK89;s>R(;V&#KC@3p8gI2z`w-?dY*2coY`3{La z`Y?-m32+)WoU%u?D)(JqR3eJ4-M2v+ovX*M0|tDH6weBL30-XMy9;{u6VE>rRGhul z#w@5U-Jk)3sRJ~)9RsHU&~$C^U!67&nE!T=j;L9)jv z>?$iM{fwgK`x(-+$c2lDh}6cz3W}%eY{*8?i zkkUUdw(}Abd&V?0Z0t8Ne|WpN4r5v>iYZQhVCv%hfV1^tC+z}3!~rv=FW%Xx-7K(v zWKR_z8~dQBxVX|+Crdr+ekhB|``Dn9piAKpTru?Z^d5Mv&aJOcU^JPe<3u{Fp@*Q^ zux?=^4#&I8tze`T&}7eUTU&Fmz)VR>>c8Bd+YHBdPUp#!n{chd=VvWfjS&Q%Xku;M z@lZu&;xYrn)P$ibqdm8)4FMtHk8o4B@1FAIS*6b{LYg93PalR zwEmPy+1RW(BV^h|2KkE%3qy|H3!OgG3-lD zPOgyssASXz=H$5I8P>caeL~n&UQ_el3r5u^a2eLzeSC+~&7;A|)zud9hq1yB&CIgY z;kQzvV`WLnbWl*x{C#isD{h`kiGD zK>3|K7=J&E{m|C7P!avx)ALy8r6ehjMfZo>&Wqh=z=bL9HS}S$cf!>b8&=v)NThpc z{s@Gx{L1VmYB;E~Q{}N^9_6E?q=X~OkuJV+Jb6N;d#i= zC6eXz)fz_)H{G{nZtA(<6IM2}os%&iP08mLTgV)?HHgf62L`Z|J5Dm)G&IQJOJsh7 zCV(=Xl}-#H4Qp|7WeM;00SWqt=9yjVw?}{9sowvn-J|fui)mD8N7uo@LDs^td0>D- zK9WufE+56_oKFF>`SLO|GdG_+dGb@`{oP9lxBaAOJ-F*S{A^t1G~g-=K_5Wdw5itJ za{|Uw1zaUQ)+;dsPPcmr9Vz1+gwK1|G}fI6%{uMJt1hP|Bv`;FtMO}bM+`L$f%-Oj zj5Xo)1S2-r*DPS6$ME7wY49vegwLY;PBH)%NAKU$TtJY}KpdQ%t+5<5%EMq^M3S)U ziZ=8r^CA)B=8Z=S$woaY5H1T+b{iB_Rpp_Xzj)EuSGTaTjG*45$#S)-W^pimx0yu3 z;01_iv?NadHP7+$^JfXC-38MIpLcCdhudaoH&FNu_J(hOu|~9`&A|ok&Q$ zSksYon_<3l=kso9EB#3u00@}vD(`+@gt=))NE|+m%b~+lX=8u>>@4@Dk&34^?!jm;PNYJ{8TE4= z{?|Y}ZL@1`%P6y6yR+QJ;+~xP*+XAtuLe5LmHb>fX&IRt@7n(Tv2UFD+xCto!g+Ow z!~1wS7nUgffDrU;-igO*fGq?DuFk6&7#Q>_><6k_xSGMjmHoYgjfv!`WP)N?k+r;5 zWDSGzAa5cY8yz+D`x_(g3tM>thz&l_ziI(*e5UT>B^7Is8~A8=Dp2f<0UKU;%>;sz#b-ABBl`0mc^ZU^mNQ9 zm>@U^d!}x^V^NW|w!XbI@qZgs@x4J}Qyeguq|uc(((I48E}FnyX+Rp=bYY*{*QegzZfMYv2c9ed66c zJi696o5JbEYTEkycSI1s7rrAIYz6V8Zz0IPtpygd9a5(AuhrF~zuMaJIfaFfWe|)~ zo$<_N&KZTIw80)W7m5Y(W_KBx-03H`NeKBVnf17ja$yixvPSGk_R061=b zpI+VNB#YEPqtPlYByic4>+|J9tR;bfyW z((mBuAIS6mou6#F;c>tBEO;IUKSC9P*YN>54z{-!48MQ}I&(ly4KviLzUX|`fDF7k3!={Uqg#;IaO67+r}5i!zb25 zpB;$^2~X9S$l`W~$zM*|+(k|AEa#>*ob1D?$4U3vE@}`}7?3kmB{wv-@61i}tyzX_ z@;s6BEkOACxZ4Mq(`ssJ|5jixk&&&XCHIQG`uohxn;n6HfkejC5)l!x4o+BLV$e{Mx<|-%tjr5;U3GP}hl`!vh9wN1H8wE#?1b79f(>}D zM!#C5r9ph~3XJ|NMP~XjH8nK>CX$Omh?&WJlw1qFlA5MZo;VG+wJnq4H0Wy_E@eeE z6sfT_2)$TK9EK8odU-jtmBCL`f|r+_hIa0^yfg=9z}EOMw7c z4U`r{w{G1c$H2rS5EB)B3a(p^)J3JI&4Wc7;S?hL(}Ny63(N43 zVvmE$6hl6WUJil-y$hM3Ch!e>qV%fl2_2*B>+4kfRuo8h|86G6%k;M$^T9H=8h$uc zk9T0aoc0o?SUw~jaU-Fc#2`$m{Jt|*ZfytKZz@ciar_2-3iI3^ z7&d0zhP=vy{noAL-B8@n3EEGtT?}Zb)-P>r7!_JMA8Z(ExEQLnW$YF`m8m|tm+tiD z{Tr^76Vw>F>HRkdCUm2;UApl-DSU49U1ws_3xj%xR}@kd@$L>O&o7B z=>?36Pg@qm5@4S09qiat*@CBo?2jHj5`_lcdYH-X8W*n3u2od)MJ9xpZ2xV$W-4Ew zvGNID_ctZ*^{Rg~P33(?St!FYKHEuD{rLHF1*HH-WW^aOhv1A1(=;DKBBHGkvnVMh zGBJRLO(D>9s3<9|9Mlbi;5AehBS`w?moL0RLPDS+jy#AY#mG>@Q&v_kgGE~IO_m~; zxYn=Dq<;8Nw>AAOz;}Y-4vc4&1uHuvZPJB}fm*G%-n@lT+u%A^85SXP6S;S9wAfh! zK2l)LJ)oTS*x%omkW8X8VAMRagpFU)4HxGpf$);{NZPa%YN0sTP*->Kdyn{u&3ES> zv8(pBwka%Rq3@3wZ-V_NLy${V@}|x+B_blakG7WgZSPozKZtofo+~%9{~+qoCwDXE zb5B=S`S17?0J6OH3M(fIO3TY9BG2V)KS#ZOjkn-b9j%l-Qudr24s`8nE*k+_FqLbm zzL3#e50tzaBgsaQnVpRdXUGtTgN>~zMr+bJ0;(XfPF! z{`EhozPWU9PHUrBr;?g+b3iCRE=PV`PH$VbXt6={mlvCp^&LQESl}QK&FlaGF=Ks@ z7#(UyB6POg+|)~wi4N3|%u3_Eeft(LOlBNzq9!g-&T+shtO6^*$i^X#j#9`;vAly{ zC>n3#YJ&|<#2OnzDgshajMsBc)zpYU{@ZQHM!Q9N0-hOP;;zG{Ld*ar<0TGZ3=0ia z1bpra+}4+X6r_+KAEC@kyyu*gtiV*Tl(G4en$KLvxXR(%WdwW##$spEPSy%)ce36q z2Vv>s{Pqa31Gk_IJ8&MrqJ$mh*n?NT(4|F>r?sT&7bN|AlSeZzFvjn6jzKJSlf!SM za?1D5+!p%eGzlzYc(&?UK7Bgi!7Oys?N8aI^_9)E)Kt5k8HcCnWpfc9KQg6t+d>-g z0Cq0aFu^(^B4MSUpV~7r3rlTmZBOj-SoryA}KZ);2pm+yX=(QQyd@8?!_sxgzQPduh&utehMi@VJTGrWkM=Gt}79i;Jh! zM|;M{4L)V+34XSltZNhTJw3#{;f}y)IbQ-vJ&P?lY_Vbr4%o@Llf-Ayu+eaDd}PG3 z%e&&z$nU)FF>6S0 zFizGcglzN}kX(OKCxds3Lx7^;BCDGBj9;ve0m@y}@_To0Zw7EM0H2ycv;b`s+}vt8 z8rC*8vH(F4(~G`-^9CPCGEN_eS*6y)oS%*AX~1yMMsxM*)k=OIp3;usQH69>RPc*t zPV!LM`NxkR+k&?<7%}wExb=~3<-Gz^CIB%`;BcS+gZjH+qW(9G+_30`OaKE%%0I)+ zu;9{-bpTMrCW)HAfA__40PuSuwfkVF##XK7{6GiiMHTm3GOFL?nHQyIt>Q-@FE)p? z!3RAma8BbZAWadFaA>zYDV6RQCky>(tjgHTAMaN+HkcCgBo`-~kB8?Qq)!gJOX{Ng zBW8H`__K&ZjrY;^HpJF$n4SI(n!xUX+5xlVS$pg)!1DkU0f&UB9sg5yF}>%H2i!F) zDc(7P08A{q7&Q8Q-svh-a@{0iU?!Kjz2E&KlU_r0HhLd9$tox)JX27>V`%>oztfW@ zaj_3CZNtmQw@yn#^H@huZ)N5iQ&7gUXV2&hjPKmJ^B(n7_Wu2a)1$?-a{!S)K$2Zg zO-_!9aOmpljzbRqY#Gw6hE@dL6NTIi2q#QRbrN~ATlxKpfuxv)zqmF>c$e!{d*Ov2 zR$&m)SeAeF9i+oW&r=rDyTDBx7C^nO7=u1Z*{LkKaXR3{v& z%*6NaUqHS4VvLs7wI*%J3E+`9F*(r40_MJtu&oyI)$1m&uCD&clK%nl(oaeX3fbD) z+C}NE2-C4YUc2Si!|@vst!1pOtry*S8XxX7um@VmYD?V=)Iq4Go{tmTXV%mRw*nWr zu*#a|y=@FjBfVe)0ge0YJt+L9(_j@z{25WwZ~mH!PXOd?1K@RGP-dx)iaq*0Fuw_y zX%0jKwp+KpK?=lR2@DznIqt5eLla~haNMc*%n4zqgu0Q@xj$Gg+j z#WXG<;p+Ir29McKJh+Q|FtxdHJd_#-_c&*^9<0Bst*uR}V2+1}=N{m*-ni|DW5?YD zqOQkaXUFF(GlL*qwwv3$wv)MXA{yx?V94cyYzbxPA4T8z=xcioDz#PpZ)g8Ya*x5H?JT~ z!9=u=PYw^UViOW-T~}7!0iIq2jOGpkN`S8dP?wk?i}75>My!-!jWrH4udHFy003%Z z_a&FHNv~XSHHC$s5|~TFFV0|foRm5R7)C~Many$obbwstkue>}0aF5n75G<@qzAz; z%!5=Kha&PW#SEz*_BsANlO?ZD+Mb>@(D4J@&OPF3H5lsg9WEepb6h}BP&=W`9fiPc z9cU@ho7rk*V6Y;;%OW5!MA?)9P8dgCEexF%8&o0&&ne-o~$dShe5D(J>#X+lH@`c^hZ!64m3WuJ^6ox*V!bUjZ& zH~WYVWaX5X4_cv{l<RmXQxoiel%Y1brn(&w6E(OA14Gv8_E^*8cNt&nF!Pv zq*sD>1tpdkO5HY%fP6KBpQiBep)V&V=SIqpAJEZd<`VR;BNpG?S{$lXi{T&7aPR1$1TK4FObC;oL^ks)t0HwgUM#EkiT-Y^A!^Ktn z)yT*Q1399QQ=~W7S9R$=`u?OeIyspD7=5ri|1NX0*&m@K>wW;Oz}GHS2ggT8H(*EN zoVTBB;>_tevD^KT4@0y9+Qmi@kQJ4dR94zw!ow3nrpJIKH^CYM?kL!$tC`gRNeSES+cJiR*I;HFkXo8E66Tm?%P-A92@1R5 z05C>{wY+L*5Qp{~c!tg$N&u*P`}#1d4bFQVar~FTEt~HzoJq5q*{jWsO8+wdy1Dma z889?}`nJKS9FE|IegfX5$xpOmBpXnxty@URFJxcA0uT$LvdtR*d1P<*iF zPT1al)9Lo@PqmPdvq)z+*hope>_TtQ>MG!%z`vKDpI-;+7Y$@1&oN0(BljUcFE@7+ zkV3$WN6^!jS5`9e^Iw5`8KlV`q;n_OfHMRxx!}_$sA(}QEG&Sg{ys8NC68M889`g+ zb-?-I!v}8H70s;O-Ca4vS8JySgh|qBcLI}>X@OyN5W9PKmjh~mnYXwsoSb$NmRC<8 zMYBNK;P{4x3>6eXjT8n+Z7XQm_N!LTk_GLJegj`5sFpPSmhZgTwm>ng&6&Cx)Z;{!BX z$ng#hPMG35mS?K(@7`kYN5!_mJeQ9KoCze)_;0zs{j7j0bNTdkKpL-YcYC{Ld4B%c zrKUtXR!kG(rWn#kQtGi|B6laqH*m19;Ly(jS;;LR0IfjS0D#R*PxqQ#Y;SKz3LucF zVKSthBzvAIUgvAH{jU~a0aPE{qGzSlIM|+I^YL%r@{%Bc1K3F}ry2>uxiAAWQ(atK zbjz>w-e1%0fxQRIcd0iOKxpdPWEOr+gc7bnOnjuZwe{fSgqoIi6*WBqWN<6sqsr^P zaGJoy%K=JBLrV*orwLRLH-bxaKBMXv#h82exw#Rrj?`3oFbyU$MfrI~Gcz+CeSH}w zGFQ4)+YhKFz%0Z(8xjB7S})9vgfc%W4tPhp6mlG^%O4e(`f$_ZYiB@ZeQ0EE&Z3&3 zX1PsGwX79Auw4Wg#WA2k-r#$OOyJ#Ysfmjo1j`s1rP|xG!Z!@|fKIThgsc}c9i#m~ z7u5s{@@kA4eb160F?OmAF@yQWW1I>>FkwQTPuQGXJpLMj!^(et-Sn7VWD9^BNzxw-Kd_c0>zg6!`xJ` zCI5Ht$bl}6fs4l>!lF7hS~!|dFg{OBNm>6f@1%-e*Zqu*V4jMJl~vyS=~M4c^RFUg zH0R8lZi4YgcKVZ8qf?o)cOFm(;JuSoIcak93bzlTc{m^faFCadDs6b z(j%GQD+eJ`>>Wq|=1AWUp$ess!JiaoX{G@=VF_6X1FCBLU36cX_?hX)pW9JD?Y}B4 zt8zR9Y?Nn7aop0@R!&wH>tUKW(e2x}&j8xY0-zfJO2{?P7=Z(TsT#=aNzIV)?}l&p znaKDdaV8dQJ9_mY=*1xbekolxq4@}U$s>#zzb$XhDJq^z+7YY z+qX@hJ`Dtr5Ax{mUP z=5U6HLYiY>hj=BDNOT>m=@1f!c3MF@m&+#T3K*6;B|J#tm9uDb_nHM<2Xlo1=*MTN zz43>KKWXhP%@T1BH~lXDY&MjZmcphIz;${An3!bOec|#TD`Ml~l7~nc!Ui!7oiIbj zPZ^f2XvbHs=CPY!lwFW6jrS7#D_~EiR#sy%n=3;cg%VCcl*ko_I$pZL%hqy+?yr%9 zvtRGolozbg&r%UQtL$fqr6#Se*(j>J1Wka5Gc&hL^!BPzQd8@0gS~Hqw%r^W zh4ayJp*NY{y&RWcG(r=+dR9(9rw}=C)KM1zBUD*0zCe?CFnscKU~=-Dq*O;VG44gD z{Y1@`z6o;xW0Hj&pWwt2nA^_&U+G$Cj)5u5ZTss*)I^O)ybuvL+9R zSpzU7Gp$WyC|$ArKZ!kyXOLuwpnjv{>pFWNuN3)m=J;Th=)dZ}s>W3(f~LcU9}&=k za+8@E8}17mJNv7cn9ES+qorvOTs4v3pqrC4O=@mw7&h{XK+vdLUU#EgZt>1a#j3B- zo|paZ%?8UWV+4I!B_;plfW!LI&@c%rq>Zf=CnqK*Ol@q!kB^TdMRA>~>lk^8Af!uY zAR*0CUS1+U!>KXl(; z;sbSG3hUf@H^lyO-frW2Yn%X}V@Ph#wuGs8DZLpbhhqBUC+u$%tq z?InfRhsqIzQs2}KM~lb|g)j1!o`2N|d%d>49)>F{ey!&ErY#-Ru9uN=0iraIg(NOe zUj?GUk!*83vfiiyS*yn)eX-|b8I%BCyIlBO-KPUDMEB25}Jb+_f|@zVQH4E~PX``o9D)&(V!g^+eDD|^WV5}Lr^|~rUf?|e8+9v9UQ`@ ziZ5UKa%;QDSsqv-Y8i?ig098dplpG+5lMoZUZ)OKD5hk{_YwX4?r+!OjbTf=0}d+W zPjUQD6%i(LCCc`>OYGs{;Vj(f29(DrLJ>%6jeNH=Mb6fV_@VvTAw!&E3KEAt+N zatVZ#-}2P6KtmG=K-L3;ax1MUQ?Znm2*75(4G&+v8G{F?_w~T*92`V~cH=^rCMd|Q z+-6H=?4~ZrV8y=xHl~tW=E-m2+Bu~URd~w#g zDJCXHMMLwwsR@Cfsi*q-b76>{%F%66tf*LzV%8<1iZ%#+t{H6jXoryHZ0M5l`EzHP z7u6$(0xAF({(__78XsOM=zFG>Rfdq1JZZt_(B*|G0TG56Cd1^aqTk>LKdwzP-~^!? zHsCooDDX3KbBDLGpu`4(_Nj#hBNQ~>q5ocEqW;y5tgeZPGa865d-1sUX?1jT?n-vy zD4EYHVkOU@hB#$m741ChVZ=(>7%v>l$%}%Afu;r#>P{&0NuRFWV?4mw!ky~u*`S%Q)EBKBZ8#`emrO<4$Z(S^3O@{EWOW zE>i8$qbH-iy-l~+*h=Umd{38PBt?l3UALUHLbU+>tHB=);M!h(R4{9ewDsR_j{0An zVc`2q%Ib`fg8Y2Nd6w+K4}53LoSfYlN}E^xkP}qh{j}{?A1U)ZY7HHok?c2*y}W8W zAmI>y+xGN3Yy=|@jHW{>e>`zyKFR`rI=Z;negsfINp*^+ zywsq~b=dx^n0MO_Hp-!uD(G^NgF{YH@zVR`y9pR zi_uw7SrzwmcURydP?r^GeR_Px;Liu@wZT7+QYM%U*PA99eDqo8_J0BmiX$ATnW45@ z@o(eyrfNuyT*x&`uYU87CSE|;KI`i0qVw`Pi3g1i7F)fg$dn8bz=0mcjpxTT-Pf`o z1rbZ)I0}z61YV-=lA=e5nFXy+i4ry^xVf}1S?Ifq6(H}YZ zNqZHnI)6|;Lk-RDKw<_eY`|hx^JHb!DTL@A%4b)MkB`$r1snrt*=Co%B!_4FU|-tb znXw1ol_fr0IXXPlgtcnn>%OUz>jG;T)>oHsrM^xsEZ@?|p$q19%oP?WCzbvIYd)qD zlasYK0k!d2qju<;-|=x4Bum3cwPEbjta~3p>u+x4k5PEp4u< z=Q4ow%!tHsuWs4HLd>k4={k8!^JY^K9LO4CRY<=za7ben21h z{9gZeyjuL}$29;>bn4EJSGkaDuc8Xh{6rW|Rz4L^BL6PdQ#^Du+{Vr~$uXEHUazq$ zV+Z8DzG?TYAOGf972%3drk01{d*ebg5wimik@b^`?&6gEe&KZ;jX(L1to0HKTBQBr^L)I1$c)bjLg-FKjPUFFHgv z>-Z8$h)yKEnvkZB&L~O@s@+4RDI4NhN6Yh`R51+%M99F5a5@6)bbww2iT3u9{*(j9 zUnANG2ldV~XtdpeJwJq3IeG%}p$=?Y%@(kJA0+(f>#4_9!e~K*xq+y80I4k5J4$kt z9^ps=oqK6S^oLVS4Hry=adfcQw#OcT(J|s_3@K9c+fo?*V`F-NFACkeCzbukwe8h! z!EC7b)bcgqn|<3%cHCW^G9b=PgHT+vyTPK^M~PHM9q;Etn-V7S&%N$Gl`fgd>kQw? zRiZbUHVD@I!oq!|2{aG|lDV^P_f*;9l)gjmY6tJQu@=+>3El6|crF_$9*YKr);SjI zH0bNF?-F;q zd?^j>A@ZTCCRi?TUGa%-k4d3)x0+SI@?GxXnEMwnY;NLSq0|HbI zpjO}D^X;_#PJn3j=ctIhOGv29IC<6A_vmVGiq`QHU`&46$Sn4QJM@CY<`#E%=T$_K zH1K_9-U+A@aUo+#hF!H6F$SE&HDy;xv0`!>p*!QOG@v9fNVaiyY2#Mb1+{~#YoR_A z+_WeZY7seoq9DZMKi1V%_`7!sE$6&apLUWq2I%T0AgL#e4ZEy-6_W#V1~o2ijrsY@ z2jB~qIS95cN40ucS~kJ}+lVER6Kq5;Rw+9KifhP%0fjwCgRvwxSy*t;0wiT+0$@g? zYH_!Y-EM^BoDT zNYh(pWhYn&md1*g2?W_5SN(3EI0EZR+=YCOcRlkpg)_^_1}3_@A6}!O(Syr6?nghx zeEt05sK?I^yQK1jf1_XZxuMzxpVdQ>L~AUm4;t)ofq-nRzy|Gpn15gaxWs_sDi|YR z+T_Ufn>U|`_`f-)o5C{K-q|5a9S2&w2Z`37PV56k$hlP3Z*M0+wJw2vgG$0z6mWlE zRsn$*BB|*pM+Ul(qgA1<2o+=2Bq&Y8<2&X>&|DLs+noCr$>%QS+-@9=)K)tYPtqMF z@`YZ0^NLFPl1e_&LWBspu29U*%|%=mq{q+!F)Cl@5lyhCck?&Kz@)-$)I@$By`-66 zH>w`&tO;7r&P-tQt34zesT;+nruKjukJq}97;si93zBl^nJK+x%6OEImPEg0awTzH z@PCfgyDHNKf#r6ARO##`@%fEj8v@Fi{uI)qe z`}Zu>wY9n5ngU?v8!>W-Ha3LYY9J4T$|K9-wdopa4!F+<3T4z8RIIDJ3AZTlyCHt1fpnpYxQ2O=+!W$u&8Xsk_CbMY^xxUR)GAgIu+xw( z;zL-g(N*S52m^vv|4tFmf!I#fbfcrAHKq5Q7hH6G*G6~{Nd<-14`m1Kn&+KjpdYB% z?2~4JF5~@h2WJ{AK(bG-tl$G*TQVxfKp-q40tB|h<|LqxchRaV8v%V*2S6G} z#>QqBx{@J5sQ+&M^{VeqmmuY;!06Z*zCbb&aR?@CSIHY(;Up0NY?&q^Cxk0J={d~e zIuT}Pw=%kaKRE3iBM0-dpq%=ecoByke$dUllj|YP>ODz(i~5M$gL1{|c+xWJ16*Kk zZ$Utzdp@Xb>|>yz!FM@W<)zBH(o>sCMhzZqI(FpW-rku97=Ce0O^p#|I`<=Ql;YbI zh^R!O^iej?pD#a2|Md8it_e#nQE$bwj(7>wA&!4mOff2bQ{uQkHhVgZt3d~;SuZUW z#k!8&n|w9r8&~`5%Z#z;AHk$ZvvV)D{V6XAD=TX_-90i64j*Io@|;lw-NFP#?JVfd z?mue?r&Db7zORr#bD0782dxlmfFH?YG@*G+q;Z7?=vlDFIaVI?x*A8$gil5QfLkCR z&>|KI_>ke1B2_^{R+W}!?5v{Fg=cA5i~DfFtf5+R8}x4c7Rls5_-hEmDM#Pg8q=zC};O2P2jeMQ|};><;>=$c(2@L z)ipgqCB6yVEi2|ftX{lnN`GEw*BNRyne2Xb2DXU&(!#tvhiX8{?Q>OmhnN(pY@^&c_&s_<5P7@-H;)0#ks3u1 zsM-&f{IL*Gdf4wOE(;+?;jOHx=?zWxE3X1-nf$3lgL!rZ^zDiq%@UHEvYz+n7>ary z{tLqo$_x{fwz66|h7|PKBZ@dVQmp)IxomGRukZc{B`*dvvgqsAue?B`U%}+wV0gG_ z%(B{Yxrq%ag$Qkg4KEnw;^tO~dFDTgcZ`zn!h36g5JP~t0w694@bNXG;h;4V5C%sF z8rfXbIPOIEL?*K#5OU3Z*)Ct~9UQp9COyj}u$R`P{QUf&xeH0R(CSGMu_z^^f*v@C zeK<fD3F4L=2l5lbs848^zbgc2YI%R`@i9sSkSB?tMBIxB1LAlQGl9Nz~3 z`AqEXqo9=rULjAD-SB?o{jA^RX?FJZf{XXCDCF+F+;?0mvkbL;C`z@Slet1{54A5Zt>U=B8 z&jtXD4XCXmq2s@&Cy|Gd;L!C;=&s1m@7`afSmH|<=5ev>~2+S-B`h?SL9PS1P( z+Yn1BdufyhV3dG39G1ogxMh_*YN(&T#&+Z>olA?>kFZ&=V}U3}9YxZm5&JkVP2Aus`Pje8yK?Wsuuw(pfCDoX>e zM#q`r^{ZG~!$RkTEzlsQLxG5k5U{)vO{_N~@&?!L64;lxjHw80R7gvhW^ zLDJuj{xy>bqA950);Yz@tgH*{^hoF#R#H}G%zm^S2I`=(p=84sI);W~vt5Eyr&EBX zO?i5G`H6w@)vV+J%a=%~kyrZ0%V*#C-VdkbOaP3a1O%XE<>fCs=4tM@@(6;STNss7 zQ95<#pBn*G)+?~T={$(3?Foz*oq?92QxhmpE(*E6LmDmy?rEi1 zll@t65i0=yiY)JfrmCG=WiGtF0F#{z$i00)>hDE=U;h&jyG;)OnCX_89Ajb6-RiBN zKF}pN>27w7Frg=L+$T>kd@b_n^4x@l(I+S5-9$N{T6J2QniRPba6i`xo8D!z#g|g^ zH^cH(9Yhr94lhwIRY0#O{e>CbT&q8R{2R2iWcdI(@xoq@(_XuF4Fs2#_V)4sAwn_{ z!Ra_O*%2EXiexnf(or1Z1EaNG(%c-6RpjpwU;%3M_IJ z3IF}GZ*sC5r=$eh@IC>v5tw>;GaLG`v;eYc{5>|-4%5%JxAynX*+fM}k051mZ0qba zFw)l-@r9&m$|RkoE?Crre#bl?r4}6jj%k^=se53KmVnQTub{53F61ICAwm1rXOfBL zmo)&yO%A^p@}%?hn>)8L<83aF_Y-OnQz*4d5%a2uI1exeBm%OTC`1Qy+5r+d>8DSb zU=bS%S~oa@E1=3?nlAb8d=1(zBULpu z6}Dib_7ESYVwgrPBklaalhs(;0nk?@YSQ;nkxJ0cAni{StspUISwS$)GGN8;*jsB_RFZAi~ElSahnsrj*@>231v9-rd7& z0>9q}s@?-sc;jXMUk<_-7}G%YeTFklve}Rha{7As?eq6n45*c}Ncfu90NJwu^)kKw z)&AbzX?I|^|3Ns3hk(836Cy52c=Xwl@5!z@dz_HttZbB{vYQk>A>n{n9yeb#bQsD& zo?0ZTC{m=!9+Q$1Apvy>rZ7ubOMy1n6of&DVboR7XOU6;p9KM6U?5k`*ObnFBvtr0 z;QDLMQ7+(X(CidgoII3J-p-Ozd#`R3qgSiCym%qa@(%q^0c{I{UjMr^M8L7(y=npw zscCM@<$HM21NW3cD_5ZJhdQBd`U8ltm*U%44^L0u+Z6a(=*G%^IHsaV&43S_uO8?v z7?-NtzQ6v!8|qEHb)UTY`g%`5xV6omJekDcxRZx^AP%0sm6@5D91x45^aS3RjotX? znXLDpE4z0lg+A$Q==7{>eKx>dJeb${!R~H1(9%F;k6H#vXVk{zfBG~xI6NE@MR#wT z{Z6tFHyo`TP`5Ut_>jxjTsepKum?a`9a6+8wLsy{0)*I34`@CS&6bj2-zdD_ef+!%gA1(QX(VV2xUb2WR$u{N|B1Jl8f*WGD@Ya zl2J;wGJmi8eZGJF{`ft=o`)yyeR6Wnd5_mR`TM`OrKhJ0HItRSUhg32)Dk7WnGnR* z3Ugxvd!`9CQ@@QwXAON}w#cP{@MAh|7Y)D25Vsj3Xpb{KK6UB3M30G?*}9C1%51~S zy$MZMwuSSYeXe^zuUsjs?*7Q`g2<@K5LVWnMGpOJ@?gnGA2zN^cq~JSp3IY*_^813CJLS_&*y=gQASJab45iVIhN|jEsTLc8r1n$*MgZVtCKg~;L!1;^YghywwFE9%1 zPNas8&T18Ona=zd40DG@zkT~NaccPI&myO%o-LQrF;fhDYI$dD6>oew6Y1?63dVns zc8Z5}nZGP%;X>Cy_CxrwC61Q+AJHWa(M?Rua_aLj4&C#Rh5qP=(tAh7q}(96(4z6l^4}E zzwPdRkK5qsoMgeByu3-+EBEO)3mhu541+uu6;ZfO5D$QYgdOat?SKvK}aXyk=PKl#hPNOxC zZ{0OI2N~NKd7Uz^1xdPFcMme@DypxOLmuC1f9r7BG+N|Q5XSZ-42IR0mwMf*t3y5fg zdD@m~cehs=|3WgAVtrd%!$kUebjO$n%3%fOHJ5u*(h*XBD2iWOC3A!y=`!4kQ#F&~ zR)bM`IEG)4&OEIcJJ&sW+PZq-s1>F1ih1;sNvur~OheS&zTo6r^2fMia_ct954DWc zt@MgZHHp5L5duWH?`Ne%fU9tGN+P4_7T0BQLDEeCY(5yQxs8f^re`Z-TyyXZ!8jMXJ|eyOG8rTMp>T%Chn&GeS<|ZQimw(EIgf zjCpB!_v>-fSKzEKK&|^`r@Z`?V<%2*+n1K_91&4dT3frWfNAl;(9lp4^Z*;i`KOmh zr;-Hf$7+NW`CR`h&U}dtjmlRXV4c1U#->HcqsEKE>+qqQPmyqrgD)W-GU)ufck6n3 z4vhU3z21Ea*R=@(BjKb_85*W4Tl{+-9Eb&8v>g)Z>cD6<0n_EE)u?CQgD}K^e`o-R zs8#7SIZDUGuH74E*O|v@Vq3lCBiaIW5jC;JKo?(Aqf^#@tIa9eUYMUhY!a|w9e9>I z*Y}RdU(gTe8ywVQDiir$20x-DHv4&iQgi?`n~V|tJO;(jhS8(fTHXkg5q#nftTUr| zc;{f)M6m#{kP)IFX7c0rV4SmcP0(;5Y2v*gR~GfHhi)wA4rXTwHvOD17cQx_Z)$G- z4T;|5(N&+12oD%UjzTe98o!l~Jl!&1@^n|5&uL3r+phO`&1KaK|5*+|h36<|-;QjP zw8}oL6~5qarl+TeW7;luXEEVCdwk5)Q~<2RqI!D5P`5;|D1xA#f?NPOF;tG0lM)}n z(0FN2W1ICk{&2qCv8I41XAySSxp_-)j>+xxfyr&~m1pXuZYFjUcIIhi6GyA-Jozsw zKdKWiU2CH%_V0qj=>Guo%NIW4Z@LX9pK1pKr48PR$VHFmm6fSP2vRN0Z0#R1ywqR8 z-gh3AtZN8>ftao?l74yA&wTsWGfjMb6Fe1M*8kow2j$jxmoFBtt%;4!LQ?2_ zLFjyl-&kH=E`j%&-o=tIu$ zBb7Nm74|vF!6P}2w;W0~8F3pizU%+nek$^QfXiJfw%sL1~pcG4#0YodJ>17R{OWs43R z%+ZLgh}vK&6ZP}q!_-HKsh9iX!x}zL?kNb?`Y{{Q^wP@CRok+p$ocug9ax`!_G8Qq zpusHgnCia0$R?n+3zufc&ID-z--F*=p}*82k%;wXnF?hMc;UBHY09R{D1%W@5auiLYd@PD9l=9f8GMC8aQ^usyA zXwUC2&#UugdziWWcX>vEYc#{zWb*oFfb6Q65j`Hc)J}eIeg`eJ6@r_3g#-n&0ZA#G z^7EUPla`)&^x(mdueD#PqsL>{x-3lFi%JxSACrppi3+6em{_AhO^*YP>gxA^zczqc z5{^Rz5{XAGnn@){cl|!^%4mq+HW$td8@6Yp^wlE+1)$O%b8|jG*}EB%2s}_0@j{ZD#VFSB%e}S$nsI;LOchdl#pIG0G)rStC7y^1IPrWQ6;IW#y2cDV#P1>T%v zryu=&mvmv_ZMr)%c`vyzmjTW(Sa7X}Eevm!BR2=(e zyMJBgC2U#pk8lG}p~W#VRC?-TkumN!wK3Qk+O&+#3ZFeC-z|Xg`VQ4?w?kBv%1DI~ zcGwxpo47gZQL|MPb5Ao5hj#mn@(<^_Us?;fmnkPN7ZJ2iIVh??Kg|=AUWWS4oh>J@ zpE%yUd9#WD53CM=bEFBHjvQPu9a*fsVQJ#RK?*wF=ZF0>SA%Yp?&{@?*p_l+lBkxO z`35}lgbunE-I^AcE&qnhcter+1A^RzUDr=4$12 zs$-gJGIiPj)sAD8)1yz2tEqXnWhP;K&!%7XDlFCC==&T5o_y*a@#n%7X&6NB<>x2S zO<9G6R2tz_Gv$;9x5dVnd$}4llsFGcC3L?Ds65^rxm2jokt1oyHA{C^>nhvTKV>TE z2e?goun5RU!13qQsk^1PCgKVT{Lakh>4UF6twgGHR+8O%YaFVkZ!9Q;Y#BF_7F0NJ4#+W6$Kf6JuL=oM>6_c_PWML9x(mYFHw z+9tP0S)61+UR_$&&I)D^D3pqiRGk^IhAeAcm^5eZZSI>Kde54C^4$`3_TfQRdxl8X z=lpY(N^RP%aneE1KMnvUF)i+M_IEq~xVkJ4Na-u6M;?dGAG@={B(&Ah*7oYT#o*r& zxr4aQq8W73!J%cTE}K}u@$(7K81m-f=FXO6u0MxWQ^(s6Wf_JARJYWO3`zJ?Ps39m z?tY{%?uA3ytsyE%XPBhs7~k&QFfbql%@80MZj)TFpiUA<0jBE5E#L`It)3r%#PyDt zsOSqCZR*FXr9nM=aMs6c_te*$EJVR~n zwxFnJ3DCOzAcj1;-@a||ev=)l1y@K?e7xBP6I%|0jJ#fwyn$cI{rkQ>pSj)q6 ztUV_TWZFkt8&t*GlDuSQJ)WFMa#Qb_nNZ38DwKb?wh{)*jTqe2=nY%}6opJyjlDR9 zn_W{$X%nCgDq&parQ<-AC;{(CB+5DN{mFb}W`M}oSYuI*`plWNEoFWm_Yi&<;};!V zc*Rm_8Z1aOmYdxU%cgrHa=H)$_jaJeC2u*N-&eFQ_RhgJ8cDab@=g+z#IKoU7$=`VCh@Olty;aTv~)f7Yd}Xr9Ly5l6#u2T zH8Fvt6PVH%ch5{ucU?ExcU!xvRauvu0!~t>KB)@MDfy$&->BdtEmfRP6D+*EX*mJT zkA#A|fYD(YKwP-~P1^?sdVN8pmnoBLB`jr3(JT~~C4s@=w!mk3iEAn8liM8IJ)v}% zp-PXwPKU^_ss2?o#&F88v?>bqhxtwoAlD3pwCq1R)0O*00)u6LD8%p!8*tv*d-rJ* zH1ZQvt??L?KOc~BC|J-QhfR|YSM6r1nNP~vx+9+6zy|RtDY%}tnWxF7iL0W|4i-69 zOd6$$%MDcD5I1j!yubn0XqP3(h1L=qzC2bJywU_2gfpN*8*Yv%>^x!T%<#03{txzfVzpwY?S6@}>hxi*Ddb@s#Rr&WS%Q|{L zWy>&!|6(v4+o%}Q(IP#c9G=FRgK)(J4@ri+2wD=8qt#~%zhOvi=>A=w4ZH=9sUM5s z(B&k(R9m=S@PR#tMPGwd4y{xNh_(F&;RhCCY4tadmgz3{?p=4g$joPAI|kbS96YUO z4kA0`H;|2c0Kl&xT38qBvb%ue)ilt^EWl zw=rnG*Hw|LVTPfhe^pS{CqJn_!_U;_SMjzC#B|>d2gN#N3y*x%zWc- za#wS?jm9*FP75id|5WyrHImRZ&6Gl1kS6T6`_G;&+dV$9tE8~7g@=HZVuWzecd?!z zc4hT?yvtVya;*$Tn^D#3>K=OqZWc0Ft<^wGJgr~}Mw?!}q6+HJ5H6*pMEzUHWF9c)y@X+k(C|G{jP zm(hOivN;$ZEMld>78;J}Cl9#uucE@jUQO@=$Rnln_k)q(f`HH0*H<5aAU8|n7*X!1 zIop^vZ7!Z>NazT$?vv8$HltRh1&`8Pqf?@mPELKl;3fP;u*mlOrF`sNtuvjdb8UQW zGp1*vuS6A0uJclwW41L9BQ>tX+;9|EH&aizAM;zsLwS)w98U=&d0o@{_q`(HWQ}%O znJR`_NO4cXD)5(#!Za9r@!}MO4x2bRiD;3tS@EBOXF$w@6E#G?*+>#5UM&AkozLUw z>JNC>%p##4YtuosdIOc0s c-mkdM6ck!p8MK-G27y23CRWCe3|*uD2mSdTF8}}l literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/wpicons.png b/sources/wp-includes/images/wpicons.png new file mode 100644 index 0000000000000000000000000000000000000000..8eef01eed85624e002ce3d2f6213d5319029afcb GIT binary patch literal 16089 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 K7p)OC2>2gg>T@Ij literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/wpmini-blue-2x.png b/sources/wp-includes/images/wpmini-blue-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3bfb20a06dd3a97034d1940a6bb18802a9315320 GIT binary patch literal 2087 zcmV+?2-x?DP)NklY^0t}32h5=>(33ge;q^lk6s0K$y4}ZQ1O@zE2zXX^6i?W_~Wg>N$|^ z8q93$Y#W_j>T!E~b6Z>Rv++H*@jLcmU+%+w|62h}{B^R7y@|Gk*B#B**ZqM>5Vpux z*8I5rU>>*b&I%iuS>!f;C&0ekhx>92j`g$xq@(Wq@tLY#&)UWq2-8ce$hmS8u|@~N z6U+#YFN7?iKv+b40k`ox_90&{7~Gd*aI7cI#%|=wy@}ST^!iWQ!J}RGVnYOpVcWh>688wx7H#{m0N1rHNWrn0gSmDSknz*(>d%5Bm%aHe z)Nh=I;&=|^w8kghNfo4 zv)i+Z`wJeZk}bmbU`io&196Np7jsGl;@)*^gW3Hj828M}eGn3K7ge9sROEUR3*p;I=!u#DLFTtp?) zI;WIEmQsx9Bs2bIsY57qj!RG_7C?T|PQE2jkdSys6GE}3+C{9vovH)W_B6TIuB%0t}UIBv>JTAos=3-9fW&yJsn*n$K)EtzwzQ^qi zkis7b;IM&~fr5pnRw6953UZo-m}E0%7avcu`WpjO1?M3%xP-5qu4;&l=-g@PYLG($tF>LQe;*&Lzz;9h}3d~rBy?2EJJLH6(e`2AjN}4 z57mD@BJ~auP$B%(RF?hY!Vj5LCH(%Q;rn1t=H3?2ac2rjnm!GUz|qzXDcT3dS)2$M zo>nEUN8hW2&+A1f{&emFqIJcPky!RSm}K;Oj)+~Y^&8>#l z>lJJIqBa)~Da(U+L{t6CtYXB_NcU5o+?lus--aKD3`NlBiXfvwG8c0)_hTE8q3&a- zj7~BKesao*Kwx`k6yNqACgmYkXTy8{XaVC$MlmIAAqqa|gcMmdEr`>a@Q1Sw_bL2n2-vF|P(udI!gR;(r&@6=3uTT9ZL67a?Aw}rK~!d>UMl)0YT6P zfjPgXPyeFo7Vd zKc$kQ(MD(0l7P#QpKU_a+YL~ks>H$cQd;8;1mWHAhaSr{U+Tx?NOnz^_%V?niK--u zc1uNCIf=L^ghZv5izJInFT>FEg7o}1_Vb*Y&M)(05}FfPTpfIdx)^T&o@o) z3>*KZaU1V&0_@9uxG%@xSpV0b(=qpQw|m7m55UjH_uTeB|C|!OM)oY(x5=I(izL&q zJ+tQ<2fq2M*N%Pnm8^>I9m^Xe8zKU*@jbWkJN9AUU_Xw*u{b8jW)3OmzW^b~mFN^A RrQiSn002ovPDHLkV1nUL@5KNB literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/wpmini-blue.png b/sources/wp-includes/images/wpmini-blue.png new file mode 100644 index 0000000000000000000000000000000000000000..a6197620504050e8f8b8f3d8e48f401194085cee GIT binary patch literal 751 zcmV*LW?jeDoP7M$ZCeurlQD}7UIfzo|`U9 zZ60@WlUnLOhj?bWd6+vmcYONZ4<}`P@cg`o=Xw73`~Lsib>N9?Cyp=_GmJ1q2ozI| zdOP|2kydLYQ2gj%PW5VbZMU}1HgB1kom(SNOf~8eC(e%>5Oy#T?H+X>nepz-A~6?hp*mZEfc$fBSuTZ%<&WsheED z6^Rler2(;6jMsAO`*E?T8Ql;DZf}0yqk|xulX3)k3vc7Soly;!mAn-gKi6FgPg~y6v%(y&Auj+ztGeibn zGO*J)Ic=lJlIszPMj<%Xa7o+>{lqldw0dqLZXG~lzXcUtX56l5{c8*5bRcT$BCfsH z!8E(V1^G>bs8VT>Sx^D6+&b-mzz#80REN4=bNmn`{4*ZPtzLF{0=B2^R+RSHxq)-t zkF2r=oPJn@Rj(hhXbb}r3&^Z&XT1%9G^8a1K1Gta(d_aCy}2qY{J}7so&YYqX+Tnb z4U|TKPw`=R5{qkoFLCMZ|NP1)MfKxs|MvAj82$DoT$lDDL-rL?cBr(dcdAhFbLX$j zF9v|^%XF`<=i88d(F|aPKrz+gmkGf3Wumo*VIRX`hGTmZPuxmKf7Y@8ZpnN?Mji+h hQ;mAWAuef1`x^0JSf{J=!RA^?PR$69o0gB}c&6SlaJZ5HvhxN8*#ZgVm&{^Lpgs;8J&U(d%gCN?@e zA_YP~h(8dB_wV2T{rBI0{q@(ockllE^Ut?$-@bYC=Jo5>fBf;st5>gn|NZxgiHVml zU%q(pVtjmjY;5ee-+p`k{Q0wI&z?Sg`sB%z$B!RBdh}>?boAF>e|`Ay;mF9y@bK`1 z2M_MwzdtlIw{HFTh~_4R%K{r6X{T)BMta&K>MPft&GcXwA;m)&mf z?Ck95=&;#rR;%^9@4ox?+ix#jy42p@e(~bP3l}b&KYzZht?ip{zBza9+}X2dTU%St zoH^6d($d`AY_V9r{`%|Fr%#_cb*ibU>8r24I(hQsmtTI_*x2~R7hg0qG@LkbqQ1WV z`0?X)b#-R5*<>;uJ9g~o(W6I>9I36XJ$(4^p+kob9z0l6Q*+?Jf&KgU@7uSpy1M%F z&p)rKs;aE4G#ZV2_wKEzsMxb-&+gs3%gf8l%F1@_+ErRwT2fL{TwH8081#C*PN&mq zwHl2^tyb^cxpT*k9ox5W|Ln8RTxWs!|DXT2{{Z(rX^AXxnMACRg#-)GNY}S>-(ZM% zgdPzz`Aa6R34-t*K_qg*Rn}tO`nTj&;l0;AdA@{2wS1LmcNjS|JMssue-|l>{q{{N z24CSlN3R<1bnM3LMX$DS1~LgmIyb6t)FPJP$PohS;~)BuR~UAhYWd<+DFO7Gr*f!~ zIs+hMQcsG7-5rth6(&J^s-6JO|17mlsp-Hlw|Ja3@--R0o`H$=;bM<<0~F7}bNiqn z_-@oJeCoRg$Fb$^0g9mCzYkU2Au=El-)!jZsTI-1n?u?wem04-ulsp~9OO>qpqLZA>A_|nH9;urqtXLd+jH` ze=E`9UOp`FcwQ5pWP{jAn)W1gE!K;bzSGtqOlxwCv$upMRa4@wu6;n-Gx z$&xYW18QVY0csD)-I#{NK5cWjEf{l1Xi-6Sv>_x&ia=tMV^Ik@<+zR(g+S^zZ&HMJ zL+J!ijX;AC@UojR7`Z1o5gnGR98ugF?K(Iv!v#wEK+^CML+;HZjaJqq+n3yZ` zSY0sG#ZuM^rKE)2^YCJ(^j3-6@H}MK`NSj*_F{4yX|q=bB4HHE(9EfJzxLL#QmDQ!1vYs6?fCTDQz611Hb zA+JJLy_riM*&b}6`iA1o%^H79MJVuBkwvKq$9e-1LGL{=qxdTi=Rf7Q3+eBm@O#tc zM#nm1W%&m6yVw24d)y843d3}8R3A%>0n=Tqhi;@xLDA^k9w^5um3!WZRYMpW`{Q4r zWn`fqqy@I>3~1^LYuStzb-cUO9*&^{X5|n8m~A>YMsBb3(ANT%Av)*xAksIM$Ha7K`tGEHnLUL`l26W?08^nzuml4B$h!ySHB*Z zM-~o2MFNo;+2rfgy3ikm@Axbo@RBhTlAB{T1I?8p1ez%lA#uv2V$n=~I*!@4L@aY( zQQ!O{T*yXR&swS9>)=3gK|HitK9u9WT&d~uNG=?gv17=pXJ=7lE7DJA6e}=lK|0nw zG0Da2D$`e+Jm<8RKSLE*JT=mQxBUk9zfnPBtaRSc^NU`*NclHzZ%hg(``uxKN3yEF zi?y~k7li^4R`exZFJc*~e5*wU^ANy~)FIRO|&He}eJyjIUltrA^ z+N&Mq?3=AM;kg}$3_GvMBl7AA^yz7T2gOa%Op)!=4NK3b9PcK33X)ru<_@{HVaJ@j zJ~Id&@QF|jv>!av1-SE2c3wzFbMH|dMa{tA$u8V!e`o2jT!sodxn^>}%6 z8+f(KZK_;>8&4sw)@;Jv6yAPw#yFqNx)R^~R#!sx6Xq)#yX2MrN6HZiZPQ8!^tm?> z3y>Y1o2d(!*@Yo|kWtmWtLeRuUQ$Of&;un|7J2;#Td`^qzQZYH1 zoL9U^8D!QoUfdMQy@To6Zr3>-K;qaK8<-oH-lpH6d+IRl&?!~6QdX~u&ibgnrVi$X z@wKprJxh!g*1opyncFg22Qw!Ik7oj(BC*VP=9eIia>HcAFyfrUBpC%RW+pBYcCAu{ zWfiOG1)dtr?KjAnxMgu-toz5cxxAQAetjpJCW6*^=xUI%|Eyb{VsKwE)|@GwM!g@6 zri3GYMQ7>`mO`5pq-gegRNuz-1+DXRi$j9u_WEv!>^pt&4#Nt29`e5nVbcP6y*``B zDKKGQ{LmM0y7P`n6xur!7@b~IlrQy>b4$7pRSE5l!C1_H4fJpa!lpyTLdk_=xXuy~ zno&ZC${v0T=9+xr|?BI#VaH|aaUHFvwDiG zl)USGOrA^^ZkF8+m21py^hhsC^RsC?ZbjIQ;NSvyd-!#s%Tv6Nhb(Q(h zt_o6Gq(p{kH5i?8r{fgBq#X;hu{}m4o|~4{hv#aY1dZ}&CyhZk(x*dRrOH;J!gCF`+J<2k zWQnPyts1kZo}AL@L;D02W85rqn`Et8Tui{S5eUjwp8++R_H-~!n#mC&5Q!+r^?YHg z)hLp{VMT)?NSp>9Ns;VJ#6b=uo@X7YqD87S%T|EuhoYPdw@0cT#pZq?TIFxFqDW!J zqoTBW(7JD>mr88{INLzKM2GWGJ^qvc*Kn31K3xC5gs$kSo}+dNeF9IdrV}TH?uf2+ z3H{vV6!m>OX|o3|?`2n+d*HHjO|gx}J@~!oPc5wv47(V-m@?3lfhpY^kjH#$M!J=D zh%#%#nh)}((?2lMoJRWIkGYO;6E(8SZJO)+g(1??>%Q{~h6OD#LzG<}D9Vd8*`n&{ zOAqONR=+Btos3Wo4w_4bu-Z*H?BkG(Mb#IV?7z$Nc0X0&JvV27{bHTtkS2tAG9p%1 zR((1}8(fs1;Y!QdS$#DrGBa7D!i}8IJF#eAcOtMZF{`A6ayum5PPkkQ;tiRWvF96Q z&!IVUlk{Vi(L={Lq1B!53(Zn9VY&{p{&L6B|J)HrOna_Kn%-T=3SL#Psp{gj{WDiJ z-TE1dDooVDONM(ov}xqJXm~@8t!w8hrUyPwZxZ%;2Q@i{fVjRB4$n_iHrXz~o$xsY zIAPQR!Cq$_o@)k@j>CbGMs|fsL7Y~j(h|kNdK_EXXzo(W zl!Z=+XH;kpEZ|ogy;Dnt5@MuNNbq52_eK-^?GY$OzM-JUgM$!>5DTGLdby5?L=m{m zZRuXi>Q_h+h%f-*4O|7)($(EI4c?CoX#I2$R|_k`f677?@e`vdQ>qm@PuO6wov3+r zKcW|>AKp^Zh#*)+-kkxM9=vDPSRme~Nl5TQT{0P|6}U;i4?3~YDX&EuEF1G@_Euf1 zK%pzjay_vzpwjAM(}F-#MW6=5OjL=_d9_;~d17RWKp#@|hUZ8E&xAlzBFBQUx2};o zeDXhnDgmJ1hHU*6*M533rfrz(v9^?x(IyBCfoD8I1Rm)nu?AKm`FKE zLVguDhQ=*c>WXy}Lo_ncfW~EX9a$lIr-!@b>C> z%qhV?vG?yPH=>#0AF%Ja>PDSZIUjw^rShMxlPW)K&((7Ir z%^@_~l%d>v6UzWyJO^Gg3YYwK>kxeNU=oBnl#B5k( zxSG5VE><;F?)TJZvfSyS$kQt4t=8%m&bFD`k(l0Y_M53 z+Z*;_o__OU#! z`{251YSV9e;sYP@gm`%ReMOStFN*h^T4Apj@w{1!#5Im}`ReRL4DN=oED44AqvePn zKtWoI5ltosjdo}*ff8CB-brU2v~m%6eqx8tpU>;u9a`6>Ak09S6a+y7wsWt5nM<$W z;GhS(x%>ewDei(u58uBET8oink!xIwtm%d}HMxRpW~bRE37 z-qZoCsSuWWNyr@~hcHaFb9<=V{t(KmRil8slg^_IPre;S?(kJ1F!w2`IEsI%0__F7 zF~h`Z>@qF=Ha#!Hldz~vgmP<(KMd#A-hfa;0Q_q~*tX>Qm=Dl8rVTr*KT% z!gq=@7h@jHllyQJKbwi6$5~Fbd#Mo5@u8#hun}D2imG%!h<&cD*pP`GF{Sb*s`9nOCX< z;;rBSvXUU4^@%9^vbL)%HX#0JB$tq$QlVM*ZP9oKmUp!(v0k+GzJ8bcUeqnMr&s>s z{WIpA;BUW?ez|Iz&oN6|W#!3_n_~0lq_ps2s{#n_j8zFH1cIu!7Os>xd|AblSFq{% zDzaIKLhx~j`ab(~btO9>Aw8w6t85(@3Cp|1(_;8E&%6v12p2KZe6!M1E4gs$F%Nk$ zxDSc+_-tC3_x=5lSdCdI*Qu=tRQ9b`gyE8xeo2HXD62g*(QiS^AA`GGB}yaaKc&C_ z+T3|r{2QKH^hYUds^HAKubWzk5O32ti9cIye)!LI1jr~t0mCtJ%Ira9Cnb?1HKBkY z<635DpGcx5$a<|Pau~vwEbLXLP)NChA~ZGGSxF97^L6C+bbpk1`aIXk(bEO}q#3Qw z4iW^XPpM$UiNs6sQ*&V;(BeE!`dE~R!hp)B0%0b61U#>*r zR^>T02YA&g6cE^GSsgQ7p&I#zHea=iMV@|F2Nk{k$I3(Oi8sIEA#1=F8uW;@;n=1v z0VtwGalxpa`%Vwyj_%J6O#B}t$j4;+!!<6?V;U>=xltxPZ;3wQ^86KKmCN&lG!Njy z103a0=(-;V=&j%q;$HN}WAXfTr4`e&twrNEGQQs*l=*^>sYf@E4Mkff%P5wC<(yr6>cB&$ELP*VE6P-8^RfoF+0UDANL&QV`}u7+}&1a4Lo_S9e3}6j?)@ zsCQ$X`&J7kR(a6%5jIQ|zd#o=pI?BbEvP5z4I7!lqpk@^+0)~}{M?LczBHs_9FSxTdZkUQF- z@QE030Uyy8*aK}O*l$A7&XZ4Y-h~SL2GWTkDLKTU=%m=sMG(m7OAqm+3)wEsyI@33 zl8Yh*Tft6p*q~BJKXBTWgrs{&EzY~Zsljub?mWLZvmK!$hYpxJeRZ$nHPRq{K?#XN zAj7t)H7XeRa8F(W=9oO@O_R}YQNft4`^iz~re0#Fvda&6hWG&>QCqrck1HJGJ%JX7 zma)01-PgcuI`@JlpLl}?KiaK11Fx5gxZ>d2p$*a5t(Ms`FODYq`i$ddJD!RAFzEcd z@dce=$o9z#Ag`$YVEjgHpUe0oeKp}it;|r=*hipu*ulB~!OYZ4J{bRs1rk6A^=uAQMxK6s)b?!hIQ&qR`SA zKkiZ^#LMgFonFi7pYE8=NG|C zGp;Zr+W(U81I;`2p}HEE;#FjA4>N(sH^|idi4F|72-3h|Wd2$v8%D}lEStzy;upy4 zQ1kc`_FdDroKuk9lbm%}|EflXTiA`px|OWqLL?5jDR5GOnavnCX|~z8L#$Mbah_SG zZYYb)UhNaha}@-O)xussL|%VA&O1jS-OCv8i-Ir_*Ol4+;@cnh$o+RKv_yWr z1t!hv73nD9qZU`mjG*h?C@q@(I|@w#7yGqpEfCc9fo_$AYI`+?rWfS|h^1$}vO3T7 zpLRUIIDXIg?A+qv&z?%>aNg)I1jaoHZlA4OJc~u4R_PYc4Ew2={`8z6w|&lC5PNcG zy8z-c>YE*YY2icbObNB|`{4~^XIn%wBM&~7LpN`#;uDrAxKP82#A-EX}-h5=liE{kz%9^J%z5r&9y}+G<}{CV^ru~2=W_-^hAb# z&PJuNoQ%K|RN$0{i~F_ie1*t+2$p!q5)O{P=yKIU9znxLjAAo61pR{^`Jiht%fJp! zmM0@KMuL-J?>^DIP_SAr%D>&xWh%Z^AMdv6lC0cgHfCdv(_;SSX^{1dG9Y3sy5vDm z#@h4RjEG!Kcx2&gfzNS3v%D$!a&R$JL4!Ir_0u(1LOx5QEBsBESU8d0g z#h8jp*BA-E(UeM>Wd#l5)nE#S5zD8iN#@-hMUjPlu8^Gf)Y(ac z$?p zhfJp+KWM${piArfSJEr%q(qkctII7qEXh4UmE;=VCs$FQSfpubupUq22$DZ@wnEj?O`Gfi~lNfz8ipCzb#hA%uLCkw8xn|fvWYj!P25*WqD9$LKvq+&mCjO5| z*`~6gutYi(rgXSz5>aYaSueL)C}`v<-F45z5+lyAFsf*5EW&O?1z@6sOtn4uIRuyshrT2x#Qf&s4iq#Aex4QOp?onk z0{MV--Oy%zU?64om=eDkcqBG3mnFu#D$ik|oP)~E>>{`Sq(W2YC)d#`LCV9?J+#@ z=1U5BeAjAqGDIf>&*Cw*$kzxxC}HPfTstqD>k4I!CzF{YCJ)rFd=-!KZ)^}7CVJ9Qi*bS?j%w5dHq?9h!rqM{(%PltCNWPD{ zX!M>{xPXrI3hM992mUg5yG@b*)6D<-HBjg(Lq9b0J#m%f$#K3HHQCHxZTd&n|?{F14SA;FO+)))8XRHXpC!{jWo`6 zrw1pF!WnaUrN2PbD1wN{B3?V!!wP)bpw+0GguR|~234Ju@I*66<%}zQ*;&Q( zZXaE*_!mFreWQ*#-x47=(ho++{niu>O+TdN5${6redk>u5|Hw(^IcOJO~vQ+vOX#7 z|CP0hdIQPLY2C`FEqFa9p%*$DK)>W18bJYa$GNUXQabmkM>+<;i{0J{34YSB)q1*II)5WG zL6L&B{Irc53^Ap=Cv8i}V*436-)6t?Yz--geV^*zDUIM`2<%_sC%?5SJO_857+YA_F67ZV1NUuSCSy SZEl;GO#+TWWmJj~^ZyTE{8Q5a literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/wpspin.gif b/sources/wp-includes/images/wpspin.gif new file mode 100644 index 0000000000000000000000000000000000000000..e10b97ff9d84d7ff8d7efe5c4c09783dd390e338 GIT binary patch literal 2193 zcmai#eNYtl8ON7(yJ6M6J=n0lMb_k8_Sd=PxP4*6q$V@fTkd$f1L8|!_`^Xw3?Nkk zC~rnNUV;$tr4l4p@CCR74h~C3V$$*262*vAVuOO9F=^{`jLEdlbka`yN0YrH{R4+i zKYO$L&)&@Qd4Au0p44>vi$C3^hxE`L2>MRrpJD#C#9u-@(0)tI%{|brFf(B$XJ#ff z!neubWH8KlFgU(MU_3BB9$3Qb4TP?MS0jA$c6+;*=;+X%9bwwSG`6)hhN%rx9zrV( z`hOU|Ta#tmwpHDnW0Ni7stE0U8AyT5q5p<7A@qYyo)eU5%q72Sl1mQe^)ydB z`SS9{o7alJO>^Lgb;EdZWTwCI-|IkR2DcbLR~R4Xo1bpfM@9-Z_5djw3Bo8~hYg%S z9p#NqBNqW-7U?J<>6|(Vf?!D^_2uVOT@nGE5ey`m(4iVdp5iSW7^kII2u23Llu=I2 z(B=VwodQXuV*iw881{Dcn@X+_N8f*NTPnzsc=mIUkhH^TwOP`B>rgj`RDSf7%7tYr z`F-gdqQ3f_rqcRCk=ci;YFH(8H?AWcno4r@%NtC0r&Cz{TEX@TL5aqLMgc!ea{^70 zAr%0_nhJF?tkQ)@-4u29d>`x;)(x693l4%j9H8lJ<{*O+&r&I$o#^b`3DC}rZepD^l?;g@|32TV~aZNyQ4R*PCVW$pR6*xek#2p z*6)7>ix2yhh<$SUE+A zJl3Gd%yTT8f;Zg12&+D=Wo@O?_OKlFLm$VxKvIE2x{Qamm{6^{srfOJ~YD>iv@x*qQU^lWMR*DmuX zE&U%?6pY@QdN{${*!bnzL~uWOy=!rh%>N9u+wUo{!TT5O`MsmlPcRHuKvR|C)_Pr~ zDJbS9z8z((6%5H$au|ZPT15qcA$SNG&e%yngMQ4kPc&dd4VlZj`rkq-wXTA`cDZw= zH2t0SjXi5WtAA5U{q)h~miHX5s^84Uyb~}#Xelj_qfSfHf0jy;n*YA~W`EfiML1qz zQp`u{+zL-tRGKiX*n&Wjf`d3=l~!qn2XOR+Xk{bdp;ZWijyeE3G!np%oW@6#IInfZ zyp=8G?KNN48~w7**>_St^~V>TIYrIIW6zG|{K zZbu^wLFIOWIHF)s#J(n?zyQN`k;HM``?RN%jhu2b@%myx*{&)`BK5&5RgB z=vj^w(2o=#ioCu#YDnP#g3fDaevjZwm0S~kcL668Tv=jpfn-~qsy2Z3|Br-)4wl;b z2M37RdtIT|5;4*A?oI@%vlYj-zkKD#5qtA$e#X#=tp53(j)lQlDS46e-5Q^&D@5Ei zD&3@@?(H=)^)_DLpgAzsY+a3HASqzQvK5m`dSe_Y=Ere@@Fvs{!vTV7uo}scOO6#o zwqL8|A2;Hm_VZi1dNC*`v%IKmHC)$x~ecdHdeT3e3rlgwcr^{9j zSJe;040k{8u4am``YjNoxURu&F$eBo@9H~6eKfbYciUHOjw{C|Zi)UJ(D_6<;`xsi zt3Ol^7sNilPG+n>l94Kf+|CaF+O#SYFRF?pxPGi!S4i=)hq2#6@klklFH%S%)2*P)EP^gW#~vR42A literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/xit-2x.gif b/sources/wp-includes/images/xit-2x.gif new file mode 100644 index 0000000000000000000000000000000000000000..64ab2ce789b4553820bcb932f5688ea2ea0376ed GIT binary patch literal 823 zcmdVX=}VJw0KoCzGaipUu1)2crcRpI6wM=>S9UxKra?vNH0o9Qrszd1Fi9er8)Av! zNb?|*$5EosLLvi|4BW{M+B#&Ly4fZgxT)yevm@OW{uzD$gAd=@E0@bFnsWdO{$M~Z zm%ID>wOXy;@Au$%(Czk&kLz?gpU)TE-w%aCHk-{iKkrv4!l97GV$tjM3WdVybZ%{J zkyBF!gW+&x#b`ACU0x;$B7Afd+}-thz3#z5&%1XABO`~as~Z~|>+9?8p`k;Y%`cN} zZ*NlK zJ9{uZd@weq(P&7LRH;;EvpF0Nga5g-01N?ufz!u`<0l|0EWm_9gu`IQ#W5KiMARpu zXVTD;5|oxn7x%Fe0X~i=vPOj|Nf03=l2RtpiX}6kIBhg98gt;+nQRaz4g1Z zgG=Gs>t@b~BO%&-P=5mJk(H-Tfb8pyy(+9s%^zYc3163!-=4yE&R)a6mNDwt>6HA5 zbXHBvk4`f$;SIa}9Nk{cXuxh%FvO0?wkP==JkSW$#%x+r1s|)bm|ZNkgn_`I@*mW? BI+Oqa literal 0 HcmV?d00001 diff --git a/sources/wp-includes/images/xit.gif b/sources/wp-includes/images/xit.gif new file mode 100644 index 0000000000000000000000000000000000000000..80c251fdd75c5a9a960b87e4120509a1100e131b GIT binary patch literal 182 zcmZ?wbhEHb6k*_E*v!E2Y4YUH^X7fqzWv9E6F)Cs{&nNV|NsAAzI^%Y*|P@^9$dS2 z?Zk-_hYlSA3NnC!;!hSv1_oXR9S{#>1_Mj-hOLXQ1-YM6auR5rW{@(|gL%Qa!$%}I zIwj5oGO#TaVhhmdk#sr{z`ET>9X{ ht8-b~4Q^eRnCh|IEo*6(r-qn>6t9e&f{-ACH2~T}Oo9La literal 0 HcmV?d00001 diff --git a/sources/wp-includes/js/admin-bar.js b/sources/wp-includes/js/admin-bar.js new file mode 100644 index 0000000..b75823c --- /dev/null +++ b/sources/wp-includes/js/admin-bar.js @@ -0,0 +1,343 @@ +// use jQuery and hoverIntent if loaded +if ( typeof(jQuery) != 'undefined' ) { + if ( typeof(jQuery.fn.hoverIntent) == 'undefined' ) { + // hoverIntent r6 - Copy of wp-includes/js/hoverIntent.min.js + (function(a){a.fn.hoverIntent=function(m,d,h){var j={interval:100,sensitivity:7,timeout:0};if(typeof m==="object"){j=a.extend(j,m)}else{if(a.isFunction(d)){j=a.extend(j,{over:m,out:d,selector:h})}else{j=a.extend(j,{over:m,out:m,selector:d})}}var l,k,g,f;var e=function(n){l=n.pageX;k=n.pageY};var c=function(o,n){n.hoverIntent_t=clearTimeout(n.hoverIntent_t);if((Math.abs(g-l)+Math.abs(f-k)) .ab-item').bind('keydown.adminbar', function(e){ + if ( e.which != 13 ) + return; + + var target = $(e.target), wrap = target.closest('ab-sub-wrapper'); + + e.stopPropagation(); + e.preventDefault(); + + if ( !wrap.length ) + wrap = $('#wpadminbar .quicklinks'); + + wrap.find('.menupop').removeClass('hover'); + target.parent().toggleClass('hover'); + target.siblings('.ab-sub-wrapper').find('.ab-item').each(refresh); + }).each(refresh); + + $('#wpadminbar .ab-item').bind('keydown.adminbar', function(e){ + if ( e.which != 27 ) + return; + + var target = $(e.target); + + e.stopPropagation(); + e.preventDefault(); + + target.closest('.hover').removeClass('hover').children('.ab-item').focus(); + target.siblings('.ab-sub-wrapper').find('.ab-item').each(refresh); + }); + + $('#wpadminbar').click( function(e) { + if ( e.target.id != 'wpadminbar' && e.target.id != 'wp-admin-bar-top-secondary' ) + return; + + e.preventDefault(); + $('html, body').animate({ scrollTop: 0 }, 'fast'); + }); + + // fix focus bug in WebKit + $('.screen-reader-shortcut').keydown( function(e) { + if ( 13 != e.which ) + return; + + var id = $(this).attr('href'); + + var ua = navigator.userAgent.toLowerCase(); + if ( ua.indexOf('applewebkit') != -1 && id && id.charAt(0) == '#' ) { + setTimeout(function () { + $(id).focus(); + }, 100); + } + }); + + // Empty sessionStorage on logging out + if ( 'sessionStorage' in window ) { + $('#wp-admin-bar-logout a').click( function() { + try { + for ( var key in sessionStorage ) { + if ( key.indexOf('wp-autosave-') != -1 ) + sessionStorage.removeItem(key); + } + } catch(e) {} + }); + } + }); +} else { + (function(d, w) { + var addEvent = function( obj, type, fn ) { + if ( obj.addEventListener ) + obj.addEventListener(type, fn, false); + else if ( obj.attachEvent ) + obj.attachEvent('on' + type, function() { return fn.call(obj, window.event);}); + }, + + aB, hc = new RegExp('\\bhover\\b', 'g'), q = [], + rselected = new RegExp('\\bselected\\b', 'g'), + + /** + * Get the timeout ID of the given element + */ + getTOID = function(el) { + var i = q.length; + while ( i-- ) { + if ( q[i] && el == q[i][1] ) + return q[i][0]; + } + return false; + }, + + addHoverClass = function(t) { + var i, id, inA, hovering, ul, li, + ancestors = [], + ancestorLength = 0; + + while ( t && t != aB && t != d ) { + if ( 'LI' == t.nodeName.toUpperCase() ) { + ancestors[ ancestors.length ] = t; + id = getTOID(t); + if ( id ) + clearTimeout( id ); + t.className = t.className ? ( t.className.replace(hc, '') + ' hover' ) : 'hover'; + hovering = t; + } + t = t.parentNode; + } + + // Remove any selected classes. + if ( hovering && hovering.parentNode ) { + ul = hovering.parentNode; + if ( ul && 'UL' == ul.nodeName.toUpperCase() ) { + i = ul.childNodes.length; + while ( i-- ) { + li = ul.childNodes[i]; + if ( li != hovering ) + li.className = li.className ? li.className.replace( rselected, '' ) : ''; + } + } + } + + /* remove the hover class for any objects not in the immediate element's ancestry */ + i = q.length; + while ( i-- ) { + inA = false; + ancestorLength = ancestors.length; + while( ancestorLength-- ) { + if ( ancestors[ ancestorLength ] == q[i][1] ) + inA = true; + } + + if ( ! inA ) + q[i][1].className = q[i][1].className ? q[i][1].className.replace(hc, '') : ''; + } + }, + + removeHoverClass = function(t) { + while ( t && t != aB && t != d ) { + if ( 'LI' == t.nodeName.toUpperCase() ) { + (function(t) { + var to = setTimeout(function() { + t.className = t.className ? t.className.replace(hc, '') : ''; + }, 500); + q[q.length] = [to, t]; + })(t); + } + t = t.parentNode; + } + }, + + clickShortlink = function(e) { + var i, l, node, + t = e.target || e.srcElement; + + // Make t the shortlink menu item, or return. + while ( true ) { + // Check if we've gone past the shortlink node, + // or if the user is clicking on the input. + if ( ! t || t == d || t == aB ) + return; + // Check if we've found the shortlink node. + if ( t.id && t.id == 'wp-admin-bar-get-shortlink' ) + break; + t = t.parentNode; + } + + // IE doesn't support preventDefault, and does support returnValue + if ( e.preventDefault ) + e.preventDefault(); + e.returnValue = false; + + if ( -1 == t.className.indexOf('selected') ) + t.className += ' selected'; + + for ( i = 0, l = t.childNodes.length; i < l; i++ ) { + node = t.childNodes[i]; + if ( node.className && -1 != node.className.indexOf('shortlink-input') ) { + node.focus(); + node.select(); + node.onblur = function() { + t.className = t.className ? t.className.replace( rselected, '' ) : ''; + }; + break; + } + } + return false; + }, + + scrollToTop = function(t) { + var distance, speed, step, steps, timer, speed_step; + + // Ensure that the #wpadminbar was the target of the click. + if ( t.id != 'wpadminbar' && t.id != 'wp-admin-bar-top-secondary' ) + return; + + distance = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; + + if ( distance < 1 ) + return; + + speed_step = distance > 800 ? 130 : 100; + speed = Math.min( 12, Math.round( distance / speed_step ) ); + step = distance > 800 ? Math.round( distance / 30 ) : Math.round( distance / 20 ); + steps = []; + timer = 0; + + // Animate scrolling to the top of the page by generating steps to + // the top of the page and shifting to each step at a set interval. + while ( distance ) { + distance -= step; + if ( distance < 0 ) + distance = 0; + steps.push( distance ); + + setTimeout( function() { + window.scrollTo( 0, steps.shift() ); + }, timer * speed ); + + timer++; + } + }; + + addEvent(w, 'load', function() { + aB = d.getElementById('wpadminbar'); + + if ( d.body && aB ) { + d.body.appendChild( aB ); + + if ( aB.className ) + aB.className = aB.className.replace(/nojs/, ''); + + addEvent(aB, 'mouseover', function(e) { + addHoverClass( e.target || e.srcElement ); + }); + + addEvent(aB, 'mouseout', function(e) { + removeHoverClass( e.target || e.srcElement ); + }); + + addEvent(aB, 'click', clickShortlink ); + + addEvent(aB, 'click', function(e) { + scrollToTop( e.target || e.srcElement ); + }); + + addEvent( document.getElementById('wp-admin-bar-logout'), 'click', function() { + if ( 'sessionStorage' in window ) { + try { + for ( var key in sessionStorage ) { + if ( key.indexOf('wp-autosave-') != -1 ) + sessionStorage.removeItem(key); + } + } catch(e) {} + } + }); + } + + if ( w.location.hash ) + w.scrollBy(0,-32); + }); + })(document, window); + +} diff --git a/sources/wp-includes/js/admin-bar.min.js b/sources/wp-includes/js/admin-bar.min.js new file mode 100644 index 0000000..90b8ed3 --- /dev/null +++ b/sources/wp-includes/js/admin-bar.min.js @@ -0,0 +1 @@ +"undefined"!=typeof jQuery?("undefined"==typeof jQuery.fn.hoverIntent&&!function(a){a.fn.hoverIntent=function(b,c,d){var e={interval:100,sensitivity:7,timeout:0};e="object"==typeof b?a.extend(e,b):a.isFunction(c)?a.extend(e,{over:b,out:c,selector:d}):a.extend(e,{over:b,out:b,selector:c});var f,g,h,i,j=function(a){f=a.pageX,g=a.pageY},k=function(b,c){return c.hoverIntent_t=clearTimeout(c.hoverIntent_t),Math.abs(h-f)+Math.abs(i-g) .ab-item").bind("keydown.adminbar",function(c){if(13==c.which){var d=a(c.target),e=d.closest("ab-sub-wrapper");c.stopPropagation(),c.preventDefault(),e.length||(e=a("#wpadminbar .quicklinks")),e.find(".menupop").removeClass("hover"),d.parent().toggleClass("hover"),d.siblings(".ab-sub-wrapper").find(".ab-item").each(b)}}).each(b),a("#wpadminbar .ab-item").bind("keydown.adminbar",function(c){if(27==c.which){var d=a(c.target);c.stopPropagation(),c.preventDefault(),d.closest(".hover").removeClass("hover").children(".ab-item").focus(),d.siblings(".ab-sub-wrapper").find(".ab-item").each(b)}}),a("#wpadminbar").click(function(b){("wpadminbar"==b.target.id||"wp-admin-bar-top-secondary"==b.target.id)&&(b.preventDefault(),a("html, body").animate({scrollTop:0},"fast"))}),a(".screen-reader-shortcut").keydown(function(b){if(13==b.which){var c=a(this).attr("href"),d=navigator.userAgent.toLowerCase();-1!=d.indexOf("applewebkit")&&c&&"#"==c.charAt(0)&&setTimeout(function(){a(c).focus()},100)}}),"sessionStorage"in window&&a("#wp-admin-bar-logout a").click(function(){try{for(var a in sessionStorage)-1!=a.indexOf("wp-autosave-")&&sessionStorage.removeItem(a)}catch(b){}})})):!function(a,b){var c,d=function(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,function(){return c.call(a,window.event)})},e=new RegExp("\\bhover\\b","g"),f=[],g=new RegExp("\\bselected\\b","g"),h=function(a){for(var b=f.length;b--;)if(f[b]&&a==f[b][1])return f[b][0];return!1},i=function(b){for(var d,i,j,k,l,m,n=[],o=0;b&&b!=c&&b!=a;)"LI"==b.nodeName.toUpperCase()&&(n[n.length]=b,i=h(b),i&&clearTimeout(i),b.className=b.className?b.className.replace(e,"")+" hover":"hover",k=b),b=b.parentNode;if(k&&k.parentNode&&(l=k.parentNode,l&&"UL"==l.nodeName.toUpperCase()))for(d=l.childNodes.length;d--;)m=l.childNodes[d],m!=k&&(m.className=m.className?m.className.replace(g,""):"");for(d=f.length;d--;){for(j=!1,o=n.length;o--;)n[o]==f[d][1]&&(j=!0);j||(f[d][1].className=f[d][1].className?f[d][1].className.replace(e,""):"")}},j=function(b){for(;b&&b!=c&&b!=a;)"LI"==b.nodeName.toUpperCase()&&!function(a){var b=setTimeout(function(){a.className=a.className?a.className.replace(e,""):""},500);f[f.length]=[b,a]}(b),b=b.parentNode},k=function(b){for(var d,e,f,h=b.target||b.srcElement;;){if(!h||h==a||h==c)return;if(h.id&&"wp-admin-bar-get-shortlink"==h.id)break;h=h.parentNode}for(b.preventDefault&&b.preventDefault(),b.returnValue=!1,-1==h.className.indexOf("selected")&&(h.className+=" selected"),d=0,e=h.childNodes.length;e>d;d++)if(f=h.childNodes[d],f.className&&-1!=f.className.indexOf("shortlink-input")){f.focus(),f.select(),f.onblur=function(){h.className=h.className?h.className.replace(g,""):""};break}return!1},l=function(a){var b,c,d,e,f,g;if(!("wpadminbar"!=a.id&&"wp-admin-bar-top-secondary"!=a.id||(b=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,1>b)))for(g=b>800?130:100,c=Math.min(12,Math.round(b/g)),d=b>800?Math.round(b/30):Math.round(b/20),e=[],f=0;b;)b-=d,0>b&&(b=0),e.push(b),setTimeout(function(){window.scrollTo(0,e.shift())},f*c),f++};d(b,"load",function(){c=a.getElementById("wpadminbar"),a.body&&c&&(a.body.appendChild(c),c.className&&(c.className=c.className.replace(/nojs/,"")),d(c,"mouseover",function(a){i(a.target||a.srcElement)}),d(c,"mouseout",function(a){j(a.target||a.srcElement)}),d(c,"click",k),d(c,"click",function(a){l(a.target||a.srcElement)}),d(document.getElementById("wp-admin-bar-logout"),"click",function(){if("sessionStorage"in window)try{for(var a in sessionStorage)-1!=a.indexOf("wp-autosave-")&&sessionStorage.removeItem(a)}catch(b){}})),b.location.hash&&b.scrollBy(0,-32)})}(document,window); \ No newline at end of file diff --git a/sources/wp-includes/js/autosave.js b/sources/wp-includes/js/autosave.js new file mode 100644 index 0000000..f339c94 --- /dev/null +++ b/sources/wp-includes/js/autosave.js @@ -0,0 +1,702 @@ +var autosave, autosaveLast = '', autosavePeriodical, autosaveDelayPreview = false, notSaved = true, blockSave = false, fullscreen, autosaveLockRelease = true; + +jQuery(document).ready( function($) { + + if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) { + autosaveLast = wp.autosave.getCompareString({ + post_title : $('#title').val() || '', + content : switchEditors.pre_wpautop( $('#content').val() ) || '', + excerpt : $('#excerpt').val() || '' + }); + } else { + autosaveLast = wp.autosave.getCompareString(); + } + + autosavePeriodical = $.schedule({time: autosaveL10n.autosaveInterval * 1000, func: function() { autosave(); }, repeat: true, protect: true}); + + //Disable autosave after the form has been submitted + $("#post").submit(function() { + $.cancel(autosavePeriodical); + autosaveLockRelease = false; + }); + + $('input[type="submit"], a.submitdelete', '#submitpost').click(function(){ + blockSave = true; + window.onbeforeunload = null; + $(':button, :submit', '#submitpost').each(function(){ + var t = $(this); + if ( t.hasClass('button-primary') ) + t.addClass('button-primary-disabled'); + else + t.addClass('button-disabled'); + }); + if ( $(this).attr('id') == 'publish' ) + $('#major-publishing-actions .spinner').show(); + else + $('#minor-publishing .spinner').show(); + }); + + window.onbeforeunload = function(){ + var editor = typeof(tinymce) != 'undefined' ? tinymce.activeEditor : false, compareString; + + if ( editor && ! editor.isHidden() ) { + if ( editor.isDirty() ) + return autosaveL10n.saveAlert; + } else { + if ( fullscreen && fullscreen.settings.visible ) { + compareString = wp.autosave.getCompareString({ + post_title: $('#wp-fullscreen-title').val() || '', + content: $('#wp_mce_fullscreen').val() || '', + excerpt: $('#excerpt').val() || '' + }); + } else { + compareString = wp.autosave.getCompareString(); + } + + if ( compareString != autosaveLast ) + return autosaveL10n.saveAlert; + } + }; + + $(window).unload( function(e) { + if ( ! autosaveLockRelease ) + return; + + // unload fires (twice) on removing the Thickbox iframe. Make sure we process only the main document unload. + if ( e.target && e.target.nodeName != '#document' ) + return; + + $.ajax({ + type: 'POST', + url: ajaxurl, + async: false, + data: { + action: 'wp-remove-post-lock', + _wpnonce: $('#_wpnonce').val(), + post_ID: $('#post_ID').val(), + active_post_lock: $('#active_post_lock').val() + } + }); + } ); + + // preview + $('#post-preview').click(function(){ + if ( $('#auto_draft').val() == '1' && notSaved ) { + autosaveDelayPreview = true; + autosave(); + return false; + } + doPreview(); + return false; + }); + + doPreview = function() { + $('input#wp-preview').val('dopreview'); + $('form#post').attr('target', 'wp-preview').submit().attr('target', ''); + + /* + * Workaround for WebKit bug preventing a form submitting twice to the same action. + * https://bugs.webkit.org/show_bug.cgi?id=28633 + */ + var ua = navigator.userAgent.toLowerCase(); + if ( ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1 ) { + $('form#post').attr('action', function(index, value) { + return value + '?t=' + new Date().getTime(); + }); + } + + $('input#wp-preview').val(''); + } + + // This code is meant to allow tabbing from Title to Post content. + $('#title').on('keydown.editor-focus', function(e) { + var ed; + + if ( e.which != 9 ) + return; + + if ( !e.ctrlKey && !e.altKey && !e.shiftKey ) { + if ( typeof(tinymce) != 'undefined' ) + ed = tinymce.get('content'); + + if ( ed && !ed.isHidden() ) { + $(this).one('keyup', function(e){ + $('#content_tbl td.mceToolbar > a').focus(); + }); + } else { + $('#content').focus(); + } + + e.preventDefault(); + } + }); + + // autosave new posts after a title is typed but not if Publish or Save Draft is clicked + if ( '1' == $('#auto_draft').val() ) { + $('#title').blur( function() { + if ( !this.value || $('#auto_draft').val() != '1' ) + return; + delayed_autosave(); + }); + } + + // When connection is lost, keep user from submitting changes. + $(document).on('heartbeat-connection-lost.autosave', function( e, error, status ) { + if ( 'timeout' === error || 503 == status ) { + var notice = $('#lost-connection-notice'); + if ( ! wp.autosave.local.hasStorage ) { + notice.find('.hide-if-no-sessionstorage').hide(); + } + notice.show(); + autosave_disable_buttons(); + } + }).on('heartbeat-connection-restored.autosave', function() { + $('#lost-connection-notice').hide(); + autosave_enable_buttons(); + }); +}); + +function autosave_parse_response( response ) { + var res = wpAjax.parseAjaxResponse(response, 'autosave'), post_id, sup; + + if ( res && res.responses && res.responses.length ) { + if ( res.responses[0].supplemental ) { + sup = res.responses[0].supplemental; + + jQuery.each( sup, function( selector, value ) { + if ( selector.match(/^replace-/) ) + jQuery( '#' + selector.replace('replace-', '') ).val( value ); + }); + } + + // if no errors: add slug UI and update autosave-message + if ( !res.errors ) { + if ( post_id = parseInt( res.responses[0].id, 10 ) ) + autosave_update_slug( post_id ); + + if ( res.responses[0].data ) // update autosave message + jQuery('.autosave-message').text( res.responses[0].data ); + } + } + + return res; +} + +// called when autosaving pre-existing post +function autosave_saved(response) { + blockSave = false; + autosave_parse_response(response); // parse the ajax response + autosave_enable_buttons(); // re-enable disabled form buttons +} + +// called when autosaving new post +function autosave_saved_new(response) { + blockSave = false; + var res = autosave_parse_response(response), post_id; + + if ( res && res.responses.length && !res.errors ) { + // An ID is sent only for real auto-saves, not for autosave=0 "keepalive" saves + post_id = parseInt( res.responses[0].id, 10 ); + + if ( post_id ) { + notSaved = false; + jQuery('#auto_draft').val('0'); // No longer an auto-draft + } + + autosave_enable_buttons(); + + if ( autosaveDelayPreview ) { + autosaveDelayPreview = false; + doPreview(); + } + } else { + autosave_enable_buttons(); // re-enable disabled form buttons + } +} + +function autosave_update_slug(post_id) { + // create slug area only if not already there + if ( 'undefined' != makeSlugeditClickable && jQuery.isFunction(makeSlugeditClickable) && !jQuery('#edit-slug-box > *').size() ) { + jQuery.post( ajaxurl, { + action: 'sample-permalink', + post_id: post_id, + new_title: fullscreen && fullscreen.settings.visible ? jQuery('#wp-fullscreen-title').val() : jQuery('#title').val(), + samplepermalinknonce: jQuery('#samplepermalinknonce').val() + }, + function(data) { + if ( data !== '-1' ) { + var box = jQuery('#edit-slug-box'); + box.html(data); + if (box.hasClass('hidden')) { + box.fadeIn('fast', function () { + box.removeClass('hidden'); + }); + } + makeSlugeditClickable(); + } + } + ); + } +} + +function autosave_loading() { + jQuery('.autosave-message').html(autosaveL10n.savingText); +} + +function autosave_enable_buttons() { + jQuery(document).trigger('autosave-enable-buttons'); + if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) { + // delay that a bit to avoid some rare collisions while the DOM is being updated. + setTimeout(function(){ + var parent = jQuery('#submitpost'); + parent.find(':button, :submit').removeAttr('disabled'); + parent.find('.spinner').hide(); + }, 500); + } +} + +function autosave_disable_buttons() { + jQuery(document).trigger('autosave-disable-buttons'); + jQuery('#submitpost').find(':button, :submit').prop('disabled', true); + // Re-enable 5 sec later. Just gives autosave a head start to avoid collisions. + setTimeout( autosave_enable_buttons, 5000 ); +} + +function delayed_autosave() { + setTimeout(function(){ + if ( blockSave ) + return; + autosave(); + }, 200); +} + +autosave = function() { + var post_data = wp.autosave.getPostData(), + compareString, + successCallback; + + blockSave = true; + + // post_data.content cannot be retrieved at the moment + if ( ! post_data.autosave ) + return false; + + // No autosave while thickbox is open (media buttons) + if ( jQuery("#TB_window").css('display') == 'block' ) + return false; + + compareString = wp.autosave.getCompareString( post_data ); + + // Nothing to save or no change. + if ( compareString == autosaveLast ) + return false; + + autosaveLast = compareString; + jQuery(document).triggerHandler('wpcountwords', [ post_data["content"] ]); + + // Disable buttons until we know the save completed. + autosave_disable_buttons(); + + if ( post_data["auto_draft"] == '1' ) { + successCallback = autosave_saved_new; // new post + } else { + successCallback = autosave_saved; // pre-existing post + } + + jQuery.ajax({ + data: post_data, + beforeSend: autosave_loading, + type: "POST", + url: ajaxurl, + success: successCallback + }); + + return true; +} + +// Autosave in localStorage +// set as simple object/mixin for now +window.wp = window.wp || {}; +wp.autosave = wp.autosave || {}; + +(function($){ +// Returns the data for saving in both localStorage and autosaves to the server +wp.autosave.getPostData = function() { + var ed = typeof tinymce != 'undefined' ? tinymce.activeEditor : null, post_name, parent_id, cats = [], + data = { + action: 'autosave', + autosave: true, + post_id: $('#post_ID').val() || 0, + autosavenonce: $('#autosavenonce').val() || '', + post_type: $('#post_type').val() || '', + post_author: $('#post_author').val() || '', + excerpt: $('#excerpt').val() || '' + }; + + if ( ed && !ed.isHidden() ) { + // Don't run while the tinymce spellcheck is on. It resets all found words. + if ( ed.plugins.spellchecker && ed.plugins.spellchecker.active ) { + data.autosave = false; + return data; + } else { + if ( 'mce_fullscreen' == ed.id ) + tinymce.get('content').setContent(ed.getContent({format : 'raw'}), {format : 'raw'}); + + tinymce.triggerSave(); + } + } + + if ( typeof fullscreen != 'undefined' && fullscreen.settings.visible ) { + data['post_title'] = $('#wp-fullscreen-title').val() || ''; + data['content'] = $('#wp_mce_fullscreen').val() || ''; + } else { + data['post_title'] = $('#title').val() || ''; + data['content'] = $('#content').val() || ''; + } + + /* + // We haven't been saving tags with autosave since 2.8... Start again? + $('.the-tags').each( function() { + data[this.name] = this.value; + }); + */ + + $('input[id^="in-category-"]:checked').each( function() { + cats.push(this.value); + }); + data['catslist'] = cats.join(','); + + if ( post_name = $('#post_name').val() ) + data['post_name'] = post_name; + + if ( parent_id = $('#parent_id').val() ) + data['parent_id'] = parent_id; + + if ( $('#comment_status').prop('checked') ) + data['comment_status'] = 'open'; + + if ( $('#ping_status').prop('checked') ) + data['ping_status'] = 'open'; + + if ( $('#auto_draft').val() == '1' ) + data['auto_draft'] = '1'; + + return data; +}; + +// Concatenate title, content and excerpt. Used to track changes when auto-saving. +wp.autosave.getCompareString = function( post_data ) { + if ( typeof post_data === 'object' ) { + return ( post_data.post_title || '' ) + '::' + ( post_data.content || '' ) + '::' + ( post_data.excerpt || '' ); + } + + return ( $('#title').val() || '' ) + '::' + ( $('#content').val() || '' ) + '::' + ( $('#excerpt').val() || '' ); +}; + +wp.autosave.local = { + + lastSavedData: '', + blog_id: 0, + hasStorage: false, + + // Check if the browser supports sessionStorage and it's not disabled + checkStorage: function() { + var test = Math.random(), result = false; + + try { + sessionStorage.setItem('wp-test', test); + result = sessionStorage.getItem('wp-test') == test; + sessionStorage.removeItem('wp-test'); + } catch(e) {} + + this.hasStorage = result; + return result; + }, + + /** + * Initialize the local storage + * + * @return mixed False if no sessionStorage in the browser or an Object containing all post_data for this blog + */ + getStorage: function() { + var stored_obj = false; + // Separate local storage containers for each blog_id + if ( this.hasStorage && this.blog_id ) { + stored_obj = sessionStorage.getItem( 'wp-autosave-' + this.blog_id ); + + if ( stored_obj ) + stored_obj = JSON.parse( stored_obj ); + else + stored_obj = {}; + } + + return stored_obj; + }, + + /** + * Set the storage for this blog + * + * Confirms that the data was saved successfully. + * + * @return bool + */ + setStorage: function( stored_obj ) { + var key; + + if ( this.hasStorage && this.blog_id ) { + key = 'wp-autosave-' + this.blog_id; + sessionStorage.setItem( key, JSON.stringify( stored_obj ) ); + return sessionStorage.getItem( key ) !== null; + } + + return false; + }, + + /** + * Get the saved post data for the current post + * + * @return mixed False if no storage or no data or the post_data as an Object + */ + getData: function() { + var stored = this.getStorage(), post_id = $('#post_ID').val(); + + if ( !stored || !post_id ) + return false; + + return stored[ 'post_' + post_id ] || false; + }, + + /** + * Set (save or delete) post data in the storage. + * + * If stored_data evaluates to 'false' the storage key for the current post will be removed + * + * $param stored_data The post data to store or null/false/empty to delete the key + * @return bool + */ + setData: function( stored_data ) { + var stored = this.getStorage(), post_id = $('#post_ID').val(); + + if ( !stored || !post_id ) + return false; + + if ( stored_data ) + stored[ 'post_' + post_id ] = stored_data; + else if ( stored.hasOwnProperty( 'post_' + post_id ) ) + delete stored[ 'post_' + post_id ]; + else + return false; + + return this.setStorage(stored); + }, + + /** + * Save post data for the current post + * + * Runs on a 15 sec. schedule, saves when there are differences in the post title or content. + * When the optional data is provided, updates the last saved post data. + * + * $param data optional Object The post data for saving, minimum 'post_title' and 'content' + * @return bool + */ + save: function( data ) { + var result = false, post_data, compareString; + + if ( ! data ) { + post_data = wp.autosave.getPostData(); + } else { + post_data = this.getData() || {}; + $.extend( post_data, data ); + post_data.autosave = true; + } + + // Cannot get the post data at the moment + if ( ! post_data.autosave ) + return false; + + compareString = wp.autosave.getCompareString( post_data ); + + // If the content, title and excerpt did not change since the last save, don't save again + if ( compareString == this.lastSavedData ) + return false; + + post_data['save_time'] = (new Date()).getTime(); + post_data['status'] = $('#post_status').val() || ''; + result = this.setData( post_data ); + + if ( result ) + this.lastSavedData = compareString; + + return result; + }, + + // Initialize and run checkPost() on loading the script (before TinyMCE init) + init: function( settings ) { + var self = this; + + // Check if the browser supports sessionStorage and it's not disabled + if ( ! this.checkStorage() ) + return; + + // Don't run if the post type supports neither 'editor' (textarea#content) nor 'excerpt'. + if ( ! $('#content').length && ! $('#excerpt').length ) + return; + + if ( settings ) + $.extend( this, settings ); + + if ( !this.blog_id ) + this.blog_id = typeof window.autosaveL10n != 'undefined' ? window.autosaveL10n.blog_id : 0; + + $(document).ready( function(){ self.run(); } ); + }, + + // Run on DOM ready + run: function() { + var self = this; + + // Check if the local post data is different than the loaded post data. + this.checkPost(); + + // Set the schedule + this.schedule = $.schedule({ + time: 15 * 1000, + func: function() { wp.autosave.local.save(); }, + repeat: true, + protect: true + }); + + $('form#post').on('submit.autosave-local', function() { + var editor = typeof tinymce != 'undefined' && tinymce.get('content'), post_id = $('#post_ID').val() || 0; + + if ( editor && ! editor.isHidden() ) { + // Last onSubmit event in the editor, needs to run after the content has been moved to the textarea. + editor.onSubmit.add( function() { + wp.autosave.local.save({ + post_title: $('#title').val() || '', + content: $('#content').val() || '', + excerpt: $('#excerpt').val() || '' + }); + }); + } else { + self.save({ + post_title: $('#title').val() || '', + content: $('#content').val() || '', + excerpt: $('#excerpt').val() || '' + }); + } + + wpCookies.set( 'wp-saving-post-' + post_id, 'check' ); + }); + }, + + // Strip whitespace and compare two strings + compare: function( str1, str2 ) { + function remove( string ) { + return string.toString().replace(/[\x20\t\r\n\f]+/g, ''); + } + + return ( remove( str1 || '' ) == remove( str2 || '' ) ); + }, + + /** + * Check if the saved data for the current post (if any) is different than the loaded post data on the screen + * + * Shows a standard message letting the user restore the post data if different. + * + * @return void + */ + checkPost: function() { + var self = this, post_data = this.getData(), content, post_title, excerpt, notice, + post_id = $('#post_ID').val() || 0, cookie = wpCookies.get( 'wp-saving-post-' + post_id ); + + if ( ! post_data ) + return; + + if ( cookie ) { + wpCookies.remove( 'wp-saving-post-' + post_id ); + + if ( cookie == 'saved' ) { + // The post was saved properly, remove old data and bail + this.setData( false ); + return; + } + } + + // There is a newer autosave. Don't show two "restore" notices at the same time. + if ( $('#has-newer-autosave').length ) + return; + + content = $('#content').val() || ''; + post_title = $('#title').val() || ''; + excerpt = $('#excerpt').val() || ''; + + if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) + content = switchEditors.pre_wpautop( content ); + + // cookie == 'check' means the post was not saved properly, always show #local-storage-notice + if ( cookie != 'check' && this.compare( content, post_data.content ) && this.compare( post_title, post_data.post_title ) && this.compare( excerpt, post_data.excerpt ) ) { + return; + } + + this.restore_post_data = post_data; + this.undo_post_data = { + content: content, + post_title: post_title, + excerpt: excerpt + }; + + notice = $('#local-storage-notice'); + $('.wrap h2').first().after( notice.addClass('updated').show() ); + + notice.on( 'click', function(e) { + var target = $( e.target ); + + if ( target.hasClass('restore-backup') ) { + self.restorePost( self.restore_post_data ); + target.parent().hide(); + $(this).find('p.undo-restore').show(); + } else if ( target.hasClass('undo-restore-backup') ) { + self.restorePost( self.undo_post_data ); + target.parent().hide(); + $(this).find('p.local-restore').show(); + } + + e.preventDefault(); + }); + }, + + // Restore the current title, content and excerpt from post_data. + restorePost: function( post_data ) { + var editor; + + if ( post_data ) { + // Set the last saved data + this.lastSavedData = wp.autosave.getCompareString( post_data ); + + if ( $('#title').val() != post_data.post_title ) + $('#title').focus().val( post_data.post_title || '' ); + + $('#excerpt').val( post_data.excerpt || '' ); + editor = typeof tinymce != 'undefined' && tinymce.get('content'); + + if ( editor && ! editor.isHidden() && typeof switchEditors != 'undefined' ) { + // Make sure there's an undo level in the editor + editor.undoManager.add(); + editor.setContent( post_data.content ? switchEditors.wpautop( post_data.content ) : '' ); + } else { + // Make sure the Text editor is selected + $('#content-html').click(); + $('#content').val( post_data.content ); + } + + return true; + } + + return false; + } +}; + +wp.autosave.local.init(); + +}(jQuery)); diff --git a/sources/wp-includes/js/autosave.min.js b/sources/wp-includes/js/autosave.min.js new file mode 100644 index 0000000..2e846dd --- /dev/null +++ b/sources/wp-includes/js/autosave.min.js @@ -0,0 +1 @@ +function autosave_parse_response(a){var b,c,d=wpAjax.parseAjaxResponse(a,"autosave");return d&&d.responses&&d.responses.length&&(d.responses[0].supplemental&&(c=d.responses[0].supplemental,jQuery.each(c,function(a,b){a.match(/^replace-/)&&jQuery("#"+a.replace("replace-","")).val(b)})),d.errors||((b=parseInt(d.responses[0].id,10))&&autosave_update_slug(b),d.responses[0].data&&jQuery(".autosave-message").text(d.responses[0].data))),d}function autosave_saved(a){blockSave=!1,autosave_parse_response(a),autosave_enable_buttons()}function autosave_saved_new(a){blockSave=!1;var b,c=autosave_parse_response(a);c&&c.responses.length&&!c.errors?(b=parseInt(c.responses[0].id,10),b&&(notSaved=!1,jQuery("#auto_draft").val("0")),autosave_enable_buttons(),autosaveDelayPreview&&(autosaveDelayPreview=!1,doPreview())):autosave_enable_buttons()}function autosave_update_slug(a){"undefined"!=makeSlugeditClickable&&jQuery.isFunction(makeSlugeditClickable)&&!jQuery("#edit-slug-box > *").size()&&jQuery.post(ajaxurl,{action:"sample-permalink",post_id:a,new_title:fullscreen&&fullscreen.settings.visible?jQuery("#wp-fullscreen-title").val():jQuery("#title").val(),samplepermalinknonce:jQuery("#samplepermalinknonce").val()},function(a){if("-1"!==a){var b=jQuery("#edit-slug-box");b.html(a),b.hasClass("hidden")&&b.fadeIn("fast",function(){b.removeClass("hidden")}),makeSlugeditClickable()}})}function autosave_loading(){jQuery(".autosave-message").html(autosaveL10n.savingText)}function autosave_enable_buttons(){jQuery(document).trigger("autosave-enable-buttons"),wp.heartbeat&&wp.heartbeat.hasConnectionError()||setTimeout(function(){var a=jQuery("#submitpost");a.find(":button, :submit").removeAttr("disabled"),a.find(".spinner").hide()},500)}function autosave_disable_buttons(){jQuery(document).trigger("autosave-disable-buttons"),jQuery("#submitpost").find(":button, :submit").prop("disabled",!0),setTimeout(autosave_enable_buttons,5e3)}function delayed_autosave(){setTimeout(function(){blockSave||autosave()},200)}var autosave,autosaveLast="",autosavePeriodical,autosaveDelayPreview=!1,notSaved=!0,blockSave=!1,fullscreen,autosaveLockRelease=!0;jQuery(document).ready(function(a){autosaveLast=a("#wp-content-wrap").hasClass("tmce-active")&&"undefined"!=typeof switchEditors?wp.autosave.getCompareString({post_title:a("#title").val()||"",content:switchEditors.pre_wpautop(a("#content").val())||"",excerpt:a("#excerpt").val()||""}):wp.autosave.getCompareString(),autosavePeriodical=a.schedule({time:1e3*autosaveL10n.autosaveInterval,func:function(){autosave()},repeat:!0,protect:!0}),a("#post").submit(function(){a.cancel(autosavePeriodical),autosaveLockRelease=!1}),a('input[type="submit"], a.submitdelete',"#submitpost").click(function(){blockSave=!0,window.onbeforeunload=null,a(":button, :submit","#submitpost").each(function(){var b=a(this);b.hasClass("button-primary")?b.addClass("button-primary-disabled"):b.addClass("button-disabled")}),"publish"==a(this).attr("id")?a("#major-publishing-actions .spinner").show():a("#minor-publishing .spinner").show()}),window.onbeforeunload=function(){var b,c="undefined"!=typeof tinymce?tinymce.activeEditor:!1;if(c&&!c.isHidden()){if(c.isDirty())return autosaveL10n.saveAlert}else if(b=fullscreen&&fullscreen.settings.visible?wp.autosave.getCompareString({post_title:a("#wp-fullscreen-title").val()||"",content:a("#wp_mce_fullscreen").val()||"",excerpt:a("#excerpt").val()||""}):wp.autosave.getCompareString(),b!=autosaveLast)return autosaveL10n.saveAlert},a(window).unload(function(b){autosaveLockRelease&&(b.target&&"#document"!=b.target.nodeName||a.ajax({type:"POST",url:ajaxurl,async:!1,data:{action:"wp-remove-post-lock",_wpnonce:a("#_wpnonce").val(),post_ID:a("#post_ID").val(),active_post_lock:a("#active_post_lock").val()}}))}),a("#post-preview").click(function(){return"1"==a("#auto_draft").val()&¬Saved?(autosaveDelayPreview=!0,autosave(),!1):(doPreview(),!1)}),doPreview=function(){a("input#wp-preview").val("dopreview"),a("form#post").attr("target","wp-preview").submit().attr("target","");var b=navigator.userAgent.toLowerCase();-1!=b.indexOf("safari")&&-1==b.indexOf("chrome")&&a("form#post").attr("action",function(a,b){return b+"?t="+(new Date).getTime()}),a("input#wp-preview").val("")},a("#title").on("keydown.editor-focus",function(b){var c;9==b.which&&(b.ctrlKey||b.altKey||b.shiftKey||("undefined"!=typeof tinymce&&(c=tinymce.get("content")),c&&!c.isHidden()?a(this).one("keyup",function(){a("#content_tbl td.mceToolbar > a").focus()}):a("#content").focus(),b.preventDefault()))}),"1"==a("#auto_draft").val()&&a("#title").blur(function(){this.value&&"1"==a("#auto_draft").val()&&delayed_autosave()}),a(document).on("heartbeat-connection-lost.autosave",function(b,c,d){if("timeout"===c||503==d){var e=a("#lost-connection-notice");wp.autosave.local.hasStorage||e.find(".hide-if-no-sessionstorage").hide(),e.show(),autosave_disable_buttons()}}).on("heartbeat-connection-restored.autosave",function(){a("#lost-connection-notice").hide(),autosave_enable_buttons()})}),autosave=function(){var a,b,c=wp.autosave.getPostData();return blockSave=!0,c.autosave?"block"==jQuery("#TB_window").css("display")?!1:(a=wp.autosave.getCompareString(c),a==autosaveLast?!1:(autosaveLast=a,jQuery(document).triggerHandler("wpcountwords",[c.content]),autosave_disable_buttons(),b="1"==c.auto_draft?autosave_saved_new:autosave_saved,jQuery.ajax({data:c,beforeSend:autosave_loading,type:"POST",url:ajaxurl,success:b}),!0)):!1},window.wp=window.wp||{},wp.autosave=wp.autosave||{},function(a){wp.autosave.getPostData=function(){var b,c,d="undefined"!=typeof tinymce?tinymce.activeEditor:null,e=[],f={action:"autosave",autosave:!0,post_id:a("#post_ID").val()||0,autosavenonce:a("#autosavenonce").val()||"",post_type:a("#post_type").val()||"",post_author:a("#post_author").val()||"",excerpt:a("#excerpt").val()||""};if(d&&!d.isHidden()){if(d.plugins.spellchecker&&d.plugins.spellchecker.active)return f.autosave=!1,f;"mce_fullscreen"==d.id&&tinymce.get("content").setContent(d.getContent({format:"raw"}),{format:"raw"}),tinymce.triggerSave()}return"undefined"!=typeof fullscreen&&fullscreen.settings.visible?(f.post_title=a("#wp-fullscreen-title").val()||"",f.content=a("#wp_mce_fullscreen").val()||""):(f.post_title=a("#title").val()||"",f.content=a("#content").val()||""),a('input[id^="in-category-"]:checked').each(function(){e.push(this.value)}),f.catslist=e.join(","),(b=a("#post_name").val())&&(f.post_name=b),(c=a("#parent_id").val())&&(f.parent_id=c),a("#comment_status").prop("checked")&&(f.comment_status="open"),a("#ping_status").prop("checked")&&(f.ping_status="open"),"1"==a("#auto_draft").val()&&(f.auto_draft="1"),f},wp.autosave.getCompareString=function(b){return"object"==typeof b?(b.post_title||"")+"::"+(b.content||"")+"::"+(b.excerpt||""):(a("#title").val()||"")+"::"+(a("#content").val()||"")+"::"+(a("#excerpt").val()||"")},wp.autosave.local={lastSavedData:"",blog_id:0,hasStorage:!1,checkStorage:function(){var a=Math.random(),b=!1;try{sessionStorage.setItem("wp-test",a),b=sessionStorage.getItem("wp-test")==a,sessionStorage.removeItem("wp-test")}catch(c){}return this.hasStorage=b,b},getStorage:function(){var a=!1;return this.hasStorage&&this.blog_id&&(a=sessionStorage.getItem("wp-autosave-"+this.blog_id),a=a?JSON.parse(a):{}),a},setStorage:function(a){var b;return this.hasStorage&&this.blog_id?(b="wp-autosave-"+this.blog_id,sessionStorage.setItem(b,JSON.stringify(a)),null!==sessionStorage.getItem(b)):!1},getData:function(){var b=this.getStorage(),c=a("#post_ID").val();return b&&c?b["post_"+c]||!1:!1},setData:function(b){var c=this.getStorage(),d=a("#post_ID").val();if(!c||!d)return!1;if(b)c["post_"+d]=b;else{if(!c.hasOwnProperty("post_"+d))return!1;delete c["post_"+d]}return this.setStorage(c)},save:function(b){var c,d,e=!1;return b?(c=this.getData()||{},a.extend(c,b),c.autosave=!0):c=wp.autosave.getPostData(),c.autosave?(d=wp.autosave.getCompareString(c),d==this.lastSavedData?!1:(c.save_time=(new Date).getTime(),c.status=a("#post_status").val()||"",e=this.setData(c),e&&(this.lastSavedData=d),e)):!1},init:function(b){var c=this;this.checkStorage()&&(a("#content").length||a("#excerpt").length)&&(b&&a.extend(this,b),this.blog_id||(this.blog_id="undefined"!=typeof window.autosaveL10n?window.autosaveL10n.blog_id:0),a(document).ready(function(){c.run()}))},run:function(){var b=this;this.checkPost(),this.schedule=a.schedule({time:15e3,func:function(){wp.autosave.local.save()},repeat:!0,protect:!0}),a("form#post").on("submit.autosave-local",function(){var c="undefined"!=typeof tinymce&&tinymce.get("content"),d=a("#post_ID").val()||0;c&&!c.isHidden()?c.onSubmit.add(function(){wp.autosave.local.save({post_title:a("#title").val()||"",content:a("#content").val()||"",excerpt:a("#excerpt").val()||""})}):b.save({post_title:a("#title").val()||"",content:a("#content").val()||"",excerpt:a("#excerpt").val()||""}),wpCookies.set("wp-saving-post-"+d,"check")})},compare:function(a,b){function c(a){return a.toString().replace(/[\x20\t\r\n\f]+/g,"")}return c(a||"")==c(b||"")},checkPost:function(){var b,c,d,e,f=this,g=this.getData(),h=a("#post_ID").val()||0,i=wpCookies.get("wp-saving-post-"+h);if(g)return i&&(wpCookies.remove("wp-saving-post-"+h),"saved"==i)?(this.setData(!1),void 0):(a("#has-newer-autosave").length||(b=a("#content").val()||"",c=a("#title").val()||"",d=a("#excerpt").val()||"",a("#wp-content-wrap").hasClass("tmce-active")&&"undefined"!=typeof switchEditors&&(b=switchEditors.pre_wpautop(b)),"check"!=i&&this.compare(b,g.content)&&this.compare(c,g.post_title)&&this.compare(d,g.excerpt)||(this.restore_post_data=g,this.undo_post_data={content:b,post_title:c,excerpt:d},e=a("#local-storage-notice"),a(".wrap h2").first().after(e.addClass("updated").show()),e.on("click",function(b){var c=a(b.target);c.hasClass("restore-backup")?(f.restorePost(f.restore_post_data),c.parent().hide(),a(this).find("p.undo-restore").show()):c.hasClass("undo-restore-backup")&&(f.restorePost(f.undo_post_data),c.parent().hide(),a(this).find("p.local-restore").show()),b.preventDefault()}))),void 0)},restorePost:function(b){var c;return b?(this.lastSavedData=wp.autosave.getCompareString(b),a("#title").val()!=b.post_title&&a("#title").focus().val(b.post_title||""),a("#excerpt").val(b.excerpt||""),c="undefined"!=typeof tinymce&&tinymce.get("content"),c&&!c.isHidden()&&"undefined"!=typeof switchEditors?(c.undoManager.add(),c.setContent(b.content?switchEditors.wpautop(b.content):"")):(a("#content-html").click(),a("#content").val(b.content)),!0):!1}},wp.autosave.local.init()}(jQuery); \ No newline at end of file diff --git a/sources/wp-includes/js/backbone.min.js b/sources/wp-includes/js/backbone.min.js new file mode 100644 index 0000000..8555eca --- /dev/null +++ b/sources/wp-includes/js/backbone.min.js @@ -0,0 +1,7 @@ +// Backbone.js 1.0.0 + +// (c) 2010-2013 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org +(function(){var t=this;var e=t.Backbone;var i=[];var r=i.push;var s=i.slice;var n=i.splice;var a;if(typeof exports!=="undefined"){a=exports}else{a=t.Backbone={}}a.VERSION="1.0.0";var h=t._;if(!h&&typeof require!=="undefined")h=require("underscore");a.$=t.jQuery||t.Zepto||t.ender||t.$;a.noConflict=function(){t.Backbone=e;return this};a.emulateHTTP=false;a.emulateJSON=false;var o=a.Events={on:function(t,e,i){if(!l(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,i){if(!l(this,"once",t,[e,i])||!e)return this;var r=this;var s=h.once(function(){r.off(t,s);e.apply(this,arguments)});s._callback=e;return this.on(t,s,i)},off:function(t,e,i){var r,s,n,a,o,u,c,f;if(!this._events||!l(this,"off",t,[e,i]))return this;if(!t&&!e&&!i){this._events={};return this}a=t?[t]:h.keys(this._events);for(o=0,u=a.length;o").attr(t);this.setElement(e,false)}else{this.setElement(h.result(this,"el"),false)}}});a.sync=function(t,e,i){var r=k[t];h.defaults(i||(i={}),{emulateHTTP:a.emulateHTTP,emulateJSON:a.emulateJSON});var s={type:r,dataType:"json"};if(!i.url){s.url=h.result(e,"url")||U()}if(i.data==null&&e&&(t==="create"||t==="update"||t==="patch")){s.contentType="application/json";s.data=JSON.stringify(i.attrs||e.toJSON(i))}if(i.emulateJSON){s.contentType="application/x-www-form-urlencoded";s.data=s.data?{model:s.data}:{}}if(i.emulateHTTP&&(r==="PUT"||r==="DELETE"||r==="PATCH")){s.type="POST";if(i.emulateJSON)s.data._method=r;var n=i.beforeSend;i.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",r);if(n)return n.apply(this,arguments)}}if(s.type!=="GET"&&!i.emulateJSON){s.processData=false}if(s.type==="PATCH"&&window.ActiveXObject&&!(window.external&&window.external.msActiveXFilteringEnabled)){s.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var o=i.xhr=a.ajax(h.extend(s,i));e.trigger("request",e,o,i);return o};var k={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};a.ajax=function(){return a.$.ajax.apply(a.$,arguments)};var S=a.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var $=/\((.*?)\)/g;var T=/(\(\?)?:\w+/g;var H=/\*\w+/g;var A=/[\-{}\[\]+?.,\\\^$|#\s]/g;h.extend(S.prototype,o,{initialize:function(){},route:function(t,e,i){if(!h.isRegExp(t))t=this._routeToRegExp(t);if(h.isFunction(e)){i=e;e=""}if(!i)i=this[e];var r=this;a.history.route(t,function(s){var n=r._extractParameters(t,s);i&&i.apply(r,n);r.trigger.apply(r,["route:"+e].concat(n));r.trigger("route",e,n);a.history.trigger("route",r,e,n)});return this},navigate:function(t,e){a.history.navigate(t,e);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=h.result(this,"routes");var t,e=h.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(A,"\\$&").replace($,"(?:$1)?").replace(T,function(t,e){return e?t:"([^/]+)"}).replace(H,"(.*?)");return new RegExp("^"+t+"$")},_extractParameters:function(t,e){var i=t.exec(e).slice(1);return h.map(i,function(t){return t?decodeURIComponent(t):null})}});var I=a.History=function(){this.handlers=[];h.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var N=/^[#\/]|\s+$/g;var P=/^\/+|\/+$/g;var O=/msie [\w.]+/;var C=/\/$/;I.started=false;h.extend(I.prototype,o,{interval:50,getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=this.location.pathname;var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.substr(i.length)}else{t=this.getHash()}}return t.replace(N,"")},start:function(t){if(I.started)throw new Error("Backbone.history has already been started");I.started=true;this.options=h.extend({},{root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var e=this.getFragment();var i=document.documentMode;var r=O.exec(navigator.userAgent.toLowerCase())&&(!i||i<=7);this.root=("/"+this.root+"/").replace(P,"/");if(r&&this._wantsHashChange){this.iframe=a.$(''}c.style.display="none";c.removeAttribute("autoplay");return j},updateNative:function(a, +b){var c=a.htmlMediaElement,d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}}; +mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="//www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}},iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId, +{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused; +c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]= +a;var b,c="//www.youtube.com/apiplayer?enablejsapi=1&playerapiid="+a.pluginId+"&version=3&autoplay=0&controls=0&modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML=''}else a.container.innerHTML=''},flashReady:function(a){var b=this.flashPlayers[a],c= +document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250)},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"loadedmetadata");break;case 0:c.paused=false; +c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)}window.mejs=mejs;window.MediaElement=mejs.MediaElement; +(function(a,b){var c={locale:{language:"",strings:{}},methods:{}};c.locale.getLanguage=function(){return c.locale.language||navigator.language};if(typeof mejsL10n!="undefined")c.locale.language=mejsL10n.language;c.locale.INIT_LANGUAGE=c.locale.getLanguage();c.methods.checkPlain=function(d){var e,f,g={"&":"&",'"':""","<":"<",">":">"};d=String(d);for(e in g)if(g.hasOwnProperty(e)){f=RegExp(e,"g");d=d.replace(f,g[e])}return d};c.methods.formatString=function(d,e){for(var f in e){switch(f.charAt(0)){case "@":e[f]= +c.methods.checkPlain(e[f]);break;case "!":break;default:e[f]=''+c.methods.checkPlain(e[f])+""}d=d.replace(f,e[f])}return d};c.methods.t=function(d,e,f){if(c.locale.strings&&c.locale.strings[f.context]&&c.locale.strings[f.context][d])d=c.locale.strings[f.context][d];if(e)d=c.methods.formatString(d,e);return d};c.t=function(d,e,f){if(typeof d==="string"&&d.length>0){var g=c.locale.getLanguage();f=f||{context:g};return c.methods.t(d,e,f)}else throw{name:"InvalidArgumentException", +message:"First argument is either not a string or empty."};};b.i18n=c})(document,mejs);(function(a){if(typeof mejsL10n!="undefined")a[mejsL10n.language]=mejsL10n.strings})(mejs.i18n.locale.strings);(function(a){a.de={Fullscreen:"Vollbild","Go Fullscreen":"Vollbild an","Turn off Fullscreen":"Vollbild aus",Close:"Schlie\u00dfen"}})(mejs.i18n.locale.strings); +(function(a){a.zh={Fullscreen:"\u5168\u87a2\u5e55","Go Fullscreen":"\u5168\u5c4f\u6a21\u5f0f","Turn off Fullscreen":"\u9000\u51fa\u5168\u5c4f\u6a21\u5f0f",Close:"\u95dc\u9589"}})(mejs.i18n.locale.strings); + +/*! + * MediaElementPlayer + * http://mediaelementjs.com/ + * + * Creates a controller bar for HTML5

    ').addClass(a.$media[0].className).insertBefore(a.$media); +a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=a.isVideo?"video":"audio";e=b.substring(0, +1).toUpperCase()+b.substring(1);a.width=a.options[b+"Width"]>0||a.options[b+"Width"].toString().indexOf("%")>-1?a.options[b+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+e+"Width"];a.height=a.options[b+"Height"]>0||a.options[b+"Height"].toString().indexOf("%")>-1?a.options[b+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!== +null?a.$media.attr("height"):a.options["default"+e+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.width;c.pluginHeight=a.height}mejs.MediaElement(a.$media[0],c);typeof a.container!="undefined"&&a.controlsAreVisible&&a.container.trigger("controlsshown")},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true;b.container.trigger("controlsshown")}); +b.container.find(".mejs-control").css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility","visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true;b.container.trigger("controlsshown")}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!(!b.controlsAreVisible||b.options.alwaysShowControls))if(a){b.controls.stop(true, +true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")}}, +controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"?a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false); +this.controlsEnabled=true},meReady:function(a,b){var c=this,e=mejs.MediaFeatures,d=b.getAttribute("autoplay");d=!(typeof d=="undefined"||d===null||d==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(e.isAndroid&&c.options.AndroidUseNativeControls)&&!(e.isiPad&&c.options.iPadUseNativeControls)&&!(e.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media); +c.findTracks();for(g in c.options.features){e=c.options.features[g];if(c["build"+e])try{c["build"+e](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);else c.controlsEnabled&&c.showControls(false)});else{mejs.MediaElementPlayer.prototype.clickToPlayPauseCallback=function(){if(c.options.clickToPlayPause)c.media.paused? +c.media.play():c.media.pause()};c.media.addEventListener("click",c.clickToPlayPauseCallback,false);c.container.bind("mouseenter mouseover",function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&& +c.startControlsTimer(1E3)})}c.options.hideVideoControlsOnLoad&&c.hideControls(false);d&&!c.options.alwaysShowControls&&c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(j){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(j.target.videoHeight)){c.setPlayerSize(j.target.videoWidth,j.target.videoHeight);c.setControlsSize();c.media.setVideoSize(j.target.videoWidth,j.target.videoHeight)}},false)}a.addEventListener("play",function(){for(var j in mejs.players){var m= +mejs.players[j];m.id!=c.id&&c.options.pauseOtherPlayers&&!m.paused&&!m.ended&&m.pause();m.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){if(c.options.autoRewind)try{c.media.setCurrentTime(0)}catch(j){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",function(){c.updateDuration&& +c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);c.globalBind("resize",function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(d&&a.pluginType=="native"){a.load(); +a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media,c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0||this.$node.css("max-width")==="100%"||parseInt(this.$node.css("max-width").replace(/px/,""),10)/this.$node.offsetParent().width()=== +1||this.$node[0].currentStyle&&this.$node[0].currentStyle.maxWidth==="100%"){var c=this.isVideo?this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth:this.options.defaultAudioWidth,e=this.isVideo?this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight:this.options.defaultAudioHeight,d=this.container.parent().closest(":visible").width();c=this.isVideo||!this.options.autosizeProgress?parseInt(d*e/c,10):e;if(this.container.parent()[0].tagName.toLowerCase()=== +"body"){d=f(window).width();c=f(window).height()}if(c!=0&&d!=0){this.container.width(d).height(c);this.$media.add(this.container.find(".mejs-shim")).width("100%").height("100%");this.isVideo&&this.media.setVideoSize&&this.media.setVideoSize(d,c);this.layers.children(".mejs-layer").width("100%").height("100%")}}else{this.container.width(this.width).height(this.height);this.layers.children(".mejs-layer").width(this.width).height(this.height)}d=this.layers.find(".mejs-overlay-play");c=d.find(".mejs-overlay-button"); +d.height(this.container.height()-this.controls.height());c.css("margin-top","-"+(c.height()/2-this.controls.height()/2).toString()+"px")},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),e=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var d=c.siblings();if(this.options&&!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){d.each(function(){var g=f(this);if(g.css("position")!= +"absolute"&&g.is(":visible"))a+=f(this).outerWidth(true)});b=this.controls.width()-a-(c.outerWidth(true)-c.width())}c.width(b);e.width(b-(e.outerWidth(true)-e.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,e){var d=f('
    ').appendTo(c);b=a.$media.attr("poster");if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):d.hide();e.addEventListener("play",function(){d.hide()}, +false);a.options.showPosterWhenEnded&&a.options.autoRewind&&e.addEventListener("ended",function(){d.show()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"),c=b.find("img");if(c.length==0)c=f('').appendTo(b);c.attr("src",a);b.css({"background-image":"url("+a+")"})},buildoverlays:function(a,b,c,e){var d=this;if(a.isVideo){var g=f('
    ').hide().appendTo(c), +k=f('
    ').hide().appendTo(c),j=f('
    ').appendTo(c).click(function(){if(d.options.clickToPlayPause)e.paused?e.play():e.pause()});e.addEventListener("play",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("playing",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide(); +k.hide()},false);e.addEventListener("seeking",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("seeked",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||j.show()},false);e.addEventListener("waiting",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("loadeddata",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("canplay", +function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("error",function(){g.hide();b.find(".mejs-time-buffering").hide();k.show();k.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,e){this.globalBind("keydown",function(d){if(a.hasFocus&&a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g').appendTo(b).click(function(g){g.preventDefault();e.paused?e.play():e.pause();return false});e.addEventListener("play",function(){d.removeClass("mejs-play").addClass("mejs-pause")}, +false);e.addEventListener("playing",function(){d.removeClass("mejs-play").addClass("mejs-pause")},false);e.addEventListener("pause",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false);e.addEventListener("paused",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,e){f('
    ').appendTo(b).click(function(){e.paused||e.pause();if(e.currentTime>0){e.setCurrentTime(0);e.pause();b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left", +"0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$); +(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,e){f('
    00:00
    ').appendTo(b);b.find(".mejs-time-buffering").hide();var d= +this,g=b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var k=b.find(".mejs-time-current"),j=b.find(".mejs-time-handle"),m=b.find(".mejs-time-float"),q=b.find(".mejs-time-float-current"),p=function(h){h=h.pageX;var l=g.offset(),r=g.outerWidth(true),n=0,o=n=0;if(e.duration){if(hr+l.left)h=r+l.left;o=h-l.left;n=o/r;n=n<=0.02?0:n*e.duration;t&&n!==e.currentTime&&e.setCurrentTime(n);if(!mejs.MediaFeatures.hasTouch){m.css("left",o);q.html(mejs.Utility.secondsToTimeCode(n)); +m.show()}}},t=false;g.bind("mousedown",function(h){if(h.which===1){t=true;p(h);d.globalBind("mousemove.dur",function(l){p(l)});d.globalBind("mouseup.dur",function(){t=false;m.hide();d.globalUnbind(".dur")});return false}}).bind("mouseenter",function(){d.globalBind("mousemove.dur",function(h){p(h)});mejs.MediaFeatures.hasTouch||m.show()}).bind("mouseleave",function(){if(!t){d.globalUnbind(".dur");m.hide()}});e.addEventListener("progress",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false); +e.addEventListener("timeupdate",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);d.loaded=c;d.total=g;d.current=k;d.handle=j},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1, +Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=Math.round(this.total.width()*this.media.currentTime/this.media.duration),b=a-Math.round(this.handle.outerWidth(true)/2);this.current.width(a);this.handle.css("left",b)}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" | "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,e){f('
    '+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"
    ").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");e.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a,b, +c,e){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+''+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container"); +f('
    '+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"
    ").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");e.addEventListener("timeupdate",function(){a.updateDuration()}, +false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){this.container.toggleClass("mejs-long-video",this.media.duration>3600);if(this.durationD&&(this.options.duration>0||this.media.duration))this.durationD.html(mejs.Utility.secondsToTimeCode(this.options.duration>0?this.options.duration: +this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{muteText:mejs.i18n.t("Mute Toggle"),hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,e){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var d=this,g=d.isVideo?d.options.videoVolume:d.options.audioVolume,k=g=="horizontal"?f('
    ').appendTo(b):f('
    ').appendTo(b), +j=d.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),m=d.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),q=d.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),p=d.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),t=function(n,o){if(!j.is(":visible")&&typeof o=="undefined"){j.show();t(n,true);j.hide()}else{n=Math.max(0,n);n=Math.min(n,1);n==0?k.removeClass("mejs-mute").addClass("mejs-unmute"):k.removeClass("mejs-unmute").addClass("mejs-mute"); +if(g=="vertical"){var s=m.height(),u=m.position(),v=s-s*n;p.css("top",Math.round(u.top+v-p.height()/2));q.height(s-v);q.css("top",u.top+v)}else{s=m.width();u=m.position();s=s*n;p.css("left",Math.round(u.left+s-p.width()/2));q.width(Math.round(s))}}},h=function(n){var o=null,s=m.offset();if(g=="vertical"){o=m.height();parseInt(m.css("top").replace(/px/,""),10);o=(o-(n.pageY-s.top))/o;if(s.top==0||s.left==0)return}else{o=m.width();o=(n.pageX-s.left)/o}o=Math.max(0,o);o=Math.min(o,1);t(o);o==0?e.setMuted(true): +e.setMuted(false);e.setVolume(o)},l=false,r=false;k.hover(function(){j.show();r=true},function(){r=false;!l&&g=="vertical"&&j.hide()});j.bind("mouseover",function(){r=true}).bind("mousedown",function(n){h(n);d.globalBind("mousemove.vol",function(o){h(o)});d.globalBind("mouseup.vol",function(){l=false;d.globalUnbind(".vol");!r&&g=="vertical"&&j.hide()});l=true;return false});k.find("button").click(function(){e.setMuted(!e.muted)});e.addEventListener("volumechange",function(){if(!l)if(e.muted){t(0); +k.removeClass("mejs-mute").addClass("mejs-unmute")}else{t(e.volume);k.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(d.container.is(":visible")){t(a.options.startVolume);a.options.startVolume===0&&e.setMuted(true);e.pluginType==="native"&&e.setVolume(a.options.startVolume)}}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:mejs.i18n.t("Fullscreen")});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,isInIframe:false,buildfullscreen:function(a,b,c,e){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=function(){if(a.isFullScreen)if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen= +false;a.exitFullScreen()}};mejs.MediaFeatures.hasMozNativeFullScreen?a.globalBind(mejs.MediaFeatures.fullScreenEventName,c):a.container.bind(mejs.MediaFeatures.fullScreenEventName,c)}var d=this,g=f('
    ').appendTo(b);if(d.media.pluginType==="native"||!d.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&& +mejs.MediaFeatures.isFullScreen()||a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;if(function(){var h=document.createElement("x"),l=document.documentElement,r=window.getComputedStyle;if(!("pointerEvents"in h.style))return false;h.style.pointerEvents="auto";h.style.pointerEvents="x";l.appendChild(h);r=r&&r(h,"").pointerEvents==="auto";l.removeChild(h);return!!r}()&&!mejs.MediaFeatures.isOpera){var j=false,m=function(){if(j){for(var h in q)q[h].hide();g.css("pointer-events", +"");d.controls.css("pointer-events","");d.media.removeEventListener("click",d.clickToPlayPauseCallback);j=false}},q={};b=["top","left","right","bottom"];var p,t=function(){var h=g.offset().left-d.container.offset().left,l=g.offset().top-d.container.offset().top,r=g.outerWidth(true),n=g.outerHeight(true),o=d.container.width(),s=d.container.height();for(p in q)q[p].css({position:"absolute",top:0,left:0});q.top.width(o).height(l);q.left.width(h).height(n).css({top:l});q.right.width(o-h-r).height(n).css({top:l, +left:h+r});q.bottom.width(o).height(s-n-l).css({top:l+n})};d.globalBind("resize",function(){t()});p=0;for(c=b.length;p').appendTo(d.container).mouseover(m).hide();g.on("mouseover",function(){if(!d.isFullScreen){var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,false);g.css("pointer-events","none");d.controls.css("pointer-events","none");d.media.addEventListener("click",d.clickToPlayPauseCallback);for(p in q)q[p].show(); +t();j=true}});e.addEventListener("fullscreenchange",function(){d.isFullScreen=!d.isFullScreen;d.isFullScreen?d.media.removeEventListener("click",d.clickToPlayPauseCallback):d.media.addEventListener("click",d.clickToPlayPauseCallback);m()});d.globalBind("mousemove",function(h){if(j){var l=g.offset();if(h.pageYl.top+g.outerHeight(true)||h.pageXl.left+g.outerWidth(true)){g.css("pointer-events","");d.controls.css("pointer-events","");j=false}}})}else g.on("mouseover", +function(){if(k!==null){clearTimeout(k);delete k}var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,true)}).on("mouseout",function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){e.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;d.globalBind("keydown",function(h){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||d.isFullScreen)&&h.keyCode==27)a.exitFullScreen()})}},cleanfullscreen:function(a){a.exitFullScreen()}, +containerSizeTimeout:null,enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){f(document.documentElement).addClass("mejs-fullscreen");normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!== +screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},250);else{a.pause();window.open(b,a.id, +"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");a.containerSizeTimeout=setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.media.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find(".mejs-shim").width("100%").height("100%");a.media.setVideoSize(f(window).width(), +f(window).height())}a.layers.children("div").width("100%").height("100%");a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){clearTimeout(this.containerSizeTimeout);if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen(); +f(document.documentElement).removeClass("mejs-fullscreen");this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.media.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find(".mejs-shim").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen"); +this.setControlsSize();this.isFullScreen=false}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:mejs.i18n.t("Captions/Subtitles"),hideCaptionsButtonWhenEmpty:true,toggleCaptionsButtonWhenOnlyOne:false,slidesSelector:""});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,e){if(a.tracks.length!=0){var d;if(this.domNode.textTracks)for(d=this.domNode.textTracks.length-1;d>=0;d--)this.domNode.textTracks[d].mode="hidden";a.chapters=f('
    ').prependTo(c).hide();a.captions= +f('
    ').prependTo(c).hide();a.captionsText=a.captions.find(".mejs-captions-text");a.captionsButton=f('
    ").appendTo(b);for(d=b=0;d0&&b.displayChapters(c)},false);c.kind=="slides"&&b.setupSlides(c)},error:function(){b.loadNextTrack()}})},enableTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("input[value="+a+"]").prop("disabled",false).siblings("label").html(b); +this.options.startLanguage==a&&f("#"+this.id+"_captions_"+a).click();this.adjustLanguageBox()},addTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("ul").append(f('
  • "));this.adjustLanguageBox();this.container.find(".mejs-captions-translations option[value="+a+"]").remove()}, +adjustLanguageBox:function(){this.captionsButton.find(".mejs-captions-selector").height(this.captionsButton.find(".mejs-captions-selector ul").outerHeight(true)+this.captionsButton.find(".mejs-captions-translations").outerHeight(true))},checkForTracks:function(){var a=false;if(this.options.hideCaptionsButtonWhenEmpty){for(i=0;i=b.entries.times[a].start&&this.media.currentTime<=b.entries.times[a].stop){this.captionsText.html(b.entries.text[a]);this.captions.show().height(0);return}this.captions.hide()}},setupSlides:function(a){this.slides=a;this.slides.entries.imgs=[this.slides.entries.text.length];this.showSlide(0)},showSlide:function(a){if(!(typeof this.tracks=="undefined"||typeof this.slidesContainer== +"undefined")){var b=this,c=b.slides.entries.text[a],e=b.slides.entries.imgs[a];if(typeof e=="undefined"||typeof e.fadeIn=="undefined")b.slides.entries.imgs[a]=e=f('').on("load",function(){e.appendTo(b.slidesContainer).hide().fadeIn().siblings(":visible").fadeOut()});else!e.is(":visible")&&!e.is(":animated")&&e.fadeIn().siblings(":visible").fadeOut()}},displaySlides:function(){if(typeof this.slides!="undefined"){var a=this.slides,b;for(b=0;b= +a.entries.times[b].start&&this.media.currentTime<=a.entries.times[b].stop){this.showSlide(b);break}}},displayChapters:function(){var a;for(a=0;a100||c==a.entries.times.length- +1&&e+d<100)e=100-d;b.chapters.append(f('
    '+a.entries.text[c]+''+mejs.Utility.secondsToTimeCode(a.entries.times[c].start)+"–"+mejs.Utility.secondsToTimeCode(a.entries.times[c].stop)+"
    "));d+=e}b.chapters.find("div.mejs-chapter").click(function(){b.media.setCurrentTime(parseFloat(f(this).attr("rel"))); +b.media.paused&&b.media.play()});b.chapters.show()}});mejs.language={codes:{af:"Afrikaans",sq:"Albanian",ar:"Arabic",be:"Belarusian",bg:"Bulgarian",ca:"Catalan",zh:"Chinese","zh-cn":"Chinese Simplified","zh-tw":"Chinese Traditional",hr:"Croatian",cs:"Czech",da:"Danish",nl:"Dutch",en:"English",et:"Estonian",tl:"Filipino",fi:"Finnish",fr:"French",gl:"Galician",de:"German",el:"Greek",ht:"Haitian Creole",iw:"Hebrew",hi:"Hindi",hu:"Hungarian",is:"Icelandic",id:"Indonesian",ga:"Irish",it:"Italian",ja:"Japanese", +ko:"Korean",lv:"Latvian",lt:"Lithuanian",mk:"Macedonian",ms:"Malay",mt:"Maltese",no:"Norwegian",fa:"Persian",pl:"Polish",pt:"Portuguese",ro:"Romanian",ru:"Russian",sr:"Serbian",sk:"Slovak",sl:"Slovenian",es:"Spanish",sw:"Swahili",sv:"Swedish",tl:"Tagalog",th:"Thai",tr:"Turkish",uk:"Ukrainian",vi:"Vietnamese",cy:"Welsh",yi:"Yiddish"}};mejs.TrackFormatParser={webvvt:{pattern_identifier:/^([a-zA-z]+-)?[0-9]+$/,pattern_timecode:/^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, +parse:function(a){var b=0;a=mejs.TrackFormatParser.split2(a,/\r?\n/);for(var c={text:[],times:[]},e,d;b$1
    ");c.text.push(d);c.times.push({start:mejs.Utility.convertSMPTEtoSeconds(e[1])==0?0.2:mejs.Utility.convertSMPTEtoSeconds(e[1]), +stop:mejs.Utility.convertSMPTEtoSeconds(e[3]),settings:e[5]})}}return c}},dfxp:{parse:function(a){a=f(a).filter("tt");var b=0;b=a.children("div").eq(0);var c=b.find("p");b=a.find("#"+b.attr("style"));var e,d;a={text:[],times:[]};if(b.length){d=b.removeAttr("id").get(0).attributes;if(d.length){e={};for(b=0;b$1");a.text.push(d);if(a.times.start==0)a.times.start=2}return a}},split2:function(a,b){return a.split(b)}};if("x\n\ny".split(/\n/gi).length!=3)mejs.TrackFormatParser.split2=function(a,b){var c=[],e="",d;for(d=0;d').appendTo(f("body")).hide();a.container.bind("contextmenu",function(b){if(a.isContextMenuEnabled){b.preventDefault();a.renderContextMenu(b.clientX-1,b.clientY-1);return false}});a.container.bind("click",function(){a.contextMenu.hide()});a.contextMenu.bind("mouseleave",function(){a.startContextMenuTimer()})},cleancontextmenu:function(a){a.contextMenu.remove()}, +isContextMenuEnabled:true,enableContextMenu:function(){this.isContextMenuEnabled=true},disableContextMenu:function(){this.isContextMenuEnabled=false},contextMenuTimeout:null,startContextMenuTimer:function(){var a=this;a.killContextMenuTimer();a.contextMenuTimer=setTimeout(function(){a.hideContextMenu();a.killContextMenuTimer()},750)},killContextMenuTimer:function(){var a=this.contextMenuTimer;if(a!=null){clearTimeout(a);delete a}},hideContextMenu:function(){this.contextMenu.hide()},renderContextMenu:function(a, +b){for(var c=this,e="",d=c.options.contextMenuItems,g=0,k=d.length;g';else{var j=d[g].render(c);if(j!=null)e+='
    '+j+"
    "}c.contextMenu.empty().append(f(e)).css({top:b,left:a}).show();c.contextMenu.find(".mejs-contextmenu-item").each(function(){var m=f(this),q=parseInt(m.data("itemindex"),10),p=c.options.contextMenuItems[q];typeof p.show!= +"undefined"&&p.show(m,c);m.click(function(){typeof p.click!="undefined"&&p.click(c);c.contextMenu.hide()})});setTimeout(function(){c.killControlsTimer("rev3")},100)}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{postrollCloseText:mejs.i18n.t("Close")});f.extend(MediaElementPlayer.prototype,{buildpostroll:function(a,b,c){var e=this.container.find('link[rel="postroll"]').attr("href");if(typeof e!=="undefined"){a.postroll=f('').prependTo(c).hide();this.media.addEventListener("ended", +function(){f.ajax({dataType:"html",url:e,success:function(d){c.find(".mejs-postroll-layer-content").html(d)}});a.postroll.show()},false)}}})})(mejs.$); + diff --git a/sources/wp-includes/js/mediaelement/mediaelementplayer.min.css b/sources/wp-includes/js/mediaelement/mediaelementplayer.min.css new file mode 100644 index 0000000..5d88e84 --- /dev/null +++ b/sources/wp-includes/js/mediaelement/mediaelementplayer.min.css @@ -0,0 +1 @@ +.mejs-container{position:relative;background:#000;font-family:Helvetica,Arial;text-align:left;vertical-align:top;text-indent:0;}.me-plugin{position:absolute;}.mejs-embed,.mejs-embed body{width:100%;height:100%;margin:0;padding:0;background:#000;overflow:hidden;}.mejs-fullscreen{overflow:hidden!important;}.mejs-container-fullscreen{position:fixed;left:0;top:0;right:0;bottom:0;overflow:hidden;z-index:1000;}.mejs-container-fullscreen .mejs-mediaelement,.mejs-container-fullscreen video{width:100%;height:100%;}.mejs-clear{clear:both;}.mejs-background{position:absolute;top:0;left:0;}.mejs-mediaelement{position:absolute;top:0;left:0;width:100%;height:100%;}.mejs-poster{position:absolute;top:0;left:0;background-size:contain;background-position:50% 50%;background-repeat:no-repeat;}:root .mejs-poster img{display:none;}.mejs-poster img{border:0;padding:0;border:0;}.mejs-overlay{position:absolute;top:0;left:0;}.mejs-overlay-play{cursor:pointer;}.mejs-overlay-button{position:absolute;top:50%;left:50%;width:100px;height:100px;margin:-50px 0 0 -50px;background:url(bigplay.svg) no-repeat;}.no-svg .mejs-overlay-button{background-image:url(bigplay.png);}.mejs-overlay:hover .mejs-overlay-button{background-position:0 -100px;}.mejs-overlay-loading{position:absolute;top:50%;left:50%;width:80px;height:80px;margin:-40px 0 0 -40px;background:#333;background:url(background.png);background:rgba(0,0,0,0.9);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.9)),to(rgba(0,0,0,0.9)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-moz-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-o-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-ms-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:linear-gradient(rgba(50,50,50,0.9),rgba(0,0,0,0.9));}.mejs-overlay-loading span{display:block;width:80px;height:80px;background:transparent url(loading.gif) 50% 50% no-repeat;}.mejs-container .mejs-controls{position:absolute;list-style-type:none;margin:0;padding:0;bottom:0;left:0;background:url(background.png);background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));height:30px;width:100%;}.mejs-container .mejs-controls div{list-style-type:none;background-image:none;display:block;float:left;margin:0;padding:0;width:26px;height:26px;font-size:11px;line-height:11px;font-family:Helvetica,Arial;border:0;}.mejs-controls .mejs-button button{cursor:pointer;display:block;font-size:0;line-height:0;text-decoration:none;margin:7px 5px;padding:0;position:absolute;height:16px;width:16px;border:0;background:transparent url(controls.svg) no-repeat;}.no-svg .mejs-controls .mejs-button button{background-image:url(controls.png);}.mejs-controls .mejs-button button:focus{outline:solid 1px yellow;}.mejs-container .mejs-controls .mejs-time{color:#fff;display:block;height:17px;width:auto;padding:8px 3px 0 3px;overflow:hidden;text-align:center;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}.mejs-container .mejs-controls .mejs-time span{color:#fff;font-size:11px;line-height:12px;display:block;float:left;margin:1px 2px 0 0;width:auto;}.mejs-controls .mejs-play button{background-position:0 0;}.mejs-controls .mejs-pause button{background-position:0 -16px;}.mejs-controls .mejs-stop button{background-position:-112px 0;}.mejs-controls div.mejs-time-rail{direction:ltr;width:200px;padding-top:5px;}.mejs-controls .mejs-time-rail span{display:block;position:absolute;width:180px;height:10px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;cursor:pointer;}.mejs-controls .mejs-time-rail .mejs-time-total{margin:5px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-time-rail .mejs-time-buffering{width:100%;background-image:-o-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:15px 15px;-moz-background-size:15px 15px;-o-background-size:15px 15px;background-size:15px 15px;-webkit-animation:buffering-stripes 2s linear infinite;-moz-animation:buffering-stripes 2s linear infinite;-ms-animation:buffering-stripes 2s linear infinite;-o-animation:buffering-stripes 2s linear infinite;animation:buffering-stripes 2s linear infinite;}@-webkit-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-moz-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-ms-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-o-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}.mejs-controls .mejs-time-rail .mejs-time-loaded{background:#3caac8;background:rgba(60,170,200,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(44,124,145,0.8)),to(rgba(78,183,212,0.8)));background:-webkit-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-moz-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-o-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-ms-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:linear-gradient(rgba(44,124,145,0.8),rgba(78,183,212,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-current{background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-handle{display:none;position:absolute;margin:0;width:10px;background:#fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;border:solid 2px #333;top:-2px;text-align:center;}.mejs-controls .mejs-time-rail .mejs-time-float{position:absolute;display:none;background:#eee;width:36px;height:17px;border:solid 1px #333;top:-26px;margin-left:-18px;text-align:center;color:#111;}.mejs-controls .mejs-time-rail .mejs-time-float-current{margin:2px;width:30px;display:block;text-align:center;left:0;}.mejs-controls .mejs-time-rail .mejs-time-float-corner{position:absolute;display:block;width:0;height:0;line-height:0;border:solid 5px #eee;border-color:#eee transparent transparent transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:15px;left:13px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float{width:48px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-current{width:44px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-corner{left:18px;}.mejs-controls .mejs-fullscreen-button button{background-position:-32px 0;}.mejs-controls .mejs-unfullscreen button{background-position:-32px -16px;}.mejs-controls .mejs-mute button{background-position:-16px -16px;}.mejs-controls .mejs-unmute button{background-position:-16px 0;}.mejs-controls .mejs-volume-button{position:relative;}.mejs-controls .mejs-volume-button .mejs-volume-slider{display:none;height:115px;width:25px;background:url(background.png);background:rgba(50,50,50,0.7);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:-115px;left:0;z-index:1;position:absolute;margin:0;}.mejs-controls .mejs-volume-button:hover{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.5);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.9);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle{position:absolute;left:4px;top:-3px;width:16px;height:6px;background:#ddd;background:rgba(255,255,255,0.9);cursor:N-resize;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;margin:0;}.mejs-controls div.mejs-horizontal-volume-slider{height:26px;width:60px;position:relative;}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle{display:none;}.mejs-controls .mejs-captions-button{position:relative;}.mejs-controls .mejs-captions-button button{background-position:-48px 0;}.mejs-controls .mejs-captions-button .mejs-captions-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-controls .mejs-captions-button .mejs-captions-translations{font-size:10px;margin:0 0 5px 0;}.mejs-chapters{position:absolute;top:0;left:0;-xborder-right:solid 1px #fff;width:10000px;z-index:1;}.mejs-chapters .mejs-chapter{position:absolute;float:left;background:#222;background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#323232,endColorstr=#000000);overflow:hidden;border:0;}.mejs-chapters .mejs-chapter .mejs-chapter-block{font-size:11px;color:#fff;padding:5px;display:block;border-right:solid 1px #333;border-bottom:solid 1px #333;cursor:pointer;}.mejs-chapters .mejs-chapter .mejs-chapter-block-last{border-right:none;}.mejs-chapters .mejs-chapter .mejs-chapter-block:hover{background:#666;background:rgba(102,102,102,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(102,102,102,0.7)),to(rgba(50,50,50,0.6)));background:-webkit-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-moz-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-o-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-ms-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:linear-gradient(rgba(102,102,102,0.7),rgba(50,50,50,0.6));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#666666,endColorstr=#323232);}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title{font-size:12px;font-weight:bold;display:block;white-space:nowrap;text-overflow:ellipsis;margin:0 0 3px 0;line-height:12px;}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan{font-size:12px;line-height:12px;margin:3px 0 4px 0;display:block;white-space:nowrap;text-overflow:ellipsis;}.mejs-captions-layer{position:absolute;bottom:0;left:0;text-align:center;line-height:22px;font-size:12px;color:#fff;}.mejs-captions-layer a{color:#fff;text-decoration:underline;}.mejs-captions-layer[lang=ar]{font-size:20px;font-weight:normal;}.mejs-captions-position{position:absolute;width:100%;bottom:15px;left:0;}.mejs-captions-position-hover{bottom:45px;}.mejs-captions-text{padding:3px 5px;background:url(background.png);background:rgba(20,20,20,0.8);}.me-cannotplay a{color:#fff;font-weight:bold;}.me-cannotplay span{padding:15px;display:block;}.mejs-controls .mejs-loop-off button{background-position:-64px -16px;}.mejs-controls .mejs-loop-on button{background-position:-64px 0;}.mejs-controls .mejs-backlight-off button{background-position:-80px -16px;}.mejs-controls .mejs-backlight-on button{background-position:-80px 0;}.mejs-controls .mejs-picturecontrols-button{background-position:-96px 0;}.mejs-contextmenu{position:absolute;width:150px;padding:10px;border-radius:4px;top:0;left:0;background:#fff;border:solid 1px #999;z-index:1001;}.mejs-contextmenu .mejs-contextmenu-separator{height:1px;font-size:0;margin:5px 6px;background:#333;}.mejs-contextmenu .mejs-contextmenu-item{font-family:Helvetica,Arial;font-size:12px;padding:4px 6px;cursor:pointer;color:#333;}.mejs-contextmenu .mejs-contextmenu-item:hover{background:#2C7C91;color:#fff;}.mejs-controls .mejs-sourcechooser-button{position:relative;}.mejs-controls .mejs-sourcechooser-button button{background-position:-128px 0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-postroll-layer{position:absolute;bottom:0;left:0;width:100%;height:100%;background:url(background.png);background:rgba(50,50,50,0.7);z-index:1000;overflow:hidden;}.mejs-postroll-layer-content{width:100%;height:100%;}.mejs-postroll-close{position:absolute;right:0;top:0;background:url(background.png);background:rgba(50,50,50,0.7);color:#fff;padding:4px;z-index:100;cursor:pointer;} \ No newline at end of file diff --git a/sources/wp-includes/js/mediaelement/silverlightmediaelement.xap b/sources/wp-includes/js/mediaelement/silverlightmediaelement.xap new file mode 100644 index 0000000000000000000000000000000000000000..9d55c2e46ae51017ab91f61b05cf4f4838ab10ab GIT binary patch literal 12461 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 Y;npiigG2o9V37YT{69ou_}||D0@79*!2kdN literal 0 HcmV?d00001 diff --git a/sources/wp-includes/js/mediaelement/wp-mediaelement.css b/sources/wp-includes/js/mediaelement/wp-mediaelement.css new file mode 100644 index 0000000..18ad948 --- /dev/null +++ b/sources/wp-includes/js/mediaelement/wp-mediaelement.css @@ -0,0 +1,15 @@ +.mejs-container, .mejs-embed, .mejs-embed body { + background: #464646; +} + +.mejs-controls .mejs-time-rail .mejs-time-loaded { + background: #21759b; +} + +.mejs-controls .mejs-time-rail .mejs-time-current { + background: #d54e21; +} + +.me-cannotplay { + width: auto !important; +} diff --git a/sources/wp-includes/js/mediaelement/wp-mediaelement.js b/sources/wp-includes/js/mediaelement/wp-mediaelement.js new file mode 100644 index 0000000..fb09e3c --- /dev/null +++ b/sources/wp-includes/js/mediaelement/wp-mediaelement.js @@ -0,0 +1,15 @@ +(function ($) { + // add mime-type aliases to MediaElement plugin support + mejs.plugins.silverlight[0].types.push('video/x-ms-wmv'); + mejs.plugins.silverlight[0].types.push('audio/x-ms-wma'); + + $(function () { + var settings = {}; + + if ( typeof _wpmejsSettings !== 'undefined' ) + settings.pluginPath = _wpmejsSettings.pluginPath; + + $('.wp-audio-shortcode, .wp-video-shortcode').mediaelementplayer( settings ); + }); + +}(jQuery)); diff --git a/sources/wp-includes/js/plupload/changelog.txt b/sources/wp-includes/js/plupload/changelog.txt new file mode 100644 index 0000000..7aaff4c --- /dev/null +++ b/sources/wp-includes/js/plupload/changelog.txt @@ -0,0 +1,241 @@ +Version 1.5.7 (2013-04-10) + HTML5: Workaround for squish problem in iOS6, when uploading resized images. + HTML5: Fix failing workaround for FormData+Blob bug on Android... + HTML5: Allow multiple uploads on iOS. + Include VB build script that doesn't depend on Ant and is said to be native to Windows. +Version 1.5.6 (2013-02-28) + Fix regression: getPos() wrong on ie6/7. + HTML5: Send file as binary string if it was mangled, even if multipart is set to false. + HTML5: Add workaround Android browsers, that are unable to properly send blobs in FormData. + HTML4/Flash/Silverlight: Destroy fails to cleanup everything when container not defined. + UI, Queue: Use html() instead of text(), otherwise special characters fail to display properly. + UI, Queue: Use on() instead of delegate() or live(). Update examples to use jQuery 1.9.0 by default. + Queue: Blur rename input field when ESC is pressed. + Additional language packs: Slovak. +Version 1.5.5 (2013-01-23) + UI Widget: Fix sortable feature, broken in jQuery UI 1.9. + Queue: Replace live() with delegate(), as live() was removed from jQuery 1.9. + HTML5: window.getComputedStyle in Firefox doesn't support dashed rulenames - use zIndex instead of z-index. + HTML5/Flash/Silverlight/Gears: Process JPEGs, if quality parameter is present, whatever the scale factor. + Flash: Survive invalid EXIF tag offsets. + Flash: Allow only letters, digits and underscore in runtime id to avoid script injection. + SilverLight: Prepend ampersand to the query string, for non multipart cases (as in Flash and HTML5). + Add mime types for m2v,3gp,3g2 extensions. +Version 1.5.4 (2012-04-12) + Flash: Disable scripting if swf was loaded from another domain. +Version 1.5.3 (2012-04-05) + HTML5: Check if xhr object is initialized, before calling abort() on it. + HTML4: Postpone form removal until uploaders state changes, to avoid error on resuming stopped uploads. + BrowserPlus: Fix mechanical typo, that caused error during mime type check. + BrowserPlus: browserPlus.Uploader.Cancel() has two required parameters, dies with the error if not passed. + Flash: Improve runtime's behaviour during upload cancellation. + Flash: Survive the case when GPSVersionID contains unexpected value. + Flash: Fix random freeze in Chrome's bundled Flash Player. + Flash: Avoid the silent break when URLStream not yet open, but close is called on it. + Flash: Move Destroy handler out of Flash:Init handler, since it might be called not only after Flash:Init but also before it. + Flash: Avoid warning during build with mxmlc. + Try removeEventListener first in IE and only if it fails - detachEvent. + Fix plupload.getPos to return proper value in IE8+. + Do not initiate plupload.STARTED state, if file queue is empty. + Additional language packs: Estonian, Polish, Korean, French-Canadian, Greek, Persian/Farsi. +Version 1.5.2 (2012-01-06) + UI Widget: Do not show UI if no runtime can be initialized. + UI Widget: Timely update file size and total size if resize in action. + UI Widget: Constrain renaming feature to queued files only. + UI Widget: Disable Add button properly, if requested, rather then just hide. + HTML4/HTML5/BrowserPlus: Avoid adding mime type twice to dialog trigger. + HTML5: fix regression, when unresized images were failing on FF3.6. + HTML5: Constrain Gecko 2,5,6 workaround to multipart mode only. + HTML5/Flash: Take into account weird possibilities of ExifVersion being a string, rather then standard Undefined. + Flash: Simplify event dispatching in BitmapDataUnlimited class, in order to avoid freezing on resizing in FP11. + Add ability to disable file dialog trigger on request (uploader.disableBrowse(true/false)). + Support for immediate abort of upload process, be it chunked upload or regular one. + Abort all activity, before destroying uploader. + Revive temporary file removal logic in upload.php. + Fix potential vulnerability in dump.php and upload.php. + Additional MIME types: application/vnd.openxmlformats-officedocument.*, application/x-javascript, application/json, text/css,css, application/vnd.oasis.opendocument.formula-templat. + Additional language packs: Hungarian, Croatian, Serbian, Romanian. +Version 1.5.1.1 (2011-09-27) + HTML5: Fix mechanical typo, that successfully broke drag and drop, wherever could. +Version 1.5.1 (2011-09-26) + HTML4: Add support for server responses in HTML format. + HTML5: Disable multiple file selection in Safari 5.x for Windows (see #363). + HTML5: Gecko 2/5/6 should upload chunks as binary strings when in chunking mode and client side resize is requested. + Flash: Enforce URLStream mode when custom headers are passed. + Flash: Fix embedding problems in IE9 (and all other IEs). + Flash/Gears/BrowserPlus/SilverLight: Expose multi_selection feature, to be used in required_features (mainly to overcome Safari for Windows problem). + SilverLight: Properly handle custom and null headers. + UploadComplete moved to fire after the last StateChanged event. + Additional language packs: Finnish. +Version 1.5b (2011-09-11) + UI Widget: Fix sortable logic. + UI Widget: Fix bug, when message was displayed simultaneously across all Plupload UI instances on the page. + UI Widget: notify() method is now public - users can throw their own messages into the widget header. + HTML4/HTML5: Revise input[type=file] placement logic to support cursor styling on Geko 2+. + HTML5: Revise Drag'n'Drop detection logic. + HTML5: Make Exif and GPS information available to user, introduce two new events: ExifData and GpsData. + HTML5: Add support for File.prototype.slice() method (mozSlice/webkitSlice) in order to be able to upload files in chunks without preloading. + HTML5: Remove any JPEG headers before restoring them, 'cause user agent (like Chrome), might be inserting it's own. + Flash: Remove a limit on the depth of image header check, since it still fails in some cases and performance gain is negligible. + Flash: Fix regression, when runtime hanged when not images where passed in as images. + SilverLight: Fix bug, when JSON serializer was failing on null. + SilverLight: Remove cast to integer for chunk boundary, which resulted in a wrong size for last chunks on huge files. + SilverLight: Increase read buffer, add disposal of ImageStream and FileStream, optimize for performance. + Updated build.xml to include language packs in release package under js/ folder. + Gears/BrowserPlus: Add support for * file filter. + BeforeUpload now can cancel upload if required. + Additional MIME types: text/csv, image/photoshop, video/x-ms-wmv, video/avi, video/webm support + Additional language packs: Japanese + Cleaned examples. +Version 1.4.3.2 (2011-04-13) + Fixed bug in HTML5 runtime, when was reduced by a factor of 100 after every upload. +Version 1.4.3.1 (2011-04-12) + Fixed build script, mistakenly populating jquery.plupload.queue directory from jquery.ui.plupload sources. + Fixed script urls in all examples, build script now will alter them automatically from dev to release when needed. + Fixed isEmptyObj undefined error in HTML4 runtime. + Fixed bug in UI Widget preventing UploadComplete from triggering. +Version 1.4.3 (2011-04-11) + Added Latvian language pack and updated French. + Fixed bug in Flash runtime when JPEG header was not investigated deep enough to reach SOFn marker in large images. + Fixed bug, when PNGs were cropped to width in Flash runtimes, rather then resized. + Fixed Flash to allow multiple uploading of the same file, with different settings. + Fixed Flash runtime to clean anonymous listeners properly. + Fixed HTML5 runtime to resolve to mimeType in case-insensitive way. + Fixed HTML5/Flash/SilverLight/Gears runtimes for inconsistency in naming of chunks feature, comparing to other runtimes. + Fixed HTML4/HTML5 runtimes for input[type=file] to outsize contaner effectively enough to fill the whole click area. + Fixed all runtimes to preserve position (relative/absolute) rule on containers that already have it. + Fixed SilverLight runtime to support large files (over 2GB). + Restructured the examples, src and build scripts to make it more clear that jQuery is optional. + Added support for *.* filter. + Added support for preserving ICC and IPTC headers when resizing JPEGs. + Added Image.onerror/onabort handlers to HTML5 in order to gracefully bypass faulty images. + Added ability to drop image size (by lowering quality), while preserving original dimension (HTML5/Flash/Gears). + Ported EXIF, ICC, IPTC preservation code to Flash runtime. +Version 1.4.2 (2011-02-20) + Added Brazilian Portuguese, German, Russian and Spanish translations. + Added support for file_data_name option to SilverLight runtime. + Added support for better quality image resizing to Flash runtime. + Added support for properly handling images with dimensions up to 8191x8191 pixels to Flash runtime. + Added 'updatelist' event to UI Widget, which will be triggered every time file list will get redrawn. + Added support for dynamically changing options to UI Widget. + Fixed HTML4 runtime bug, when UploadFile handler was attached twice. + Fixed HTML5 to use FileReader.readAsBinaryString() instead of File.getAsBinary() on newer WebKit browsers (like Chrome 9). + Fixed Flash runtime from sending duplicate Filename param, when using FileReference.upload(). + Updated S3 example to illustrate support for a proper progress indication. +Version 1.4.1 (2011-02-01) + Added an example on how to use Plupload with Amazon S3 written in PHP but can easily be ported to other languages. + Fixed bug where hidden input elements wasn't created when the multiple_queues option wasn't used. + Fixed bug where FF4 would produce an exception about missing BlobBuilder. +Version 1.4.0 (2011-01-26) + Added removeEvent and removeAllEvents methods and modified addEvent accordingly, in order to support dynamic unload. + Added unbindAll method. + Added UploadComplete event, which fires when internal iterator reaches the end of the queue. + Added public destroy method to plupload object, new event - Destroy, and corresponding handlers to all runtimes. + Added Czech, Italian, French, Dutch translations. + Added support for translatable error messages. + Added two new options: browse_button_hover and browse_button_active, in order to support browse_button interactivity. + Added support for 'multi_selection: false' to Silverlight runtime. + Added support for video/mp4, video/x-m4v and audio/mp4 MIME Types. + Added artificial sendAsBinary method to XMLHttpRequest.prototype for browsers that have support for BlobBuilder and typed arrays. + Added version tracking variable into plupload object and version comment to the header of every file. + Fixed measurements of browse_button element in order to size and position input[type=file] element to fit it fully. + Fixed Flash runtime behavior for multiple_select=false and other simpleUpload usage cases: basically new FileReference has to be created for every select dialog. + Fixed browser sniffer to match only Safari, for fakeSafariDragDrop (seems like Safari on Mac doesn't require it either). + Fixed so that ExternalInterface escapes strings properly, before passing them to JS. + Fixed eventual reinitialization of flash/silverlight runtimes, especially for cases when object wrapper needed to be programmatically hidden and then shown again. + Fixed so that Plupload will now ignore files with duplicate names when adding to the queue, in one set. Mainly introduced to work around Safari on Windows bug (https://bugs.webkit.org/show_bug.cgi?id=37957). + Fixed bug, when final UploadProgress was firing after FileUploaded for Flash simpleUpload. + Fixed bug where upload would fail if an error was produced inside the FilesAdded event. + Fixed bug in Flash runtime when it used a wrong size when resizing, but not chunking. + Fixed bug in Silverlight runtime that would keep sending 0 byte packages when a picture was chunked before resized. + Disabled blur filter (is going to be replaced with some bilinear resampling in next release). + Completely revised UI Widget, to be more jQuery UI oriented. Optionally depends on UI Button, UI Sortable, UI ProgressBar. +Version 1.3.0 (2010-11-24) + Added new jQuery UI widget that supports jQuery UI themes. + Added new multiple_queues option that enables you to upload multiple times in the queue widgets. + Added support for crossdomain loading of the XAP and SWF files and crossdomain upload. + Added new multiple_queues option that enables you to upload multiple times in the queue widgets. + Added support for crossdomain loading of the XAP and SWF files and crossdomain upload. + Added preinit/init options to to ease up the binding of custom events to queueWidget and the Uploader class. + Added drag/drop support for Safari until they fix the broken drag/drop support on Windows. + Added events example file that show how to bind all events and display event specific data. + Added support for retaining Exif data on images when they where resized using the HTML5 runtime. + Fixed logic issue with the upload.php example file. Chunking wasn't working correctly. + Fixed issue with HTML4 not handling the form encoding correctly on older IE versions. Patch contributed by jinxdone. + Fixed so the HTML4 runtime only submits the defined multipart_params arguments. + Fixes issue where it wasn't possible to dynamically override url or mutlipart_params for the HTML4 runtime. + Fixed so all runtimes pass the name, chunk and chunks parameters as multipart parameters instead of querystring parameters. + Fixed so files are read using the newer FileReader class if it's available if not it tries the older getAsXXX on Gecko. + Fixed bug where IE 9 beta 1 wouldn't render Silverlight properly. + Fixed bug where Flash would do extra empty requests if images below a specific size would be uploaded. + Fixed bug where Google Gears would resize and re-encode images even if the it wasn't changed in scale. + Fixed bug where the HTML5 runtime wouldn't free memory after each request on Gecko. +Version 1.2.4 (2010-09-08) + Added new BeforeUpload event to make it easier to override settings before a file is uploaded. + Added new automatic usage of FileReference in Flash if it's possible. Contributed by Marcel Jackwerth. + Added new chunking support for Chrome 5 and Firefox 3.6 using the HTML 5 runtime. + Added new multipart upload support for WebKit using the HTML 5 runtime and the FormData object. + Added new image scaling method for the Flash runtime contributed by rcoopman. + Added new alert error message if the user selected invalid files. + Added new automatic unique name generation to the example.php script. Contributed by Brandon Kelly. + Changed so the default upload method is multipart and the default chunk size is 0. + Fixed progress issue with the HTML5 runtime running on Gecko. + Fixed so longer extensions can be used such as .tar.gz. + Fixed so the file extension is retained when using the unique_names option. +Version 1.2.3 (2010-05-27) + Added new drag/drop support for HTML5 running on Chrome beta. + Added new multipart state for the features object. It's now possible to detect multipart support. + Added new getFeatures function to all runtime. Basic concept by Javier Martinez Fernandez. + Fixed bug where runtimes where initialized even if they didn't match the required_features setting. +Version 1.2.2.1 (2010-05-04) + Added new headers option, enables you to set custom headers for the upload requests. + Fixed bug where the file extension checking was case sensitive. +Version 1.2.2 (2010-04-26) + Added new file_data_name option that enables you to set the multipart file data param. Patch contributed by Alex Ganov. + Added new FILE_SIZE_ERROR type that will be triggered if the user selected a file that is to large or zero bytes. + Added new FILE_EXTENSION_ERROR type that will be triggered if you add a file with an invalid file extension. + Added new required_features setting, enables you to specify a list of required features that the runtime must have. + Fixed so the plupload.buildUrl function uses the UTF compatible encodeURIComponent method instead of escape. + Fixed so that all file types can be selected if you don't specify a filter setting. + Fixed so more valid HTTP status codes are accepted as valid responses. + Fixed so all runtimes fills the features object with available features. + Fixed some issues with the HTML4 runtime if there wasn't any existing forms on the page. + Fixed some conflict issues with HTML4 runtime and forms with the input names of action or target. + Fixed bug where some Gecko versions would produce exceptions when checking the HTTP status of a XHR. +Version 1.2.1 (2010-03-22) + Fixed bug with incorrect aspect ratio in Flash image scaling. + Fixed bug where chunked uploads could get scrambled in the Flash runtime. Patch contributed by Grady Werner. + Fixed bug where a beta version of Chrome wouldn't handle drag/drop correctly because of missing drag effect. + Fixed so the HTML 4 runtime displays N/A for file sizes and the progress is based on uploaded files instead of bytes. + Fixed so chunking can be disabled properly in Flash but that will affect the progress bar. + Fixed so queue widget displays the drag/drop message if file queue is emptied. + Fixed small files are uploaded as one single chunk and not forced into 4 chunks in the Flash runtime. +Version 1.2 (2010-03-09) + Added new rename file support for jQuery queue widget, click on a file name to rename it if it's enabled. + Added official ChunkUploaded event, it similar to FileUploaded but executed for each chunk. + Added bytes per second support to total queue progress. + Added better error handling to core API using the new Error event. + Added better error handling to jQuery queue widget. + Fixed so chunking uploads is dispatch from JS not from inside Flash/Silverlight. +Version 1.1.1 (2010-02-25) + Added new setup setting to queue widget. Makes it easier to bind custom events to uploader instance. + Fixed so it's possible to disable chunking compleatly. It's now disabled by default. + Fixed bug where multipart mode was enabled all the time in the Flash runtime. + Fixed bug where chunked uploading in Silverlight would fail. + Fixed bug where the delete button was visible while uploading. + Fixed bug where unique_names setting wasn't working when the core API was used. + Fixed bug where the queue widget wouldn't display the currently uploaded file if the unique_names was enabled. +Version 1.1 (2010-02-24) + Added new multipart and multipart_params support. + Added new container option, enables you to specify where flash/silverlight objects would be added. + Added chunking support to BrowserPlus runtime, contributed by Steve Spencer. + Added FileUploaded event that fires when a file is uploaded. + Added more easily understandable buttons to queue widget. + Added html4 runtime, contributed by Ryan Demmer. + Fixed issues with i18n support and added a Swedish and Danish language pack. + Fixed bug where the Flash runtime could do empty requests if the image was scaled down. + Fixed bug where uploading small images in Silverlight would produce an exception. + Fixed so the runtime list can include whitespace or missing runtimes. Patch contributed by Øyvind Sean Kinsey. + Fixed so to large files are ignored and never dispatched to the FilesAdded event. +Version 1.0 (2010-02-03) + First official release of Plupload. diff --git a/sources/wp-includes/js/plupload/handlers.js b/sources/wp-includes/js/plupload/handlers.js new file mode 100644 index 0000000..0b9937c --- /dev/null +++ b/sources/wp-includes/js/plupload/handlers.js @@ -0,0 +1,491 @@ +var topWin = window.dialogArguments || opener || parent || top, uploader, uploader_init; + +function fileDialogStart() { + jQuery("#media-upload-error").empty(); +} + +// progress and success handlers for media multi uploads +function fileQueued(fileObj) { + // Get rid of unused form + jQuery('.media-blank').remove(); + + var items = jQuery('#media-items').children(), postid = post_id || 0; + + // Collapse a single item + if ( items.length == 1 ) { + items.removeClass('open').find('.slidetoggle').slideUp(200); + } + // Create a progress bar containing the filename + jQuery('
    ') + .attr( 'id', 'media-item-' + fileObj.id ) + .addClass('child-of-' + postid) + .append('
    0%
    ', + jQuery('
    ').text( ' ' + fileObj.name )) + .appendTo( jQuery('#media-items' ) ); + + // Disable submit + jQuery('#insert-gallery').prop('disabled', true); +} + +function uploadStart() { + try { + if ( typeof topWin.tb_remove != 'undefined' ) + topWin.jQuery('#TB_overlay').unbind('click', topWin.tb_remove); + } catch(e){} + + return true; +} + +function uploadProgress(up, file) { + var item = jQuery('#media-item-' + file.id); + + jQuery('.bar', item).width( (200 * file.loaded) / file.size ); + jQuery('.percent', item).html( file.percent + '%' ); +} + +// check to see if a large file failed to upload +function fileUploading(up, file) { + var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10); + + if ( max > hundredmb && file.size > hundredmb ) { + setTimeout(function(){ + var done; + + if ( file.status < 3 && file.loaded == 0 ) { // not uploading + wpFileError(file, pluploadL10n.big_upload_failed.replace('%1$s', '').replace('%2$s', '')); + up.stop(); // stops the whole queue + up.removeFile(file); + up.start(); // restart the queue + } + }, 10000); // wait for 10 sec. for the file to start uploading + } +} + +function updateMediaForm() { + var items = jQuery('#media-items').children(); + + // Just one file, no need for collapsible part + if ( items.length == 1 ) { + items.addClass('open').find('.slidetoggle').show(); + jQuery('.insert-gallery').hide(); + } else if ( items.length > 1 ) { + items.removeClass('open'); + // Only show Gallery button when there are at least two files. + jQuery('.insert-gallery').show(); + } + + // Only show Save buttons when there is at least one file. + if ( items.not('.media-blank').length > 0 ) + jQuery('.savebutton').show(); + else + jQuery('.savebutton').hide(); +} + +function uploadSuccess(fileObj, serverData) { + var item = jQuery('#media-item-' + fileObj.id); + + // on success serverData should be numeric, fix bug in html4 runtime returning the serverData wrapped in a
     tag
    +	serverData = serverData.replace(/^
    (\d+)<\/pre>$/, '$1');
    +
    +	// if async-upload returned an error message, place it in the media item div and return
    +	if ( serverData.match(/media-upload-error|error-div/) ) {
    +		item.html(serverData);
    +		return;
    +	} else {
    +		jQuery('.percent', item).html( pluploadL10n.crunching );
    +	}
    +
    +	prepareMediaItem(fileObj, serverData);
    +	updateMediaForm();
    +
    +	// Increment the counter.
    +	if ( post_id && item.hasClass('child-of-' + post_id) )
    +		jQuery('#attachments-count').text(1 * jQuery('#attachments-count').text() + 1);
    +}
    +
    +function setResize(arg) {
    +	if ( arg ) {
    +		if ( uploader.features.jpgresize )
    +			uploader.settings['resize'] = { width: resize_width, height: resize_height, quality: 100 };
    +		else
    +			uploader.settings.multipart_params.image_resize = true;
    +	} else {
    +		delete(uploader.settings.resize);
    +		delete(uploader.settings.multipart_params.image_resize);
    +	}
    +}
    +
    +function prepareMediaItem(fileObj, serverData) {
    +	var f = ( typeof shortform == 'undefined' ) ? 1 : 2, item = jQuery('#media-item-' + fileObj.id);
    +	if ( f == 2 && shortform > 2 )
    +		f = shortform;
    +
    +	try {
    +		if ( typeof topWin.tb_remove != 'undefined' )
    +			topWin.jQuery('#TB_overlay').click(topWin.tb_remove);
    +	} catch(e){}
    +
    +	if ( isNaN(serverData) || !serverData ) { // Old style: Append the HTML returned by the server -- thumbnail and form inputs
    +		item.append(serverData);
    +		prepareMediaItemInit(fileObj);
    +	} else { // New style: server data is just the attachment ID, fetch the thumbnail and form html from the server
    +		item.load('async-upload.php', {attachment_id:serverData, fetch:f}, function(){prepareMediaItemInit(fileObj);updateMediaForm()});
    +	}
    +}
    +
    +function prepareMediaItemInit(fileObj) {
    +	var item = jQuery('#media-item-' + fileObj.id);
    +	// Clone the thumbnail as a "pinkynail" -- a tiny image to the left of the filename
    +	jQuery('.thumbnail', item).clone().attr('class', 'pinkynail toggle').prependTo(item);
    +
    +	// Replace the original filename with the new (unique) one assigned during upload
    +	jQuery('.filename.original', item).replaceWith( jQuery('.filename.new', item) );
    +
    +	// Bind AJAX to the new Delete button
    +	jQuery('a.delete', item).click(function(){
    +		// Tell the server to delete it. TODO: handle exceptions
    +		jQuery.ajax({
    +			url: ajaxurl,
    +			type: 'post',
    +			success: deleteSuccess,
    +			error: deleteError,
    +			id: fileObj.id,
    +			data: {
    +				id : this.id.replace(/[^0-9]/g, ''),
    +				action : 'trash-post',
    +				_ajax_nonce : this.href.replace(/^.*wpnonce=/,'')
    +			}
    +		});
    +		return false;
    +	});
    +
    +	// Bind AJAX to the new Undo button
    +	jQuery('a.undo', item).click(function(){
    +		// Tell the server to untrash it. TODO: handle exceptions
    +		jQuery.ajax({
    +			url: ajaxurl,
    +			type: 'post',
    +			id: fileObj.id,
    +			data: {
    +				id : this.id.replace(/[^0-9]/g,''),
    +				action: 'untrash-post',
    +				_ajax_nonce: this.href.replace(/^.*wpnonce=/,'')
    +			},
    +			success: function(data, textStatus){
    +				var item = jQuery('#media-item-' + fileObj.id);
    +
    +				if ( type = jQuery('#type-of-' + fileObj.id).val() )
    +					jQuery('#' + type + '-counter').text(jQuery('#' + type + '-counter').text()-0+1);
    +
    +				if ( post_id && item.hasClass('child-of-'+post_id) )
    +					jQuery('#attachments-count').text(jQuery('#attachments-count').text()-0+1);
    +
    +				jQuery('.filename .trashnotice', item).remove();
    +				jQuery('.filename .title', item).css('font-weight','normal');
    +				jQuery('a.undo', item).addClass('hidden');
    +				jQuery('.menu_order_input', item).show();
    +				item.css( {backgroundColor:'#ceb'} ).animate( {backgroundColor: '#fff'}, { queue: false, duration: 500, complete: function(){ jQuery(this).css({backgroundColor:''}); } }).removeClass('undo');
    +			}
    +		});
    +		return false;
    +	});
    +
    +	// Open this item if it says to start open (e.g. to display an error)
    +	jQuery('#media-item-' + fileObj.id + '.startopen').removeClass('startopen').addClass('open').find('slidetoggle').fadeIn();
    +}
    +
    +// generic error message
    +function wpQueueError(message) {
    +	jQuery('#media-upload-error').show().html( '

    ' + message + '

    ' ); +} + +// file-specific error messages +function wpFileError(fileObj, message) { + itemAjaxError(fileObj.id, message); +} + +function itemAjaxError(id, message) { + var item = jQuery('#media-item-' + id), filename = item.find('.filename').text(), last_err = item.data('last-err'); + + if ( last_err == id ) // prevent firing an error for the same file twice + return; + + item.html('
    ' + + '' + pluploadL10n.dismiss + '' + + '' + pluploadL10n.error_uploading.replace('%s', jQuery.trim(filename)) + ' ' + + message + + '
    ').data('last-err', id); +} + +function deleteSuccess(data, textStatus) { + if ( data == '-1' ) + return itemAjaxError(this.id, 'You do not have permission. Has your session expired?'); + + if ( data == '0' ) + return itemAjaxError(this.id, 'Could not be deleted. Has it been deleted already?'); + + var id = this.id, item = jQuery('#media-item-' + id); + + // Decrement the counters. + if ( type = jQuery('#type-of-' + id).val() ) + jQuery('#' + type + '-counter').text( jQuery('#' + type + '-counter').text() - 1 ); + + if ( post_id && item.hasClass('child-of-'+post_id) ) + jQuery('#attachments-count').text( jQuery('#attachments-count').text() - 1 ); + + if ( jQuery('form.type-form #media-items').children().length == 1 && jQuery('.hidden', '#media-items').length > 0 ) { + jQuery('.toggle').toggle(); + jQuery('.slidetoggle').slideUp(200).siblings().removeClass('hidden'); + } + + // Vanish it. + jQuery('.toggle', item).toggle(); + jQuery('.slidetoggle', item).slideUp(200).siblings().removeClass('hidden'); + item.css( {backgroundColor:'#faa'} ).animate( {backgroundColor:'#f4f4f4'}, {queue:false, duration:500} ).addClass('undo'); + + jQuery('.filename:empty', item).remove(); + jQuery('.filename .title', item).css('font-weight','bold'); + jQuery('.filename', item).append(' ' + pluploadL10n.deleted + ' ').siblings('a.toggle').hide(); + jQuery('.filename', item).append( jQuery('a.undo', item).removeClass('hidden') ); + jQuery('.menu_order_input', item).hide(); + + return; +} + +function deleteError(X, textStatus, errorThrown) { + // TODO +} + +function uploadComplete() { + jQuery('#insert-gallery').prop('disabled', false); +} + +function switchUploader(s) { + if ( s ) { + deleteUserSetting('uploader'); + jQuery('.media-upload-form').removeClass('html-uploader'); + + if ( typeof(uploader) == 'object' ) + uploader.refresh(); + } else { + setUserSetting('uploader', '1'); // 1 == html uploader + jQuery('.media-upload-form').addClass('html-uploader'); + } +} + +function dndHelper(s) { + var d = document.getElementById('dnd-helper'); + + if ( s ) { + d.style.display = 'block'; + } else { + d.style.display = 'none'; + } +} + +function uploadError(fileObj, errorCode, message, uploader) { + var hundredmb = 100 * 1024 * 1024, max; + + switch (errorCode) { + case plupload.FAILED: + wpFileError(fileObj, pluploadL10n.upload_failed); + break; + case plupload.FILE_EXTENSION_ERROR: + wpFileError(fileObj, pluploadL10n.invalid_filetype); + break; + case plupload.FILE_SIZE_ERROR: + uploadSizeError(uploader, fileObj); + break; + case plupload.IMAGE_FORMAT_ERROR: + wpFileError(fileObj, pluploadL10n.not_an_image); + break; + case plupload.IMAGE_MEMORY_ERROR: + wpFileError(fileObj, pluploadL10n.image_memory_exceeded); + break; + case plupload.IMAGE_DIMENSIONS_ERROR: + wpFileError(fileObj, pluploadL10n.image_dimensions_exceeded); + break; + case plupload.GENERIC_ERROR: + wpQueueError(pluploadL10n.upload_failed); + break; + case plupload.IO_ERROR: + max = parseInt(uploader.settings.max_file_size, 10); + + if ( max > hundredmb && fileObj.size > hundredmb ) + wpFileError(fileObj, pluploadL10n.big_upload_failed.replace('%1$s', '').replace('%2$s', '')); + else + wpQueueError(pluploadL10n.io_error); + break; + case plupload.HTTP_ERROR: + wpQueueError(pluploadL10n.http_error); + break; + case plupload.INIT_ERROR: + jQuery('.media-upload-form').addClass('html-uploader'); + break; + case plupload.SECURITY_ERROR: + wpQueueError(pluploadL10n.security_error); + break; +/* case plupload.UPLOAD_ERROR.UPLOAD_STOPPED: + case plupload.UPLOAD_ERROR.FILE_CANCELLED: + jQuery('#media-item-' + fileObj.id).remove(); + break;*/ + default: + wpFileError(fileObj, pluploadL10n.default_error); + } +} + +function uploadSizeError( up, file, over100mb ) { + var message; + + if ( over100mb ) + message = pluploadL10n.big_upload_queued.replace('%s', file.name) + ' ' + pluploadL10n.big_upload_failed.replace('%1$s', '').replace('%2$s', ''); + else + message = pluploadL10n.file_exceeds_size_limit.replace('%s', file.name); + + jQuery('#media-items').append('

    ' + message + '

    '); + up.removeFile(file); +} + +jQuery(document).ready(function($){ + $('.media-upload-form').bind('click.uploader', function(e) { + var target = $(e.target), tr, c; + + if ( target.is('input[type="radio"]') ) { // remember the last used image size and alignment + tr = target.closest('tr'); + + if ( tr.hasClass('align') ) + setUserSetting('align', target.val()); + else if ( tr.hasClass('image-size') ) + setUserSetting('imgsize', target.val()); + + } else if ( target.is('button.button') ) { // remember the last used image link url + c = e.target.className || ''; + c = c.match(/url([^ '"]+)/); + + if ( c && c[1] ) { + setUserSetting('urlbutton', c[1]); + target.siblings('.urlfield').val( target.data('link-url') ); + } + } else if ( target.is('a.dismiss') ) { + target.parents('.media-item').fadeOut(200, function(){ + $(this).remove(); + }); + } else if ( target.is('.upload-flash-bypass a') || target.is('a.uploader-html') ) { // switch uploader to html4 + $('#media-items, p.submit, span.big-file-warning').css('display', 'none'); + switchUploader(0); + e.preventDefault(); + } else if ( target.is('.upload-html-bypass a') ) { // switch uploader to multi-file + $('#media-items, p.submit, span.big-file-warning').css('display', ''); + switchUploader(1); + e.preventDefault(); + } else if ( target.is('a.describe-toggle-on') ) { // Show + target.parent().addClass('open'); + target.siblings('.slidetoggle').fadeIn(250, function(){ + var S = $(window).scrollTop(), H = $(window).height(), top = $(this).offset().top, h = $(this).height(), b, B; + + if ( H && top && h ) { + b = top + h; + B = S + H; + + if ( b > B ) { + if ( b - B < top - S ) + window.scrollBy(0, (b - B) + 10); + else + window.scrollBy(0, top - S - 40); + } + } + }); + e.preventDefault(); + } else if ( target.is('a.describe-toggle-off') ) { // Hide + target.siblings('.slidetoggle').fadeOut(250, function(){ + target.parent().removeClass('open'); + }); + e.preventDefault(); + } + }); + + // init and set the uploader + uploader_init = function() { + uploader = new plupload.Uploader(wpUploaderInit); + + $('#image_resize').bind('change', function() { + var arg = $(this).prop('checked'); + + setResize( arg ); + + if ( arg ) + setUserSetting('upload_resize', '1'); + else + deleteUserSetting('upload_resize'); + }); + + uploader.bind('Init', function(up) { + var uploaddiv = $('#plupload-upload-ui'); + + setResize( getUserSetting('upload_resize', false) ); + + if ( up.features.dragdrop && ! $(document.body).hasClass('mobile') ) { + uploaddiv.addClass('drag-drop'); + $('#drag-drop-area').bind('dragover.wp-uploader', function(){ // dragenter doesn't fire right :( + uploaddiv.addClass('drag-over'); + }).bind('dragleave.wp-uploader, drop.wp-uploader', function(){ + uploaddiv.removeClass('drag-over'); + }); + } else { + uploaddiv.removeClass('drag-drop'); + $('#drag-drop-area').unbind('.wp-uploader'); + } + + if ( up.runtime == 'html4' ) + $('.upload-flash-bypass').hide(); + }); + + uploader.init(); + + uploader.bind('FilesAdded', function(up, files) { + var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10); + + $('#media-upload-error').html(''); + uploadStart(); + + plupload.each(files, function(file){ + if ( max > hundredmb && file.size > hundredmb && up.runtime != 'html5' ) + uploadSizeError( up, file, true ); + else + fileQueued(file); + }); + + up.refresh(); + up.start(); + }); + + uploader.bind('BeforeUpload', function(up, file) { + // something + }); + + uploader.bind('UploadFile', function(up, file) { + fileUploading(up, file); + }); + + uploader.bind('UploadProgress', function(up, file) { + uploadProgress(up, file); + }); + + uploader.bind('Error', function(up, err) { + uploadError(err.file, err.code, err.message, up); + up.refresh(); + }); + + uploader.bind('FileUploaded', function(up, file, response) { + uploadSuccess(file, response.response); + }); + + uploader.bind('UploadComplete', function(up, files) { + uploadComplete(); + }); + } + + if ( typeof(wpUploaderInit) == 'object' ) + uploader_init(); + +}); diff --git a/sources/wp-includes/js/plupload/handlers.min.js b/sources/wp-includes/js/plupload/handlers.min.js new file mode 100644 index 0000000..1eb7a5b --- /dev/null +++ b/sources/wp-includes/js/plupload/handlers.min.js @@ -0,0 +1 @@ +function fileDialogStart(){jQuery("#media-upload-error").empty()}function fileQueued(a){jQuery(".media-blank").remove();var b=jQuery("#media-items").children(),c=post_id||0;1==b.length&&b.removeClass("open").find(".slidetoggle").slideUp(200),jQuery('
    ').attr("id","media-item-"+a.id).addClass("child-of-"+c).append('
    0%
    ',jQuery('
    ').text(" "+a.name)).appendTo(jQuery("#media-items")),jQuery("#insert-gallery").prop("disabled",!0)}function uploadStart(){try{"undefined"!=typeof topWin.tb_remove&&topWin.jQuery("#TB_overlay").unbind("click",topWin.tb_remove)}catch(a){}return!0}function uploadProgress(a,b){var c=jQuery("#media-item-"+b.id);jQuery(".bar",c).width(200*b.loaded/b.size),jQuery(".percent",c).html(b.percent+"%")}function fileUploading(a,b){var c=104857600,d=parseInt(a.settings.max_file_size,10);d>c&&b.size>c&&setTimeout(function(){b.status<3&&0==b.loaded&&(wpFileError(b,pluploadL10n.big_upload_failed.replace("%1$s",'').replace("%2$s","")),a.stop(),a.removeFile(b),a.start())},1e4)}function updateMediaForm(){var a=jQuery("#media-items").children();1==a.length?(a.addClass("open").find(".slidetoggle").show(),jQuery(".insert-gallery").hide()):a.length>1&&(a.removeClass("open"),jQuery(".insert-gallery").show()),a.not(".media-blank").length>0?jQuery(".savebutton").show():jQuery(".savebutton").hide()}function uploadSuccess(a,b){var c=jQuery("#media-item-"+a.id);return b=b.replace(/^
    (\d+)<\/pre>$/,"$1"),b.match(/media-upload-error|error-div/)?(c.html(b),void 0):(jQuery(".percent",c).html(pluploadL10n.crunching),prepareMediaItem(a,b),updateMediaForm(),post_id&&c.hasClass("child-of-"+post_id)&&jQuery("#attachments-count").text(1*jQuery("#attachments-count").text()+1),void 0)}function setResize(a){a?uploader.features.jpgresize?uploader.settings.resize={width:resize_width,height:resize_height,quality:100}:uploader.settings.multipart_params.image_resize=!0:(delete uploader.settings.resize,delete uploader.settings.multipart_params.image_resize)}function prepareMediaItem(a,b){var c="undefined"==typeof shortform?1:2,d=jQuery("#media-item-"+a.id);2==c&&shortform>2&&(c=shortform);try{"undefined"!=typeof topWin.tb_remove&&topWin.jQuery("#TB_overlay").click(topWin.tb_remove)}catch(e){}isNaN(b)||!b?(d.append(b),prepareMediaItemInit(a)):d.load("async-upload.php",{attachment_id:b,fetch:c},function(){prepareMediaItemInit(a),updateMediaForm()})}function prepareMediaItemInit(a){var b=jQuery("#media-item-"+a.id);jQuery(".thumbnail",b).clone().attr("class","pinkynail toggle").prependTo(b),jQuery(".filename.original",b).replaceWith(jQuery(".filename.new",b)),jQuery("a.delete",b).click(function(){return jQuery.ajax({url:ajaxurl,type:"post",success:deleteSuccess,error:deleteError,id:a.id,data:{id:this.id.replace(/[^0-9]/g,""),action:"trash-post",_ajax_nonce:this.href.replace(/^.*wpnonce=/,"")}}),!1}),jQuery("a.undo",b).click(function(){return jQuery.ajax({url:ajaxurl,type:"post",id:a.id,data:{id:this.id.replace(/[^0-9]/g,""),action:"untrash-post",_ajax_nonce:this.href.replace(/^.*wpnonce=/,"")},success:function(){var b=jQuery("#media-item-"+a.id);(type=jQuery("#type-of-"+a.id).val())&&jQuery("#"+type+"-counter").text(jQuery("#"+type+"-counter").text()-0+1),post_id&&b.hasClass("child-of-"+post_id)&&jQuery("#attachments-count").text(jQuery("#attachments-count").text()-0+1),jQuery(".filename .trashnotice",b).remove(),jQuery(".filename .title",b).css("font-weight","normal"),jQuery("a.undo",b).addClass("hidden"),jQuery(".menu_order_input",b).show(),b.css({backgroundColor:"#ceb"}).animate({backgroundColor:"#fff"},{queue:!1,duration:500,complete:function(){jQuery(this).css({backgroundColor:""})}}).removeClass("undo")}}),!1}),jQuery("#media-item-"+a.id+".startopen").removeClass("startopen").addClass("open").find("slidetoggle").fadeIn()}function wpQueueError(a){jQuery("#media-upload-error").show().html('

    '+a+"

    ")}function wpFileError(a,b){itemAjaxError(a.id,b)}function itemAjaxError(a,b){var c=jQuery("#media-item-"+a),d=c.find(".filename").text(),e=c.data("last-err");e!=a&&c.html('
    '+pluploadL10n.dismiss+""+pluploadL10n.error_uploading.replace("%s",jQuery.trim(d))+" "+b+"
    ").data("last-err",a)}function deleteSuccess(a){if("-1"==a)return itemAjaxError(this.id,"You do not have permission. Has your session expired?");if("0"==a)return itemAjaxError(this.id,"Could not be deleted. Has it been deleted already?");var b=this.id,c=jQuery("#media-item-"+b);(type=jQuery("#type-of-"+b).val())&&jQuery("#"+type+"-counter").text(jQuery("#"+type+"-counter").text()-1),post_id&&c.hasClass("child-of-"+post_id)&&jQuery("#attachments-count").text(jQuery("#attachments-count").text()-1),1==jQuery("form.type-form #media-items").children().length&&jQuery(".hidden","#media-items").length>0&&(jQuery(".toggle").toggle(),jQuery(".slidetoggle").slideUp(200).siblings().removeClass("hidden")),jQuery(".toggle",c).toggle(),jQuery(".slidetoggle",c).slideUp(200).siblings().removeClass("hidden"),c.css({backgroundColor:"#faa"}).animate({backgroundColor:"#f4f4f4"},{queue:!1,duration:500}).addClass("undo"),jQuery(".filename:empty",c).remove(),jQuery(".filename .title",c).css("font-weight","bold"),jQuery(".filename",c).append(' '+pluploadL10n.deleted+" ").siblings("a.toggle").hide(),jQuery(".filename",c).append(jQuery("a.undo",c).removeClass("hidden")),jQuery(".menu_order_input",c).hide()}function deleteError(){}function uploadComplete(){jQuery("#insert-gallery").prop("disabled",!1)}function switchUploader(a){a?(deleteUserSetting("uploader"),jQuery(".media-upload-form").removeClass("html-uploader"),"object"==typeof uploader&&uploader.refresh()):(setUserSetting("uploader","1"),jQuery(".media-upload-form").addClass("html-uploader"))}function dndHelper(a){var b=document.getElementById("dnd-helper");b.style.display=a?"block":"none"}function uploadError(a,b,c,d){var e,f=104857600;switch(b){case plupload.FAILED:wpFileError(a,pluploadL10n.upload_failed);break;case plupload.FILE_EXTENSION_ERROR:wpFileError(a,pluploadL10n.invalid_filetype);break;case plupload.FILE_SIZE_ERROR:uploadSizeError(d,a);break;case plupload.IMAGE_FORMAT_ERROR:wpFileError(a,pluploadL10n.not_an_image);break;case plupload.IMAGE_MEMORY_ERROR:wpFileError(a,pluploadL10n.image_memory_exceeded);break;case plupload.IMAGE_DIMENSIONS_ERROR:wpFileError(a,pluploadL10n.image_dimensions_exceeded);break;case plupload.GENERIC_ERROR:wpQueueError(pluploadL10n.upload_failed);break;case plupload.IO_ERROR:e=parseInt(d.settings.max_file_size,10),e>f&&a.size>f?wpFileError(a,pluploadL10n.big_upload_failed.replace("%1$s",'').replace("%2$s","")):wpQueueError(pluploadL10n.io_error);break;case plupload.HTTP_ERROR:wpQueueError(pluploadL10n.http_error);break;case plupload.INIT_ERROR:jQuery(".media-upload-form").addClass("html-uploader");break;case plupload.SECURITY_ERROR:wpQueueError(pluploadL10n.security_error);break;default:wpFileError(a,pluploadL10n.default_error)}}function uploadSizeError(a,b,c){var d;d=c?pluploadL10n.big_upload_queued.replace("%s",b.name)+" "+pluploadL10n.big_upload_failed.replace("%1$s",'').replace("%2$s",""):pluploadL10n.file_exceeds_size_limit.replace("%s",b.name),jQuery("#media-items").append('

    '+d+"

    "),a.removeFile(b)}var topWin=window.dialogArguments||opener||parent||top,uploader,uploader_init;jQuery(document).ready(function(a){a(".media-upload-form").bind("click.uploader",function(b){var c,d,e=a(b.target);e.is('input[type="radio"]')?(c=e.closest("tr"),c.hasClass("align")?setUserSetting("align",e.val()):c.hasClass("image-size")&&setUserSetting("imgsize",e.val())):e.is("button.button")?(d=b.target.className||"",d=d.match(/url([^ '"]+)/),d&&d[1]&&(setUserSetting("urlbutton",d[1]),e.siblings(".urlfield").val(e.data("link-url")))):e.is("a.dismiss")?e.parents(".media-item").fadeOut(200,function(){a(this).remove()}):e.is(".upload-flash-bypass a")||e.is("a.uploader-html")?(a("#media-items, p.submit, span.big-file-warning").css("display","none"),switchUploader(0),b.preventDefault()):e.is(".upload-html-bypass a")?(a("#media-items, p.submit, span.big-file-warning").css("display",""),switchUploader(1),b.preventDefault()):e.is("a.describe-toggle-on")?(e.parent().addClass("open"),e.siblings(".slidetoggle").fadeIn(250,function(){var b,c,d=a(window).scrollTop(),e=a(window).height(),f=a(this).offset().top,g=a(this).height();e&&f&&g&&(b=f+g,c=d+e,b>c&&(f-d>b-c?window.scrollBy(0,b-c+10):window.scrollBy(0,f-d-40)))}),b.preventDefault()):e.is("a.describe-toggle-off")&&(e.siblings(".slidetoggle").fadeOut(250,function(){e.parent().removeClass("open")}),b.preventDefault())}),uploader_init=function(){uploader=new plupload.Uploader(wpUploaderInit),a("#image_resize").bind("change",function(){var b=a(this).prop("checked");setResize(b),b?setUserSetting("upload_resize","1"):deleteUserSetting("upload_resize")}),uploader.bind("Init",function(b){var c=a("#plupload-upload-ui");setResize(getUserSetting("upload_resize",!1)),b.features.dragdrop&&!a(document.body).hasClass("mobile")?(c.addClass("drag-drop"),a("#drag-drop-area").bind("dragover.wp-uploader",function(){c.addClass("drag-over")}).bind("dragleave.wp-uploader, drop.wp-uploader",function(){c.removeClass("drag-over")})):(c.removeClass("drag-drop"),a("#drag-drop-area").unbind(".wp-uploader")),"html4"==b.runtime&&a(".upload-flash-bypass").hide()}),uploader.init(),uploader.bind("FilesAdded",function(b,c){var d=104857600,e=parseInt(b.settings.max_file_size,10);a("#media-upload-error").html(""),uploadStart(),plupload.each(c,function(a){e>d&&a.size>d&&"html5"!=b.runtime?uploadSizeError(b,a,!0):fileQueued(a)}),b.refresh(),b.start()}),uploader.bind("BeforeUpload",function(){}),uploader.bind("UploadFile",function(a,b){fileUploading(a,b)}),uploader.bind("UploadProgress",function(a,b){uploadProgress(a,b)}),uploader.bind("Error",function(a,b){uploadError(b.file,b.code,b.message,a),a.refresh()}),uploader.bind("FileUploaded",function(a,b,c){uploadSuccess(b,c.response)}),uploader.bind("UploadComplete",function(){uploadComplete()})},"object"==typeof wpUploaderInit&&uploader_init()}); \ No newline at end of file diff --git a/sources/wp-includes/js/plupload/license.txt b/sources/wp-includes/js/plupload/license.txt new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/sources/wp-includes/js/plupload/license.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sources/wp-includes/js/plupload/plupload.flash.js b/sources/wp-includes/js/plupload/plupload.flash.js new file mode 100644 index 0000000..7d3f008 --- /dev/null +++ b/sources/wp-includes/js/plupload/plupload.flash.js @@ -0,0 +1 @@ +(function(f,b,d,e){var a={},g={};function c(){var h;try{h=navigator.plugins["Shockwave Flash"];h=h.description}catch(j){try{h=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(i){h="0.0"}}h=h.match(/\d+/g);return parseFloat(h[0]+"."+h[1])}d.flash={trigger:function(j,h,i){setTimeout(function(){var m=a[j],l,k;if(m){m.trigger("Flash:"+h,i)}},0)}};d.runtimes.Flash=d.addRuntime("flash",{getFeatures:function(){return{jpgresize:true,pngresize:true,maxWidth:8091,maxHeight:8091,chunks:true,progress:true,multipart:true,multi_selection:true}},init:function(m,o){var k,l,h=0,i=b.body;if(c()<10){o({success:false});return}g[m.id]=false;a[m.id]=m;k=b.getElementById(m.settings.browse_button);l=b.createElement("div");l.id=m.id+"_flash_container";d.extend(l.style,{position:"absolute",top:"0px",background:m.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100%",height:"100%"});l.className="plupload flash";if(m.settings.container){i=b.getElementById(m.settings.container);if(d.getStyle(i,"position")==="static"){i.style.position="relative"}}i.appendChild(l);(function(){var p,q;p='';if(d.ua.ie){q=b.createElement("div");l.appendChild(q);q.outerHTML=p;q=null}else{l.innerHTML=p}}());function n(){return b.getElementById(m.id+"_flash")}function j(){if(h++>5000){o({success:false});return}if(g[m.id]===false){setTimeout(j,1)}}j();k=l=null;m.bind("Destroy",function(p){var q;d.removeAllEvents(b.body,p.id);delete g[p.id];delete a[p.id];q=b.getElementById(p.id+"_flash_container");if(q){q.parentNode.removeChild(q)}});m.bind("Flash:Init",function(){var r={},q;try{n().setFileFilters(m.settings.filters,m.settings.multi_selection)}catch(p){o({success:false});return}if(g[m.id]){return}g[m.id]=true;m.bind("UploadFile",function(s,u){var v=s.settings,t=m.settings.resize||{};n().uploadFile(r[u.id],v.url,{name:u.target_name||u.name,mime:d.mimeTypes[u.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:v.chunk_size,width:t.width,height:t.height,quality:t.quality,multipart:v.multipart,multipart_params:v.multipart_params||{},file_data_name:v.file_data_name,format:/\.(jpg|jpeg)$/i.test(u.name)?"jpg":"png",headers:v.headers,urlstream_upload:v.urlstream_upload})});m.bind("CancelUpload",function(){n().cancelUpload()});m.bind("Flash:UploadProcess",function(t,s){var u=t.getFile(r[s.id]);if(u.status!=d.FAILED){u.loaded=s.loaded;u.size=s.size;t.trigger("UploadProgress",u)}});m.bind("Flash:UploadChunkComplete",function(s,u){var v,t=s.getFile(r[u.id]);v={chunk:u.chunk,chunks:u.chunks,response:u.text};s.trigger("ChunkUploaded",t,v);if(t.status!==d.FAILED&&s.state!==d.STOPPED){n().uploadNextChunk()}if(u.chunk==u.chunks-1){t.status=d.DONE;s.trigger("FileUploaded",t,{response:u.text})}});m.bind("Flash:SelectFiles",function(s,v){var u,t,w=[],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 literal 0 HcmV?d00001 diff --git a/sources/wp-includes/js/plupload/plupload.html4.js b/sources/wp-includes/js/plupload/plupload.html4.js new file mode 100644 index 0000000..0a8f403 --- /dev/null +++ b/sources/wp-includes/js/plupload/plupload.html4.js @@ -0,0 +1 @@ +(function(d,a,b,c){function e(f){return a.getElementById(f)}b.runtimes.Html4=b.addRuntime("html4",{getFeatures:function(){return{multipart:true,triggerDialog:(b.ua.gecko&&d.FormData||b.ua.webkit)}},init:function(f,g){f.bind("Init",function(p){var j=a.body,n,h="javascript",k,x,q,z=[],r=/MSIE/.test(navigator.userAgent),t=[],m=p.settings.filters,o,l,s,w;no_type_restriction:for(o=0;o